From de9fa9b6bbaece9cbb90513e566b7978da5f88e4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Aug 2012 12:04:47 -0400 Subject: [PATCH 001/492] Reenable W1 drivers. (rhbz 849430) --- config-generic | 19 ++++++++++++++++++- kernel.spec | 3 +++ mod-extra.list | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 20024fbba..d6cb2b7e9 100644 --- a/config-generic +++ b/config-generic @@ -2268,7 +2268,24 @@ CONFIG_SENSORS_MAX1668=m # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_W1 is not set +CONFIG_W1=m +CONFIG_W1_CON=y +# CONFIG_W1_MASTER_MATROX is not set +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_BQ27000=m # # Mice diff --git a/kernel.spec b/kernel.spec index be6c5b060..16d90a8d7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2305,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Mon Aug 20 2012 Dave Jones +- Reenable W1 drivers. (rhbz 849430) + * Fri Aug 17 2012 Josh Boyer - 3.6.0-0.rc2.git0.2 - Reenable debugging options. diff --git a/mod-extra.list b/mod-extra.list index c35fb625f..b01f05eb4 100644 --- a/mod-extra.list +++ b/mod-extra.list @@ -172,3 +172,18 @@ tpm_tis.ko slip.ko nilfs2.ko batman-adv.ko +wire.ko +ds1wm.ko +ds2490.ko +ds2482.ko +w1_ds2780.ko +w1_therm.ko +w1_ds2433.ko +w1_ds2760.ko +w1_ds28e04.ko +w1_ds2408.ko +w1_ds2781.ko +w1_smem.ko +w1_ds2431.ko +w1_ds2423.ko +w1_bq27000.ko From ec127a3f2b0e867cf8e327d4bd240681f1ac92b7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 20 Aug 2012 16:56:20 -0400 Subject: [PATCH 002/492] Linux v3.6-rc2-206-g10c63c9 --- kernel.spec | 17 +- ...n-20120814.patch => modsign-20120816.patch | 2376 ++++++++++++++--- sources | 1 + vfs-fix-file-creation-bugs.patch | 393 --- 4 files changed, 2040 insertions(+), 747 deletions(-) rename modsign-20120814.patch => modsign-20120816.patch (79%) delete mode 100644 vfs-fix-file-creation-bugs.patch diff --git a/kernel.spec b/kernel.spec index 16d90a8d7..05f65d2c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 2 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -678,7 +678,7 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-20120814.patch +Patch900: modsign-20120816.patch # secure boot Patch1000: secure-boot-20120809.patch @@ -747,9 +747,6 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 836742 Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch -#rhbz 844485 -Patch22060: vfs-fix-file-creation-bugs.patch - # END OF PATCH DEFINITIONS %endif @@ -1382,7 +1379,7 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ -ApplyPatch modsign-20120814.patch +ApplyPatch modsign-20120816.patch # secure boot ApplyPatch secure-boot-20120809.patch @@ -1440,9 +1437,6 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 836742 ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch -#rhbz 844485 -ApplyPatch vfs-fix-file-creation-bugs.patch - # END OF PATCH APPLICATIONS %endif @@ -2305,6 +2299,9 @@ fi # ||----w | # || || %changelog +* Mon Aug 20 2012 Josh Boyer - 3.6.0-0.rc2.git1.1 +- Linux v3.6-rc2-206-g10c63c9 + * Mon Aug 20 2012 Dave Jones - Reenable W1 drivers. (rhbz 849430) diff --git a/modsign-20120814.patch b/modsign-20120816.patch similarity index 79% rename from modsign-20120814.patch rename to modsign-20120816.patch index deb6ccb98..886e313c8 100644 --- a/modsign-20120814.patch +++ b/modsign-20120816.patch @@ -1,7 +1,963 @@ -From 711fd460b3d44d666fbddd80a91ae5f825c7ebb6 Mon Sep 17 00:00:00 2001 +From bcb9a5e7e8108872ec9fd7083209cbf3a47ef952 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 13:59:15 +0100 -Subject: [PATCH 01/28] MPILIB: Provide count_leading/trailing_zeros() based +Date: Thu, 16 Aug 2012 00:14:14 +0100 +Subject: [PATCH 01/32] KEYS: Add payload preparsing opportunity prior to key + instantiate or update + +Give the key type the opportunity to preparse the payload prior to the +instantiation and update routines being called. This is done with the +provision of two new key type operations: + + int (*preparse)(struct key_preparsed_payload *prep); + void (*free_preparse)(struct key_preparsed_payload *prep); + +If the first operation is present, then it is called before key creation (in +the add/update case) or before the key semaphore is taken (in the update and +instantiate cases). The second operation is called to clean up if the first +was called. + +preparse() is given the opportunity to fill in the following structure: + + struct key_preparsed_payload { + char *description; + void *type_data[2]; + void *payload; + const void *data; + size_t datalen; + size_t quotalen; + }; + +Before the preparser is called, the first three fields will have been cleared, +the payload pointer and size will be stored in data and datalen and the default +quota size from the key_type struct will be stored into quotalen. + +The preparser may parse the payload in any way it likes and may store data in +the type_data[] and payload fields for use by the instantiate() and update() +ops. + +The preparser may also propose a description for the key by attaching it as a +string to the description field. This can be used by passing a NULL or "" +description to the add_key() system call or the key_create_or_update() +function. This cannot work with request_key() as that required the description +to tell the upcall about the key to be created. + +This, for example permits keys that store PGP public keys to generate their own +name from the user ID and public key fingerprint in the key. + +The instantiate() and update() operations are then modified to look like this: + + int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + int (*update)(struct key *key, struct key_preparsed_payload *prep); + +and the new payload data is passed in *prep, whether or not it was preparsed. + +Signed-off-by: David Howells +--- + Documentation/security/keys.txt | 50 +++++++++++++- + fs/cifs/cifs_spnego.c | 6 +- + fs/cifs/cifsacl.c | 8 +-- + include/keys/user-type.h | 6 +- + include/linux/key-type.h | 35 +++++++++- + net/ceph/crypto.c | 9 +-- + net/dns_resolver/dns_key.c | 6 +- + net/rxrpc/ar-key.c | 40 ++++++------ + security/keys/encrypted-keys/encrypted.c | 16 +++-- + security/keys/key.c | 108 ++++++++++++++++++++++--------- + security/keys/keyctl.c | 18 ++++-- + security/keys/keyring.c | 6 +- + security/keys/request_key_auth.c | 8 +-- + security/keys/trusted.c | 16 +++-- + security/keys/user_defined.c | 14 ++-- + 15 files changed, 245 insertions(+), 101 deletions(-) + +diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt +index aa0dbd7..7d9ca92 100644 +--- a/Documentation/security/keys.txt ++++ b/Documentation/security/keys.txt +@@ -412,6 +412,10 @@ The main syscalls are: + to the keyring. In this case, an error will be generated if the process + does not have permission to write to the keyring. + ++ If the key type supports it, if the description is NULL or an empty ++ string, the key type will try and generate a description from the content ++ of the payload. ++ + The payload is optional, and the pointer can be NULL if not required by + the type. The payload is plen in size, and plen can be zero for an empty + payload. +@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: + it should return 0. + + +- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ (*) int (*preparse)(struct key_preparsed_payload *prep); ++ ++ This optional method permits the key type to attempt to parse payload ++ before a key is created (add key) or the key semaphore is taken (update or ++ instantiate key). The structure pointed to by prep looks like: ++ ++ struct key_preparsed_payload { ++ char *description; ++ void *type_data[2]; ++ void *payload; ++ const void *data; ++ size_t datalen; ++ size_t quotalen; ++ }; ++ ++ Before calling the method, the caller will fill in data and datalen with ++ the payload blob parameters; quotalen will be filled in with the default ++ quota size from the key type and the rest will be cleared. ++ ++ If a description can be proposed from the payload contents, that should be ++ attached as a string to the description field. This will be used for the ++ key description if the caller of add_key() passes NULL or "". ++ ++ The method can attach anything it likes to type_data[] and payload. These ++ are merely passed along to the instantiate() or update() operations. ++ ++ The method should return 0 if success ful or a negative error code ++ otherwise. ++ ++ ++ (*) void (*free_preparse)(struct key_preparsed_payload *prep); ++ ++ This method is only required if the preparse() method is provided, ++ otherwise it is unused. It cleans up anything attached to the ++ description, type_data and payload fields of the key_preparsed_payload ++ struct as filled in by the preparse() method. ++ ++ ++ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + This method is called to attach a payload to a key during construction. + The payload attached need not bear any relation to the data passed to this + function. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + If the amount of data attached to the key differs from the size in + keytype->def_datalen, then key_payload_reserve() should be called. + +@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: + If this type of key can be updated, then this method should be provided. + It is called to update a key's payload from the blob of data provided. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + key_payload_reserve() should be called if the data length might change + before any changes are actually made. Note that if this succeeds, the type + is committed to changing the key because it's already been altered, so all +diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c +index e622863..086f381 100644 +--- a/fs/cifs/cifs_spnego.c ++++ b/fs/cifs/cifs_spnego.c +@@ -31,18 +31,18 @@ + + /* create a new cifs key */ + static int +-cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + int ret; + + ret = -ENOMEM; +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + goto error; + + /* attach the data */ +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; + ret = 0; + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 05f4dc2..f3c60e2 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { + }; + + static int +-cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + return -ENOMEM; + +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; +- key->datalen = datalen; ++ key->datalen = prep->datalen; + return 0; + } + +diff --git a/include/keys/user-type.h b/include/keys/user-type.h +index bc9ec1d..5e452c8 100644 +--- a/include/keys/user-type.h ++++ b/include/keys/user-type.h +@@ -35,8 +35,10 @@ struct user_key_payload { + extern struct key_type key_type_user; + extern struct key_type key_type_logon; + +-extern int user_instantiate(struct key *key, const void *data, size_t datalen); +-extern int user_update(struct key *key, const void *data, size_t datalen); ++struct key_preparsed_payload; ++ ++extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); ++extern int user_update(struct key *key, struct key_preparsed_payload *prep); + extern int user_match(const struct key *key, const void *criterion); + extern void user_revoke(struct key *key); + extern void user_destroy(struct key *key); +diff --git a/include/linux/key-type.h b/include/linux/key-type.h +index f0c651c..518a53a 100644 +--- a/include/linux/key-type.h ++++ b/include/linux/key-type.h +@@ -26,6 +26,27 @@ struct key_construction { + struct key *authkey;/* authorisation for key being constructed */ + }; + ++/* ++ * Pre-parsed payload, used by key add, update and instantiate. ++ * ++ * This struct will be cleared and data and datalen will be set with the data ++ * and length parameters from the caller and quotalen will be set from ++ * def_datalen from the key type. Then if the preparse() op is provided by the ++ * key type, that will be called. Then the struct will be passed to the ++ * instantiate() or the update() op. ++ * ++ * If the preparse() op is given, the free_preparse() op will be called to ++ * clear the contents. ++ */ ++struct key_preparsed_payload { ++ char *description; /* Proposed key description (or NULL) */ ++ void *type_data[2]; /* Private key-type data */ ++ void *payload; /* Proposed payload */ ++ const void *data; /* Raw data */ ++ size_t datalen; /* Raw datalen */ ++ size_t quotalen; /* Quota length for proposed payload */ ++}; ++ + typedef int (*request_key_actor_t)(struct key_construction *key, + const char *op, void *aux); + +@@ -45,18 +66,28 @@ struct key_type { + /* vet a description */ + int (*vet_description)(const char *description); + ++ /* Preparse the data blob from userspace that is to be the payload, ++ * generating a proposed description and payload that will be handed to ++ * the instantiate() and update() ops. ++ */ ++ int (*preparse)(struct key_preparsed_payload *prep); ++ ++ /* Free a preparse data structure. ++ */ ++ void (*free_preparse)(struct key_preparsed_payload *prep); ++ + /* instantiate a key of this type + * - this method should call key_payload_reserve() to determine if the + * user's quota will hold the payload + */ +- int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + /* update a key of this type (optional) + * - this method should call key_payload_reserve() to recalculate the + * quota consumption + * - the key must be locked against read when modifying + */ +- int (*update)(struct key *key, const void *data, size_t datalen); ++ int (*update)(struct key *key, struct key_preparsed_payload *prep); + + /* match a key against a description */ + int (*match)(const struct key *key, const void *desc); +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 9da7fdd..af14cb4 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, + } + } + +-int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) ++int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct ceph_crypto_key *ckey; ++ size_t datalen = prep->datalen; + int ret; + void *p; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto err; + + ret = key_payload_reserve(key, datalen); +@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) + goto err; + + /* TODO ceph_crypto_key_decode should really take const input */ +- p = (void *)data; +- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); ++ p = (void *)prep->data; ++ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); + if (ret < 0) + goto err_ckey; + +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index d9507dd..859ab8b 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; + * "ip1,ip2,...#foo=bar" + */ + static int +-dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) ++dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; + unsigned long derrno; + int ret; +- size_t result_len = 0; +- const char *data = _data, *end, *opt; ++ size_t datalen = prep->datalen, result_len = 0; ++ const char *data = prep->data, *end, *opt; + + kenter("%%%d,%s,'%*.*s',%zu", + key->serial, key->description, +diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c +index 8b1f9f4..106c5a6 100644 +--- a/net/rxrpc/ar-key.c ++++ b/net/rxrpc/ar-key.c +@@ -26,8 +26,8 @@ + #include "ar-internal.h" + + static int rxrpc_vet_description_s(const char *); +-static int rxrpc_instantiate(struct key *, const void *, size_t); +-static int rxrpc_instantiate_s(struct key *, const void *, size_t); ++static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); ++static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); + static void rxrpc_destroy(struct key *); + static void rxrpc_destroy_s(struct key *); + static void rxrpc_describe(const struct key *, struct seq_file *); +@@ -678,7 +678,7 @@ error: + * + * if no data is provided, then a no-security key is made + */ +-static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) ++static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + const struct rxrpc_key_data_v1 *v1; + struct rxrpc_key_token *token, **pp; +@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + u32 kver; + int ret; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + + /* handle a no-security key */ +- if (!data && datalen == 0) ++ if (!prep->data && prep->datalen == 0) + return 0; + + /* determine if the XDR payload format is being used */ +- if (datalen > 7 * 4) { +- ret = rxrpc_instantiate_xdr(key, data, datalen); ++ if (prep->datalen > 7 * 4) { ++ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); + if (ret != -EPROTO) + return ret; + } + + /* get the key interface version number */ + ret = -EINVAL; +- if (datalen <= 4 || !data) ++ if (prep->datalen <= 4 || !prep->data) + goto error; +- memcpy(&kver, data, sizeof(kver)); +- data += sizeof(kver); +- datalen -= sizeof(kver); ++ memcpy(&kver, prep->data, sizeof(kver)); ++ prep->data += sizeof(kver); ++ prep->datalen -= sizeof(kver); + + _debug("KEY I/F VERSION: %u", kver); + +@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + + /* deal with a version 1 key */ + ret = -EINVAL; +- if (datalen < sizeof(*v1)) ++ if (prep->datalen < sizeof(*v1)) + goto error; + +- v1 = data; +- if (datalen != sizeof(*v1) + v1->ticket_length) ++ v1 = prep->data; ++ if (prep->datalen != sizeof(*v1) + v1->ticket_length) + goto error; + + _debug("SCIX: %u", v1->security_index); +@@ -784,17 +784,17 @@ error: + * instantiate a server secret key + * data should be a pointer to the 8-byte secret key + */ +-static int rxrpc_instantiate_s(struct key *key, const void *data, +- size_t datalen) ++static int rxrpc_instantiate_s(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct crypto_blkcipher *ci; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + +- if (datalen != 8) ++ if (prep->datalen != 8) + return -EINVAL; + +- memcpy(&key->type_data, data, 8); ++ memcpy(&key->type_data, prep->data, 8); + + ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(ci)) { +@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, + return PTR_ERR(ci); + } + +- if (crypto_blkcipher_setkey(ci, data, 8) < 0) ++ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) + BUG(); + + key->payload.data = ci; +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 2d1bb8a..9e1e005 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int encrypted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = NULL; + char *datablob = NULL; +@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, + char *master_desc = NULL; + char *decrypted_datalen = NULL; + char *hex_encoded_iv = NULL; ++ size_t datalen = prep->datalen; + int ret; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; + datablob[datalen] = 0; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + ret = datablob_parse(datablob, &format, &master_desc, + &decrypted_datalen, &hex_encoded_iv); + if (ret < 0) +@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_update(struct key *key, const void *data, size_t datalen) ++static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = key->payload.data; + struct encrypted_key_payload *new_epayload; + char *buf; + char *new_master_desc = NULL; + const char *format = NULL; ++ size_t datalen = prep->datalen; + int ret = 0; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + buf = kmalloc(datalen + 1, GFP_KERNEL); +@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) + return -ENOMEM; + + buf[datalen] = 0; +- memcpy(buf, data, datalen); ++ memcpy(buf, prep->data, datalen); + ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); + if (ret < 0) + goto out; +diff --git a/security/keys/key.c b/security/keys/key.c +index 50d96d4..732a53e 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); + * key_construction_mutex. + */ + static int __key_instantiate_and_link(struct key *key, +- const void *data, +- size_t datalen, ++ struct key_preparsed_payload *prep, + struct key *keyring, + struct key *authkey, + unsigned long *_prealloc) +@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, + /* can't instantiate twice */ + if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { + /* instantiate the key */ +- ret = key->type->instantiate(key, data, datalen); ++ ret = key->type->instantiate(key, prep); + + if (ret == 0) { + /* mark the key as being instantiated */ +@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, + struct key *keyring, + struct key *authkey) + { ++ struct key_preparsed_payload prep; + unsigned long prealloc; + int ret; + ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = data; ++ prep.datalen = datalen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; ++ } ++ + if (keyring) { + ret = __key_link_begin(keyring, key->type, key->description, + &prealloc); + if (ret < 0) +- return ret; ++ goto error_free_preparse; + } + +- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, ++ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, + &prealloc); + + if (keyring) + __key_link_end(keyring, key->type, prealloc); + ++error_free_preparse: ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + +@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) + * if we get an error. + */ + static inline key_ref_t __key_update(key_ref_t key_ref, +- const void *payload, size_t plen) ++ struct key_preparsed_payload *prep) + { + struct key *key = key_ref_to_ptr(key_ref); + int ret; +@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, + + down_write(&key->sem); + +- ret = key->type->update(key, payload, plen); ++ ret = key->type->update(key, prep); + if (ret == 0) + /* updating a negative key instantiates it */ + clear_bit(KEY_FLAG_NEGATIVE, &key->flags); +@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + unsigned long flags) + { + unsigned long prealloc; ++ struct key_preparsed_payload prep; + const struct cred *cred = current_cred(); + struct key_type *ktype; + struct key *keyring, *key = NULL; +@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + } + + key_ref = ERR_PTR(-EINVAL); +- if (!ktype->match || !ktype->instantiate) +- goto error_2; ++ if (!ktype->match || !ktype->instantiate || ++ (!description && !ktype->preparse)) ++ goto error_put_type; + + keyring = key_ref_to_ptr(keyring_ref); + +@@ -798,18 +814,33 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + + key_ref = ERR_PTR(-ENOTDIR); + if (keyring->type != &key_type_keyring) +- goto error_2; ++ goto error_put_type; ++ ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = ktype->def_datalen; ++ if (ktype->preparse) { ++ ret = ktype->preparse(&prep); ++ if (ret < 0) ++ goto error_put_type; ++ if (!description) ++ description = prep.description; ++ ret = -EINVAL; ++ if (!description) ++ goto error_free_prep; ++ } + + ret = __key_link_begin(keyring, ktype, description, &prealloc); + if (ret < 0) +- goto error_2; ++ goto error_free_prep; + + /* if we're going to allocate a new key, we're going to have + * to modify the keyring */ + ret = key_permission(keyring_ref, KEY_WRITE); + if (ret < 0) { + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + /* if it's possible to update this type of key, search for an existing +@@ -840,25 +871,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + perm, flags); + if (IS_ERR(key)) { + key_ref = ERR_CAST(key); +- goto error_3; ++ goto error_link_end; + } + + /* instantiate it and link it into the target keyring */ +- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, +- &prealloc); ++ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); + if (ret < 0) { + key_put(key); + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); + +- error_3: ++error_link_end: + __key_link_end(keyring, ktype, prealloc); +- error_2: ++error_free_prep: ++ if (ktype->preparse) ++ ktype->free_preparse(&prep); ++error_put_type: + key_type_put(ktype); +- error: ++error: + return key_ref; + + found_matching_key: +@@ -866,10 +899,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + * - we can drop the locks first as we have the key pinned + */ + __key_link_end(keyring, ktype, prealloc); +- key_type_put(ktype); + +- key_ref = __key_update(key_ref, payload, plen); +- goto error; ++ key_ref = __key_update(key_ref, &prep); ++ goto error_free_prep; + } + EXPORT_SYMBOL(key_create_or_update); + +@@ -888,6 +920,7 @@ EXPORT_SYMBOL(key_create_or_update); + */ + int key_update(key_ref_t key_ref, const void *payload, size_t plen) + { ++ struct key_preparsed_payload prep; + struct key *key = key_ref_to_ptr(key_ref); + int ret; + +@@ -900,18 +933,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) + + /* attempt to update it if supported */ + ret = -EOPNOTSUPP; +- if (key->type->update) { +- down_write(&key->sem); +- +- ret = key->type->update(key, payload, plen); +- if (ret == 0) +- /* updating a negative key instantiates it */ +- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ if (!key->type->update) ++ goto error; + +- up_write(&key->sem); ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; + } + +- error: ++ down_write(&key->sem); ++ ++ ret = key->type->update(key, &prep); ++ if (ret == 0) ++ /* updating a negative key instantiates it */ ++ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ ++ up_write(&key->sem); ++ ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + EXPORT_SYMBOL(key_update); +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 3364fbf..505d40b 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, + * Extract the description of a new key from userspace and either add it as a + * new key to the specified keyring or update a matching key in that keyring. + * ++ * If the description is NULL or an empty string, the key type is asked to ++ * generate one from the payload. ++ * + * The keyring must be writable so that we can attach the key to it. + * + * If successful, the new key's serial number is returned, otherwise an error +@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, + if (ret < 0) + goto error; + +- description = strndup_user(_description, PAGE_SIZE); +- if (IS_ERR(description)) { +- ret = PTR_ERR(description); +- goto error; ++ description = NULL; ++ if (_description) { ++ description = strndup_user(_description, PAGE_SIZE); ++ if (IS_ERR(description)) { ++ ret = PTR_ERR(description); ++ goto error; ++ } ++ if (!*description) { ++ kfree(description); ++ description = NULL; ++ } + } + + /* pull the payload in if one was supplied */ +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 81e7852..f04d8cf 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) + * operations. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen); ++ struct key_preparsed_payload *prep); + static int keyring_match(const struct key *keyring, const void *criterion); + static void keyring_revoke(struct key *keyring); + static void keyring_destroy(struct key *keyring); +@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) + * Returns 0 on success, -EINVAL if given any data. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen) ++ struct key_preparsed_payload *prep) + { + int ret; + + ret = -EINVAL; +- if (datalen == 0) { ++ if (prep->datalen == 0) { + /* make the keyring available by name if it has one */ + keyring_publish_name(keyring); + ret = 0; +diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c +index 60d4e3f..85730d5 100644 +--- a/security/keys/request_key_auth.c ++++ b/security/keys/request_key_auth.c +@@ -19,7 +19,8 @@ + #include + #include "internal.h" + +-static int request_key_auth_instantiate(struct key *, const void *, size_t); ++static int request_key_auth_instantiate(struct key *, ++ struct key_preparsed_payload *); + static void request_key_auth_describe(const struct key *, struct seq_file *); + static void request_key_auth_revoke(struct key *); + static void request_key_auth_destroy(struct key *); +@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { + * Instantiate a request-key authorisation key. + */ + static int request_key_auth_instantiate(struct key *key, +- const void *data, +- size_t datalen) ++ struct key_preparsed_payload *prep) + { +- key->payload.data = (struct request_key_auth *) data; ++ key->payload.data = (struct request_key_auth *)prep->data; + return 0; + } + +diff --git a/security/keys/trusted.c b/security/keys/trusted.c +index 2d5d041..42036c7 100644 +--- a/security/keys/trusted.c ++++ b/security/keys/trusted.c +@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) + * + * On success, return 0. Otherwise return errno. + */ +-static int trusted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int trusted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct trusted_key_payload *payload = NULL; + struct trusted_key_options *options = NULL; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + int key_cmd; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + + options = trusted_options_alloc(); +@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) + /* + * trusted_update - reseal an existing key with new PCR values + */ +-static int trusted_update(struct key *key, const void *data, size_t datalen) ++static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct trusted_key_payload *p = key->payload.data; + struct trusted_key_payload *new_p; + struct trusted_key_options *new_o; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + + if (!p->migratable) + return -EPERM; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); +@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) + goto out; + } + +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + ret = datablob_parse(datablob, new_p, new_o); + if (ret != Opt_update) { +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index c7660a2..55dc889 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); + /* + * instantiate a user defined key + */ +-int user_instantiate(struct key *key, const void *data, size_t datalen) ++int user_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + ret = key_payload_reserve(key, datalen); +@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) + + /* attach the data */ + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + rcu_assign_keypointer(key, upayload); + ret = 0; + +@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); + * update a user defined key + * - the key's semaphore is write-locked + */ +-int user_update(struct key *key, const void *data, size_t datalen) ++int user_update(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload, *zap; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + /* construct a replacement payload */ +@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) + goto error; + + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + + /* check the quota and attach the new data */ + zap = upayload; +-- +1.7.11.4 + + +From 2f5f2d483565648dbe050fda8767edd5d65b1d98 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 16 Aug 2012 00:14:17 +0100 +Subject: [PATCH 02/32] MPILIB: Provide count_leading/trailing_zeros() based on arch functions Provide count_leading/trailing_zeros() macros based on extant arch bit scanning @@ -356,13 +1312,13 @@ index 67f3e79..5464c87 100644 c = BITS_PER_MPI_LIMB - 1 - c; -- -1.7.11.2 +1.7.11.4 -From 1d6e2f2b87e6651bead1c0ccca699681f92dd52c Mon Sep 17 00:00:00 2001 +From 15b76403afcc626b91e5fcee8b6a950a51f284ef Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 13:59:51 +0100 -Subject: [PATCH 02/28] KEYS: Create a key type that can be used for general +Date: Thu, 16 Aug 2012 00:14:18 +0100 +Subject: [PATCH 03/32] KEYS: Create a key type that can be used for general cryptographic operations Create a key type that can be used for general cryptographic operations, such @@ -373,16 +1329,16 @@ algorithms. Signed-off-by: David Howells --- - Documentation/security/keys-crypto.txt | 181 ++++++++++++++++++++++++++ - include/keys/crypto-subtype.h | 56 ++++++++ - include/keys/crypto-type.h | 25 ++++ + Documentation/security/keys-crypto.txt | 181 ++++++++++++++++++++++ + include/keys/crypto-subtype.h | 57 +++++++ + include/keys/crypto-type.h | 25 +++ security/keys/Kconfig | 2 + security/keys/Makefile | 1 + security/keys/crypto/Kconfig | 7 + security/keys/crypto/Makefile | 7 + security/keys/crypto/crypto_keys.h | 28 ++++ - security/keys/crypto/crypto_type.c | 228 +++++++++++++++++++++++++++++++++ - 9 files changed, 535 insertions(+) + security/keys/crypto/crypto_type.c | 272 +++++++++++++++++++++++++++++++++ + 9 files changed, 580 insertions(+) create mode 100644 Documentation/security/keys-crypto.txt create mode 100644 include/keys/crypto-subtype.h create mode 100644 include/keys/crypto-type.h @@ -580,10 +1536,10 @@ index 0000000..97dee80 + reference on the subtype module. diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h new file mode 100644 -index 0000000..fa87555 +index 0000000..1f546e6 --- /dev/null +++ b/include/keys/crypto-subtype.h -@@ -0,0 +1,56 @@ +@@ -0,0 +1,57 @@ +/* Cryptographic key subtype + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -628,12 +1584,13 @@ index 0000000..fa87555 + struct module *owner; + const char *name; + -+ /* Attempt to instantiate a key from the data blob passed to add_key() -+ * or keyctl_instantiate(). ++ /* Attempt to parse a key from the data blob passed to add_key() or ++ * keyctl_instantiate(). Should also generate a proposed description ++ * that the caller can optionally use for the key. + * + * Return EBADMSG if not recognised. + */ -+ int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ int (*preparse)(struct key_preparsed_payload *prep); +}; + +extern int register_crypto_key_parser(struct crypto_key_parser *); @@ -718,7 +1675,7 @@ index 0000000..36db1d5 +crypto_keys-y := crypto_type.o diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h new file mode 100644 -index 0000000..a339ce0 +index 0000000..eb11788 --- /dev/null +++ b/security/keys/crypto/crypto_keys.h @@ -0,0 +1,28 @@ @@ -739,7 +1696,7 @@ index 0000000..a339ce0 + return key->type_data.p[0]; +} + -+static inline char *crypto_key_id(const struct key *key) ++static inline const char *crypto_key_id(const struct key *key) +{ + return key->type_data.p[1]; +} @@ -752,10 +1709,10 @@ index 0000000..a339ce0 +extern struct rw_semaphore crypto_key_parsers_sem; diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c new file mode 100644 -index 0000000..33d279b +index 0000000..e8f83a6 --- /dev/null +++ b/security/keys/crypto/crypto_type.c -@@ -0,0 +1,228 @@ +@@ -0,0 +1,272 @@ +/* Cryptographic key type + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -868,17 +1825,20 @@ index 0000000..33d279b +} + +/* -+ * Instantiate a crypto_key defined key ++ * Preparse a crypto payload to get format the contents appropriately for the ++ * internal payload to cut down on the number of scans of the data performed. ++ * ++ * We also generate a proposed description from the contents of the key that ++ * can be used to name the key if the user doesn't want to provide one. + */ -+static int crypto_key_instantiate(struct key *key, -+ const void *data, size_t datalen) ++static int crypto_key_preparse(struct key_preparsed_payload *prep) +{ + struct crypto_key_parser *parser; + int ret; + + pr_devel("==>%s()\n", __func__); + -+ if (datalen == 0) ++ if (prep->datalen == 0) + return -EINVAL; + + down_read(&crypto_key_parsers_sem); @@ -887,7 +1847,7 @@ index 0000000..33d279b + list_for_each_entry(parser, &crypto_key_parsers, link) { + pr_debug("Trying parser '%s'\n", parser->name); + -+ ret = parser->instantiate(key, data, datalen); ++ ret = parser->preparse(prep); + if (ret != -EBADMSG) { + pr_debug("Parser recognised the format (ret %d)\n", + ret); @@ -901,6 +1861,45 @@ index 0000000..33d279b +} + +/* ++ * Clean up the preparse data ++ */ ++static void crypto_key_free_preparse(struct key_preparsed_payload *prep) ++{ ++ struct crypto_key_subtype *subtype = prep->type_data[0]; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (subtype) { ++ subtype->destroy(prep->payload); ++ module_put(subtype->owner); ++ } ++ kfree(prep->type_data[1]); ++ kfree(prep->description); ++} ++ ++/* ++ * Instantiate a crypto_key defined key ++ */ ++static int crypto_key_instantiate(struct key *key, struct key_preparsed_payload *prep) ++{ ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ ret = key_payload_reserve(key, prep->quotalen); ++ if (ret == 0) { ++ key->type_data.p[0] = prep->type_data[0]; ++ key->type_data.p[1] = prep->type_data[1]; ++ key->payload.data = prep->payload; ++ prep->type_data[0] = NULL; ++ prep->type_data[1] = NULL; ++ prep->payload = NULL; ++ } ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++ ++/* + * dispose of the data dangling from the corpse of a crypto key + */ +static void crypto_key_destroy(struct key *key) @@ -917,6 +1916,8 @@ index 0000000..33d279b + +struct key_type key_type_crypto = { + .name = "crypto", ++ .preparse = crypto_key_preparse, ++ .free_preparse = crypto_key_free_preparse, + .instantiate = crypto_key_instantiate, + .match = crypto_key_match, + .destroy = crypto_key_destroy, @@ -985,13 +1986,13 @@ index 0000000..33d279b +module_init(crypto_key_init); +module_exit(crypto_key_cleanup); -- -1.7.11.2 +1.7.11.4 -From 24d9655ce0fc046012078867baaedd3bf2eaedd2 Mon Sep 17 00:00:00 2001 +From a4e8ef15db9c013c4d3141424120c5ba74376483 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 13:59:51 +0100 -Subject: [PATCH 03/28] KEYS: Add signature verification facility +Date: Thu, 16 Aug 2012 00:14:18 +0100 +Subject: [PATCH 04/32] KEYS: Add signature verification facility Add a facility whereby a key subtype may be asked to verify a signature against the data it is purported to have signed. @@ -1023,16 +2024,18 @@ This adds four routines: Signed-off-by: David Howells --- - Documentation/security/keys-crypto.txt | 101 +++++++++++++++++++++++++++++ - include/keys/crypto-subtype.h | 21 +++++++ - include/keys/crypto-type.h | 9 +++ + Documentation/security/keys-crypto.txt | 100 +++++++++++++++++++++ + include/keys/crypto-subtype.h | 36 +++++++- + include/keys/crypto-type.h | 9 ++ security/keys/crypto/Makefile | 2 +- - security/keys/crypto/crypto_verify.c | 112 +++++++++++++++++++++++++++++++++ - 5 files changed, 244 insertions(+), 1 deletion(-) + security/keys/crypto/crypto_keys.h | 1 - + security/keys/crypto/crypto_type.c | 2 +- + security/keys/crypto/crypto_verify.c | 159 +++++++++++++++++++++++++++++++++ + 7 files changed, 304 insertions(+), 5 deletions(-) create mode 100644 security/keys/crypto/crypto_verify.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt -index 97dee80..a964717 100644 +index 97dee80..0a886ec 100644 --- a/Documentation/security/keys-crypto.txt +++ b/Documentation/security/keys-crypto.txt @@ -7,6 +7,7 @@ Contents: @@ -1109,15 +2112,7 @@ index 97dee80..a964717 100644 =========================== IMPLEMENTING CRYPTO PARSERS =========================== -@@ -96,6 +156,7 @@ IMPLEMENTING CRYPTO PARSERS - The crypto key type keeps a list of registered data parsers. An example of - such a parser is one that parses OpenPGP packet formatted data [RFC 4880]. - -+ - During key instantiation each parser in the list is tried until one doesn't - return -EBADMSG. - -@@ -107,6 +168,8 @@ The parser definition structure looks like the following: +@@ -107,6 +167,8 @@ The parser definition structure looks like the following: int (*instantiate)(struct key *key, const void *data, size_t datalen); @@ -1126,7 +2121,7 @@ index 97dee80..a964717 100644 }; The owner and name fields should be set to the owning module and the name of -@@ -135,6 +198,44 @@ but it is expected that at least one will be defined. +@@ -135,6 +197,44 @@ but it is expected that at least one will be defined. algorithm such as RSA and DSA this will likely be a printable hex version of the key's fingerprint. @@ -1172,60 +2167,73 @@ index 97dee80..a964717 100644 int register_crypto_key_parser(struct crypto_key_parser *parser); diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h -index fa87555..f2b927a 100644 +index 1f546e6..61a5338 100644 --- a/include/keys/crypto-subtype.h +++ b/include/keys/crypto-subtype.h -@@ -20,6 +20,20 @@ - extern struct key_type key_type_crypto; +@@ -34,8 +34,7 @@ struct crypto_key_subtype { + }; /* +- * Data parser. Called during instantiation and signature verification +- * initiation. ++ * Key data parser. Called during key instantiation. + */ + struct crypto_key_parser { + struct list_head link; +@@ -54,4 +53,37 @@ struct crypto_key_parser { + extern int register_crypto_key_parser(struct crypto_key_parser *); + extern void unregister_crypto_key_parser(struct crypto_key_parser *); + ++/* + * Context base for signature verification methods. Allocated by the subtype + * and presumably embedded in something appropriate. + */ -+struct crypto_key_verify_context { ++struct crypto_sig_verify_context { + struct key *key; -+ struct crypto_key_parser *parser; -+ int (*add_data)(struct crypto_key_verify_context *ctx, ++ struct crypto_sig_parser *parser; ++ int (*add_data)(struct crypto_sig_verify_context *ctx, + const void *data, size_t datalen); -+ int (*end)(struct crypto_key_verify_context *ctx, ++ int (*end)(struct crypto_sig_verify_context *ctx, + const u8 *sig, size_t siglen); -+ void (*cancel)(struct crypto_key_verify_context *ctx); ++ void (*cancel)(struct crypto_sig_verify_context *ctx); +}; + +/* - * Keys of this type declare a subtype that indicates the handlers and - * capabilities. - */ -@@ -48,6 +62,13 @@ struct crypto_key_parser { - * Return EBADMSG if not recognised. - */ - int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ * Signature data parser. Called during signature verification initiation. ++ */ ++struct crypto_sig_parser { ++ struct list_head link; ++ struct module *owner; ++ const char *name; + + /* Attempt to recognise a signature blob and find a matching key. + * + * Return EBADMSG if not recognised. + */ -+ struct crypto_key_verify_context *(*verify_sig_begin)( ++ struct crypto_sig_verify_context *(*verify_sig_begin)( + struct key *keyring, const u8 *sig, size_t siglen); - }; - - extern int register_crypto_key_parser(struct crypto_key_parser *); ++}; ++ ++extern int register_crypto_sig_parser(struct crypto_sig_parser *); ++extern void unregister_crypto_sig_parser(struct crypto_sig_parser *); ++ + #endif /* _KEYS_CRYPTO_SUBTYPE_H */ diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h -index 47c00c7..6b93366 100644 +index 47c00c7..0fb362a 100644 --- a/include/keys/crypto-type.h +++ b/include/keys/crypto-type.h @@ -18,6 +18,15 @@ extern struct key_type key_type_crypto; -+struct crypto_key_verify_context; -+extern struct crypto_key_verify_context *verify_sig_begin( ++struct crypto_sig_verify_context; ++extern struct crypto_sig_verify_context *verify_sig_begin( + struct key *key, const void *sig, size_t siglen); -+extern int verify_sig_add_data(struct crypto_key_verify_context *ctx, ++extern int verify_sig_add_data(struct crypto_sig_verify_context *ctx, + const void *data, size_t datalen); -+extern int verify_sig_end(struct crypto_key_verify_context *ctx, ++extern int verify_sig_end(struct crypto_sig_verify_context *ctx, + const void *sig, size_t siglen); -+extern void verify_sig_cancel(struct crypto_key_verify_context *ctx); ++extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx); + /* * The payload is at the discretion of the subtype. @@ -1240,12 +2248,35 @@ index 36db1d5..67001bc 100644 -crypto_keys-y := crypto_type.o +crypto_keys-y := crypto_type.o crypto_verify.o +diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h +index eb11788..ab9b381 100644 +--- a/security/keys/crypto/crypto_keys.h ++++ b/security/keys/crypto/crypto_keys.h +@@ -24,5 +24,4 @@ static inline const char *crypto_key_id(const struct key *key) + /* + * crypto_type.c + */ +-extern struct list_head crypto_key_parsers; + extern struct rw_semaphore crypto_key_parsers_sem; +diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c +index e8f83a6..821db37 100644 +--- a/security/keys/crypto/crypto_type.c ++++ b/security/keys/crypto/crypto_type.c +@@ -18,7 +18,7 @@ + + MODULE_LICENSE("GPL"); + +-LIST_HEAD(crypto_key_parsers); ++static LIST_HEAD(crypto_key_parsers); + DECLARE_RWSEM(crypto_key_parsers_sem); + + /* diff --git a/security/keys/crypto/crypto_verify.c b/security/keys/crypto/crypto_verify.c new file mode 100644 -index 0000000..3f2964b +index 0000000..d64f1c7 --- /dev/null +++ b/security/keys/crypto/crypto_verify.c -@@ -0,0 +1,112 @@ +@@ -0,0 +1,159 @@ +/* Signature verification with a crypto key + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -1264,6 +2295,8 @@ index 0000000..3f2964b +#include +#include "crypto_keys.h" + ++static LIST_HEAD(crypto_sig_parsers); ++ +/** + * verify_sig_begin - Initiate the use of a crypto key to verify a signature + * @keyring: The public keys to verify against @@ -1272,11 +2305,11 @@ index 0000000..3f2964b + * + * Returns a context or an error. + */ -+struct crypto_key_verify_context *verify_sig_begin( ++struct crypto_sig_verify_context *verify_sig_begin( + struct key *keyring, const void *sig, size_t siglen) +{ -+ struct crypto_key_verify_context *ret; -+ struct crypto_key_parser *parser; ++ struct crypto_sig_verify_context *ret; ++ struct crypto_sig_parser *parser; + + pr_devel("==>%s()\n", __func__); + @@ -1286,7 +2319,7 @@ index 0000000..3f2964b + down_read(&crypto_key_parsers_sem); + + ret = ERR_PTR(-EBADMSG); -+ list_for_each_entry(parser, &crypto_key_parsers, link) { ++ list_for_each_entry(parser, &crypto_sig_parsers, link) { + if (parser->verify_sig_begin) { + if (!try_module_get(parser->owner)) + continue; @@ -1321,7 +2354,7 @@ index 0000000..3f2964b + * + * This may be called multiple times. + */ -+int verify_sig_add_data(struct crypto_key_verify_context *ctx, ++int verify_sig_add_data(struct crypto_sig_verify_context *ctx, + const void *data, size_t datalen) +{ + return ctx->add_data(ctx, data, datalen); @@ -1334,10 +2367,10 @@ index 0000000..3f2964b + * @sig: The signature data + * @siglen: The signature length + */ -+int verify_sig_end(struct crypto_key_verify_context *ctx, ++int verify_sig_end(struct crypto_sig_verify_context *ctx, + const void *sig, size_t siglen) +{ -+ struct crypto_key_parser *parser = ctx->parser; ++ struct crypto_sig_parser *parser = ctx->parser; + int ret; + + ret = ctx->end(ctx, sig, siglen); @@ -1350,22 +2383,67 @@ index 0000000..3f2964b + * verify_sig_end - Cancel signature verification + * @ctx: The context from verify_sig_begin() + */ -+void verify_sig_cancel(struct crypto_key_verify_context *ctx) ++void verify_sig_cancel(struct crypto_sig_verify_context *ctx) +{ -+ struct crypto_key_parser *parser = ctx->parser; ++ struct crypto_sig_parser *parser = ctx->parser; + + ctx->cancel(ctx); + module_put(parser->owner); +} +EXPORT_SYMBOL_GPL(verify_sig_cancel); ++ ++/** ++ * register_crypto_sig_parser - Register a crypto sig blob parser ++ * @parser: The parser to register ++ */ ++int register_crypto_sig_parser(struct crypto_sig_parser *parser) ++{ ++ struct crypto_sig_parser *cursor; ++ int ret; ++ ++ down_write(&crypto_key_parsers_sem); ++ ++ list_for_each_entry(cursor, &crypto_sig_parsers, link) { ++ if (strcmp(cursor->name, parser->name) == 0) { ++ pr_err("Crypto signature parser '%s' already registered\n", ++ parser->name); ++ ret = -EEXIST; ++ goto out; ++ } ++ } ++ ++ list_add_tail(&parser->link, &crypto_sig_parsers); ++ ++ pr_notice("Crypto signature parser '%s' registered\n", parser->name); ++ ret = 0; ++ ++out: ++ up_write(&crypto_key_parsers_sem); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(register_crypto_sig_parser); ++ ++/** ++ * unregister_crypto_sig_parser - Unregister a crypto sig blob parser ++ * @parser: The parser to unregister ++ */ ++void unregister_crypto_sig_parser(struct crypto_sig_parser *parser) ++{ ++ down_write(&crypto_key_parsers_sem); ++ list_del(&parser->link); ++ up_write(&crypto_key_parsers_sem); ++ ++ pr_notice("Crypto signature parser '%s' unregistered\n", parser->name); ++} ++EXPORT_SYMBOL_GPL(unregister_crypto_sig_parser); -- -1.7.11.2 +1.7.11.4 -From a0fe6700fba7b7497cf137dc6a969d299ee59c67 Mon Sep 17 00:00:00 2001 +From d8cb66a6f69869c8c2992f67915a7c238066f2fb Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 13:59:52 +0100 -Subject: [PATCH 04/28] KEYS: Asymmetric public-key algorithm crypto key +Date: Thu, 16 Aug 2012 00:14:18 +0100 +Subject: [PATCH 05/32] KEYS: Asymmetric public-key algorithm crypto key subtype Add a subtype for supporting asymmetric public-key encryption algorithms such @@ -1375,9 +2453,9 @@ Signed-off-by: David Howells --- security/keys/crypto/Kconfig | 10 ++++ security/keys/crypto/Makefile | 3 +- - security/keys/crypto/public_key.c | 55 ++++++++++++++++++++ - security/keys/crypto/public_key.h | 106 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 173 insertions(+), 1 deletion(-) + security/keys/crypto/public_key.c | 82 +++++++++++++++++++++++++ + security/keys/crypto/public_key.h | 123 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 security/keys/crypto/public_key.c create mode 100644 security/keys/crypto/public_key.h @@ -1413,10 +2491,10 @@ index 67001bc..6384306 100644 +obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c new file mode 100644 -index 0000000..c00ddac +index 0000000..ebb31ec --- /dev/null +++ b/security/keys/crypto/public_key.c -@@ -0,0 +1,55 @@ +@@ -0,0 +1,82 @@ +/* Asymmetric public key crypto subtype + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -1430,11 +2508,36 @@ index 0000000..c00ddac + +#define pr_fmt(fmt) "PKEY: "fmt +#include ++#include +#include +#include "public_key.h" + +MODULE_LICENSE("GPL"); + ++const char *const pkey_algo[PKEY_ALGO__LAST] = { ++ [PKEY_ALGO_DSA] = "DSA", ++ [PKEY_ALGO_RSA] = "RSA", ++}; ++EXPORT_SYMBOL_GPL(pkey_algo); ++ ++const char *const pkey_hash_algo[PKEY_HASH__LAST] = { ++ [PKEY_HASH_MD4] = "md4", ++ [PKEY_HASH_MD5] = "md5", ++ [PKEY_HASH_SHA1] = "sha1", ++ [PKEY_HASH_RIPE_MD_160] = "rmd160", ++ [PKEY_HASH_SHA256] = "sha256", ++ [PKEY_HASH_SHA384] = "sha384", ++ [PKEY_HASH_SHA512] = "sha512", ++ [PKEY_HASH_SHA224] = "sha224", ++}; ++EXPORT_SYMBOL_GPL(pkey_hash_algo); ++ ++const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { ++ [PKEY_ID_PGP] = "PGP", ++ [PKEY_ID_X509] = "X509", ++}; ++EXPORT_SYMBOL_GPL(pkey_id_type); ++ +/* + * Provide a part of a description of the key for /proc/keys. + */ @@ -1444,13 +2547,14 @@ index 0000000..c00ddac + struct public_key *key = crypto_key->payload.data; + + if (key) -+ seq_puts(m, key->algo->name); ++ seq_printf(m, "%s.%s", ++ pkey_id_type[key->id_type], key->algo->name); +} + +/* + * Destroy a public key algorithm key + */ -+static void public_key_destroy(void *payload) ++void public_key_destroy(void *payload) +{ + struct public_key *key = payload; + int i; @@ -1461,6 +2565,7 @@ index 0000000..c00ddac + kfree(key); + } +} ++EXPORT_SYMBOL_GPL(public_key_destroy); + +/* + * Public key algorithm crypto key subtype @@ -1474,10 +2579,10 @@ index 0000000..c00ddac +EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype); diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h new file mode 100644 -index 0000000..81ed603 +index 0000000..228090d --- /dev/null +++ b/security/keys/crypto/public_key.h -@@ -0,0 +1,106 @@ +@@ -0,0 +1,123 @@ +/* Asymmetric public-key algorithm definitions + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -1499,7 +2604,16 @@ index 0000000..81ed603 +struct public_key; +struct public_key_signature; + ++enum pkey_algo { ++ PKEY_ALGO_DSA, ++ PKEY_ALGO_RSA, ++ PKEY_ALGO__LAST ++}; ++ ++extern const char *const pkey_algo[PKEY_ALGO__LAST]; ++ +enum pkey_hash_algo { ++ PKEY_HASH_MD4, + PKEY_HASH_MD5, + PKEY_HASH_SHA1, + PKEY_HASH_RIPE_MD_160, @@ -1510,6 +2624,16 @@ index 0000000..81ed603 + PKEY_HASH__LAST +}; + ++extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; ++ ++enum pkey_id_type { ++ PKEY_ID_PGP, /* OpenPGP generated key ID */ ++ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ ++ PKEY_ID_TYPE__LAST ++}; ++ ++extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; ++ +/* + * Public key type definition + */ @@ -1534,6 +2658,7 @@ index 0000000..81ed603 +#define PKEY_CAN_SIGN 0x04 +#define PKEY_CAN_VERIFY 0x08 +#define PKEY_CAN_SIGVER (PKEY_CAN_SIGN | PKEY_CAN_VERIFY) ++ enum pkey_id_type id_type : 8; + union { + MPI mpi[5]; + struct { @@ -1560,7 +2685,7 @@ index 0000000..81ed603 + * Asymmetric public key algorithm signature data + */ +struct public_key_signature { -+ struct crypto_key_verify_context base; ++ struct crypto_sig_verify_context base; + u8 *digest; + enum pkey_hash_algo pkey_hash_algo : 8; + u8 signed_hash_msw[2]; @@ -1578,20 +2703,17 @@ index 0000000..81ed603 + struct shash_desc hash; /* This must go last! */ +}; + -+extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( -+ struct key *crypto_key, const u8 *sigdata, size_t siglen); -+ +extern struct crypto_key_subtype public_key_crypto_key_subtype; + +#endif /* _LINUX_PUBLIC_KEY_H */ -- -1.7.11.2 +1.7.11.4 -From 39eaf7c28e0ca07dcb5e1e2a12db62815890f0e7 Mon Sep 17 00:00:00 2001 +From 76b6843d2be046bd5ab8fbae8a1cc5b5d2d48a80 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:10:37 +0100 -Subject: [PATCH 05/28] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA +Date: Thu, 16 Aug 2012 00:14:18 +0100 +Subject: [PATCH 06/32] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA signature verification Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by @@ -1693,13 +2815,13 @@ index 0000000..1871e7b +} +EXPORT_SYMBOL_GPL(mpi_cmp); -- -1.7.11.2 +1.7.11.4 -From c995ac0765cfffe9b293327717e080c2cd253779 Mon Sep 17 00:00:00 2001 +From 48c4be1c886e51edbbbebdb65421a7ca120a8d21 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:10:39 +0100 -Subject: [PATCH 06/28] KEYS: RSA: Implement signature verification algorithm +Date: Thu, 16 Aug 2012 00:14:18 +0100 +Subject: [PATCH 07/32] KEYS: RSA: Implement signature verification algorithm [PKCS#1 / RFC3447] Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only @@ -1710,9 +2832,9 @@ Signed-off-by: David Howells --- security/keys/crypto/Kconfig | 7 + security/keys/crypto/Makefile | 1 + - security/keys/crypto/crypto_rsa.c | 264 ++++++++++++++++++++++++++++++++++++++ + security/keys/crypto/crypto_rsa.c | 267 ++++++++++++++++++++++++++++++++++++++ security/keys/crypto/public_key.h | 2 + - 4 files changed, 274 insertions(+) + 4 files changed, 277 insertions(+) create mode 100644 security/keys/crypto/crypto_rsa.c diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig @@ -1741,10 +2863,10 @@ index 6384306..b6b1a5a 100644 +obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c new file mode 100644 -index 0000000..845285c +index 0000000..6e95e60 --- /dev/null +++ b/security/keys/crypto/crypto_rsa.c -@@ -0,0 +1,264 @@ +@@ -0,0 +1,267 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -1965,6 +3087,9 @@ index 0000000..845285c + + kenter(""); + ++ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) ++ return -ENOTSUPP; ++ + /* (1) Check the signature size against the public key modulus size */ + k = (mpi_get_nbits(key->rsa.n) + 7) / 8; + @@ -2010,10 +3135,10 @@ index 0000000..845285c +}; +EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h -index 81ed603..7913615 100644 +index 228090d..947817b 100644 --- a/security/keys/crypto/public_key.h +++ b/security/keys/crypto/public_key.h -@@ -42,6 +42,8 @@ struct public_key_algorithm { +@@ -61,6 +61,8 @@ struct public_key_algorithm { const struct public_key_signature *sig); }; @@ -2023,13 +3148,13 @@ index 81ed603..7913615 100644 * Asymmetric public key data */ -- -1.7.11.2 +1.7.11.4 -From d9acf3806acdc9ab5e26a1c604989070a7ae6840 Mon Sep 17 00:00:00 2001 +From 311305a6e970236bd30d8942552a26e6f93730ce Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:19 +0100 -Subject: [PATCH 07/28] KEYS: RSA: Fix signature verification for shorter +Date: Thu, 16 Aug 2012 00:14:19 +0100 +Subject: [PATCH 08/32] KEYS: RSA: Fix signature verification for shorter signatures gpg can produce a signature file where length of signature is less than the @@ -2048,11 +3173,11 @@ Signed-off-by: David Howells 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c -index 845285c..a4a63be 100644 +index 6e95e60..796ed1d 100644 --- a/security/keys/crypto/crypto_rsa.c +++ b/security/keys/crypto/crypto_rsa.c -@@ -219,15 +219,23 @@ static int RSA_verify_signature(const struct public_key *key, - kenter(""); +@@ -222,15 +222,23 @@ static int RSA_verify_signature(const struct public_key *key, + return -ENOTSUPP; /* (1) Check the signature size against the public key modulus size */ - k = (mpi_get_nbits(key->rsa.n) + 7) / 8; @@ -2079,13 +3204,13 @@ index 845285c..a4a63be 100644 ret = RSAVP1(key, sig->rsa.s, &m); if (ret < 0) -- -1.7.11.2 +1.7.11.4 -From 9a2a2b1faa27be883b3aa2c47bbc367bd1a1f653 Mon Sep 17 00:00:00 2001 +From a9b954d2c225dc99ecc319ea760576f525f0a623 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:19 +0100 -Subject: [PATCH 08/28] PGPLIB: PGP definitions (RFC 4880) +Date: Thu, 16 Aug 2012 00:14:19 +0100 +Subject: [PATCH 09/32] PGPLIB: PGP definitions (RFC 4880) Provide some useful PGP definitions from RFC 4880. These describe details of public key crypto as used by crypto keys for things like signature @@ -2310,13 +3435,13 @@ index 0000000..1359f64 + +#endif /* _LINUX_PGP_H */ -- -1.7.11.2 +1.7.11.4 -From 0b8ec95fe7220288c143a820b8d8996c356129f1 Mon Sep 17 00:00:00 2001 +From 1937e5a7e8ae1abdb7f1dc72f7b128e33c31d644 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:20 +0100 -Subject: [PATCH 09/28] PGPLIB: Basic packet parser +Date: Thu, 16 Aug 2012 01:33:13 +0100 +Subject: [PATCH 10/32] PGPLIB: Basic packet parser Provide a simple parser that extracts the packets from a PGP packet blob and passes the desirous ones to the given processor function: @@ -2423,7 +3548,7 @@ index b6b1a5a..5fbe54e 100644 +obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c new file mode 100644 -index 0000000..af396d6 +index 0000000..39d2878 --- /dev/null +++ b/security/keys/crypto/pgp_library.c @@ -0,0 +1,268 @@ @@ -2477,7 +3602,7 @@ index 0000000..af396d6 + const u8 *data = *_data; + size_t size, datalen = *_datalen; + -+ pr_devel("-->pgp_parse_packet_header(,%zu,,)", datalen); ++ pr_devel("-->pgp_parse_packet_header(,%zu,,)\n", datalen); + + if (datalen < 2) + goto short_packet; @@ -2696,13 +3821,13 @@ index 0000000..af396d6 +} +EXPORT_SYMBOL_GPL(pgp_parse_public_key); -- -1.7.11.2 +1.7.11.4 -From a3673ac73f4634bcdd97d642b3bdd87998eb2100 Mon Sep 17 00:00:00 2001 +From 3379efc21d2ecc93de135e3265baabbe1f326d5a Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:20 +0100 -Subject: [PATCH 10/28] PGPLIB: Signature parser +Date: Thu, 16 Aug 2012 01:33:17 +0100 +Subject: [PATCH 11/32] PGPLIB: Signature parser Provide some PGP signature parsing helpers: @@ -2761,7 +3886,7 @@ index a045b3a..34594a9 100644 #endif /* CONFIG_PGP_LIBRARY */ diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c -index af396d6..c9218df 100644 +index 39d2878..50b7fa0 100644 --- a/security/keys/crypto/pgp_library.c +++ b/security/keys/crypto/pgp_library.c @@ -266,3 +266,283 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen, @@ -3049,13 +4174,13 @@ index af396d6..c9218df 100644 +} +EXPORT_SYMBOL_GPL(pgp_parse_sig_params); -- -1.7.11.2 +1.7.11.4 -From dd59f49ce7179b145f55bdca3b43f4761ae0769d Mon Sep 17 00:00:00 2001 +From 39b6dd66338812a1e1806489d3fed50620011b14 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:21 +0100 -Subject: [PATCH 11/28] KEYS: PGP data parser +Date: Thu, 16 Aug 2012 01:33:17 +0100 +Subject: [PATCH 12/32] KEYS: PGP data parser Implement a PGP data parser for the crypto key type to use when instantiating a key. @@ -3075,8 +4200,8 @@ Signed-off-by: David Howells security/keys/crypto/Kconfig | 12 ++ security/keys/crypto/Makefile | 4 + security/keys/crypto/pgp_parser.h | 23 +++ - security/keys/crypto/pgp_public_key.c | 348 ++++++++++++++++++++++++++++++++++ - 4 files changed, 387 insertions(+) + security/keys/crypto/pgp_public_key.c | 344 ++++++++++++++++++++++++++++++++++ + 4 files changed, 383 insertions(+) create mode 100644 security/keys/crypto/pgp_parser.h create mode 100644 security/keys/crypto/pgp_public_key.c @@ -3143,10 +4268,10 @@ index 0000000..1cda231 +struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c new file mode 100644 -index 0000000..8a8b7c0 +index 0000000..c260e02 --- /dev/null +++ b/security/keys/crypto/pgp_public_key.c -@@ -0,0 +1,348 @@ +@@ -0,0 +1,344 @@ +/* Instantiate a public key crypto key from PGP format data [RFC 4880] + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -3328,6 +4453,7 @@ index 0000000..8a8b7c0 + + memcpy(&key->key_id, raw_fingerprint + offset, 8); + key->key_id_size = 8; ++ key->id_type = PKEY_ID_PGP; + + ctx->fingerprint = fingerprint; + ret = 0; @@ -3438,18 +4564,13 @@ index 0000000..8a8b7c0 + * Attempt to parse the instantiation data blob for a key as a PGP packet + * message holding a key. + */ -+static int pgp_key_instantiate(struct key *key, -+ const void *data, size_t datalen) ++static int pgp_key_preparse(struct key_preparsed_payload *prep) +{ + struct pgp_key_data_parse_context ctx; + int ret; + + kenter(""); + -+ ret = key_payload_reserve(key, datalen); -+ if (ret < 0) -+ return ret; -+ + ctx.pgp.types_of_interest = + (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); + ctx.pgp.process_packet = pgp_process_public_key; @@ -3457,27 +4578,27 @@ index 0000000..8a8b7c0 + ctx.fingerprint = NULL; + ctx.payload = NULL; + -+ ret = pgp_parse_packets(data, datalen, &ctx.pgp); ++ ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp); + if (ret < 0) { + if (ctx.payload) + ctx.subtype->destroy(ctx.payload); + if (ctx.subtype) + module_put(ctx.subtype->owner); + kfree(ctx.fingerprint); -+ key_payload_reserve(key, 0); + return ret; + } + -+ key->type_data.p[0] = ctx.subtype; -+ key->type_data.p[1] = ctx.fingerprint; -+ key->payload.data = ctx.payload; ++ prep->type_data[0] = ctx.subtype; ++ prep->type_data[1] = ctx.fingerprint; ++ prep->payload = ctx.payload; ++ prep->quotalen = prep->datalen; + return 0; +} + +static struct crypto_key_parser pgp_key_parser = { + .owner = THIS_MODULE, + .name = "pgp", -+ .instantiate = pgp_key_instantiate, ++ .preparse = pgp_key_preparse, +}; + +/* @@ -3496,13 +4617,13 @@ index 0000000..8a8b7c0 +module_init(pgp_key_init); +module_exit(pgp_key_exit); -- -1.7.11.2 +1.7.11.4 -From 80437db0342877f06d689d33babcc99175d34b82 Mon Sep 17 00:00:00 2001 +From 1095ff02a49868cf8f3706dd2c83474bcf2081f8 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:21 +0100 -Subject: [PATCH 12/28] KEYS: PGP-based public key signature verification +Date: Thu, 16 Aug 2012 01:33:17 +0100 +Subject: [PATCH 13/32] KEYS: PGP-based public key signature verification Provide handlers for PGP-based public-key algorithm signature verification. This does most of the work involved in signature verification as most of it is @@ -3532,7 +4653,7 @@ index 35733fc..0c8b8a1 100644 + pgp_public_key.o \ + pgp_sig_verify.o diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h -index 1cda231..a6192ce 100644 +index 1cda231..6f5b3af 100644 --- a/security/keys/crypto/pgp_parser.h +++ b/security/keys/crypto/pgp_parser.h @@ -21,3 +21,9 @@ @@ -3543,11 +4664,11 @@ index 1cda231..a6192ce 100644 +/* + * pgp_pubkey_sig.c + */ -+extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( ++extern struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin( + struct key *crypto_key, const u8 *sigdata, size_t siglen); diff --git a/security/keys/crypto/pgp_sig_verify.c b/security/keys/crypto/pgp_sig_verify.c new file mode 100644 -index 0000000..82c89da +index 0000000..f9bb949 --- /dev/null +++ b/security/keys/crypto/pgp_sig_verify.c @@ -0,0 +1,325 @@ @@ -3583,11 +4704,11 @@ index 0000000..82c89da + [PGP_HASH_SHA224].algo = PKEY_HASH_SHA224, +}; + -+static int pgp_pkey_verify_sig_add_data(struct crypto_key_verify_context *ctx, ++static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx, + const void *data, size_t datalen); -+static int pgp_pkey_verify_sig_end(struct crypto_key_verify_context *ctx, ++static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx, + const u8 *sig, size_t siglen); -+static void pgp_pkey_verify_sig_cancel(struct crypto_key_verify_context *ctx); ++static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx); + +struct pgp_pkey_sig_parse_context { + struct pgp_parse_context pgp; @@ -3613,7 +4734,7 @@ index 0000000..82c89da + * metadata will be put, and parsing the signature to check that it matches the + * key. + */ -+struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( ++struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin( + struct key *crypto_key, const u8 *sigdata, size_t siglen) +{ + struct pgp_pkey_sig_parse_context p; @@ -3720,7 +4841,7 @@ index 0000000..82c89da +/* + * Load data into the hash + */ -+static int pgp_pkey_verify_sig_add_data(struct crypto_key_verify_context *ctx, ++static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx, + const void *data, size_t datalen) +{ + struct public_key_signature *sig = @@ -3825,7 +4946,7 @@ index 0000000..82c89da + * The data is now all loaded into the hash; load the metadata, finalise the + * hash and perform the verification step. + */ -+static int pgp_pkey_verify_sig_end(struct crypto_key_verify_context *ctx, ++static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx, + const u8 *sigdata, size_t siglen) +{ + struct public_key_signature *sig = @@ -3859,7 +4980,7 @@ index 0000000..82c89da +/* + * Cancel an in-progress data loading + */ -+static void pgp_pkey_verify_sig_cancel(struct crypto_key_verify_context *ctx) ++static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx) +{ + struct public_key_signature *sig = + container_of(ctx, struct public_key_signature, base); @@ -3877,13 +4998,13 @@ index 0000000..82c89da + kleave(""); +} -- -1.7.11.2 +1.7.11.4 -From 1826f7b562237c008c66ad63b7d7d4c7c44b98fb Mon Sep 17 00:00:00 2001 +From 69d9f31b888090b5705b7148760143a6b706a116 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:21 +0100 -Subject: [PATCH 13/28] KEYS: PGP format signature parser +Date: Thu, 16 Aug 2012 01:33:17 +0100 +Subject: [PATCH 14/32] KEYS: PGP format signature parser Implement a signature parser that will attempt to parse a signature blob as a PGP packet format message. If it can, it will find an appropriate crypto key @@ -3892,10 +5013,8 @@ and set the public-key algorithm according to the data in the signature. Signed-off-by: David Howells --- security/keys/crypto/Makefile | 1 + - security/keys/crypto/pgp_parser.h | 6 ++ - security/keys/crypto/pgp_public_key.c | 1 + - security/keys/crypto/pgp_sig_parser.c | 114 ++++++++++++++++++++++++++++++++++ - 4 files changed, 122 insertions(+) + security/keys/crypto/pgp_sig_parser.c | 136 ++++++++++++++++++++++++++++++++++ + 2 files changed, 137 insertions(+) create mode 100644 security/keys/crypto/pgp_sig_parser.c diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile @@ -3908,41 +5027,12 @@ index 0c8b8a1..a9a34c6 100644 pgp_public_key.o \ + pgp_sig_parser.o \ pgp_sig_verify.o -diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h -index a6192ce..73c900e 100644 ---- a/security/keys/crypto/pgp_parser.h -+++ b/security/keys/crypto/pgp_parser.h -@@ -23,6 +23,12 @@ extern const - struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; - - /* -+ * pgp_sig_parser.c -+ */ -+extern struct crypto_key_verify_context *pgp_verify_sig_begin( -+ struct key *keyring, const u8 *sig, size_t siglen); -+ -+/* - * pgp_pubkey_sig.c - */ - extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( -diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c -index 8a8b7c0..5ab926d 100644 ---- a/security/keys/crypto/pgp_public_key.c -+++ b/security/keys/crypto/pgp_public_key.c -@@ -329,6 +329,7 @@ static struct crypto_key_parser pgp_key_parser = { - .owner = THIS_MODULE, - .name = "pgp", - .instantiate = pgp_key_instantiate, -+ .verify_sig_begin = pgp_verify_sig_begin, - }; - - /* diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c new file mode 100644 -index 0000000..f5feb2b +index 0000000..683eb53 --- /dev/null +++ b/security/keys/crypto/pgp_sig_parser.c -@@ -0,0 +1,114 @@ +@@ -0,0 +1,136 @@ +/* Handling for PGP public key signature data [RFC 4880] + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -4042,10 +5132,10 @@ index 0000000..f5feb2b + * Attempt to parse a signature as a PGP packet format blob and find a + * matching key. + */ -+struct crypto_key_verify_context *pgp_verify_sig_begin( ++static struct crypto_sig_verify_context *pgp_verify_sig_begin( + struct key *keyring, const u8 *sig, size_t siglen) +{ -+ struct crypto_key_verify_context *ctx; ++ struct crypto_sig_verify_context *ctx; + struct key *key; + + key = find_key_for_pgp_sig(keyring, sig, siglen); @@ -4057,14 +5147,169 @@ index 0000000..f5feb2b + key_put(key); + return ctx; +} ++ ++static struct crypto_sig_parser pgp_sig_parser = { ++ .owner = THIS_MODULE, ++ .name = "pgp", ++ .verify_sig_begin = pgp_verify_sig_begin, ++}; ++ ++/* ++ * Module stuff ++ */ ++static int __init pgp_sig_init(void) ++{ ++ return register_crypto_sig_parser(&pgp_sig_parser); ++} ++ ++static void __exit pgp_sig_exit(void) ++{ ++ unregister_crypto_sig_parser(&pgp_sig_parser); ++} ++ ++module_init(pgp_sig_init); ++module_exit(pgp_sig_exit); -- -1.7.11.2 +1.7.11.4 -From 68b4585107d4d014b4de3536c972c63f617c48f5 Mon Sep 17 00:00:00 2001 +From fe109b5adbb22b3503cb1f72f5585543218ba990 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:11:21 +0100 -Subject: [PATCH 14/28] KEYS: Provide a function to load keys from a PGP +Date: Thu, 16 Aug 2012 01:33:17 +0100 +Subject: [PATCH 15/32] KEYS: Provide PGP key description autogeneration + +Provide a facility to autogenerate the name of PGP keys from the contents of +the payload. If add_key() is given a blank description, a description is +constructed from the last user ID packet in the payload data plus the last 8 +hex digits of the key ID. For instance: + + keyctl padd crypto "" @s +--- + security/keys/crypto/pgp_public_key.c | 64 +++++++++++++++++++++++++++++------ + 1 file changed, 53 insertions(+), 11 deletions(-) + +diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c +index c260e02..2347ecd 100644 +--- a/security/keys/crypto/pgp_public_key.c ++++ b/security/keys/crypto/pgp_public_key.c +@@ -52,6 +52,9 @@ struct pgp_key_data_parse_context { + struct crypto_key_subtype *subtype; + char *fingerprint; + void *payload; ++ const char *user_id; ++ size_t user_id_len; ++ size_t fingerprint_len; + }; + + /* +@@ -166,6 +169,7 @@ static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx, + if (ret < 0) + goto cleanup_raw_fingerprint; + ++ ctx->fingerprint_len = digest_size * 2; + fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL); + if (!fingerprint) + goto cleanup_raw_fingerprint; +@@ -212,6 +216,13 @@ static int pgp_process_public_key(struct pgp_parse_context *context, + + kenter(",%u,%u,,%zu", type, headerlen, datalen); + ++ if (type == PGP_PKT_USER_ID) { ++ ctx->user_id = data; ++ ctx->user_id_len = datalen; ++ kleave(" = 0 [user ID]"); ++ return 0; ++ } ++ + if (ctx->subtype) { + kleave(" = -ENOKEY [already]"); + return -EBADMSG; +@@ -297,21 +308,44 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep) + + kenter(""); + ++ memset(&ctx, 0, sizeof(ctx)); + ctx.pgp.types_of_interest = +- (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); ++ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY) | ++ (1 << PGP_PKT_USER_ID); + ctx.pgp.process_packet = pgp_process_public_key; +- ctx.subtype = NULL; +- ctx.fingerprint = NULL; +- ctx.payload = NULL; + + ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp); +- if (ret < 0) { +- if (ctx.payload) +- ctx.subtype->destroy(ctx.payload); +- if (ctx.subtype) +- module_put(ctx.subtype->owner); +- kfree(ctx.fingerprint); +- return ret; ++ if (ret < 0) ++ goto error; ++ ++ if (ctx.user_id && ctx.user_id_len > 0) { ++ /* Propose a description for the key (user ID without the comment) */ ++ size_t ulen = ctx.user_id_len, flen = ctx.fingerprint_len; ++ const char *p; ++ ++ p = memchr(ctx.user_id, '(', ulen); ++ if (p) { ++ /* Remove the comment */ ++ do { ++ p--; ++ } while (*p == ' ' && p > ctx.user_id); ++ if (*p != ' ') ++ p++; ++ ulen = p - ctx.user_id; ++ } ++ ++ if (ulen > 255 - 9) ++ ulen = 255 - 9; ++ prep->description = kmalloc(ulen + 1 + 8 + 1, GFP_KERNEL); ++ ret = -ENOMEM; ++ if (!prep->description) ++ goto error; ++ memcpy(prep->description, ctx.user_id, ulen); ++ prep->description[ulen] = ' '; ++ memcpy(prep->description + ulen + 1, ++ ctx.fingerprint + flen - 8, 8); ++ prep->description[ulen + 9] = 0; ++ pr_debug("desc '%s'\n", prep->description); + } + + prep->type_data[0] = ctx.subtype; +@@ -319,6 +353,14 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep) + prep->payload = ctx.payload; + prep->quotalen = prep->datalen; + return 0; ++ ++error: ++ if (ctx.payload) ++ ctx.subtype->destroy(ctx.payload); ++ if (ctx.subtype) ++ module_put(ctx.subtype->owner); ++ kfree(ctx.fingerprint); ++ return ret; + } + + static struct crypto_key_parser pgp_key_parser = { +-- +1.7.11.4 + + +From 77b00423d002eb013293177310644c8284b6ea2f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 16 Aug 2012 01:33:18 +0100 +Subject: [PATCH 16/32] KEYS: Provide a function to load keys from a PGP keyring blob Provide a function to load keys from a PGP keyring blob for use in initialising @@ -4089,16 +5334,16 @@ out some errors. Signed-off-by: David Howells --- - Documentation/security/keys-crypto.txt | 20 +++++++ - include/keys/crypto-type.h | 3 ++ - security/keys/crypto/Kconfig | 9 ++++ - security/keys/crypto/Makefile | 1 + - security/keys/crypto/pgp_preload.c | 96 ++++++++++++++++++++++++++++++++++ - 5 files changed, 129 insertions(+) + Documentation/security/keys-crypto.txt | 20 ++++++ + include/keys/crypto-type.h | 3 + + security/keys/crypto/Kconfig | 9 +++ + security/keys/crypto/Makefile | 1 + + security/keys/crypto/pgp_preload.c | 115 +++++++++++++++++++++++++++++++++ + 5 files changed, 148 insertions(+) create mode 100644 security/keys/crypto/pgp_preload.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt -index a964717..ba2ab55 100644 +index 0a886ec..be5067e 100644 --- a/Documentation/security/keys-crypto.txt +++ b/Documentation/security/keys-crypto.txt @@ -10,6 +10,7 @@ Contents: @@ -4109,7 +5354,7 @@ index a964717..ba2ab55 100644 ======== -@@ -280,3 +281,22 @@ There are a number of operations defined by the subtype: +@@ -279,3 +280,22 @@ There are a number of operations defined by the subtype: Mandatory. This should free the memory associated with the key. The crypto key will look after freeing the fingerprint and releasing the reference on the subtype module. @@ -4123,25 +5368,25 @@ index a964717..ba2ab55 100644 +into a PGP packet format blob: + + int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring, const char *descprefix); ++ struct key *keyring); + +This takes the blob of data defined by pgpdata and pgpdatalen, extracts keys -+from them and adds them to the specified keyring. The keys are labelled with -+descprefix plus a simple uniquifier - it is not expected that the description -+will be used to identify the key. The description is required to prevent all -+but the last key being discarded when the keys are linked into the keyring. ++from them and adds them to the specified keyring. The keys are labelled with a ++description generated from the fingerprint and last user ID of each key. The ++description is required to prevent all but the last key being discarded when ++the keys are linked into the keyring. + +This function is only available during initial kernel set up. diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h -index 6b93366..710e77f 100644 +index 0fb362a..ed9b203 100644 --- a/include/keys/crypto-type.h +++ b/include/keys/crypto-type.h -@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_key_verify_context *ctx); +@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx); * The payload is at the discretion of the subtype. */ +extern __init int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring, const char *descprefix); ++ struct key *keyring); + #endif /* _KEYS_CRYPTO_TYPE_H */ diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig @@ -4175,10 +5420,10 @@ index a9a34c6..c873674 100644 pgp_key_parser-y := \ diff --git a/security/keys/crypto/pgp_preload.c b/security/keys/crypto/pgp_preload.c new file mode 100644 -index 0000000..9028788 +index 0000000..ca4cfe6 --- /dev/null +++ b/security/keys/crypto/pgp_preload.c -@@ -0,0 +1,96 @@ +@@ -0,0 +1,115 @@ +/* Cryptographic key request handling + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. @@ -4202,32 +5447,23 @@ index 0000000..9028788 +struct preload_pgp_keys_context { + struct pgp_parse_context pgp; + key_ref_t keyring; -+ char descbuf[20]; -+ u8 key_n; -+ u8 dsize; ++ const u8 *key_start; ++ const u8 *key_end; ++ bool found_key; +}; + +/* -+ * Extract a public key or subkey from the PGP stream. ++ * Create a key. + */ -+static int __init found_pgp_key(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, u8 headerlen, -+ const u8 *data, size_t datalen) ++static int __init create_pgp_key(struct preload_pgp_keys_context *ctx) +{ -+ struct preload_pgp_keys_context *ctx = -+ container_of(context, struct preload_pgp_keys_context, pgp); + key_ref_t key; + -+ if (ctx->key_n >= 255) -+ return 0; /* Don't overrun descbuf */ -+ -+ sprintf(ctx->descbuf + ctx->dsize, "%d", ctx->key_n++); -+ -+ key = key_create_or_update(ctx->keyring, "crypto", ctx->descbuf, -+ data - headerlen, datalen + headerlen, ++ key = key_create_or_update(ctx->keyring, "crypto", NULL, ++ ctx->key_start, ++ ctx->key_end - ctx->key_start, + KEY_POS_ALL | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA); -+ + if (IS_ERR(key)) + return PTR_ERR(key); + @@ -4239,19 +5475,41 @@ index 0000000..9028788 + return 0; +} + ++/* ++ * Extract a public key or subkey from the PGP stream. ++ */ ++static int __init found_pgp_key(struct pgp_parse_context *context, ++ enum pgp_packet_tag type, u8 headerlen, ++ const u8 *data, size_t datalen) ++{ ++ struct preload_pgp_keys_context *ctx = ++ container_of(context, struct preload_pgp_keys_context, pgp); ++ int ret; ++ ++ if (ctx->found_key) { ++ ctx->key_end = data - headerlen; ++ ret = create_pgp_key(ctx); ++ if (ret < 0) ++ return ret; ++ } ++ ++ ctx->key_start = data - headerlen; ++ ctx->found_key = true; ++ return 0; ++} ++ +/** + * preload_pgp_keys - Load keys from a PGP keyring blob + * @pgpdata: The PGP keyring blob containing the keys. + * @pgpdatalen: The size of the @pgpdata blob. + * @keyring: The keyring to add the new keys to. -+ * @descprefix: The key description prefix. + * + * Preload a pack of keys from a PGP keyring blob. + * -+ * The keys are given description of @descprefix + the number of the key in the -+ * list. Since keys can be matched on their key IDs independently of the key -+ * description, the description is mostly irrelevant apart from the fact that -+ * keys of the same description displace one another from a keyring. ++ * The keys have their descriptions generated from the user ID and fingerprint ++ * in the PGP stream. Since keys can be matched on their key IDs independently ++ * of the key description, the description is mostly irrelevant apart from the ++ * fact that keys of the same description displace one another from a keyring. + * + * The caller should override the current creds if they want the keys to be + * owned by someone other than the current process's owner. Keys will not be @@ -4260,29 +5518,35 @@ index 0000000..9028788 + * This function may only be called whilst the kernel is booting. + */ +int __init preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring, const char *descprefix) ++ struct key *keyring) +{ + struct preload_pgp_keys_context ctx; ++ int ret; + + ctx.pgp.types_of_interest = + (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); + ctx.pgp.process_packet = found_pgp_key; + ctx.keyring = make_key_ref(keyring, 1); -+ ctx.key_n = 0; -+ ctx.dsize = strlen(descprefix); -+ BUG_ON(ctx.dsize > sizeof(ctx.descbuf) - 4); -+ strcpy(ctx.descbuf, descprefix); ++ ctx.found_key = false; + -+ return pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp); ++ ret = pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp); ++ if (ret < 0) ++ return ret; ++ ++ if (ctx.found_key) { ++ ctx.key_end = pgpdata + pgpdatalen; ++ return create_pgp_key(&ctx); ++ } ++ return 0; +} -- -1.7.11.2 +1.7.11.4 -From c9455441e0482bb5eb0ea8f1e2cfbe2e7d630560 Mon Sep 17 00:00:00 2001 +From d569964b0037289f291f5ac48df54a6b90b3435a Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:13:56 +0100 -Subject: [PATCH 15/28] Make most arch asm/module.h files use +Date: Thu, 16 Aug 2012 01:33:48 +0100 +Subject: [PATCH 17/32] Make most arch asm/module.h files use asm-generic/module.h Use the mapping of Elf_[SPE]hdr, Elf_Addr, Elf_Sym, Elf_Dyn, Elf_Rel/Rela, @@ -4319,7 +5583,10 @@ with a generic-y marker in the arch Kbuild file. Additionally, I have removed the bits from m32r and score that handle the unsupported type of relocation record as that's now handled centrally. +Thanks to Jonas Gorski for some MIPS fixes. + Signed-off-by: David Howells +Acked-by: Sam Ravnborg --- arch/Kconfig | 19 ++++++++++++++++++ arch/alpha/Kconfig | 2 ++ @@ -4346,7 +5613,7 @@ Signed-off-by: David Howells arch/m32r/include/asm/Kbuild | 2 ++ arch/m32r/include/asm/module.h | 10 ---------- arch/m32r/kernel/module.c | 15 -------------- - arch/m68k/Kconfig | 4 ++++ + arch/m68k/Kconfig | 3 +++ arch/m68k/include/asm/module.h | 6 ++---- arch/microblaze/Kconfig | 1 + arch/mips/Kconfig | 3 +++ @@ -4372,12 +5639,13 @@ Signed-off-by: David Howells arch/tile/Kconfig | 1 + arch/unicore32/Kconfig | 1 + arch/x86/Kconfig | 2 ++ + arch/x86/um/Kconfig | 2 ++ arch/xtensa/Kconfig | 1 + arch/xtensa/include/asm/module.h | 9 +-------- include/asm-generic/module.h | 40 +++++++++++++++++++++++++++++++------- include/linux/moduleloader.h | 36 ++++++++++++++++++++++++++++++---- kernel/module.c | 20 ------------------- - 56 files changed, 168 insertions(+), 223 deletions(-) + 57 files changed, 169 insertions(+), 223 deletions(-) delete mode 100644 arch/cris/include/asm/module.h delete mode 100644 arch/h8300/include/asm/module.h delete mode 100644 arch/m32r/include/asm/module.h @@ -4412,13 +5680,13 @@ index 72f2fa1..3450115 100644 + source "kernel/gcov/Kconfig" diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig -index d5b9b5e..e73a1a7 100644 +index 9944ded..7e3710c 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig -@@ -18,6 +18,8 @@ config ALPHA - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select GENERIC_SMP_IDLE_THREAD +@@ -20,6 +20,8 @@ config ALPHA select GENERIC_CMOS_UPDATE + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER + select HAVE_MOD_ARCH_SPECIFIC + select MODULES_USE_ELF_RELA help @@ -4451,7 +5719,7 @@ index 7b63743..9cd13b5 100644 #ifdef MODULE diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 7980873..f447a89 100644 +index e91c7cd..c75c217 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -50,6 +50,8 @@ config ARM @@ -4795,17 +6063,16 @@ index 3071fe8..38233b6 100644 - -} diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig -index 0b0f8b8..fcc5a65 100644 +index 4a46990..714a850 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig -@@ -12,6 +12,10 @@ config M68K +@@ -12,6 +12,9 @@ config M68K select FPU if MMU select ARCH_WANT_IPC_PARSE_VERSION select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE + select HAVE_MOD_ARCH_SPECIFIC + select MODULES_USE_ELF_REL + select MODULES_USE_ELF_RELA -+ config RWSEM_GENERIC_SPINLOCK bool @@ -5262,7 +6529,7 @@ index b0a4743..5ef0814 100644 UniCore-32 is 32-bit Instruction Set Architecture, including a series of low-power-consumption RISC chip diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index ba2657c..afea8c7 100644 +index 8ec3a1a..01726cb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -97,6 +97,8 @@ config X86 @@ -5274,6 +6541,22 @@ index ba2657c..afea8c7 100644 config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS || UPROBES) +diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig +index 9926e11..a4b0c10 100644 +--- a/arch/x86/um/Kconfig ++++ b/arch/x86/um/Kconfig +@@ -21,9 +21,11 @@ config 64BIT + config X86_32 + def_bool !64BIT + select HAVE_AOUT ++ select MODULES_USE_ELF_REL + + config X86_64 + def_bool 64BIT ++ select MODULES_USE_ELF_RELA + + config RWSEM_XCHGADD_ALGORITHM + def_bool X86_XADD && 64BIT diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8ed64cf..4816e44 100644 --- a/arch/xtensa/Kconfig @@ -5453,13 +6736,408 @@ index 4edbd9c..087aeed 100644 { unsigned int i; -- -1.7.11.2 +1.7.11.4 -From 45c9f5b2992c100a9183f753d933d3141ae4e951 Mon Sep 17 00:00:00 2001 +From c6cfa3260f1e2961e69a2e3240695954aed24976 Mon Sep 17 00:00:00 2001 +From: Ralf Baechle +Date: Thu, 16 Aug 2012 01:38:43 +0100 +Subject: [PATCH 18/32] MIPS: Fix module.c build for 32 bit + +Fixes build failure introduced by "Make most arch asm/module.h files use +asm-generic/module.h" by moving all the RELA processing code to a +separate file to be used only for RELA processing on 64-bit kernels. + + CC arch/mips/kernel/module.o +arch/mips/kernel/module.c:250:14: error: 'reloc_handlers_rela' defined but not +used [-Werror=unused-variable] +cc1: all warnings being treated as errors + +make[6]: *** [arch/mips/kernel/module.o] Error 1 + +Signed-off-by: Ralf Baechle +Signed-off-by: David Howells +--- + arch/mips/kernel/Makefile | 1 + + arch/mips/kernel/module-rela.c | 144 +++++++++++++++++++++++++++++++++++++++++ + arch/mips/kernel/module.c | 124 +---------------------------------- + arch/mips/kernel/module.h | 12 ++++ + 4 files changed, 159 insertions(+), 122 deletions(-) + create mode 100644 arch/mips/kernel/module-rela.c + create mode 100644 arch/mips/kernel/module.h + +diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile +index fdaf65e..cd1e6c2 100644 +--- a/arch/mips/kernel/Makefile ++++ b/arch/mips/kernel/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o + + obj-$(CONFIG_STACKTRACE) += stacktrace.o + obj-$(CONFIG_MODULES) += mips_ksyms.o module.o ++obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o + + obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o + +diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c +new file mode 100644 +index 0000000..4e784a8 +--- /dev/null ++++ b/arch/mips/kernel/module-rela.c +@@ -0,0 +1,144 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Copyright (C) 2001 Rusty Russell. ++ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) ++ * Copyright (C) 2005 Thiemo Seufer ++ */ ++ ++#include ++#include ++#include ++#include ++#include "module.h" ++ ++static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) ++{ ++ *location = v; ++ ++ return 0; ++} ++ ++static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) ++{ ++ if (v % 4) { ++ pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", ++ me->name); ++ return -ENOEXEC; ++ } ++ ++ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { ++ printk(KERN_ERR ++ "module %s: relocation overflow\n", ++ me->name); ++ return -ENOEXEC; ++ } ++ ++ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); ++ ++ return 0; ++} ++ ++static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) ++{ ++ *location = (*location & 0xffff0000) | ++ ((((long long) v + 0x8000LL) >> 16) & 0xffff); ++ ++ return 0; ++} ++ ++static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) ++{ ++ *location = (*location & 0xffff0000) | (v & 0xffff); ++ ++ return 0; ++} ++ ++static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) ++{ ++ *(Elf_Addr *)location = v; ++ ++ return 0; ++} ++ ++static int apply_r_mips_higher_rela(struct module *me, u32 *location, ++ Elf_Addr v) ++{ ++ *location = (*location & 0xffff0000) | ++ ((((long long) v + 0x80008000LL) >> 32) & 0xffff); ++ ++ return 0; ++} ++ ++static int apply_r_mips_highest_rela(struct module *me, u32 *location, ++ Elf_Addr v) ++{ ++ *location = (*location & 0xffff0000) | ++ ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); ++ ++ return 0; ++} ++ ++static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, ++ Elf_Addr v) = { ++ [R_MIPS_NONE] = apply_r_mips_none, ++ [R_MIPS_32] = apply_r_mips_32_rela, ++ [R_MIPS_26] = apply_r_mips_26_rela, ++ [R_MIPS_HI16] = apply_r_mips_hi16_rela, ++ [R_MIPS_LO16] = apply_r_mips_lo16_rela, ++ [R_MIPS_64] = apply_r_mips_64_rela, ++ [R_MIPS_HIGHER] = apply_r_mips_higher_rela, ++ [R_MIPS_HIGHEST] = apply_r_mips_highest_rela ++}; ++ ++int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, ++ unsigned int symindex, unsigned int relsec, ++ struct module *me) ++{ ++ Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; ++ Elf_Sym *sym; ++ u32 *location; ++ unsigned int i; ++ Elf_Addr v; ++ int res; ++ ++ pr_debug("Applying relocate section %u to %u\n", relsec, ++ sechdrs[relsec].sh_info); ++ ++ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { ++ /* This is where to make the change */ ++ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr ++ + rel[i].r_offset; ++ /* This is the symbol it is referring to */ ++ sym = (Elf_Sym *)sechdrs[symindex].sh_addr ++ + ELF_MIPS_R_SYM(rel[i]); ++ if (IS_ERR_VALUE(sym->st_value)) { ++ /* Ignore unresolved weak symbol */ ++ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) ++ continue; ++ printk(KERN_WARNING "%s: Unknown symbol %s\n", ++ me->name, strtab + sym->st_name); ++ return -ENOENT; ++ } ++ ++ v = sym->st_value + rel[i].r_addend; ++ ++ res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); ++ if (res) ++ return res; ++ } ++ ++ return 0; ++} +diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c +index 1500c80..74a7197 100644 +--- a/arch/mips/kernel/module.c ++++ b/arch/mips/kernel/module.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include "module.h" + + #include /* MODULE_START */ + +@@ -53,7 +54,7 @@ void *module_alloc(unsigned long size) + } + #endif + +-static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) ++int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) + { + return 0; + } +@@ -65,13 +66,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) + return 0; + } + +-static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- *location = v; +- +- return 0; +-} +- + static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) + { + if (v % 4) { +@@ -93,26 +87,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) + return 0; + } + +-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- if (v % 4) { +- pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", +- me->name); +- return -ENOEXEC; +- } +- +- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { +- printk(KERN_ERR +- "module %s: relocation overflow\n", +- me->name); +- return -ENOEXEC; +- } +- +- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); +- +- return 0; +-} +- + static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) + { + struct mips_hi16 *n; +@@ -134,14 +108,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) + return 0; + } + +-static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- *location = (*location & 0xffff0000) | +- ((((long long) v + 0x8000LL) >> 16) & 0xffff); +- +- return 0; +-} +- + static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) + { + unsigned long insnlo = *location; +@@ -206,38 +172,6 @@ out_danger: + return -ENOEXEC; + } + +-static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- *location = (*location & 0xffff0000) | (v & 0xffff); +- +- return 0; +-} +- +-static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- *(Elf_Addr *)location = v; +- +- return 0; +-} +- +-static int apply_r_mips_higher_rela(struct module *me, u32 *location, +- Elf_Addr v) +-{ +- *location = (*location & 0xffff0000) | +- ((((long long) v + 0x80008000LL) >> 32) & 0xffff); +- +- return 0; +-} +- +-static int apply_r_mips_highest_rela(struct module *me, u32 *location, +- Elf_Addr v) +-{ +- *location = (*location & 0xffff0000) | +- ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); +- +- return 0; +-} +- + static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, + Elf_Addr v) = { + [R_MIPS_NONE] = apply_r_mips_none, +@@ -247,18 +181,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, + [R_MIPS_LO16] = apply_r_mips_lo16_rel + }; + +-static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, +- Elf_Addr v) = { +- [R_MIPS_NONE] = apply_r_mips_none, +- [R_MIPS_32] = apply_r_mips_32_rela, +- [R_MIPS_26] = apply_r_mips_26_rela, +- [R_MIPS_HI16] = apply_r_mips_hi16_rela, +- [R_MIPS_LO16] = apply_r_mips_lo16_rela, +- [R_MIPS_64] = apply_r_mips_64_rela, +- [R_MIPS_HIGHER] = apply_r_mips_higher_rela, +- [R_MIPS_HIGHEST] = apply_r_mips_highest_rela +-}; +- + int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, + struct module *me) +@@ -299,48 +221,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, + return 0; + } + +-#ifdef CONFIG_MODULES_USE_ELF_RELA +-int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, +- unsigned int symindex, unsigned int relsec, +- struct module *me) +-{ +- Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; +- Elf_Sym *sym; +- u32 *location; +- unsigned int i; +- Elf_Addr v; +- int res; +- +- pr_debug("Applying relocate section %u to %u\n", relsec, +- sechdrs[relsec].sh_info); +- +- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { +- /* This is where to make the change */ +- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr +- + rel[i].r_offset; +- /* This is the symbol it is referring to */ +- sym = (Elf_Sym *)sechdrs[symindex].sh_addr +- + ELF_MIPS_R_SYM(rel[i]); +- if (IS_ERR_VALUE(sym->st_value)) { +- /* Ignore unresolved weak symbol */ +- if (ELF_ST_BIND(sym->st_info) == STB_WEAK) +- continue; +- printk(KERN_WARNING "%s: Unknown symbol %s\n", +- me->name, strtab + sym->st_name); +- return -ENOENT; +- } +- +- v = sym->st_value + rel[i].r_addend; +- +- res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); +- if (res) +- return res; +- } +- +- return 0; +-} +-#endif +- + /* Given an address, look for it in the module exception tables. */ + const struct exception_table_entry *search_module_dbetables(unsigned long addr) + { +diff --git a/arch/mips/kernel/module.h b/arch/mips/kernel/module.h +new file mode 100644 +index 0000000..675d091 +--- /dev/null ++++ b/arch/mips/kernel/module.h +@@ -0,0 +1,12 @@ ++/* Internal definitions for MIPS module code ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++/* ++ * module.c ++ */ ++extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v); +-- +1.7.11.4 + + +From 661f0147e9414fb2237f56d88d1f92d8a42345c9 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:13:57 +0100 -Subject: [PATCH 16/28] Provide macros for forming the name of an ELF note and +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 19/32] Provide macros for forming the name of an ELF note and its section Provide macros for stringifying the name of an ELF note and its section @@ -5493,13 +7171,13 @@ index 278e3ef..949d494 100644 #endif /* _LINUX_ELFNOTE_H */ -- -1.7.11.2 +1.7.11.4 -From 1d83fa4cf20b3b6f7ffd471459dcad47d6e2ac64 Mon Sep 17 00:00:00 2001 +From 544f02e192a8a38153d7dedc61bc107545666c0d Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:00 +0100 -Subject: [PATCH 17/28] MODSIGN: Provide gitignore and make clean rules for +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 20/32] MODSIGN: Provide gitignore and make clean rules for extra files Provide gitignore and make clean rules for extra files to hide and clean up the @@ -5542,7 +7220,7 @@ index 57af07c..7948eeb 100644 +random_seed +trustdb.gpg diff --git a/Makefile b/Makefile -index 8e4c0a7..4db9629 100644 +index ddf5be9..70a6b5b 100644 --- a/Makefile +++ b/Makefile @@ -1239,6 +1239,7 @@ clean: $(clean-dirs) @@ -5564,13 +7242,13 @@ index e9b7abe..223dfd6 100644 +mod-extract -- -1.7.11.2 +1.7.11.4 -From a284aee7526543a96a6e5694425ec7a2001d5c32 Mon Sep 17 00:00:00 2001 +From 6e21809168e7b45a830ec354ec9fc1582fcffe4f Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:01 +0100 -Subject: [PATCH 18/28] MODSIGN: Provide Documentation and Kconfig options +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 21/32] MODSIGN: Provide Documentation and Kconfig options Provide documentation and kernel configuration options for module signing. @@ -5909,13 +7587,13 @@ index af6c7f8..e23ed83 100644 config INIT_ALL_POSSIBLE -- -1.7.11.2 +1.7.11.4 -From 509093b115e362fd50584c5852c922926c2395bd Mon Sep 17 00:00:00 2001 +From 7733934d34b7f03574b4578edfad4a60d6fe3d56 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:01 +0100 -Subject: [PATCH 19/28] MODSIGN: Sign modules during the build process +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 22/32] MODSIGN: Sign modules during the build process If CONFIG_MODULE_SIG is set, then this patch will cause the module to get a signature installed. The following steps will occur: @@ -7034,13 +8712,13 @@ index 0000000..bca67c0 + +exit 0 -- -1.7.11.2 +1.7.11.4 -From 6a2e8f0245dadda42c355eda278110f496e3a6d5 Mon Sep 17 00:00:00 2001 +From ee3ca99bcf972f0d072d91f9256c39a197153b8e Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:01 +0100 -Subject: [PATCH 20/28] MODSIGN: Module signature verification stub +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 23/32] MODSIGN: Module signature verification stub Create a stub for the module signature verifier and link it into module.c so that it gets called. A field is added to struct module to record whether or @@ -7422,13 +9100,13 @@ index 087aeed..a59a9da 100644 if (last_unloaded_module[0]) printk(" [last unloaded: %s]", last_unloaded_module); -- -1.7.11.2 +1.7.11.4 -From 62c90369e58486688303c4803e39d7df44a932f9 Mon Sep 17 00:00:00 2001 +From 0f8f372047d8220e1d918797972746bb9fe345d9 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:02 +0100 -Subject: [PATCH 21/28] MODSIGN: Automatically generate module signing keys if +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 24/32] MODSIGN: Automatically generate module signing keys if missing Automatically generate keys for module signing if they're absent so that @@ -7504,13 +9182,13 @@ index cec222a..28cd248 100644 +endif +CLEAN_FILES += modsign.pub modsign.sec genkey random_seed -- -1.7.11.2 +1.7.11.4 -From 00ce30147994ed4a503bdb051350a4601c565dcc Mon Sep 17 00:00:00 2001 +From be5544dce081ccb49fd452a6273c5024208b2f06 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:02 +0100 -Subject: [PATCH 22/28] MODSIGN: Provide module signing public keys to the +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 25/32] MODSIGN: Provide module signing public keys to the kernel Include a PGP keyring containing the public keys required to perform module @@ -7582,7 +9260,7 @@ index 28cd248..1d20704 100644 echo "%no-protection: yes" >> genkey diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c new file mode 100644 -index 0000000..17e02f5 +index 0000000..5fdb082 --- /dev/null +++ b/kernel/modsign-pubkey.c @@ -0,0 +1,75 @@ @@ -7655,7 +9333,7 @@ index 0000000..17e02f5 + + if (preload_pgp_keys(modsign_public_keys, + modsign_public_keys_end - modsign_public_keys, -+ modsign_keyring, "modsign.") < 0) ++ modsign_keyring) < 0) + panic("Can't load module signing keys\n"); + + return 0; @@ -7690,13 +9368,13 @@ index 4bf857e..05473e6 100644 #include #include -- -1.7.11.2 +1.7.11.4 -From 9b94f77eea94d028df6a041e6772f9f142eb89e7 Mon Sep 17 00:00:00 2001 +From 34c918aacc002f8a7226a26a0d8af614c6f4430e Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:02 +0100 -Subject: [PATCH 23/28] MODSIGN: Check the ELF container +Date: Thu, 16 Aug 2012 01:38:45 +0100 +Subject: [PATCH 26/32] MODSIGN: Check the ELF container Check the ELF container of the kernel module to prevent the kernel from crashing or getting corrupted whilst trying to use it and locate the module @@ -8026,13 +9704,13 @@ index 05473e6..2161d11 100644 /* Deal with an unsigned module */ if (modsign_signedonly) { -- -1.7.11.2 +1.7.11.4 -From 60ca7dc263084abcf68325ed86d2765148f60225 Mon Sep 17 00:00:00 2001 +From 2de4559e24c416e6813c10edbe3cc433ecd0dd50 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:02 +0100 -Subject: [PATCH 24/28] MODSIGN: Produce a filtered and canonicalised section +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 27/32] MODSIGN: Produce a filtered and canonicalised section list Build a list of the sections in which we're interested and canonicalise the @@ -8150,13 +9828,13 @@ index 2161d11..646b104 100644 out: switch (ret) { -- -1.7.11.2 +1.7.11.4 -From b847c539c4fb7d71ab7383e79b3e6c0683a23a7e Mon Sep 17 00:00:00 2001 +From 3c8e71a46663f1fc3ee49fe3f6fa5c3bb85b704c Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:03 +0100 -Subject: [PATCH 25/28] MODSIGN: Create digest of module content and check +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 28/32] MODSIGN: Create digest of module content and check signature Apply signature checking to modules on module load, checking the signature @@ -8199,14 +9877,23 @@ somewhat smaller code. Signed-off-by: David Howells --- - kernel/module-verify-defs.h | 11 +- + kernel/module-verify-defs.h | 13 +- kernel/module-verify.c | 332 +++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 337 insertions(+), 6 deletions(-) + 2 files changed, 338 insertions(+), 7 deletions(-) diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h -index 2fe31e1..82952b0 100644 +index 2fe31e1..cb477a2 100644 --- a/kernel/module-verify-defs.h +++ b/kernel/module-verify-defs.h +@@ -19,7 +19,7 @@ extern struct key *modsign_keyring; + * Internal state + */ + struct module_verify_data { +- struct crypto_key_verify_context *mod_sig; /* Module signing context */ ++ struct crypto_sig_verify_context *mod_sig; /* Module signing context */ + union { + const void *buffer; /* module buffer */ + const Elf_Ehdr *hdr; /* ELF header */ @@ -42,15 +42,16 @@ struct module_verify_data { /* * Whether or not we support various types of ELF relocation record @@ -8230,7 +9917,7 @@ index 2fe31e1..82952b0 100644 /* diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 646b104..e275759 100644 +index 646b104..bee7e04 100644 --- a/kernel/module-verify.c +++ b/kernel/module-verify.c @@ -50,6 +50,22 @@ static bool modsign_signedonly; @@ -8456,7 +10143,7 @@ index 646b104..e275759 100644 + */ +static noinline int module_verify_signature(struct module_verify_data *mvdata) +{ -+ struct crypto_key_verify_context *mod_sig; ++ struct crypto_sig_verify_context *mod_sig; + const Elf_Shdr *sechdrs = mvdata->sections; + const char *secstrings = mvdata->secstrings; + const u8 *sig = mvdata->sig; @@ -8587,13 +10274,13 @@ index 646b104..e275759 100644 out: -- -1.7.11.2 +1.7.11.4 -From 86969bc531b37c88b499311abae41e0116666dcc Mon Sep 17 00:00:00 2001 +From 53142a9c74e2922885d03555d26213fc38553b90 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:03 +0100 -Subject: [PATCH 26/28] MODSIGN: Suppress some redundant ELF checks +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 29/32] MODSIGN: Suppress some redundant ELF checks Suppress some redundant ELF checks in module_verify_elf() that are also done by copy_and_check() in the core module loader code prior to calling @@ -8605,7 +10292,7 @@ Signed-off-by: David Howells 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index e275759..bfd1286 100644 +index bee7e04..f3a694f 100644 --- a/kernel/module-verify.c +++ b/kernel/module-verify.c @@ -97,11 +97,11 @@ do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0) @@ -8624,13 +10311,13 @@ index e275759..bfd1286 100644 /* Validate the section table contents */ mvdata->nsects = hdr->e_shnum; -- -1.7.11.2 +1.7.11.4 -From 4d5a1f0360ce04a24b847eee2da84d9618375ce8 Mon Sep 17 00:00:00 2001 +From 14d36171021b1c16f6c664bd4ab31e1d989ab282 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Tue, 24 Jul 2012 14:14:03 +0100 -Subject: [PATCH 27/28] MODSIGN: Panic the kernel if FIPS is enabled upon +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 30/32] MODSIGN: Panic the kernel if FIPS is enabled upon module signing failure If module signing fails when the kernel is running with FIPS enabled then the @@ -8644,7 +10331,7 @@ Signed-off-by: David Howells 1 file changed, 5 insertions(+) diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index bfd1286..b9c3955 100644 +index f3a694f..896c0ff 100644 --- a/kernel/module-verify.c +++ b/kernel/module-verify.c @@ -30,6 +30,7 @@ @@ -8667,13 +10354,13 @@ index bfd1286..b9c3955 100644 case 0: /* Good signature */ *_gpgsig_ok = true; -- -1.7.11.2 +1.7.11.4 -From dd6e65be6a8f225018259b16161decc26c09c300 Mon Sep 17 00:00:00 2001 +From 1e8e625508f013acfb8ade3b5c30dcc7ff710ce9 Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Thu, 2 Aug 2012 14:35:44 +0100 -Subject: [PATCH 28/28] MODSIGN: Allow modules to be signed with an unknown +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 31/32] MODSIGN: Allow modules to be signed with an unknown key unless enforcing Currently we fail the loading of modules that are signed with a public key @@ -8691,7 +10378,7 @@ Signed-off-by: David Howells 1 file changed, 7 insertions(+) diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index b9c3955..22036d4 100644 +index 896c0ff..041506f 100644 --- a/kernel/module-verify.c +++ b/kernel/module-verify.c @@ -736,6 +736,13 @@ out: @@ -8709,13 +10396,14 @@ index b9c3955..22036d4 100644 default: /* Other error (probably ENOMEM) */ break; -- -1.7.11.2 +1.7.11.4 -From bccd1bfe487e1f4df543f7a160cc9876d7d96fb7 Mon Sep 17 00:00:00 2001 + +From 7ac7095ee6624789c6a971d16f5ca823ebbde3c7 Mon Sep 17 00:00:00 2001 From: Peter Jones -Date: Thu, 2 Aug 2012 23:09:19 +0100 -Subject: [PATCH] MODSIGN: Fix documentation of signed-nokey behavior when not - enforcing. +Date: Thu, 16 Aug 2012 01:38:46 +0100 +Subject: [PATCH 32/32] MODSIGN: Fix documentation of signed-nokey behavior + when not enforcing. jwboyer's previous commit changes the behavior of module signing when there's a valid signature but we don't know the public key and are in @@ -8742,5 +10430,5 @@ index d75d473..8c4bef9 100644 Invalidly signed, public key EKEYREJECTED EKEYREJECTED Validly signed, expired key EKEYEXPIRED EKEYEXPIRED -- -1.7.11.2 +1.7.11.4 diff --git a/sources b/sources index 80d0bc7fe..568d4bd26 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 5f0ec612b5364c18386c1b8155c271ac patch-3.6-rc2.xz +12edd20554fd9469c5d7fad9935ce0af patch-3.6-rc2-git1.xz diff --git a/vfs-fix-file-creation-bugs.patch b/vfs-fix-file-creation-bugs.patch deleted file mode 100644 index b4e621645..000000000 --- a/vfs-fix-file-creation-bugs.patch +++ /dev/null @@ -1,393 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Miklos Szeredi -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems,gmane.linux.kernel.stable -Subject: [PATCH 1/4] vfs: canonicalize create mode in build_open_flags() -Date: Tue, 7 Aug 2012 14:45:46 +0200 -Lines: 37 -Approved: news@gmane.org -Message-ID: <1344343549-11887-2-git-send-email-miklos@szeredi.hu> -References: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1344343547 29032 80.91.229.3 (7 Aug 2012 12:45:47 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Aug 2012 12:45:47 +0000 (UTC) -Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, - rjones@redhat.com, steveamigauk@yahoo.co.uk, mszeredi@suse.cz, - stable@vger.kernel.org -To: viro@ZenIV.linux.org.uk -Original-X-From: linux-kernel-owner@vger.kernel.org Tue Aug 07 14:45:47 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SyjAQ-0007sm-7c - for glk-linux-kernel-3@plane.gmane.org; Tue, 07 Aug 2012 14:45:46 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754555Ab2HGMpi (ORCPT ); - Tue, 7 Aug 2012 08:45:38 -0400 -Original-Received: from mail-we0-f174.google.com ([74.125.82.174]:58092 "EHLO - mail-we0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754305Ab2HGMoe (ORCPT - ); - Tue, 7 Aug 2012 08:44:34 -0400 -Original-Received: by weyx8 with SMTP id x8so2645788wey.19 - for ; Tue, 07 Aug 2012 05:44:32 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=szeredi.hu; s=google; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; - bh=1qjbKUe4PMMa48XDr0iiAZbSQDjKIFlASvIcoWSByLY=; - b=Btq8S/0RNrAMDqIuqkWxTXUBX1CBdRNl9d47rqc2ZXzMxnyHfqOTM+/GYZBQkM5Fm7 - W11AcmLVTWQ6e6Av98QIpw4aiC35KI1NQwyEGs3+QmzJE+nO706XT4QK+TW7ynd6Rssq - UC+GVbxB6Ix7QdVmtgZO6EfXEJ4sxLMqeatuc= -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references - :x-gm-message-state; - bh=1qjbKUe4PMMa48XDr0iiAZbSQDjKIFlASvIcoWSByLY=; - b=LNbJeP9fTZ3nOJiZO4BWNTuTQ5G5tmcNb1TwWGPxerdYqKYQTyEop2fUJPOQBftC5R - t34Oi+kpvLRUhjyAAkTefiqaNupAQVXdg2kV2PgRYWDjFR9acKHnmzhbEsozi98G+Xp/ - UsERBlNsx3CYLBhuuWK70HIZ8Zp1Pg8YzhhmXO2sW4bGDRa8/ZCeTTmJ5owb7zuZugAT - I+blTuEakAco+9SubhMh9XR0T3us/2LcUxv0KIA0GK/CzBlig5iBTFH1IU9EhS6ZkBpL - rRsM1o14L6POmPxH9J5GolEUjCBfBet54Y0pPp8hytWrOGCz7cbejS++c4/Lu8mOvQfS - FgXw== -Original-Received: by 10.216.54.146 with SMTP id i18mr7274525wec.187.1344343472653; - Tue, 07 Aug 2012 05:44:32 -0700 (PDT) -Original-Received: from localhost.localdomain (77-234-87-236.pool.digikabel.hu. [77.234.87.236]) - by mx.google.com with ESMTPS id b7sm31225742wiz.9.2012.08.07.05.44.30 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 07 Aug 2012 05:44:31 -0700 (PDT) -X-Mailer: git-send-email 1.7.7 -In-Reply-To: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -X-Gm-Message-State: ALoCoQlBs8Zo4YKrYg/AUMfG82CQVVCikUAknZuRKPe9oykBM4fMvZfn22FIif3NtkSoDwAQss82 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1339000 gmane.linux.file-systems:66449 gmane.linux.kernel.stable:29234 -Archived-At: - -From: Miklos Szeredi - -Userspace can pass weird create mode in open(2) that we canonicalize to -"(mode & S_IALLUGO) | S_IFREG" in vfs_create(). - -The problem is that we use the uncanonicalized mode before calling vfs_create() -with unforseen consequences. - -So do the canonicalization early in build_open_flags(). - -Signed-off-by: Miklos Szeredi -CC: stable@vger.kernel.org ---- - fs/open.c | 7 ++++--- - 1 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/fs/open.c b/fs/open.c -index bc132e1..e1f2cdb 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -852,9 +852,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o - int lookup_flags = 0; - int acc_mode; - -- if (!(flags & O_CREAT)) -- mode = 0; -- op->mode = mode; -+ if (flags & O_CREAT) -+ op->mode = (mode & S_IALLUGO) | S_IFREG; -+ else -+ op->mode = 0; - - /* Must never be set by userspace */ - flags &= ~FMODE_NONOTIFY; --- -1.7.7 - -Path: news.gmane.org!not-for-mail -From: Miklos Szeredi -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems -Subject: [PATCH 2/4] vfs: atomic_open(): fix create mode usage -Date: Tue, 7 Aug 2012 14:45:47 +0200 -Lines: 29 -Approved: news@gmane.org -Message-ID: <1344343549-11887-3-git-send-email-miklos@szeredi.hu> -References: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1344343484 28394 80.91.229.3 (7 Aug 2012 12:44:44 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Aug 2012 12:44:44 +0000 (UTC) -Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, - rjones@redhat.com, steveamigauk@yahoo.co.uk, mszeredi@suse.cz -To: viro@ZenIV.linux.org.uk -Original-X-From: linux-kernel-owner@vger.kernel.org Tue Aug 07 14:44:43 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Syj9O-0006lB-Q1 - for glk-linux-kernel-3@plane.gmane.org; Tue, 07 Aug 2012 14:44:43 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754569Ab2HGMoi (ORCPT ); - Tue, 7 Aug 2012 08:44:38 -0400 -Original-Received: from mail-we0-f174.google.com ([74.125.82.174]:42649 "EHLO - mail-we0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754511Ab2HGMof (ORCPT - ); - Tue, 7 Aug 2012 08:44:35 -0400 -Original-Received: by mail-we0-f174.google.com with SMTP id x8so2645765wey.19 - for ; Tue, 07 Aug 2012 05:44:34 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=szeredi.hu; s=google; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; - bh=AdrwH4TefuleTVZB4XFHvywWtuGocoaapFFX4/PnPN0=; - b=ZSz4WBTINxIVhKr/eL2BAQWxfdNF5XH0PEKbSlALRQbOHT4yZ8w+3/NNDp8DjUhydl - vQQijSva0g32a2N3dORJtNjcoplZyqzo4SKSTBFbaUfXvlHIxJaOq0KcDSS5huMe/yk8 - XU1djDAt7kma9A3oTQh59ASLumUpCeVqOue6g= -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references - :x-gm-message-state; - bh=AdrwH4TefuleTVZB4XFHvywWtuGocoaapFFX4/PnPN0=; - b=Js4PjFw+6ckXxUvsGO/Sz2QTTxEdZsRF4SvTScOgL6ugRFWnK+U/4t1c+rRfHkfDfD - i5G2afUaZB0JRnPIxmpSkly92cu/sI+fdeFDpuls3m5GPQ4CMmXHbl1Ev42BTqTB6y1G - UsXYw14QYf+XbnrJgJ1MKMX+hJlBMfyu8A3kh54RtJsBYBYd4u7vWnDKRhCGudhj9XGY - s19MCkfJDyhWl7k84NjzlLUEN1LLwFF+ZDd086+95BrtlO7ta35r7WjTrj7eIz/JQ2wf - RBmbh2SHh1BplRm20j0YRNvWvrUUn0CDwCOx2PpN+zQsMRmYwAMh/cfJHbrf6sEtWmDU - HPuQ== -Original-Received: by 10.180.83.106 with SMTP id p10mr27242596wiy.21.1344343474226; - Tue, 07 Aug 2012 05:44:34 -0700 (PDT) -Original-Received: from localhost.localdomain (77-234-87-236.pool.digikabel.hu. [77.234.87.236]) - by mx.google.com with ESMTPS id b7sm31225742wiz.9.2012.08.07.05.44.32 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 07 Aug 2012 05:44:33 -0700 (PDT) -X-Mailer: git-send-email 1.7.7 -In-Reply-To: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -X-Gm-Message-State: ALoCoQn5VhymZvNT7mcpKezP10+ERZVrDOUy6d1v5xWL8OcMf7YtYh9K43mLEBvJE7elSPegM6gs -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1338997 gmane.linux.file-systems:66446 -Archived-At: - -From: Miklos Szeredi - -Don't mask S_ISREG off the create mode before passing to ->atomic_open(). Other -methods (->create, ->mknod) also get the complete file mode and filesystems -expect it. - -Reported-by: Steve -Reported-by: Richard W.M. Jones -Signed-off-by: Miklos Szeredi ---- - fs/namei.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/fs/namei.c b/fs/namei.c -index 1b46439..5bac1bb 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -2414,7 +2414,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, - goto out; - } - -- mode = op->mode & S_IALLUGO; -+ mode = op->mode; - if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) - mode &= ~current_umask(); - --- -1.7.7 - -Path: news.gmane.org!not-for-mail -From: Miklos Szeredi -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems -Subject: [PATCH 3/4] vfs: pass right create mode to may_o_create() -Date: Tue, 7 Aug 2012 14:45:48 +0200 -Lines: 25 -Approved: news@gmane.org -Message-ID: <1344343549-11887-4-git-send-email-miklos@szeredi.hu> -References: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1344343526 28841 80.91.229.3 (7 Aug 2012 12:45:26 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Aug 2012 12:45:26 +0000 (UTC) -Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, - rjones@redhat.com, steveamigauk@yahoo.co.uk, mszeredi@suse.cz -To: viro@ZenIV.linux.org.uk -Original-X-From: linux-kernel-owner@vger.kernel.org Tue Aug 07 14:45:24 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Syj9z-0007QH-Q3 - for glk-linux-kernel-3@plane.gmane.org; Tue, 07 Aug 2012 14:45:20 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754608Ab2HGMpK (ORCPT ); - Tue, 7 Aug 2012 08:45:10 -0400 -Original-Received: from mail-we0-f174.google.com ([74.125.82.174]:58092 "EHLO - mail-we0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754059Ab2HGMog (ORCPT - ); - Tue, 7 Aug 2012 08:44:36 -0400 -Original-Received: by mail-we0-f174.google.com with SMTP id x8so2645788wey.19 - for ; Tue, 07 Aug 2012 05:44:35 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=szeredi.hu; s=google; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; - bh=nl2pPzHwW8KM+I7iQTOh9PYtYJohI6BIhk/K8K5LBQo=; - b=LseVfH0Fqa0ZLiIt9+N/ozV8rHtd85QSg6ixoDjgzR5Mh28J5FMzUVGjcnJzGDrMqJ - iTGbA8CSMcE2WykswC+5rJUKFxPw9u7mjaPutqcV8aAc6Ii2i1D7oIUO7O6qhyiiPWnZ - 2fFGR2LPOOrPF/tzVZX/9Rcwc6nNJLdlr6PU0= -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references - :x-gm-message-state; - bh=nl2pPzHwW8KM+I7iQTOh9PYtYJohI6BIhk/K8K5LBQo=; - b=MkUpj/XL8pOrHQYqjessDHSpc3Cn3OK8rTtvlzSLRA7ktxqXk1w4mVGrI3SVSrat+V - eu5OziG+pXw/+SVENp5VBksJuvbeq791pBjXINPJLh/Wv4c3kRCHyymT5lIDam24tBJQ - xgvurY4/P9r5vfxHQiG6/SOltCvldN+QyHeXDfEwlvxr4GDovGJ0VvUp3t70oCPh6TnQ - w8XhnTrnaa02wThfpz7RYtCIxyDMAnZTX6vxKlzURVxcdmVjMu4kPA8CMWgizOi/S9l0 - 6ZDGhqqY0jdtbdncf6MkL25vulJvCF5Uf4WfyR8+REGS5f8V8sMWFFurp1S2LYEdLJ5o - 7WtQ== -Original-Received: by 10.180.20.11 with SMTP id j11mr27275578wie.12.1344343475796; - Tue, 07 Aug 2012 05:44:35 -0700 (PDT) -Original-Received: from localhost.localdomain (77-234-87-236.pool.digikabel.hu. [77.234.87.236]) - by mx.google.com with ESMTPS id b7sm31225742wiz.9.2012.08.07.05.44.34 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 07 Aug 2012 05:44:35 -0700 (PDT) -X-Mailer: git-send-email 1.7.7 -In-Reply-To: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -X-Gm-Message-State: ALoCoQkO1sLF/IsgU7JMCP9gmfCSYZh8gUPun3lkVeiAXebgfb+UIaib3NfgHI+ihXW0gPxiVeOq -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1338999 gmane.linux.file-systems:66448 -Archived-At: - -From: Miklos Szeredi - -Pass the umask-ed create mode to may_o_create() instead of the original one. - -Signed-off-by: Miklos Szeredi ---- - fs/namei.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/fs/namei.c b/fs/namei.c -index 5bac1bb..26c28ec 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -2452,7 +2452,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, - } - - if (open_flag & O_CREAT) { -- error = may_o_create(&nd->path, dentry, op->mode); -+ error = may_o_create(&nd->path, dentry, mode); - if (error) { - create_error = error; - if (open_flag & O_EXCL) --- -1.7.7 - -Path: news.gmane.org!not-for-mail -From: Miklos Szeredi -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems -Subject: [PATCH 4/4] fuse: check create mode in atomic open -Date: Tue, 7 Aug 2012 14:45:49 +0200 -Lines: 29 -Approved: news@gmane.org -Message-ID: <1344343549-11887-5-git-send-email-miklos@szeredi.hu> -References: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1344343501 28616 80.91.229.3 (7 Aug 2012 12:45:01 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Aug 2012 12:45:01 +0000 (UTC) -Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, - rjones@redhat.com, steveamigauk@yahoo.co.uk, mszeredi@suse.cz -To: viro@ZenIV.linux.org.uk -Original-X-From: linux-kernel-owner@vger.kernel.org Tue Aug 07 14:45:01 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Syj9g-000751-AP - for glk-linux-kernel-3@plane.gmane.org; Tue, 07 Aug 2012 14:45:01 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753956Ab2HGMol (ORCPT ); - Tue, 7 Aug 2012 08:44:41 -0400 -Original-Received: from mail-wg0-f44.google.com ([74.125.82.44]:49113 "EHLO - mail-wg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754550Ab2HGMoi (ORCPT - ); - Tue, 7 Aug 2012 08:44:38 -0400 -Original-Received: by wgbdr13 with SMTP id dr13so3821771wgb.1 - for ; Tue, 07 Aug 2012 05:44:37 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=szeredi.hu; s=google; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; - bh=2z/lG+dElZX1BvzqKB7l/eTdQWJupcJMEPoo3E7WIkA=; - b=OSiFNFL8gGKzfQF4uTbT4uuk+FiRJFon3esY5HKXETPIldNkm2zTGUf0pTSAFKp+UG - nR1uDMgw8M+lY8aSepjpSqty+93LvJBEn5N2L+7hZeMPZHw/dvkjHpV/GvbqLI++oeHY - h5H4AqTI/51xQvAZP0fid7hVJh2leMo1lGtMc= -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references - :x-gm-message-state; - bh=2z/lG+dElZX1BvzqKB7l/eTdQWJupcJMEPoo3E7WIkA=; - b=f5PRamaleMoVfPo7U0JjEgSltuT3/8qDvNRrgagcbsxz99IsBh5XZBfdcIX4BbAGYR - NNS0XMJEHgZSVE6O+imPLvlj3Oc7e4+NPYcfZTIeq3RdCpXeX5/X6woK4PJcOXIRMHML - U3L0o3trwK6EZTxyuThoOdptBVHQh+IyxzGJoHCSyoZki5ZMdjJUCnbLuOvY4A1xfaxM - a4v33nCxXl8B/698Hjm/U+Q5wIO2yloqCYTjzBeKquRsprxmLGfqErEqQSP7N7n2yGiV - cdiHfHOA2S0RbP+FTw9MRrW5he8tpeVbXodbYfrUazI0XruNSm3x09gttO8KhR0ehCSD - gshg== -Original-Received: by 10.216.134.101 with SMTP id r79mr6493496wei.60.1344343477315; - Tue, 07 Aug 2012 05:44:37 -0700 (PDT) -Original-Received: from localhost.localdomain (77-234-87-236.pool.digikabel.hu. [77.234.87.236]) - by mx.google.com with ESMTPS id b7sm31225742wiz.9.2012.08.07.05.44.35 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 07 Aug 2012 05:44:36 -0700 (PDT) -X-Mailer: git-send-email 1.7.7 -In-Reply-To: <1344343549-11887-1-git-send-email-miklos@szeredi.hu> -X-Gm-Message-State: ALoCoQmdZRlhlKJWBzIDpgy+1szkaUFmK1NUhSopmYGukU6PHpk7xwsXWx0v+JWsNJdT/Aeqwz5M -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1338998 gmane.linux.file-systems:66447 -Archived-At: - -From: Miklos Szeredi - -Verify that the VFS is passing us a complete create mode with the S_IFREG to -atomic open. - -Reported-by: Steve -Reported-by: Richard W.M. Jones -Signed-off-by: Miklos Szeredi ---- - fs/fuse/dir.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c -index 8964cf3..324bc08 100644 ---- a/fs/fuse/dir.c -+++ b/fs/fuse/dir.c -@@ -383,6 +383,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, - struct fuse_entry_out outentry; - struct fuse_file *ff; - -+ /* Userspace expects S_IFREG in create mode */ -+ BUG_ON((mode & S_IFMT) != S_IFREG); -+ - forget = fuse_alloc_forget(); - err = -ENOMEM; - if (!forget) --- -1.7.7 - From fedb4582d3db4886e7faecaf7c35abd0fba54add Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 21 Aug 2012 09:30:44 -0400 Subject: [PATCH 003/492] Add patch from Dave Airlie to fix fb cursor vs grub2 gfxterm hang --- ...etween-console-lock-and-cursor-timer.patch | 89 +++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch diff --git a/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch b/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch new file mode 100644 index 000000000..992bd252f --- /dev/null +++ b/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch @@ -0,0 +1,89 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.229.184.7 with SMTP id ci7csp32184qcb; + Mon, 20 Aug 2012 23:40:20 -0700 (PDT) +Received: by 10.236.195.97 with SMTP id o61mr24210886yhn.17.1345531220620; + Mon, 20 Aug 2012 23:40:20 -0700 (PDT) +Return-Path: +Received: from mx1.redhat.com (mx1.redhat.com. [209.132.183.28]) + by mx.google.com with ESMTP id c5si239413anp.5.2012.08.20.23.40.20; + Mon, 20 Aug 2012 23:40:20 -0700 (PDT) +Received-SPF: pass (google.com: domain of airlied@redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of airlied@redhat.com designates 209.132.183.28 as permitted sender) smtp.mail=airlied@redhat.com +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q7L6eJ4K014799 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Tue, 21 Aug 2012 02:40:19 -0400 +Received: from prime.bne.redhat.com (dhcp-41-76.bne.redhat.com [10.64.41.76]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q7L6eFfB029177; + Tue, 21 Aug 2012 02:40:16 -0400 +From: Dave Airlie +To: linux-fbdev@vger.kernel.org +Cc: dri-devel@lists.sf.net, linux-kernel@vger.kernel.org, + Linus , + Alan Cox , + Randy Dunlap , Josh Boyer , + Dave Airlie +Subject: [PATCH] fbcon: fix race condition between console lock and cursor timer +Date: Tue, 21 Aug 2012 16:40:07 +1000 +Message-Id: <1345531207-24926-1-git-send-email-airlied@redhat.com> +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 + +So we've had a fair few reports of fbcon handover breakage between +efi/vesafb and i915 surface recently, so I dedicated a couple of +days to finding the problem. + +Essentially the last thing we saw was the conflicting framebuffer +message and that was all. + +So after much tracing with direct netconsole writes (printks +under console_lock not so useful), I think I found the race. + +Thread A (driver load) Thread B (timer thread) + unbind_con_driver -> | + bind_con_driver -> | + vc->vc_sw->con_deinit -> | + fbcon_deinit -> | + console_lock() | + | | + | fbcon_flashcursor timer fires + | console_lock() <- blocked for A + | + | +fbcon_del_cursor_timer -> + del_timer_sync + (BOOM) + +Of course because all of this is under the console lock, +we never see anything, also since we also just unbound the active +console guess what we never see anything. + +Hopefully this fixes the problem for anyone seeing vesafb->kms +driver handoff. + +Signed-off-by: David Airlie +--- + drivers/video/console/fbcon.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index 2e471c2..f8a79fc 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -372,8 +372,12 @@ static void fb_flashcursor(struct work_struct *work) + struct vc_data *vc = NULL; + int c; + int mode; ++ int ret; ++ ++ ret = console_trylock(); ++ if (ret == 0) ++ return; + +- console_lock(); + if (ops && ops->currcon != -1) + vc = vc_cons[ops->currcon].d; + +-- +1.7.10.2 + diff --git a/kernel.spec b/kernel.spec index 05f65d2c0..39edbfe80 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -747,6 +747,8 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 836742 Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch +Patch22065: fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch + # END OF PATCH DEFINITIONS %endif @@ -1437,6 +1439,8 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 836742 ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch +ApplyPatch fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch + # END OF PATCH APPLICATIONS %endif @@ -2299,6 +2303,9 @@ fi # ||----w | # || || %changelog +* Tue Aug 21 2012 Josh Boyer +- Add patch from Dave Airlie to fix fb cursor vs grub2 gfxterm hang + * Mon Aug 20 2012 Josh Boyer - 3.6.0-0.rc2.git1.1 - Linux v3.6-rc2-206-g10c63c9 From 47b9eb26ca706723bfeddd0014207551b6531862 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 21 Aug 2012 10:47:07 -0400 Subject: [PATCH 004/492] Add patch from Richard W.M. Jones to fix virtio scsi oops (rhbz 847548) --- kernel.spec | 7 +++++ ...csi-Initialize-scatterlist-structure.patch | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 virtio-scsi-Initialize-scatterlist-structure.patch diff --git a/kernel.spec b/kernel.spec index 39edbfe80..5fd90d063 100644 --- a/kernel.spec +++ b/kernel.spec @@ -749,6 +749,9 @@ Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch Patch22065: fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch +#rhbz 847548 +Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch + # END OF PATCH DEFINITIONS %endif @@ -1441,6 +1444,9 @@ ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch ApplyPatch fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch +#rhbz 847548 +ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch + # END OF PATCH APPLICATIONS %endif @@ -2304,6 +2310,7 @@ fi # || || %changelog * Tue Aug 21 2012 Josh Boyer +- Add patch from Richard W.M. Jones to fix virtio scsi oops (rhbz 847548) - Add patch from Dave Airlie to fix fb cursor vs grub2 gfxterm hang * Mon Aug 20 2012 Josh Boyer - 3.6.0-0.rc2.git1.1 diff --git a/virtio-scsi-Initialize-scatterlist-structure.patch b/virtio-scsi-Initialize-scatterlist-structure.patch new file mode 100644 index 000000000..4445d6838 --- /dev/null +++ b/virtio-scsi-Initialize-scatterlist-structure.patch @@ -0,0 +1,28 @@ +From: "Richard W.M. Jones" + +The sg struct is used without being initialized. + +https://bugzilla.redhat.com/show_bug.cgi?id=847548 + +Signed-off-by: Richard W.M. Jones +--- + drivers/scsi/virtio_scsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c +index c7030fb..8a66f83 100644 +--- a/drivers/scsi/virtio_scsi.c ++++ b/drivers/scsi/virtio_scsi.c +@@ -219,7 +219,7 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi, + struct scatterlist sg; + unsigned long flags; + +- sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); ++ sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); + + spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); + +-- +1.7.10.4 + + From 78739288e5bf9c47a78ed9c152bdb672a64cfede Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 21 Aug 2012 13:18:03 -0400 Subject: [PATCH 005/492] Add patch from Dave Jones to fix suspicious RCU usage in SELinux (rhbz 846037) --- kernel.spec | 7 +++ ...de_insert-suspicious-rcu-dereference.patch | 54 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch diff --git a/kernel.spec b/kernel.spec index 5fd90d063..9d3cc3434 100644 --- a/kernel.spec +++ b/kernel.spec @@ -752,6 +752,9 @@ Patch22065: fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch #rhbz 847548 Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch +#rhbz 846037 +Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch + # END OF PATCH DEFINITIONS %endif @@ -1447,6 +1450,9 @@ ApplyPatch fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch #rhbz 847548 ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch +#rhbz 846037 +ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch + # END OF PATCH APPLICATIONS %endif @@ -2310,6 +2316,7 @@ fi # || || %changelog * Tue Aug 21 2012 Josh Boyer +- Add patch from Dave Jones to fix suspicious RCU usage in SELinux (rhbz 846037) - Add patch from Richard W.M. Jones to fix virtio scsi oops (rhbz 847548) - Add patch from Dave Airlie to fix fb cursor vs grub2 gfxterm hang diff --git a/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch b/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch new file mode 100644 index 000000000..43fddf73d --- /dev/null +++ b/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch @@ -0,0 +1,54 @@ +From: Dave Jones <> +Subject: Fix sel_netnode_insert suspicious rcu dereference. + + +I reported this a year ago (https://lkml.org/lkml/2011/4/20/308). +It's still a problem apparently ... + +=============================== +[ INFO: suspicious RCU usage. ] +3.5.0-rc1+ #63 Not tainted +------------------------------- +security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage! +other info that might help us debug this: + + +rcu_scheduler_active = 1, debug_locks = 0 +1 lock held by trinity-child1/8750: + #0: (sel_netnode_lock){+.....}, at: [] sel_netnode_sid+0x16a/0x3e0 +stack backtrace: +Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63 +Call Trace: + [] lockdep_rcu_suspicious+0xfd/0x130 + [] sel_netnode_sid+0x3b1/0x3e0 + [] ? sel_netnode_find+0x1a0/0x1a0 + [] selinux_socket_bind+0xf6/0x2c0 + [] ? trace_hardirqs_off+0xd/0x10 + [] ? lock_release_holdtime.part.9+0x15/0x1a0 + [] ? lock_hrtimer_base+0x31/0x60 + [] security_socket_bind+0x16/0x20 + [] sys_bind+0x7a/0x100 + [] ? sysret_check+0x22/0x5d + [] ? trace_hardirqs_on_caller+0x10d/0x1a0 + [] ? trace_hardirqs_on_thunk+0x3a/0x3f + [] system_call_fastpath+0x16/0x1b +This patch below does what Paul McKenney suggested in the previous thread. + +Signed-off-by: Dave Jones + +diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c +index 28f911c..c5454c0 100644 +--- a/security/selinux/netnode.c ++++ b/security/selinux/netnode.c +@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) + if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { + struct sel_netnode *tail; + tail = list_entry( +- rcu_dereference(sel_netnode_hash[idx].list.prev), ++ rcu_dereference_protected(sel_netnode_hash[idx].list.prev, ++ lockdep_is_held(&sel_netnode_lock)), + struct sel_netnode, list); + list_del_rcu(&tail->list); + kfree_rcu(tail, rcu); + + From 0cbef6d8b4cecfe9041fce06f7bde89628197486 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 22 Aug 2012 07:34:59 -0400 Subject: [PATCH 006/492] Linux v3.6-rc2-400-g23dcfa6 - CVE-2012-3520: af_netlink: invalid handling of SCM_CREDENTIALS passing --- ...etween-console-lock-and-cursor-timer.patch | 89 ------------------- kernel.spec | 18 ++-- sources | 2 +- ...ield-when-recycling-erroneous-buffer.patch | 36 -------- 4 files changed, 7 insertions(+), 138 deletions(-) delete mode 100644 fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch delete mode 100644 uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch diff --git a/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch b/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch deleted file mode 100644 index 992bd252f..000000000 --- a/fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch +++ /dev/null @@ -1,89 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.229.184.7 with SMTP id ci7csp32184qcb; - Mon, 20 Aug 2012 23:40:20 -0700 (PDT) -Received: by 10.236.195.97 with SMTP id o61mr24210886yhn.17.1345531220620; - Mon, 20 Aug 2012 23:40:20 -0700 (PDT) -Return-Path: -Received: from mx1.redhat.com (mx1.redhat.com. [209.132.183.28]) - by mx.google.com with ESMTP id c5si239413anp.5.2012.08.20.23.40.20; - Mon, 20 Aug 2012 23:40:20 -0700 (PDT) -Received-SPF: pass (google.com: domain of airlied@redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; -Authentication-Results: mx.google.com; spf=pass (google.com: domain of airlied@redhat.com designates 209.132.183.28 as permitted sender) smtp.mail=airlied@redhat.com -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q7L6eJ4K014799 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Tue, 21 Aug 2012 02:40:19 -0400 -Received: from prime.bne.redhat.com (dhcp-41-76.bne.redhat.com [10.64.41.76]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q7L6eFfB029177; - Tue, 21 Aug 2012 02:40:16 -0400 -From: Dave Airlie -To: linux-fbdev@vger.kernel.org -Cc: dri-devel@lists.sf.net, linux-kernel@vger.kernel.org, - Linus , - Alan Cox , - Randy Dunlap , Josh Boyer , - Dave Airlie -Subject: [PATCH] fbcon: fix race condition between console lock and cursor timer -Date: Tue, 21 Aug 2012 16:40:07 +1000 -Message-Id: <1345531207-24926-1-git-send-email-airlied@redhat.com> -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 - -So we've had a fair few reports of fbcon handover breakage between -efi/vesafb and i915 surface recently, so I dedicated a couple of -days to finding the problem. - -Essentially the last thing we saw was the conflicting framebuffer -message and that was all. - -So after much tracing with direct netconsole writes (printks -under console_lock not so useful), I think I found the race. - -Thread A (driver load) Thread B (timer thread) - unbind_con_driver -> | - bind_con_driver -> | - vc->vc_sw->con_deinit -> | - fbcon_deinit -> | - console_lock() | - | | - | fbcon_flashcursor timer fires - | console_lock() <- blocked for A - | - | -fbcon_del_cursor_timer -> - del_timer_sync - (BOOM) - -Of course because all of this is under the console lock, -we never see anything, also since we also just unbound the active -console guess what we never see anything. - -Hopefully this fixes the problem for anyone seeing vesafb->kms -driver handoff. - -Signed-off-by: David Airlie ---- - drivers/video/console/fbcon.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c -index 2e471c2..f8a79fc 100644 ---- a/drivers/video/console/fbcon.c -+++ b/drivers/video/console/fbcon.c -@@ -372,8 +372,12 @@ static void fb_flashcursor(struct work_struct *work) - struct vc_data *vc = NULL; - int c; - int mode; -+ int ret; -+ -+ ret = console_trylock(); -+ if (ret == 0) -+ return; - -- console_lock(); - if (ops && ops->currcon != -1) - vc = vc_cons[ops->currcon].d; - --- -1.7.10.2 - diff --git a/kernel.spec b/kernel.spec index 9d3cc3434..fe54e105d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 2 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -744,11 +744,6 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 836742 -Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch - -Patch22065: fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch - #rhbz 847548 Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch @@ -1442,11 +1437,6 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 836742 -ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch - -ApplyPatch fbcon-fix-race-condition-between-console-lock-and-cursor-timer.patch - #rhbz 847548 ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch @@ -2315,6 +2305,10 @@ fi # ||----w | # || || %changelog +* Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc2.git2.1 +- Linux v3.6-rc2-400-g23dcfa6 +- CVE-2012-3520: af_netlink: invalid handling of SCM_CREDENTIALS passing + * Tue Aug 21 2012 Josh Boyer - Add patch from Dave Jones to fix suspicious RCU usage in SELinux (rhbz 846037) - Add patch from Richard W.M. Jones to fix virtio scsi oops (rhbz 847548) diff --git a/sources b/sources index 568d4bd26..20584a4f7 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 5f0ec612b5364c18386c1b8155c271ac patch-3.6-rc2.xz -12edd20554fd9469c5d7fad9935ce0af patch-3.6-rc2-git1.xz +35f27ef57826c644eb014ecda8f22870 patch-3.6-rc2-git2.xz diff --git a/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch b/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch deleted file mode 100644 index 6606b7d3d..000000000 --- a/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3771973542a4807b251352253ed22c50e688e573 Mon Sep 17 00:00:00 2001 -From: Jayakrishnan Memana -Date: Sun, 15 Jul 2012 15:54:03 +0200 -Subject: [PATCH] uvcvideo: Reset the bytesused field when recycling an erroneous buffer - -Buffers marked as erroneous are recycled immediately by the driver if -the nodrop module parameter isn't set. The buffer payload size is reset -to 0, but the buffer bytesused field isn't. This results in the buffer -being immediately considered as complete, leading to an infinite loop in -interrupt context. - -Fix the problem by resetting the bytesused field when recycling the -buffer. - -Cc: -Signed-off-by: Jayakrishnan Memana -Signed-off-by: Laurent Pinchart ---- - drivers/media/video/uvc/uvc_queue.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c -index 9288fbd..5577381 100644 ---- a/drivers/media/video/uvc/uvc_queue.c -+++ b/drivers/media/video/uvc/uvc_queue.c -@@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { - buf->error = 0; - buf->state = UVC_BUF_STATE_QUEUED; -+ buf->bytesused = 0; - vb2_set_plane_payload(&buf->buf, 0, 0); - return buf; - } --- -1.7.2.5 - From c0d37ff400061d3a21066ecd21d0861ece078bc3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 22 Aug 2012 16:52:45 -0400 Subject: [PATCH 007/492] Linux v3.6-rc3 - Disable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 12 +++-- sources | 3 +- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/config-generic b/config-generic index d6cb2b7e9..e811d83a2 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index fe54e105d..77409225f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 2 +%define rcrev 3 # The git snapshot level -%define gitrev 2 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2305,6 +2305,10 @@ fi # ||----w | # || || %changelog +* Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc3.git0.1 +- Linux v3.6-rc3 +- Disable debugging options. + * Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc2.git2.1 - Linux v3.6-rc2-400-g23dcfa6 - CVE-2012-3520: af_netlink: invalid handling of SCM_CREDENTIALS passing diff --git a/sources b/sources index 20584a4f7..0c106ef21 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -5f0ec612b5364c18386c1b8155c271ac patch-3.6-rc2.xz -35f27ef57826c644eb014ecda8f22870 patch-3.6-rc2-git2.xz +b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz From bea0984dd42ba3e5816d4336156b3193a0d18e2e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 23 Aug 2012 07:25:15 -0400 Subject: [PATCH 008/492] Reenable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 9 ++-- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/config-generic b/config-generic index e811d83a2..d6cb2b7e9 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index 5b4187680..d99deeb2f 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set -# CONFIG_FAIL_MMC_REQUEST is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_NFSD_FAULT_INJECTION=y -# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_DEBUG_BLK_CGROUP=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index de9582a01..ad22edd8d 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_MAXSMP is not set +CONFIG_MAXSMP=y CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 77409225f..dc68a915b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2305,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 23 2012 Josh Boyer - 3.6.0-0.rc3.git0.2 +- Reenable debugging options. + * Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc3.git0.1 - Linux v3.6-rc3 - Disable debugging options. From 2406f946097b49b4bee8bb3f1bc839eba26bfe4a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 24 Aug 2012 08:13:27 -0400 Subject: [PATCH 009/492] Linux v3.6-rc3-37-g2d809dc --- kernel.spec | 7 +++++-- sources | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index dc68a915b..390dae492 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 3 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2305,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Fri Aug 24 2012 Josh Boyer - 3.6.0-0.rc3.git1.1 +- Linux v3.6-rc3-37-g2d809dc + * Thu Aug 23 2012 Josh Boyer - 3.6.0-0.rc3.git0.2 - Reenable debugging options. diff --git a/sources b/sources index 0c106ef21..549237e70 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz +54f94117e623519f4936936325b52fad patch-3.6-rc3-git1.xz From ce15971aedf144bb43353a93c2f820c57872482e Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 26 Aug 2012 09:40:58 +0100 Subject: [PATCH 010/492] Add patch to fix build on ARM, Enable USB ULPI driver to fix some USB ports --- arm-read_current_timer.patch | 39 ++++++++++++++++++++++++++++++++++++ config-arm-generic | 2 ++ kernel.spec | 6 ++++++ 3 files changed, 47 insertions(+) create mode 100644 arm-read_current_timer.patch diff --git a/arm-read_current_timer.patch b/arm-read_current_timer.patch new file mode 100644 index 000000000..dc6a4447d --- /dev/null +++ b/arm-read_current_timer.patch @@ -0,0 +1,39 @@ +read_current_timer is used in the get_cycles() function when +ARM_ARCH_TIMER is set, and that function can be inlined into +driver modules, so we should export the function to avoid +errors like + +ERROR: "read_current_timer" [drivers/video/udlfb.ko] undefined! +ERROR: "read_current_timer" [crypto/tcrypt.ko] undefined! + +Signed-off-by: Arnd Bergmann +Cc: Shinya Kuribayashi +Cc: Stephen Boyd +Cc: Will Deacon +Cc: Russell King +--- + arch/arm/kernel/arch_timer.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c +index cf25880..6327d1f 100644 +--- a/arch/arm/kernel/arch_timer.c ++++ b/arch/arm/kernel/arch_timer.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -232,6 +233,7 @@ int read_current_timer(unsigned long *timer_val) + *timer_val = arch_counter_get_cntpct(); + return 0; + } ++EXPORT_SYMBOL_GPL(read_current_timer); + + static struct clocksource clocksource_counter = { + .name = "arch_sys_counter", +-- +1.7.10 diff --git a/config-arm-generic b/config-arm-generic index 31ebd9bfe..b75fc4203 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -88,6 +88,8 @@ CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_USB_ULPI=m + CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m CONFIG_SND_SOC=m diff --git a/kernel.spec b/kernel.spec index 390dae492..582e3f00c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -723,6 +723,7 @@ Patch14010: lis3-improve-handling-of-null-rate.patch # ARM +Patch21000: arm-read_current_timer.patch # OMAP # ARM tegra @@ -1312,6 +1313,7 @@ ApplyPatch team-net-next-20120808.patch # # ARM # +ApplyPatch arm-read_current_timer.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch @@ -2305,6 +2307,10 @@ fi # ||----w | # || || %changelog +* Sat Aug 25 2012 Peter Robinson +- Add patch to fix build on ARM +- Enable USB ULPI driver to fix some USB ports + * Fri Aug 24 2012 Josh Boyer - 3.6.0-0.rc3.git1.1 - Linux v3.6-rc3-37-g2d809dc From d84e876a988af8ab610db29b145f231632039e09 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 27 Aug 2012 09:28:10 -0400 Subject: [PATCH 011/492] Linux v3.6-rc3-177-gc182ae4 --- kernel.spec | 5 ++- modsign-20120816.patch | 86 +++++++++++++++++++++--------------------- sources | 2 +- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/kernel.spec b/kernel.spec index 582e3f00c..20aa14ce6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 3 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2307,6 +2307,9 @@ fi # ||----w | # || || %changelog +* Mon Aug 27 2012 Josh Boyer - 3.6.0-0.rc3.git2.1 +- Linux v3.6-rc3-177-gc182ae4 + * Sat Aug 25 2012 Peter Robinson - Add patch to fix build on ARM - Enable USB ULPI driver to fix some USB ports diff --git a/modsign-20120816.patch b/modsign-20120816.patch index 886e313c8..3c679558d 100644 --- a/modsign-20120816.patch +++ b/modsign-20120816.patch @@ -6161,10 +6161,10 @@ index 7531ecd..c93b62b 100644 #define Elf_Mips_Rel Elf64_Mips_Rel #define Elf_Mips_Rela Elf64_Mips_Rela diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c -index a5066b1..1500c80 100644 +index 4f8c3cb..9f102cf 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c -@@ -299,6 +299,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, +@@ -324,6 +324,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, return 0; } @@ -6172,7 +6172,7 @@ index a5066b1..1500c80 100644 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) -@@ -338,6 +339,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, +@@ -363,6 +364,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, return 0; } @@ -6766,18 +6766,6 @@ Signed-off-by: David Howells create mode 100644 arch/mips/kernel/module-rela.c create mode 100644 arch/mips/kernel/module.h -diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile -index fdaf65e..cd1e6c2 100644 ---- a/arch/mips/kernel/Makefile -+++ b/arch/mips/kernel/Makefile -@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o - - obj-$(CONFIG_STACKTRACE) += stacktrace.o - obj-$(CONFIG_MODULES) += mips_ksyms.o module.o -+obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o - - obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o - diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c new file mode 100644 index 0000000..4e784a8 @@ -6928,8 +6916,38 @@ index 0000000..4e784a8 + + return 0; +} +diff --git a/arch/mips/kernel/module.h b/arch/mips/kernel/module.h +new file mode 100644 +index 0000000..675d091 +--- /dev/null ++++ b/arch/mips/kernel/module.h +@@ -0,0 +1,12 @@ ++/* Internal definitions for MIPS module code ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++/* ++ * module.c ++ */ ++extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v); +diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile +index fdaf65e..cd1e6c2 100644 +--- a/arch/mips/kernel/Makefile ++++ b/arch/mips/kernel/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o + + obj-$(CONFIG_STACKTRACE) += stacktrace.o + obj-$(CONFIG_MODULES) += mips_ksyms.o module.o ++obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o + + obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o + diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c -index 1500c80..74a7197 100644 +index 9f102cf..e7dc80b 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -30,6 +30,7 @@ @@ -6940,7 +6958,7 @@ index 1500c80..74a7197 100644 #include /* MODULE_START */ -@@ -53,7 +54,7 @@ void *module_alloc(unsigned long size) +@@ -51,7 +52,7 @@ void *module_alloc(unsigned long size) } #endif @@ -6949,7 +6967,7 @@ index 1500c80..74a7197 100644 { return 0; } -@@ -65,13 +66,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) +@@ -63,13 +64,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) return 0; } @@ -6963,7 +6981,7 @@ index 1500c80..74a7197 100644 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) { if (v % 4) { -@@ -93,26 +87,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) +@@ -91,26 +85,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) return 0; } @@ -6990,7 +7008,7 @@ index 1500c80..74a7197 100644 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) { struct mips_hi16 *n; -@@ -134,14 +108,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) +@@ -132,14 +106,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) return 0; } @@ -7002,10 +7020,10 @@ index 1500c80..74a7197 100644 - return 0; -} - - static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) + static void free_relocation_chain(struct mips_hi16 *l) { - unsigned long insnlo = *location; -@@ -206,38 +172,6 @@ out_danger: + struct mips_hi16 *next; +@@ -217,38 +183,6 @@ out_danger: return -ENOEXEC; } @@ -7044,7 +7062,7 @@ index 1500c80..74a7197 100644 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, Elf_Addr v) = { [R_MIPS_NONE] = apply_r_mips_none, -@@ -247,18 +181,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, +@@ -258,18 +192,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, [R_MIPS_LO16] = apply_r_mips_lo16_rel }; @@ -7063,7 +7081,7 @@ index 1500c80..74a7197 100644 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) -@@ -299,48 +221,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, +@@ -324,48 +246,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, return 0; } @@ -7112,24 +7130,6 @@ index 1500c80..74a7197 100644 /* Given an address, look for it in the module exception tables. */ const struct exception_table_entry *search_module_dbetables(unsigned long addr) { -diff --git a/arch/mips/kernel/module.h b/arch/mips/kernel/module.h -new file mode 100644 -index 0000000..675d091 ---- /dev/null -+++ b/arch/mips/kernel/module.h -@@ -0,0 +1,12 @@ -+/* Internal definitions for MIPS module code -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+/* -+ * module.c -+ */ -+extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v); -- 1.7.11.4 diff --git a/sources b/sources index 549237e70..29eeabe8c 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz -54f94117e623519f4936936325b52fad patch-3.6-rc3-git1.xz +3574d21ac219aa09dff8422d1a1484f1 patch-3.6-rc3-git2.xz From a0ebafd828bd571f3ac827b359c61b7c5df981ef Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 28 Aug 2012 22:57:38 +0100 Subject: [PATCH 012/492] Add patches to fix OMAP drm, radio shark, tweak ARM config --- arm-fix-omapdrm.patch | 10 ++++++++++ arm-fix_radio_shark.patch | 15 +++++++++++++++ config-arm-generic | 3 ++- config-arm-tegra | 2 +- kernel.spec | 8 ++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 arm-fix-omapdrm.patch create mode 100644 arm-fix_radio_shark.patch diff --git a/arm-fix-omapdrm.patch b/arm-fix-omapdrm.patch new file mode 100644 index 000000000..f70b861fa --- /dev/null +++ b/arm-fix-omapdrm.patch @@ -0,0 +1,10 @@ +--- linux-3.6.0-0.rc3.git2.1.fc18.x86_64/drivers/staging/omapdrm/omap_drv.c.orig 2012-08-28 22:52:35.950826671 +0100 ++++ linux-3.6.0-0.rc3.git2.1.fc18.x86_64/drivers/staging/omapdrm/omap_drv.c 2012-08-28 22:52:49.393910353 +0100 +@@ -761,7 +761,6 @@ + .irq_postinstall = dev_irq_postinstall, + .irq_uninstall = dev_irq_uninstall, + .irq_handler = dev_irq_handler, +- .reclaim_buffers = drm_core_reclaim_buffers, + #ifdef CONFIG_DEBUG_FS + .debugfs_init = omap_debugfs_init, + .debugfs_cleanup = omap_debugfs_cleanup, diff --git a/arm-fix_radio_shark.patch b/arm-fix_radio_shark.patch new file mode 100644 index 000000000..63296a90e --- /dev/null +++ b/arm-fix_radio_shark.patch @@ -0,0 +1,15 @@ +diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig +index ff3af6e..f99fa25 100644 +--- a/sound/pci/Kconfig ++++ b/sound/pci/Kconfig +@@ -2,8 +2,8 @@ + + config SND_TEA575X + tristate +- depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO +- default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO ++ depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK ++ default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK + + menuconfig SND_PCI + bool "PCI sound devices" diff --git a/config-arm-generic b/config-arm-generic index b75fc4203..fca13551a 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -37,6 +37,7 @@ CONFIG_USE_OF=y # CONFIG_OF_SELFTEST is not set CONFIG_PROC_DEVICETREE=y CONFIG_ARM_APPENDED_DTB=y +CONFIG_I2C_MUX_PINCTRL=m # Generic options we want for ARM that aren't defualt CONFIG_HIGHMEM=y @@ -88,7 +89,7 @@ CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m -CONFIG_USB_ULPI=m +CONFIG_USB_ULPI=y CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m diff --git a/config-arm-tegra b/config-arm-tegra index 870ddc526..a754dd6ba 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -8,7 +8,7 @@ CONFIG_TEGRA_PCI=y CONFIG_VFP=y CONFIG_VFPv3=y -CONFIG_MACH_HARMONY=y +# CONFIG_MACH_HARMONY is not set CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y CONFIG_MACH_SEABOARD=y diff --git a/kernel.spec b/kernel.spec index 20aa14ce6..61bfbab4d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -724,6 +724,8 @@ Patch14010: lis3-improve-handling-of-null-rate.patch # ARM Patch21000: arm-read_current_timer.patch +Patch21001: arm-fix-omapdrm.patch +Patch21002: arm-fix_radio_shark.patch # OMAP # ARM tegra @@ -1314,6 +1316,8 @@ ApplyPatch team-net-next-20120808.patch # ARM # ApplyPatch arm-read_current_timer.patch +ApplyPatch arm-fix-omapdrm.patch +ApplyPatch arm-fix_radio_shark.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch @@ -2307,6 +2311,10 @@ fi # ||----w | # || || %changelog +* Tue Aug 28 2012 Peter Robinson +- Add patches to fix OMAP drm, radio shark +- Tweak ARM config + * Mon Aug 27 2012 Josh Boyer - 3.6.0-0.rc3.git2.1 - Linux v3.6-rc3-177-gc182ae4 From a986da8f1e460e8af4be09e4e071cb944b2db08a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 29 Aug 2012 17:21:41 -0400 Subject: [PATCH 013/492] Linux v3.6-rc3-207-g318e151 --- kernel.spec | 5 ++++- sources | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 61bfbab4d..d7a4c1aa3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 3 # The git snapshot level -%define gitrev 2 +%define gitrev 3 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2311,6 +2311,9 @@ fi # ||----w | # || || %changelog +* Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.1 +- Linux v3.6-rc3-207-g318e151 + * Tue Aug 28 2012 Peter Robinson - Add patches to fix OMAP drm, radio shark - Tweak ARM config diff --git a/sources b/sources index 29eeabe8c..7eaf96700 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz -3574d21ac219aa09dff8422d1a1484f1 patch-3.6-rc3-git2.xz +2ca57532b660df2da97fe47ce69c8491 patch-3.6-rc3-git3.xz From a8b9080b42f2673f2dd63003021cbb730cf43ea0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 29 Aug 2012 17:26:05 -0400 Subject: [PATCH 014/492] Add patch to fix USB audio regression (rhbz 851619) --- ...Fix-URB-cancellation-at-stream-start.patch | 131 ++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch diff --git a/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch b/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch new file mode 100644 index 000000000..031888c3c --- /dev/null +++ b/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch @@ -0,0 +1,131 @@ +From 42ff3e2d34427dc4c6faa09052a2531f2e71d7d6 Mon Sep 17 00:00:00 2001 +From: Daniel Mack +Date: Wed, 29 Aug 2012 13:17:05 +0200 +Subject: [PATCH] ALSA: snd-usb: Fix URB cancellation at stream start + +Commit e9ba389c5 ("ALSA: usb-audio: Fix scheduling-while-atomic bug in +PCM capture stream") fixed a scheduling-while-atomic bug that happened +when snd_usb_endpoint_start was called from the trigger callback, which +is an atmic context. However, the patch breaks the idea of the endpoints +reference counting, which is the reason why the driver has been +refactored lately. + +Revert that commit and let snd_usb_endpoint_start() take care of the URB +cancellation again. As this function is called from both atomic and +non-atomic context, add a flag to denote whether the function may sleep. + +Signed-off-by: Daniel Mack +Cc: stable@kernel.org [3.5+] +--- + sound/usb/endpoint.c | 11 +++++++++-- + sound/usb/endpoint.h | 2 +- + sound/usb/pcm.c | 13 +++++-------- + 3 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index c411812..b896c55 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -799,7 +799,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + /** + * snd_usb_endpoint_start: start an snd_usb_endpoint + * +- * @ep: the endpoint to start ++ * @ep: the endpoint to start ++ * @can_sleep: flag indicating whether the operation is executed in ++ * non-atomic context + * + * A call to this function will increment the use count of the endpoint. + * In case it is not already running, the URBs for this endpoint will be +@@ -809,7 +811,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + * + * Returns an error if the URB submission failed, 0 in all other cases. + */ +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) + { + int err; + unsigned int i; +@@ -821,6 +823,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + if (++ep->use_count != 1) + return 0; + ++ /* just to be sure */ ++ deactivate_urbs(ep, 0, can_sleep); ++ if (can_sleep) ++ wait_clear_urbs(ep); ++ + ep->active_mask = 0; + ep->unlink_mask = 0; + ep->phase = 0; +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index ee2723f..a8e60c1 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + struct audioformat *fmt, + struct snd_usb_endpoint *sync_ep); + +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); + void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 62ec808..1546577 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, + } + } + +-static int start_endpoints(struct snd_usb_substream *subs) ++static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) + { + int err; + +@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs) + snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); + + ep->data_subs = subs; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); + return err; +@@ -239,7 +239,7 @@ static int start_endpoints(struct snd_usb_substream *subs) + snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + + ep->sync_slave = subs->data_endpoint; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); + return err; +@@ -544,13 +544,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + subs->last_frame_number = 0; + runtime->delay = 0; + +- /* clear the pending deactivation on the target EPs */ +- deactivate_endpoints(subs); +- + /* for playback, submit the URBs now; otherwise, the first hwptr_done + * updates for all URBs would happen at the same time when starting */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) +- return start_endpoints(subs); ++ return start_endpoints(subs, 1); + + return 0; + } +@@ -1175,7 +1172,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- err = start_endpoints(subs); ++ err = start_endpoints(subs, 0); + if (err < 0) + return err; + +-- +1.7.11.4 + diff --git a/kernel.spec b/kernel.spec index d7a4c1aa3..187e2e2cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -753,6 +753,8 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +Patch30000: 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch + # END OF PATCH DEFINITIONS %endif @@ -1449,6 +1451,8 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +ApplyPatch 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch + # END OF PATCH APPLICATIONS %endif @@ -2311,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.2 +- Add patch to fix USB audio regression (rhbz 851619) + * Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.1 - Linux v3.6-rc3-207-g318e151 From 511a194649682d8149a50d52dd0f0aa0517f0538 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 30 Aug 2012 16:59:03 -0400 Subject: [PATCH 015/492] Linux v3.6-rc3-230-g155e36d --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 187e2e2cb..5f5b6f663 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 3 # The git snapshot level -%define gitrev 3 +%define gitrev 4 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 30 2012 Josh Boyer - 3.6.0-0.rc3.git4.1 +- Linux v3.6-rc3-230-g155e36d + * Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.2 - Add patch to fix USB audio regression (rhbz 851619) diff --git a/sources b/sources index 7eaf96700..e147bfc3f 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz -2ca57532b660df2da97fe47ce69c8491 patch-3.6-rc3-git3.xz +a2f097658324024549d8c5a4e5a3bde5 patch-3.6-rc3-git4.xz From 864f675e66c2a9e0416d89b2d93b55675206bf2a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Sep 2012 09:42:53 -0400 Subject: [PATCH 016/492] Linux v3.6-rc4 - Disable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 12 +++-- sources | 3 +- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/config-generic b/config-generic index d6cb2b7e9..e811d83a2 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 5f5b6f663..4b2c975a6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 3 +%define rcrev 4 # The git snapshot level -%define gitrev 4 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2315,6 +2315,10 @@ fi # ||----w | # || || %changelog +* Mon Sep 03 2012 Josh Boyer - 3.6.0-0.rc4.git0.1 +- Linux v3.6-rc4 +- Disable debugging options. + * Thu Aug 30 2012 Josh Boyer - 3.6.0-0.rc3.git4.1 - Linux v3.6-rc3-230-g155e36d diff --git a/sources b/sources index e147bfc3f..6d42899fe 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -b67720c4ba8e3d5029e87d3210bf4a59 patch-3.6-rc3.xz -a2f097658324024549d8c5a4e5a3bde5 patch-3.6-rc3-git4.xz +85a05f267b2a883d0a444f3f2f91ec0b patch-3.6-rc4.xz From f82afd7d3de242b1d4542fd4f389e2aa7614fd16 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 4 Sep 2012 08:32:15 +0100 Subject: [PATCH 017/492] Tweak OMAP options --- config-arm-omap | 11 ++++++----- kernel.spec | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/config-arm-omap b/config-arm-omap index 36041f82d..b44a44590 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -145,6 +145,7 @@ CONFIG_PM_OPP=y # # OMAP Hardware # +CONFIG_WL_TI=y CONFIG_TI_ST=m CONFIG_GPIOLIB=y CONFIG_MTD_NAND_OMAP2=y @@ -162,18 +163,18 @@ CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_OMAP_WATCHDOG=y CONFIG_TWL4030_CORE=y -# CONFIG_TWL4030_MADC is not set +CONFIG_TWL4030_MADC=m CONFIG_TWL4030_POWER=y CONFIG_TWL4030_CODEC=y CONFIG_GPIO_TWL4030=m CONFIG_CHARGER_TWL4030=m -# CONFIG_TWL6030_PWM is not set +CONFIG_TWL6030_PWM=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_I2C_OMAP=y CONFIG_SPI_OMAP24XX=y -# CONFIG_MFD_OMAP_USB_HOST is not set -# CONFIG_MFD_WL1273_CORE is not set +CONFIG_MFD_OMAP_USB_HOST=m +CONFIG_MFD_WL1273_CORE=m CONFIG_REGULATOR_TWL4030=y CONFIG_VIDEO_OMAP2_VOUT=m # CONFIG_VIDEO_OMAP3 is not set @@ -236,7 +237,7 @@ CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD_OMAP=y CONFIG_USB_MUSB_OMAP2PLUS=y CONFIG_USB_MUSB_HDRC=y -CONFIG_MUSB_PIO_ONLY=y +# CONFIG_MUSB_PIO_ONLY is not set # CONFIG_USB_MUSB_DEBUG is not set # diff --git a/kernel.spec b/kernel.spec index 4b2c975a6..7c7a52597 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 4 2012 Peter Robinson +- Tweak OMAP options + * Mon Sep 03 2012 Josh Boyer - 3.6.0-0.rc4.git0.1 - Linux v3.6-rc4 - Disable debugging options. From e681abd972ba6711108fd20eeded2a60407aea7e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:31:54 -0400 Subject: [PATCH 018/492] handle-efi-roms.patch: Improve PCI support on UEFI systems --- handle-efi-roms.patch | 458 ++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 + 2 files changed, 467 insertions(+) create mode 100644 handle-efi-roms.patch diff --git a/handle-efi-roms.patch b/handle-efi-roms.patch new file mode 100644 index 000000000..7f02a1c3d --- /dev/null +++ b/handle-efi-roms.patch @@ -0,0 +1,458 @@ +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c 2012-08-22 15:26:32.485522068 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c 2012-08-22 15:25:40.529244868 -0400 +@@ -8,6 +8,7 @@ + * ----------------------------------------------------------------------- */ + + #include ++#include + #include + #include + #include +@@ -243,6 +244,121 @@ + *size = len; + } + ++static efi_status_t setup_efi_pci(struct boot_params *params) ++{ ++ efi_pci_io_protocol *pci; ++ efi_status_t status; ++ void **pci_handle; ++ efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; ++ unsigned long nr_pci, size = 0; ++ int i; ++ struct setup_data *data; ++ ++ data = (struct setup_data *)params->hdr.setup_data; ++ ++ while (data && data->next) ++ data = (struct setup_data *)data->next; ++ ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, &pci_proto, ++ NULL, &size, pci_handle); ++ ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, size, &pci_handle); ++ ++ if (status != EFI_SUCCESS) ++ return status; ++ ++ status = efi_call_phys5(sys_table->boottime->locate_handle, ++ EFI_LOCATE_BY_PROTOCOL, &pci_proto, ++ NULL, &size, pci_handle); ++ } ++ ++ if (status != EFI_SUCCESS) ++ goto free_handle; ++ ++ nr_pci = size / sizeof(void *); ++ for (i = 0; i < nr_pci; i++) { ++ void *h = pci_handle[i]; ++ uint64_t attributes; ++ struct pci_setup_rom *rom; ++ ++ status = efi_call_phys3(sys_table->boottime->handle_protocol, ++ h, &pci_proto, &pci); ++ ++ if (status != EFI_SUCCESS) ++ continue; ++ ++ if (!pci) ++ continue; ++ ++ status = efi_call_phys4(pci->attributes, pci, ++ EfiPciIoAttributeOperationGet, 0, ++ &attributes); ++ ++ if (status != EFI_SUCCESS) ++ continue; ++ ++ if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ++ continue; ++ ++ if (!pci->romimage || !pci->romsize) ++ continue; ++ ++ size = pci->romsize + sizeof(*rom); ++ ++ status = efi_call_phys3(sys_table->boottime->allocate_pool, ++ EFI_LOADER_DATA, size, &rom); ++ ++ if (status != EFI_SUCCESS) ++ continue; ++ ++ rom->data.type = SETUP_PCI; ++ rom->data.len = size - sizeof(struct setup_data); ++ rom->data.next = NULL; ++ rom->pcilen = pci->romsize; ++ ++ status = efi_call_phys5(pci->pci.read, pci, ++ EfiPciIoWidthUint16, PCI_VENDOR_ID, ++ 1, &(rom->vendor)); ++ ++ if (status != EFI_SUCCESS) ++ goto free_struct; ++ ++ status = efi_call_phys5(pci->pci.read, pci, ++ EfiPciIoWidthUint16, PCI_DEVICE_ID, ++ 1, &(rom->devid)); ++ ++ if (status != EFI_SUCCESS) ++ goto free_struct; ++ ++ status = efi_call_phys5(pci->get_location, pci, ++ &(rom->segment), &(rom->bus), ++ &(rom->device), &(rom->function)); ++ ++ if (status != EFI_SUCCESS) ++ goto free_struct; ++ ++ memcpy(rom->romdata, pci->romimage, pci->romsize); ++ ++ if (data) ++ data->next = (uint64_t)rom; ++ else ++ params->hdr.setup_data = (uint64_t)rom; ++ ++ data = (struct setup_data *)rom; ++ ++ continue; ++ free_struct: ++ efi_call_phys1(sys_table->boottime->free_pool, rom); ++ } ++ ++free_handle: ++ efi_call_phys1(sys_table->boottime->free_pool, pci_handle); ++ return status; ++} ++ + /* + * See if we have Graphics Output Protocol + */ +@@ -276,8 +392,9 @@ + nr_gops = size / sizeof(void *); + for (i = 0; i < nr_gops; i++) { + struct efi_graphics_output_mode_info *info; +- efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; +- void *pciio; ++ efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; ++ bool conout_found = false; ++ void *dummy; + void *h = gop_handle[i]; + + status = efi_call_phys3(sys_table->boottime->handle_protocol, +@@ -285,19 +402,21 @@ + if (status != EFI_SUCCESS) + continue; + +- efi_call_phys3(sys_table->boottime->handle_protocol, +- h, &pciio_proto, &pciio); ++ status = efi_call_phys3(sys_table->boottime->handle_protocol, ++ h, &conout_proto, &dummy); ++ ++ if (status == EFI_SUCCESS) ++ conout_found = true; + + status = efi_call_phys4(gop->query_mode, gop, + gop->mode->mode, &size, &info); +- if (status == EFI_SUCCESS && (!first_gop || pciio)) { ++ if (status == EFI_SUCCESS && (!first_gop || conout_found)) { + /* +- * Apple provide GOPs that are not backed by +- * real hardware (they're used to handle +- * multiple displays). The workaround is to +- * search for a GOP implementing the PCIIO +- * protocol, and if one isn't found, to just +- * fallback to the first GOP. ++ * Systems that use the UEFI Console Splitter may ++ * provide multiple GOP devices, not all of which are ++ * backed by real hardware. The workaround is to search ++ * for a GOP implementing the ConOut protocol, and if ++ * one isn't found, to just fall back to the first GOP. + */ + width = info->horizontal_resolution; + height = info->vertical_resolution; +@@ -308,10 +427,10 @@ + pixels_per_scan_line = info->pixels_per_scan_line; + + /* +- * Once we've found a GOP supporting PCIIO, ++ * Once we've found a GOP supporting ConOut, + * don't bother looking any further. + */ +- if (pciio) ++ if (conout_found) + break; + + first_gop = gop; +@@ -1052,6 +1171,8 @@ + + setup_graphics(boot_params); + ++ setup_efi_pci(boot_params); ++ + status = efi_call_phys3(sys_table->boottime->allocate_pool, + EFI_LOADER_DATA, sizeof(*gdt), + (void **)&gdt); +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-07-21 16:58:29.000000000 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-08-22 15:25:40.530244882 -0400 +@@ -14,6 +14,10 @@ + #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) + #define EFI_READ_CHUNK_SIZE (1024 * 1024) + ++#define EFI_CONSOLE_OUT_DEVICE_GUID \ ++ EFI_GUID( 0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ ++ 0x3f, 0xc1, 0x4d ) ++ + #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 + #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 + #define PIXEL_BIT_MASK 2 +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:26:32.485522068 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:25:40.530244882 -0400 +@@ -13,6 +13,7 @@ + #define SETUP_NONE 0 + #define SETUP_E820_EXT 1 + #define SETUP_DTB 2 ++#define SETUP_PCI 3 + + /* extensible setup data list node */ + struct setup_data { +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h 2012-07-21 16:58:29.000000000 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h 2012-08-22 15:25:40.530244882 -0400 +@@ -171,4 +171,16 @@ + } + #endif + ++struct pci_setup_rom { ++ struct setup_data data; ++ uint16_t vendor; ++ uint16_t devid; ++ uint64_t pcilen; ++ unsigned long segment; ++ unsigned long bus; ++ unsigned long device; ++ unsigned long function; ++ uint8_t romdata[0]; ++}; ++ + #endif /* _ASM_X86_PCI_H */ +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c 2012-08-22 15:24:45.477951182 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c 2012-08-22 15:25:40.530244882 -0400 +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | + PCI_PROBE_MMCONF; +@@ -608,6 +609,38 @@ + return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; + } + ++int pcibios_add_device(struct pci_dev *dev) ++{ ++ struct setup_data *data; ++ struct pci_setup_rom *rom; ++ u64 pa_data; ++ ++ if (boot_params.hdr.version < 0x0209) ++ return 0; ++ ++ pa_data = boot_params.hdr.setup_data; ++ while (pa_data) { ++ data = phys_to_virt(pa_data); ++ ++ if (data->type == SETUP_PCI) { ++ rom = (struct pci_setup_rom *)data; ++ ++ if ((pci_domain_nr(dev->bus) == rom->segment) && ++ (dev->bus->number == rom->bus) && ++ (PCI_SLOT(dev->devfn) == rom->device) && ++ (PCI_FUNC(dev->devfn) == rom->function) && ++ (dev->vendor == rom->vendor) && ++ (dev->device == rom->devid)) { ++ dev->rom = (void *)(pa_data + ++ offsetof(struct pci_setup_rom, romdata)); ++ dev->romlen = rom->pcilen; ++ } ++ } ++ pa_data = data->next; ++ } ++ return 0; ++} ++ + int pcibios_enable_device(struct pci_dev *dev, int mask) + { + int err; +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c 2012-08-22 15:24:47.425961575 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c 2012-08-22 15:26:20.147456241 -0400 +@@ -166,6 +166,11 @@ + int retval; + + pci_fixup_device(pci_fixup_final, dev); ++ ++ retval = pcibios_add_device(dev); ++ if (retval) ++ return retval; ++ + retval = device_add(&dev->dev); + if (retval) + return retval; +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c 2012-08-22 15:24:47.432961612 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c 2012-08-22 15:25:40.531244893 -0400 +@@ -1385,6 +1385,19 @@ + dr->pinned = 1; + } + ++/* ++ * pcibios_add_device - provide arch specific hooks when adding device dev ++ * @dev: the PCI device being added ++ * ++ * Permits the platform to provide architecture specific functionality when ++ * devices are added. This is the default implementation. Architecture ++ * implementations can override this. ++ */ ++int __attribute__ ((weak)) pcibios_add_device (struct pci_dev *dev) ++{ ++ return 0; ++} ++ + /** + * pcibios_disable_device - disable arch specific PCI resources for device dev + * @dev: the PCI device to disable +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-07-21 16:58:29.000000000 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-08-22 15:25:40.531244893 -0400 +@@ -126,6 +126,12 @@ + /* primary video rom always starts here */ + start = (loff_t)0xC0000; + *size = 0x20000; /* cover C000:0 through E000:0 */ ++ /* ++ * Some devices may provide ROMs via a source other than the BAR ++ */ ++ } else if (pdev->rom && pdev->romlen) { ++ *size = pdev->romlen; ++ return phys_to_virt(pdev->rom); + } else { + if (res->flags & + (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { +@@ -219,7 +225,8 @@ + if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) + return; + +- iounmap(rom); ++ if (!pdev->rom || !pdev->romlen) ++ iounmap(rom); + + /* Disable again before continuing, leave enabled if pci=rom */ + if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h 2012-08-22 15:24:49.550972911 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h 2012-08-22 15:25:40.533244906 -0400 +@@ -196,6 +196,77 @@ + void *create_event_ex; + } efi_boot_services_t; + ++typedef enum { ++ EfiPciIoWidthUint8, ++ EfiPciIoWidthUint16, ++ EfiPciIoWidthUint32, ++ EfiPciIoWidthUint64, ++ EfiPciIoWidthFifoUint8, ++ EfiPciIoWidthFifoUint16, ++ EfiPciIoWidthFifoUint32, ++ EfiPciIoWidthFifoUint64, ++ EfiPciIoWidthFillUint8, ++ EfiPciIoWidthFillUint16, ++ EfiPciIoWidthFillUint32, ++ EfiPciIoWidthFillUint64, ++ EfiPciIoWidthMaximum ++} EFI_PCI_IO_PROTOCOL_WIDTH; ++ ++typedef enum { ++ EfiPciIoAttributeOperationGet, ++ EfiPciIoAttributeOperationSet, ++ EfiPciIoAttributeOperationEnable, ++ EfiPciIoAttributeOperationDisable, ++ EfiPciIoAttributeOperationSupported, ++ EfiPciIoAttributeOperationMaximum ++} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; ++ ++ ++typedef struct { ++ void *read; ++ void *write; ++} efi_pci_io_protocol_access_t; ++ ++typedef struct { ++ void *poll_mem; ++ void *poll_io; ++ efi_pci_io_protocol_access_t mem; ++ efi_pci_io_protocol_access_t io; ++ efi_pci_io_protocol_access_t pci; ++ void *copy_mem; ++ void *map; ++ void *unmap; ++ void *allocate_buffer; ++ void *free_buffer; ++ void *flush; ++ void *get_location; ++ void *attributes; ++ void *get_bar_attributes; ++ void *set_bar_attributes; ++ uint64_t romsize; ++ void *romimage; ++} efi_pci_io_protocol; ++ ++#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 ++#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 ++#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 ++#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 ++#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 ++#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 ++#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 ++#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 ++#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 ++#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 ++#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 ++#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 ++#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ++#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 ++#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 ++#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 ++#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 ++#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 ++#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 ++ + /* + * Types and defines for EFI ResetSystem + */ +diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h +--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h 2012-08-22 15:24:48.703968392 -0400 ++++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h 2012-08-22 15:25:40.534244910 -0400 +@@ -355,6 +355,8 @@ + }; + struct pci_ats *ats; /* Address Translation Service */ + #endif ++ void *rom; /* Physical pointer to ROM if it's not from the BAR */ ++ size_t romlen; /* Length of ROM if it's not from the BAR */ + }; + + static inline struct pci_dev *pci_physfn(struct pci_dev *dev) +@@ -1582,6 +1584,7 @@ + void pcibios_set_master(struct pci_dev *dev); + int pcibios_set_pcie_reset_state(struct pci_dev *dev, + enum pcie_reset_state state); ++int pcibios_add_device(struct pci_dev *dev); + + #ifdef CONFIG_PCI_MMCONFIG + extern void __init pci_mmcfg_early_init(void); diff --git a/kernel.spec b/kernel.spec index 7c7a52597..e91f29754 100644 --- a/kernel.spec +++ b/kernel.spec @@ -683,6 +683,9 @@ Patch900: modsign-20120816.patch # secure boot Patch1000: secure-boot-20120809.patch +# Improve PCI support on UEFI +Patch1100: handle-efi-roms.patch + # virt + ksm patches Patch1555: fix_xen_guest_on_old_EC2.patch @@ -1395,6 +1398,9 @@ ApplyPatch modsign-20120816.patch # secure boot ApplyPatch secure-boot-20120809.patch +# Improved PCI support for UEFI +ApplyPatch handle-efi-roms.patch + # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch @@ -2315,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 4 2012 Matthew Garrett +- handle-efi-roms.patch: Improve PCI support on UEFI systems + * Tue Sep 4 2012 Peter Robinson - Tweak OMAP options From 3fa60a7bf3f868aa6fa8d9b6736df3e0f9d50e7d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 5 Sep 2012 08:21:09 -0400 Subject: [PATCH 019/492] Reenable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 9 ++-- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/config-generic b/config-generic index e811d83a2..d6cb2b7e9 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index 5b4187680..d99deeb2f 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set -# CONFIG_FAIL_MMC_REQUEST is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_NFSD_FAULT_INJECTION=y -# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_DEBUG_BLK_CGROUP=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index de9582a01..ad22edd8d 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_MAXSMP is not set +CONFIG_MAXSMP=y CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index e91f29754..a157e0ea4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2321,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git0.2 +- Reenable debugging options. + * Tue Sep 4 2012 Matthew Garrett - handle-efi-roms.patch: Improve PCI support on UEFI systems From 34884fe77f1d4d7a79bed66aeb45d0ea0e6012d6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 5 Sep 2012 08:24:45 -0400 Subject: [PATCH 020/492] Linux v3.6-rc4-53-g5b716ac - Add patch to fix ibmveth issue from Santiago Leon (rhbz 852842) --- ibmveth-Fix-alignment-of-rx-queue-bug.patch | 80 +++++++++++++++++++++ kernel.spec | 14 +++- sources | 1 + 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 ibmveth-Fix-alignment-of-rx-queue-bug.patch diff --git a/ibmveth-Fix-alignment-of-rx-queue-bug.patch b/ibmveth-Fix-alignment-of-rx-queue-bug.patch new file mode 100644 index 000000000..79353a61c --- /dev/null +++ b/ibmveth-Fix-alignment-of-rx-queue-bug.patch @@ -0,0 +1,80 @@ +This patch fixes a bug found by Nish Aravamudan +(https://lkml.org/lkml/2012/5/15/220) where the driver is not following +the spec (it is not aligning the rx buffer on a 16-byte boundary) and the +hypervisor aborts the registration, making the device unusable. + +The fix follows BenH's recommendation (https://lkml.org/lkml/2012/7/20/461) +to replace the kmalloc+map for a single call to dma_alloc_coherent() +because that function always aligns to a 16-byte boundary. + +The stable trees will run into this bug whenever the rx buffer kmalloc call +returns something not aligned on a 16-byte boundary. + +Cc: +Signed-off-by: Santiago Leon +--- + ibmveth.c | 26 +++++++++----------------- + 1 file changed, 9 insertions(+), 17 deletions(-) + +--- a/drivers/net/ethernet/ibm/ibmveth.c 2012-07-09 16:00:53.000000000 -0400 ++++ b/drivers/net/ethernet/ibm/ibmveth.c 2012-08-17 19:51:02.840000188 -0400 +@@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmve + } + + if (adapter->rx_queue.queue_addr != NULL) { +- if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { +- dma_unmap_single(dev, +- adapter->rx_queue.queue_dma, +- adapter->rx_queue.queue_len, +- DMA_BIDIRECTIONAL); +- adapter->rx_queue.queue_dma = DMA_ERROR_CODE; +- } +- kfree(adapter->rx_queue.queue_addr); ++ dma_free_coherent(dev, adapter->rx_queue.queue_len, ++ adapter->rx_queue.queue_addr, ++ adapter->rx_queue.queue_dma); + adapter->rx_queue.queue_addr = NULL; + } + +@@ -556,10 +551,13 @@ static int ibmveth_open(struct net_devic + goto err_out; + } + ++ dev = &adapter->vdev->dev; ++ + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * + rxq_entries; +- adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, +- GFP_KERNEL); ++ adapter->rx_queue.queue_addr = ++ dma_alloc_coherent(dev, adapter->rx_queue.queue_len, ++ &adapter->rx_queue.queue_dma, GFP_KERNEL); + + if (!adapter->rx_queue.queue_addr) { + netdev_err(netdev, "unable to allocate rx queue pages\n"); +@@ -567,19 +565,13 @@ static int ibmveth_open(struct net_devic + goto err_out; + } + +- dev = &adapter->vdev->dev; +- + adapter->buffer_list_dma = dma_map_single(dev, + adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); + adapter->filter_list_dma = dma_map_single(dev, + adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); +- adapter->rx_queue.queue_dma = dma_map_single(dev, +- adapter->rx_queue.queue_addr, +- adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); + + if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || +- (dma_mapping_error(dev, adapter->filter_list_dma)) || +- (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { ++ (dma_mapping_error(dev, adapter->filter_list_dma))) { + netdev_err(netdev, "unable to map filter or buffer list " + "pages\n"); + rc = -ENOMEM; + +-- +To unsubscribe from this list: send the line "unsubscribe netdev" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index a157e0ea4..b70854f54 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 4 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -756,6 +756,9 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 852842 +Patch22068: ibmveth-Fix-alignment-of-rx-queue-bug.patch + Patch30000: 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch # END OF PATCH DEFINITIONS @@ -1457,6 +1460,9 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 852842 +ApplyPatch ibmveth-Fix-alignment-of-rx-queue-bug.patch + ApplyPatch 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch # END OF PATCH APPLICATIONS @@ -2321,6 +2327,10 @@ fi # ||----w | # || || %changelog +* Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git1.1 +- Linux v3.6-rc4-53-g5b716ac +- Add patch to fix ibmveth issue from Santiago Leon (rhbz 852842) + * Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git0.2 - Reenable debugging options. diff --git a/sources b/sources index 6d42899fe..0c7e61629 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 85a05f267b2a883d0a444f3f2f91ec0b patch-3.6-rc4.xz +2f77d7e0612827bbcc097bcadf43a1ee patch-3.6-rc4-git1.xz From 7fd125ce03dfd957c8a527d44777d2a27996dd08 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 5 Sep 2012 14:20:56 -0400 Subject: [PATCH 021/492] Don't create empty include/linux/autoconf.h in kernel-devel (rhbz 854689) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index b70854f54..b8d81b5eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1701,7 +1701,7 @@ BuildKernel() { # Make sure the Makefile and version.h have a matching timestamp so that # external modules can be built touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Makefile $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/version.h - touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/autoconf.h + # Copy .config to include/config/auto.conf so "make prepare" is unnecessary. cp $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/config/auto.conf @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Wed Sep 05 2012 Dave Jones +- Don't create empty include/linux/autoconf.h in kernel-devel (rhbz 854689) + * Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git1.1 - Linux v3.6-rc4-53-g5b716ac - Add patch to fix ibmveth issue from Santiago Leon (rhbz 852842) From c878d6ce739759865c61d8f0fa36af31f2a740ff Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 7 Sep 2012 08:22:32 -0400 Subject: [PATCH 022/492] Linux v3.6-rc4-128-geeea3ac --- ...Fix-URB-cancellation-at-stream-start.patch | 131 ------------------ kernel.spec | 9 +- sources | 2 +- 3 files changed, 5 insertions(+), 137 deletions(-) delete mode 100644 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch diff --git a/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch b/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch deleted file mode 100644 index 031888c3c..000000000 --- a/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 42ff3e2d34427dc4c6faa09052a2531f2e71d7d6 Mon Sep 17 00:00:00 2001 -From: Daniel Mack -Date: Wed, 29 Aug 2012 13:17:05 +0200 -Subject: [PATCH] ALSA: snd-usb: Fix URB cancellation at stream start - -Commit e9ba389c5 ("ALSA: usb-audio: Fix scheduling-while-atomic bug in -PCM capture stream") fixed a scheduling-while-atomic bug that happened -when snd_usb_endpoint_start was called from the trigger callback, which -is an atmic context. However, the patch breaks the idea of the endpoints -reference counting, which is the reason why the driver has been -refactored lately. - -Revert that commit and let snd_usb_endpoint_start() take care of the URB -cancellation again. As this function is called from both atomic and -non-atomic context, add a flag to denote whether the function may sleep. - -Signed-off-by: Daniel Mack -Cc: stable@kernel.org [3.5+] ---- - sound/usb/endpoint.c | 11 +++++++++-- - sound/usb/endpoint.h | 2 +- - sound/usb/pcm.c | 13 +++++-------- - 3 files changed, 15 insertions(+), 11 deletions(-) - -diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c -index c411812..b896c55 100644 ---- a/sound/usb/endpoint.c -+++ b/sound/usb/endpoint.c -@@ -799,7 +799,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - /** - * snd_usb_endpoint_start: start an snd_usb_endpoint - * -- * @ep: the endpoint to start -+ * @ep: the endpoint to start -+ * @can_sleep: flag indicating whether the operation is executed in -+ * non-atomic context - * - * A call to this function will increment the use count of the endpoint. - * In case it is not already running, the URBs for this endpoint will be -@@ -809,7 +811,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - * - * Returns an error if the URB submission failed, 0 in all other cases. - */ --int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) -+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) - { - int err; - unsigned int i; -@@ -821,6 +823,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) - if (++ep->use_count != 1) - return 0; - -+ /* just to be sure */ -+ deactivate_urbs(ep, 0, can_sleep); -+ if (can_sleep) -+ wait_clear_urbs(ep); -+ - ep->active_mask = 0; - ep->unlink_mask = 0; - ep->phase = 0; -diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h -index ee2723f..a8e60c1 100644 ---- a/sound/usb/endpoint.h -+++ b/sound/usb/endpoint.h -@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep); - --int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); -+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); - void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, - int force, int can_sleep, int wait); - int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); -diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c -index 62ec808..1546577 100644 ---- a/sound/usb/pcm.c -+++ b/sound/usb/pcm.c -@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, - } - } - --static int start_endpoints(struct snd_usb_substream *subs) -+static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) - { - int err; - -@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs) - snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); - - ep->data_subs = subs; -- err = snd_usb_endpoint_start(ep); -+ err = snd_usb_endpoint_start(ep, can_sleep); - if (err < 0) { - clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); - return err; -@@ -239,7 +239,7 @@ static int start_endpoints(struct snd_usb_substream *subs) - snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); - - ep->sync_slave = subs->data_endpoint; -- err = snd_usb_endpoint_start(ep); -+ err = snd_usb_endpoint_start(ep, can_sleep); - if (err < 0) { - clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); - return err; -@@ -544,13 +544,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - subs->last_frame_number = 0; - runtime->delay = 0; - -- /* clear the pending deactivation on the target EPs */ -- deactivate_endpoints(subs); -- - /* for playback, submit the URBs now; otherwise, the first hwptr_done - * updates for all URBs would happen at the same time when starting */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) -- return start_endpoints(subs); -+ return start_endpoints(subs, 1); - - return 0; - } -@@ -1175,7 +1172,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: -- err = start_endpoints(subs); -+ err = start_endpoints(subs, 0); - if (err < 0) - return err; - --- -1.7.11.4 - diff --git a/kernel.spec b/kernel.spec index b8d81b5eb..51cd6bb67 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 4 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -759,8 +759,6 @@ Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch #rhbz 852842 Patch22068: ibmveth-Fix-alignment-of-rx-queue-bug.patch -Patch30000: 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch - # END OF PATCH DEFINITIONS %endif @@ -1463,8 +1461,6 @@ ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch #rhbz 852842 ApplyPatch ibmveth-Fix-alignment-of-rx-queue-bug.patch -ApplyPatch 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch - # END OF PATCH APPLICATIONS %endif @@ -2327,6 +2323,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.1 +- Linux v3.6-rc4-128-geeea3ac + * Wed Sep 05 2012 Dave Jones - Don't create empty include/linux/autoconf.h in kernel-devel (rhbz 854689) diff --git a/sources b/sources index 0c7e61629..ef9b6d4a4 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 85a05f267b2a883d0a444f3f2f91ec0b patch-3.6-rc4.xz -2f77d7e0612827bbcc097bcadf43a1ee patch-3.6-rc4-git1.xz +04fb4358588ac5de3921d308a7ad5137 patch-3.6-rc4-git2.xz From b0ae0f1026a8caff13539246b89f5b9053ff9a09 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 7 Sep 2012 10:40:42 -0400 Subject: [PATCH 023/492] Re-enable BTRFS on ppc. Brent Baude says it works now. --- config-powerpc-generic | 3 --- kernel.spec | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config-powerpc-generic b/config-powerpc-generic index e6c2ebd6d..58c3393a2 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -357,9 +357,6 @@ CONFIG_RFKILL_GPIO=m # CONFIG_NET_VENDOR_PASEMI is not set # CONFIG_NET_VENDOR_TOSHIBA is not set -# Disable btrfs until it is shown to work with 64k pages (rhbz 747079) -# CONFIG_BTRFS_FS is not set -# # CONFIG_CPU_IDLE is not set # CONFIG_OF_SELFTEST is not set # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set diff --git a/kernel.spec b/kernel.spec index 51cd6bb67..80b2433db 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2323,6 +2323,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.2 +- Re-enable BTRFS on ppc. Brent Baude says it works now. + * Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.1 - Linux v3.6-rc4-128-geeea3ac From 82d4cc2b70f15d19690d061d8400dd7cff0183a1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Sep 2012 08:36:32 -0400 Subject: [PATCH 024/492] Linux v3.6-rc5 - Disable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 14 +++--- sources | 3 +- 5 files changed, 70 insertions(+), 67 deletions(-) diff --git a/config-generic b/config-generic index d6cb2b7e9..e811d83a2 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 80b2433db..8dd5c339c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 4 +%define rcrev 5 # The git snapshot level -%define gitrev 2 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2323,6 +2323,10 @@ fi # ||----w | # || || %changelog +* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git0.1 +- Linux v3.6-rc5 +- Disable debugging options. + * Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.2 - Re-enable BTRFS on ppc. Brent Baude says it works now. diff --git a/sources b/sources index ef9b6d4a4..e5e260ff9 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -85a05f267b2a883d0a444f3f2f91ec0b patch-3.6-rc4.xz -04fb4358588ac5de3921d308a7ad5137 patch-3.6-rc4-git2.xz +64bf4320655fcf172412764eeca9fa7d patch-3.6-rc5.xz From 08a208ba15bda85d7b5c562582630e96ed63f691 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Sep 2012 08:38:51 -0400 Subject: [PATCH 025/492] Linux v3.6-rc5-32-g1a95620 - Reenable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 10 +++-- sources | 1 + 5 files changed, 68 insertions(+), 63 deletions(-) diff --git a/config-generic b/config-generic index e811d83a2..d6cb2b7e9 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # @@ -3977,7 +3977,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index 5b4187680..d99deeb2f 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set -# CONFIG_FAIL_MMC_REQUEST is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_NFSD_FAULT_INJECTION=y -# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_DEBUG_BLK_CGROUP=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index de9582a01..ad22edd8d 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_MAXSMP is not set +CONFIG_MAXSMP=y CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 8dd5c339c..a77690ce8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 5 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2323,6 +2323,10 @@ fi # ||----w | # || || %changelog +* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.1 +- Linux v3.6-rc5-32-g1a95620 +- Reenable debugging options. + * Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git0.1 - Linux v3.6-rc5 - Disable debugging options. diff --git a/sources b/sources index e5e260ff9..bdb3d54f7 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 64bf4320655fcf172412764eeca9fa7d patch-3.6-rc5.xz +fb13496db4d4e963f130f6836daa0eda patch-3.6-rc5-git1.xz From 235ab5f360023f79ce24102cee8a9678a5a5e987 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Sep 2012 09:04:07 -0400 Subject: [PATCH 026/492] Drop old Xen EC2 patch. It is no longer needed per Matt Wilson --- fix_xen_guest_on_old_EC2.patch | 34 ---------------------------------- kernel.spec | 7 ++++--- 2 files changed, 4 insertions(+), 37 deletions(-) delete mode 100644 fix_xen_guest_on_old_EC2.patch diff --git a/fix_xen_guest_on_old_EC2.patch b/fix_xen_guest_on_old_EC2.patch deleted file mode 100644 index e86200295..000000000 --- a/fix_xen_guest_on_old_EC2.patch +++ /dev/null @@ -1,34 +0,0 @@ - -Legacy hypervisors (RHEL 5.0 and RHEL 5.1) do not handle guest writes to -cr4 gracefully. If a guest attempts to write a bit of cr4 that is -unsupported, then the HV is so offended it crashes the domain. While -later guest kernels (such as RHEL6) don't assume the HV supports all -features, they do expect nicer responses. That assumption introduced -code that probes whether or not xsave is supported early in the boot. So -now when attempting to boot a RHEL6 guest on RHEL5.0 or RHEL5.1 an early -crash will occur. - -This patch is quite obviously an undesirable hack. The real fix for this -problem should be in the HV, and is, in later HVs. However, to support -running on old HVs, RHEL6 can take this small change. No impact will -occur for running on any RHEL HV (not even RHEL 5.5 supports xsave). -There is only potential for guest performance loss on upstream Xen. - ---- - arch/x86/xen/enlighten.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c -index 52f8e19..6db3d67 100644 ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -802,6 +802,7 @@ static void xen_write_cr4(unsigned long cr4) - { - cr4 &= ~X86_CR4_PGE; - cr4 &= ~X86_CR4_PSE; -+ cr4 &= ~X86_CR4_OSXSAVE; - - native_write_cr4(cr4); - } --- -1.6.6.1 diff --git a/kernel.spec b/kernel.spec index a77690ce8..f7adf31ea 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -687,7 +687,6 @@ Patch1000: secure-boot-20120809.patch Patch1100: handle-efi-roms.patch # virt + ksm patches -Patch1555: fix_xen_guest_on_old_EC2.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch @@ -1403,7 +1402,6 @@ ApplyPatch secure-boot-20120809.patch ApplyPatch handle-efi-roms.patch # Assorted Virt Fixes -ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch @@ -2323,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.2 +- Drop old Xen EC2 patch. It is no longer needed per Matt Wilson + * Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.1 - Linux v3.6-rc5-32-g1a95620 - Reenable debugging options. From c7e94d6fbff0be440bb5c83e2974d1c860cb3d12 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Sep 2012 08:47:59 -0400 Subject: [PATCH 027/492] Linux v3.6-rc5-44-g0bd1189 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index f7adf31ea..a50bfbe50 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 5 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2321,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Wed Sep 12 2012 Josh Boyer - 3.6.0-0.rc5.git2.1 +- Linux v3.6-rc5-44-g0bd1189 + * Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.2 - Drop old Xen EC2 patch. It is no longer needed per Matt Wilson diff --git a/sources b/sources index bdb3d54f7..ddf16cf32 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 64bf4320655fcf172412764eeca9fa7d patch-3.6-rc5.xz -fb13496db4d4e963f130f6836daa0eda patch-3.6-rc5-git1.xz +136a0dd334e88def7136486d53e298a9 patch-3.6-rc5-git2.xz From f98083c0c633a6b50a38e302c947e22e574ae235 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 14 Sep 2012 12:04:56 -0400 Subject: [PATCH 028/492] Fix license tag. (rhbz 450492) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index a50bfbe50..22184d024 100644 --- a/kernel.spec +++ b/kernel.spec @@ -512,7 +512,7 @@ AutoProv: yes\ Name: kernel%{?variant} Group: System Environment/Kernel -License: GPLv2 +License: GPLv2 and Redistributable, no modification permitted URL: http://www.kernel.org/ Version: %{rpmversion} Release: %{pkg_release} @@ -2321,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 14 2012 Dave Jones +- Fix license tag. (rhbz 450492) + * Wed Sep 12 2012 Josh Boyer - 3.6.0-0.rc5.git2.1 - Linux v3.6-rc5-44-g0bd1189 From f832b375f67e93ce27c4ce9397934d7a25428d8b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 14 Sep 2012 13:15:17 -0400 Subject: [PATCH 029/492] Reenable UBIFS (rhbz 823238) --- config-generic | 6 +++++- kernel.spec | 3 +++ mod-extra.list | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index d6cb2b7e9..422972e4a 100644 --- a/config-generic +++ b/config-generic @@ -3624,7 +3624,11 @@ CONFIG_DLM_DEBUG=y CONFIG_GFS2_FS=m CONFIG_GFS2_FS_LOCKING_DLM=y -# CONFIG_UBIFS_FS is not set + +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_XATTR=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set # # Partition Types diff --git a/kernel.spec b/kernel.spec index 22184d024..f7daaa8f6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2321,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 14 2012 Dave Jones +- Reenable UBIFS (rhbz 823238) + * Fri Sep 14 2012 Dave Jones - Fix license tag. (rhbz 450492) diff --git a/mod-extra.list b/mod-extra.list index b01f05eb4..124d74ef2 100644 --- a/mod-extra.list +++ b/mod-extra.list @@ -187,3 +187,4 @@ w1_smem.ko w1_ds2431.ko w1_ds2423.ko w1_bq27000.ko +ubifs.ko From 3bf92faae1f4653da8447e6ae97403f5287f8596 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 14 Sep 2012 13:27:07 -0400 Subject: [PATCH 030/492] MTD is also needed for UBIFS to be enabled. --- config-generic | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-generic b/config-generic index 422972e4a..121a6b422 100644 --- a/config-generic +++ b/config-generic @@ -189,7 +189,7 @@ CONFIG_EXTRA_FIRMWARE="" # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=m # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_FTL is not set # CONFIG_NFTL is not set @@ -212,7 +212,7 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_UBI is not set +CONFIG_MTD_UBI=m # From afb479308142d25707ea56405aea718a5b67289c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 14 Sep 2012 13:29:38 -0400 Subject: [PATCH 031/492] Enable CONFIG_DRM_LOAD_EDID_FIRMWARE (rhbz 857511) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 121a6b422..9b63e75f9 100644 --- a/config-generic +++ b/config-generic @@ -2419,7 +2419,7 @@ CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_STUB_POULSBO is not set CONFIG_DRM=m -# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_AST=m # do not enable on f17 or older CONFIG_DRM_CIRRUS_QEMU=m # do not enable on f17 or older # CONFIG_DRM_TDFX is not set diff --git a/kernel.spec b/kernel.spec index f7daaa8f6..e6e9ec3cd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2321,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 14 2012 Dave Jones +- Enable CONFIG_DRM_LOAD_EDID_FIRMWARE (rhbz 857511) + * Fri Sep 14 2012 Dave Jones - Reenable UBIFS (rhbz 823238) From 5006e294cad99968b73c89679431ab73ec6bd0ba Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 16 Sep 2012 09:12:35 -0400 Subject: [PATCH 032/492] Linux v3.6-rc5-315-g3f0c3c8 --- ibmveth-Fix-alignment-of-rx-queue-bug.patch | 80 --------------------- kernel.spec | 11 ++- sources | 2 +- 3 files changed, 5 insertions(+), 88 deletions(-) delete mode 100644 ibmveth-Fix-alignment-of-rx-queue-bug.patch diff --git a/ibmveth-Fix-alignment-of-rx-queue-bug.patch b/ibmveth-Fix-alignment-of-rx-queue-bug.patch deleted file mode 100644 index 79353a61c..000000000 --- a/ibmveth-Fix-alignment-of-rx-queue-bug.patch +++ /dev/null @@ -1,80 +0,0 @@ -This patch fixes a bug found by Nish Aravamudan -(https://lkml.org/lkml/2012/5/15/220) where the driver is not following -the spec (it is not aligning the rx buffer on a 16-byte boundary) and the -hypervisor aborts the registration, making the device unusable. - -The fix follows BenH's recommendation (https://lkml.org/lkml/2012/7/20/461) -to replace the kmalloc+map for a single call to dma_alloc_coherent() -because that function always aligns to a 16-byte boundary. - -The stable trees will run into this bug whenever the rx buffer kmalloc call -returns something not aligned on a 16-byte boundary. - -Cc: -Signed-off-by: Santiago Leon ---- - ibmveth.c | 26 +++++++++----------------- - 1 file changed, 9 insertions(+), 17 deletions(-) - ---- a/drivers/net/ethernet/ibm/ibmveth.c 2012-07-09 16:00:53.000000000 -0400 -+++ b/drivers/net/ethernet/ibm/ibmveth.c 2012-08-17 19:51:02.840000188 -0400 -@@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmve - } - - if (adapter->rx_queue.queue_addr != NULL) { -- if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { -- dma_unmap_single(dev, -- adapter->rx_queue.queue_dma, -- adapter->rx_queue.queue_len, -- DMA_BIDIRECTIONAL); -- adapter->rx_queue.queue_dma = DMA_ERROR_CODE; -- } -- kfree(adapter->rx_queue.queue_addr); -+ dma_free_coherent(dev, adapter->rx_queue.queue_len, -+ adapter->rx_queue.queue_addr, -+ adapter->rx_queue.queue_dma); - adapter->rx_queue.queue_addr = NULL; - } - -@@ -556,10 +551,13 @@ static int ibmveth_open(struct net_devic - goto err_out; - } - -+ dev = &adapter->vdev->dev; -+ - adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * - rxq_entries; -- adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, -- GFP_KERNEL); -+ adapter->rx_queue.queue_addr = -+ dma_alloc_coherent(dev, adapter->rx_queue.queue_len, -+ &adapter->rx_queue.queue_dma, GFP_KERNEL); - - if (!adapter->rx_queue.queue_addr) { - netdev_err(netdev, "unable to allocate rx queue pages\n"); -@@ -567,19 +565,13 @@ static int ibmveth_open(struct net_devic - goto err_out; - } - -- dev = &adapter->vdev->dev; -- - adapter->buffer_list_dma = dma_map_single(dev, - adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); - adapter->filter_list_dma = dma_map_single(dev, - adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); -- adapter->rx_queue.queue_dma = dma_map_single(dev, -- adapter->rx_queue.queue_addr, -- adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); - - if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || -- (dma_mapping_error(dev, adapter->filter_list_dma)) || -- (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { -+ (dma_mapping_error(dev, adapter->filter_list_dma))) { - netdev_err(netdev, "unable to map filter or buffer list " - "pages\n"); - rc = -ENOMEM; - --- -To unsubscribe from this list: send the line "unsubscribe netdev" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index e6e9ec3cd..a81e59c43 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 5 # The git snapshot level -%define gitrev 2 +%define gitrev 3 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -755,9 +755,6 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 852842 -Patch22068: ibmveth-Fix-alignment-of-rx-queue-bug.patch - # END OF PATCH DEFINITIONS %endif @@ -1456,9 +1453,6 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 852842 -ApplyPatch ibmveth-Fix-alignment-of-rx-queue-bug.patch - # END OF PATCH APPLICATIONS %endif @@ -2321,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Sun Sep 16 2012 Josh Boyer - 3.6.0-0.rc5.git3.1 +- Linux v3.6-rc5-315-g3f0c3c8 + * Fri Sep 14 2012 Dave Jones - Enable CONFIG_DRM_LOAD_EDID_FIRMWARE (rhbz 857511) diff --git a/sources b/sources index ddf16cf32..057febf26 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 64bf4320655fcf172412764eeca9fa7d patch-3.6-rc5.xz -136a0dd334e88def7136486d53e298a9 patch-3.6-rc5-git2.xz +c6374674c8226b5b470becdea700495e patch-3.6-rc5-git3.xz From 3536a72eb2788ef9467579f393ecb83bf7475e67 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Sep 2012 08:36:05 -0400 Subject: [PATCH 033/492] Linux v3.6-rc6 - Disable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 12 +++-- sources | 3 +- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/config-generic b/config-generic index 9b63e75f9..8f795f5d5 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3981,7 +3981,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index a81e59c43..1a1a75dc9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 5 +%define rcrev 6 # The git snapshot level -%define gitrev 3 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2315,6 +2315,10 @@ fi # ||----w | # || || %changelog +* Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.1 +- Linux v3.6-rc6 +- Disable debugging options. + * Sun Sep 16 2012 Josh Boyer - 3.6.0-0.rc5.git3.1 - Linux v3.6-rc5-315-g3f0c3c8 diff --git a/sources b/sources index 057febf26..1f1499ae3 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -64bf4320655fcf172412764eeca9fa7d patch-3.6-rc5.xz -c6374674c8226b5b470becdea700495e patch-3.6-rc5-git3.xz +509f0571ddeb157c6c5fd7347816e2b8 patch-3.6-rc6.xz From d790cab4557600f40a386f4885aedec029b1e71f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Sep 2012 13:09:55 -0400 Subject: [PATCH 034/492] Reenable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 9 ++-- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/config-generic b/config-generic index 8f795f5d5..9b63e75f9 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # @@ -3981,7 +3981,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index 5b4187680..d99deeb2f 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set -# CONFIG_FAIL_MMC_REQUEST is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_NFSD_FAULT_INJECTION=y -# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_DEBUG_BLK_CGROUP=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index de9582a01..ad22edd8d 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_MAXSMP is not set +CONFIG_MAXSMP=y CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 1a1a75dc9..e9361e7d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.2 +- Reenable debugging options. + * Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.1 - Linux v3.6-rc6 - Disable debugging options. From b4e76aa2ea90ebc06471f36a9a6cf9cc5108b534 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 18 Sep 2012 08:31:28 -0400 Subject: [PATCH 035/492] Linux v3.6-rc6-25-g4651afb - Enable POWER7+ crypto modules (rhbz 857971) --- config-powerpc64 | 4 ++-- config-powerpc64p7 | 4 ++-- kernel.spec | 8 ++++++-- sources | 1 + 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config-powerpc64 b/config-powerpc64 index 46ffe87c9..ccd0e85d4 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -164,8 +164,8 @@ CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m -# CONFIG_HW_RANDOM_PSERIES is not set -# CONFIG_CRYPTO_DEV_NX is not set +CONFIG_HW_RANDOM_PSERIES=m +CONFIG_CRYPTO_DEV_NX=m CONFIG_BPF_JIT=y diff --git a/config-powerpc64p7 b/config-powerpc64p7 index 7e2ea454b..ef6ac78e1 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -155,8 +155,8 @@ CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m -# CONFIG_HW_RANDOM_PSERIES is not set -# CONFIG_CRYPTO_DEV_NX is not set +CONFIG_HW_RANDOM_PSERIES=m +CONFIG_CRYPTO_DEV_NX=m CONFIG_BPF_JIT=y diff --git a/kernel.spec b/kernel.spec index e9361e7d4..8d88108c2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 6 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2315,6 +2315,10 @@ fi # ||----w | # || || %changelog +* Tue Sep 18 2012 Josh Boyer - 3.6.0-0.rc6.git1.1 +- Linux v3.6-rc6-25-g4651afb +- Enable POWER7+ crypto modules (rhbz 857971) + * Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.2 - Reenable debugging options. diff --git a/sources b/sources index 1f1499ae3..6863601c9 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 509f0571ddeb157c6c5fd7347816e2b8 patch-3.6-rc6.xz +b4f60c62b22d1503702bfe6ed6b72d47 patch-3.6-rc6-git1.xz From ee64ea8b44e17f6f857683be667caf24a3c4aad2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 08:34:38 -0400 Subject: [PATCH 036/492] Linux v3.6-rc6-52-gc46de22 --- kernel.spec | 5 ++++- sources | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8d88108c2..f92b2d88b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 6 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Thu Sep 20 2012 Josh Boyer - 3.6.0-0.rc6.git2.1 +- Linux v3.6-rc6-52-gc46de22 + * Tue Sep 18 2012 Josh Boyer - 3.6.0-0.rc6.git1.1 - Linux v3.6-rc6-25-g4651afb - Enable POWER7+ crypto modules (rhbz 857971) diff --git a/sources b/sources index 6863601c9..9dc6a4a15 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 509f0571ddeb157c6c5fd7347816e2b8 patch-3.6-rc6.xz -b4f60c62b22d1503702bfe6ed6b72d47 patch-3.6-rc6-git1.xz +d7f3518485678f06b21cc3dc20ad3da9 patch-3.6-rc6-git2.xz From 14c26cb62b1d7198a6f7cfa2c9dd851cd38f3179 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Sep 2012 08:33:02 -0400 Subject: [PATCH 037/492] Linux v3.6-rc7 - Disable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 12 +++-- sources | 3 +- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/config-generic b/config-generic index 9b63e75f9..8f795f5d5 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3981,7 +3981,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index f92b2d88b..013b6b3cc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 6 +%define rcrev 7 # The git snapshot level -%define gitrev 2 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2315,6 +2315,10 @@ fi # ||----w | # || || %changelog +* Mon Sep 24 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 +- Linux v3.6-rc7 +- Disable debugging options. + * Thu Sep 20 2012 Josh Boyer - 3.6.0-0.rc6.git2.1 - Linux v3.6-rc6-52-gc46de22 diff --git a/sources b/sources index 9dc6a4a15..076d69398 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -509f0571ddeb157c6c5fd7347816e2b8 patch-3.6-rc6.xz -d7f3518485678f06b21cc3dc20ad3da9 patch-3.6-rc6-git2.xz +7704196874c5a7ae69a3ba5363b3665d patch-3.6-rc7.xz From af4ca2c104462bc680bebe3bc221f97177a54257 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Sep 2012 12:08:11 -0400 Subject: [PATCH 038/492] Reenable debugging options. --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 9 ++-- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/config-generic b/config-generic index 8f795f5d5..9b63e75f9 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # @@ -3981,7 +3981,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index 5b4187680..d99deeb2f 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set -# CONFIG_FAIL_MMC_REQUEST is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_NFSD_FAULT_INJECTION=y -# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_DEBUG_BLK_CGROUP=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index de9582a01..ad22edd8d 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_MAXSMP is not set +CONFIG_MAXSMP=y CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 013b6b3cc..61714b81d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git0.2 +- Reenable debugging options. + * Mon Sep 24 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 - Linux v3.6-rc7 - Disable debugging options. From cf1a16641da9013ed483d80095fcca5801c4c676 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Sep 2012 12:15:46 -0400 Subject: [PATCH 039/492] Linux v3.6-rc7-10-g56d27ad --- kernel.spec | 7 +++++-- sources | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 61714b81d..fb6b7809d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 7 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2315,6 +2315,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 +- Linux v3.6-rc7-10-g56d27ad + * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git0.2 - Reenable debugging options. diff --git a/sources b/sources index 076d69398..a55fa4ef4 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 7704196874c5a7ae69a3ba5363b3665d patch-3.6-rc7.xz +47b618da3a92738d00dc7ee990b46fe5 patch-3.6-rc7-git1.xz From 1b9395fd03577c8d0e3ebb02449dda61ada515d8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Sep 2012 12:20:41 -0400 Subject: [PATCH 040/492] Update team driver from net-next from Jiri Pirko --- kernel.spec | 5 + team-net-next-update-20120924.patch | 499 ++++++++++++++++++++++++++++ 2 files changed, 504 insertions(+) create mode 100644 team-net-next-update-20120924.patch diff --git a/kernel.spec b/kernel.spec index fb6b7809d..695bc8af7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,6 +656,7 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch Patch150: team-net-next-20120808.patch +Patch151: team-net-next-update-20120924.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch @@ -1310,6 +1311,7 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch ApplyPatch team-net-next-20120808.patch +ApplyPatch team-net-next-update-20120924.patch # Architecture patches # x86(-64) @@ -2315,6 +2317,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.2 +- Update team driver from net-next from Jiri Pirko + * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 - Linux v3.6-rc7-10-g56d27ad diff --git a/team-net-next-update-20120924.patch b/team-net-next-update-20120924.patch new file mode 100644 index 000000000..c0899c5aa --- /dev/null +++ b/team-net-next-update-20120924.patch @@ -0,0 +1,499 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.59.1.102 with SMTP id bf6csp906180ved; + Sun, 23 Sep 2012 23:03:07 -0700 (PDT) +Received: by 10.68.239.5 with SMTP id vo5mr33801766pbc.102.1348466586432; + Sun, 23 Sep 2012 23:03:06 -0700 (PDT) +Return-Path: +Received: from bastion.fedoraproject.org (bastion01.fedoraproject.org. [209.132.181.2]) + by mx.google.com with ESMTP id s5si6031726pay.21.2012.09.23.23.03.04; + Sun, 23 Sep 2012 23:03:06 -0700 (PDT) +Received-SPF: pass (google.com: domain of kernel-bounces@lists.fedoraproject.org designates 209.132.181.2 as permitted sender) client-ip=209.132.181.2; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of kernel-bounces@lists.fedoraproject.org designates 209.132.181.2 as permitted sender) smtp.mail=kernel-bounces@lists.fedoraproject.org +Received: from lists.fedoraproject.org (collab03.vpn.fedoraproject.org [192.168.1.70]) + by bastion01.phx2.fedoraproject.org (Postfix) with ESMTP id 4185D224F5; + Mon, 24 Sep 2012 06:03:03 +0000 (UTC) +Received: from collab03.fedoraproject.org (localhost [127.0.0.1]) + by lists.fedoraproject.org (Postfix) with ESMTP id E30B53FCF8; + Mon, 24 Sep 2012 06:03:02 +0000 (UTC) +X-Original-To: kernel@lists.fedoraproject.org +Delivered-To: kernel@lists.fedoraproject.org +Received: from smtp-mm02.fedoraproject.org (smtp-mm02.fedoraproject.org + [66.35.62.164]) + by lists.fedoraproject.org (Postfix) with ESMTP id 7F9D03FCF8 + for ; + Mon, 24 Sep 2012 06:03:00 +0000 (UTC) +Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) + by smtp-mm02.fedoraproject.org (Postfix) with ESMTP id 3A0AA3FC66 + for ; + Mon, 24 Sep 2012 06:03:00 +0000 (UTC) +Received: from int-mx11.intmail.prod.int.phx2.redhat.com + (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8O62uU3010033 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 24 Sep 2012 02:02:59 -0400 +Received: from localhost (ovpn-116-32.ams2.redhat.com [10.36.116.32]) + by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP + id q8O62sNM029515; Mon, 24 Sep 2012 02:02:55 -0400 +From: Jiri Pirko +To: kernel@lists.fedoraproject.org +Subject: [patch F18/rawhide] team: update to latest net-next +Date: Mon, 24 Sep 2012 08:02:54 +0200 +Message-Id: <1348466574-1982-1-git-send-email-jpirko@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 +Cc: brouer@redhat.com, jforbes@redhat.com, jwboyer@redhat.com +X-BeenThere: kernel@lists.fedoraproject.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: "Fedora kernel development." +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 +Sender: kernel-bounces@lists.fedoraproject.org +Errors-To: kernel-bounces@lists.fedoraproject.org + +Update team driver to latest net-next. + +Split patches available here: +http://people.redhat.com/jpirko/f18_team_update_3/ + +Jiri Pirko (5): + team: add support for non-ethernet devices + team: don't print warn message on -ESRCH during event send + vlan: add helper which can be called to see if device is used by vlan + team: do not allow to add VLAN challenged port when vlan is used + team: send port changed when added + + drivers/net/team/Kconfig | 4 +- + drivers/net/team/team.c | 137 ++++++++++++++++++++++++-------- + drivers/net/team/team_mode_broadcast.c | 8 +- + drivers/net/team/team_mode_roundrobin.c | 8 +- + include/linux/if_team.h | 4 +- + include/linux/if_vlan.h | 9 ++- + net/8021q/vlan_core.c | 6 ++ + 7 files changed, 128 insertions(+), 48 deletions(-) + +Signed-off-by: Jiri Pirko + +diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig +index 6a7260b..6b08bd4 100644 +--- a/drivers/net/team/Kconfig ++++ b/drivers/net/team/Kconfig +@@ -21,7 +21,7 @@ config NET_TEAM_MODE_BROADCAST + ---help--- + Basic mode where packets are transmitted always by all suitable ports. + +- All added ports are setup to have team's mac address. ++ All added ports are setup to have team's device address. + + To compile this team mode as a module, choose M here: the module + will be called team_mode_broadcast. +@@ -33,7 +33,7 @@ config NET_TEAM_MODE_ROUNDROBIN + Basic mode where port used for transmitting packets is selected in + round-robin fashion using packet counter. + +- All added ports are setup to have team's mac address. ++ All added ports are setup to have team's device address. + + To compile this team mode as a module, choose M here: the module + will be called team_mode_roundrobin. +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 341b65d..17d4be3 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -54,29 +54,29 @@ static struct team_port *team_port_get_rtnl(const struct net_device *dev) + } + + /* +- * Since the ability to change mac address for open port device is tested in ++ * Since the ability to change device address for open port device is tested in + * team_port_add, this function can be called without control of return value + */ +-static int __set_port_mac(struct net_device *port_dev, +- const unsigned char *dev_addr) ++static int __set_port_dev_addr(struct net_device *port_dev, ++ const unsigned char *dev_addr) + { + struct sockaddr addr; + +- memcpy(addr.sa_data, dev_addr, ETH_ALEN); +- addr.sa_family = ARPHRD_ETHER; ++ memcpy(addr.sa_data, dev_addr, port_dev->addr_len); ++ addr.sa_family = port_dev->type; + return dev_set_mac_address(port_dev, &addr); + } + +-static int team_port_set_orig_mac(struct team_port *port) ++static int team_port_set_orig_dev_addr(struct team_port *port) + { +- return __set_port_mac(port->dev, port->orig.dev_addr); ++ return __set_port_dev_addr(port->dev, port->orig.dev_addr); + } + +-int team_port_set_team_mac(struct team_port *port) ++int team_port_set_team_dev_addr(struct team_port *port) + { +- return __set_port_mac(port->dev, port->team->dev->dev_addr); ++ return __set_port_dev_addr(port->dev, port->team->dev->dev_addr); + } +-EXPORT_SYMBOL(team_port_set_team_mac); ++EXPORT_SYMBOL(team_port_set_team_dev_addr); + + static void team_refresh_port_linkup(struct team_port *port) + { +@@ -848,7 +848,10 @@ static struct netpoll_info *team_netpoll_info(struct team *team) + } + #endif + +-static void __team_port_change_check(struct team_port *port, bool linkup); ++static void __team_port_change_port_added(struct team_port *port, bool linkup); ++ ++static int team_dev_type_check_change(struct net_device *dev, ++ struct net_device *port_dev); + + static int team_port_add(struct team *team, struct net_device *port_dev) + { +@@ -857,9 +860,8 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + char *portname = port_dev->name; + int err; + +- if (port_dev->flags & IFF_LOOPBACK || +- port_dev->type != ARPHRD_ETHER) { +- netdev_err(dev, "Device %s is of an unsupported type\n", ++ if (port_dev->flags & IFF_LOOPBACK) { ++ netdev_err(dev, "Device %s is loopback device. Loopback devices can't be added as a team port\n", + portname); + return -EINVAL; + } +@@ -870,6 +872,17 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + return -EBUSY; + } + ++ if (port_dev->features & NETIF_F_VLAN_CHALLENGED && ++ vlan_uses_dev(dev)) { ++ netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n", ++ portname); ++ return -EPERM; ++ } ++ ++ err = team_dev_type_check_change(dev, port_dev); ++ if (err) ++ return err; ++ + if (port_dev->flags & IFF_UP) { + netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", + portname); +@@ -891,7 +904,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + goto err_set_mtu; + } + +- memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); ++ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); + + err = team_port_enter(team, port); + if (err) { +@@ -948,7 +961,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) + team_port_enable(team, port); + list_add_tail_rcu(&port->list, &team->port_list); + __team_compute_features(team); +- __team_port_change_check(port, !!netif_carrier_ok(port_dev)); ++ __team_port_change_port_added(port, !!netif_carrier_ok(port_dev)); + __team_options_change_check(team); + + netdev_info(dev, "Port device %s added\n", portname); +@@ -972,7 +985,7 @@ err_vids_add: + + err_dev_open: + team_port_leave(team, port); +- team_port_set_orig_mac(port); ++ team_port_set_orig_dev_addr(port); + + err_port_enter: + dev_set_mtu(port_dev, port->orig.mtu); +@@ -983,6 +996,8 @@ err_set_mtu: + return err; + } + ++static void __team_port_change_port_removed(struct team_port *port); ++ + static int team_port_del(struct team *team, struct net_device *port_dev) + { + struct net_device *dev = team->dev; +@@ -999,8 +1014,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + __team_option_inst_mark_removed_port(team, port); + __team_options_change_check(team); + __team_option_inst_del_port(team, port); +- port->removed = true; +- __team_port_change_check(port, false); ++ __team_port_change_port_removed(port); + team_port_disable(team, port); + list_del_rcu(&port->list); + netdev_rx_handler_unregister(port_dev); +@@ -1009,7 +1023,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + vlan_vids_del_by_dev(port_dev, dev); + dev_close(port_dev); + team_port_leave(team, port); +- team_port_set_orig_mac(port); ++ team_port_set_orig_dev_addr(port); + dev_set_mtu(port_dev, port->orig.mtu); + synchronize_rcu(); + kfree(port); +@@ -1295,17 +1309,18 @@ static void team_set_rx_mode(struct net_device *dev) + + static int team_set_mac_address(struct net_device *dev, void *p) + { ++ struct sockaddr *addr = p; + struct team *team = netdev_priv(dev); + struct team_port *port; +- int err; + +- err = eth_mac_addr(dev, p); +- if (err) +- return err; ++ if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) ++ return -EADDRNOTAVAIL; ++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; + rcu_read_lock(); + list_for_each_entry_rcu(port, &team->port_list, list) +- if (team->ops.port_change_mac) +- team->ops.port_change_mac(team, port); ++ if (team->ops.port_change_dev_addr) ++ team->ops.port_change_dev_addr(team, port); + rcu_read_unlock(); + return 0; + } +@@ -1536,6 +1551,45 @@ static const struct net_device_ops team_netdev_ops = { + * rt netlink interface + ***********************/ + ++static void team_setup_by_port(struct net_device *dev, ++ struct net_device *port_dev) ++{ ++ dev->header_ops = port_dev->header_ops; ++ dev->type = port_dev->type; ++ dev->hard_header_len = port_dev->hard_header_len; ++ dev->addr_len = port_dev->addr_len; ++ dev->mtu = port_dev->mtu; ++ memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); ++ memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; ++} ++ ++static int team_dev_type_check_change(struct net_device *dev, ++ struct net_device *port_dev) ++{ ++ struct team *team = netdev_priv(dev); ++ char *portname = port_dev->name; ++ int err; ++ ++ if (dev->type == port_dev->type) ++ return 0; ++ if (!list_empty(&team->port_list)) { ++ netdev_err(dev, "Device %s is of different type\n", portname); ++ return -EBUSY; ++ } ++ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); ++ err = notifier_to_errno(err); ++ if (err) { ++ netdev_err(dev, "Refused to change device type\n"); ++ return err; ++ } ++ dev_uc_flush(dev); ++ dev_mc_flush(dev); ++ team_setup_by_port(dev, port_dev); ++ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); ++ return 0; ++} ++ + static void team_setup(struct net_device *dev) + { + ether_setup(dev); +@@ -2245,19 +2299,17 @@ static void __team_options_change_check(struct team *team) + list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); + } + err = team_nl_send_event_options_get(team, &sel_opt_inst_list); +- if (err) ++ if (err && err != -ESRCH) + netdev_warn(team->dev, "Failed to send options change via netlink (err %d)\n", + err); + } + + /* rtnl lock is held */ +-static void __team_port_change_check(struct team_port *port, bool linkup) ++ ++static void __team_port_change_send(struct team_port *port, bool linkup) + { + int err; + +- if (!port->removed && port->state.linkup == linkup) +- return; +- + port->changed = true; + port->state.linkup = linkup; + team_refresh_port_linkup(port); +@@ -2276,12 +2328,29 @@ static void __team_port_change_check(struct team_port *port, bool linkup) + + send_event: + err = team_nl_send_event_port_list_get(port->team); +- if (err) +- netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", +- port->dev->name); ++ if (err && err != -ESRCH) ++ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", ++ port->dev->name, err); + + } + ++static void __team_port_change_check(struct team_port *port, bool linkup) ++{ ++ if (port->state.linkup != linkup) ++ __team_port_change_send(port, linkup); ++} ++ ++static void __team_port_change_port_added(struct team_port *port, bool linkup) ++{ ++ __team_port_change_send(port, linkup); ++} ++ ++static void __team_port_change_port_removed(struct team_port *port) ++{ ++ port->removed = true; ++ __team_port_change_send(port, false); ++} ++ + static void team_port_change_check(struct team_port *port, bool linkup) + { + struct team *team = port->team; +diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c +index c96e4d2..9db0171 100644 +--- a/drivers/net/team/team_mode_broadcast.c ++++ b/drivers/net/team/team_mode_broadcast.c +@@ -48,18 +48,18 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) + + static int bc_port_enter(struct team *team, struct team_port *port) + { +- return team_port_set_team_mac(port); ++ return team_port_set_team_dev_addr(port); + } + +-static void bc_port_change_mac(struct team *team, struct team_port *port) ++static void bc_port_change_dev_addr(struct team *team, struct team_port *port) + { +- team_port_set_team_mac(port); ++ team_port_set_team_dev_addr(port); + } + + static const struct team_mode_ops bc_mode_ops = { + .transmit = bc_transmit, + .port_enter = bc_port_enter, +- .port_change_mac = bc_port_change_mac, ++ .port_change_dev_addr = bc_port_change_dev_addr, + }; + + static const struct team_mode bc_mode = { +diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c +index ad7ed0e..105135a 100644 +--- a/drivers/net/team/team_mode_roundrobin.c ++++ b/drivers/net/team/team_mode_roundrobin.c +@@ -66,18 +66,18 @@ drop: + + static int rr_port_enter(struct team *team, struct team_port *port) + { +- return team_port_set_team_mac(port); ++ return team_port_set_team_dev_addr(port); + } + +-static void rr_port_change_mac(struct team *team, struct team_port *port) ++static void rr_port_change_dev_addr(struct team *team, struct team_port *port) + { +- team_port_set_team_mac(port); ++ team_port_set_team_dev_addr(port); + } + + static const struct team_mode_ops rr_mode_ops = { + .transmit = rr_transmit, + .port_enter = rr_port_enter, +- .port_change_mac = rr_port_change_mac, ++ .port_change_dev_addr = rr_port_change_dev_addr, + }; + + static const struct team_mode rr_mode = { +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index aa2e167..667f2a5 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -105,7 +105,7 @@ struct team_mode_ops { + bool (*transmit)(struct team *team, struct sk_buff *skb); + int (*port_enter)(struct team *team, struct team_port *port); + void (*port_leave)(struct team *team, struct team_port *port); +- void (*port_change_mac)(struct team *team, struct team_port *port); ++ void (*port_change_dev_addr)(struct team *team, struct team_port *port); + void (*port_enabled)(struct team *team, struct team_port *port); + void (*port_disabled)(struct team *team, struct team_port *port); + }; +@@ -231,7 +231,7 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team, + return NULL; + } + +-extern int team_port_set_team_mac(struct team_port *port); ++extern int team_port_set_team_dev_addr(struct team_port *port); + extern int team_options_register(struct team *team, + const struct team_option *option, + size_t option_count); +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index a810987..e6ff12d 100644 +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -74,8 +74,6 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) + /* found in socket.c */ + extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); + +-struct vlan_info; +- + static inline int is_vlan_dev(struct net_device *dev) + { + return dev->priv_flags & IFF_802_1Q_VLAN; +@@ -101,6 +99,8 @@ extern int vlan_vids_add_by_dev(struct net_device *dev, + const struct net_device *by_dev); + extern void vlan_vids_del_by_dev(struct net_device *dev, + const struct net_device *by_dev); ++ ++extern bool vlan_uses_dev(const struct net_device *dev); + #else + static inline struct net_device * + __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) +@@ -151,6 +151,11 @@ static inline void vlan_vids_del_by_dev(struct net_device *dev, + const struct net_device *by_dev) + { + } ++ ++static inline bool vlan_uses_dev(const struct net_device *dev) ++{ ++ return false; ++} + #endif + + /** +diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c +index 8ca533c..b258da8 100644 +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_device *dev, + vlan_vid_del(dev, vid_info->vid); + } + EXPORT_SYMBOL(vlan_vids_del_by_dev); ++ ++bool vlan_uses_dev(const struct net_device *dev) ++{ ++ return rtnl_dereference(dev->vlan_info) ? true : false; ++} ++EXPORT_SYMBOL(vlan_uses_dev); + From 9da87a497f52be651f416a20f7438b3aa7460849 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 14 Sep 2012 12:25:07 -0400 Subject: [PATCH 041/492] Move the modules-extra processing to a script --- kernel.spec | 68 ++++++---------------------------------------------- mod-extra.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 61 deletions(-) create mode 100755 mod-extra.sh diff --git a/kernel.spec b/kernel.spec index 695bc8af7..ed6ce13c7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -563,6 +563,7 @@ Source11: genkey Source15: merge.pl Source16: mod-extra.list +Source17: mod-extra.sh Source19: Makefile.release Source20: Makefile.config @@ -1749,66 +1750,8 @@ BuildKernel() { rm -f modinfo modnames - pushd $RPM_BUILD_ROOT/lib/modules/$KernelVer/ - rm -rf modnames - find . -name "*.ko" -type f > modnames - # Look through all of the modules, and throw any that have a dependency in - # our list into the list as well. - rm -rf dep.list dep2.list - rm -rf req.list req2.list - touch dep.list req.list - cp %{SOURCE16} . - for dep in `cat modnames` - do - depends=`modinfo $dep | grep depends| cut -f2 -d":" | sed -e 's/^[ \t]*//'` - [ -z "$depends" ] && continue; - for mod in `echo $depends | sed -e 's/,/ /g'` - do - match=`grep "^$mod.ko" mod-extra.list` ||: - if [ -z "$match" ] - then - continue - else - # check if the module we're looking at is in mod-extra too. if so - # we don't need to mark the dep as required - mod2=`basename $dep` - match2=`grep "^$mod2" mod-extra.list` ||: - if [ -n "$match2" ] - then - continue - #echo $mod2 >> notreq.list - else - echo $mod.ko >> req.list - fi - fi - done - done - - sort -u req.list > req2.list - sort -u mod-extra.list > mod-extra2.list - join -v 1 mod-extra2.list req2.list > mod-extra3.list - - for mod in `cat mod-extra3.list` - do - # get the path for the module - modpath=`grep /$mod modnames` ||: - [ -z "$modpath" ] && continue; - echo $modpath >> dep.list - done - - sort -u dep.list > dep2.list - - # now move the modules into the extra/ directory - for mod in `cat dep2.list` - do - newpath=`dirname $mod | sed -e 's/kernel\//extra\//'` - mkdir -p $newpath - mv $mod $newpath - done - - rm modnames dep.list dep2.list req.list req2.list - rm mod-extra.list mod-extra2.list mod-extra3.list - popd + # Call the modules-extra script to move things around + %{SOURCE17} $RPM_BUILD_ROOT/lib/modules/$KernelVer %{SOURCE16} # remove files that will be auto generated by depmod at rpm -i time for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap devname softdep @@ -2317,6 +2260,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 25 2012 Josh Boyer +- Move the modules-extra processing to a script + * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.2 - Update team driver from net-next from Jiri Pirko diff --git a/mod-extra.sh b/mod-extra.sh new file mode 100755 index 000000000..115950b16 --- /dev/null +++ b/mod-extra.sh @@ -0,0 +1,66 @@ +#! /bin/bash + +Dir=$1 +List=$2 + +pushd $Dir +rm -rf modnames +find . -name "*.ko" -type f > modnames +# Look through all of the modules, and throw any that have a dependency in +# our list into the list as well. +rm -rf dep.list dep2.list +rm -rf req.list req2.list +touch dep.list req.list +cp $2 . + +for dep in `cat modnames` +do + depends=`modinfo $dep | grep depends| cut -f2 -d":" | sed -e 's/^[ \t]*//'` + [ -z "$depends" ] && continue; + for mod in `echo $depends | sed -e 's/,/ /g'` + do + match=`grep "^$mod.ko" mod-extra.list` ||: + if [ -z "$match" ] + then + continue + else + # check if the module we're looking at is in mod-extra too. if so + # we don't need to mark the dep as required + mod2=`basename $dep` + match2=`grep "^$mod2" mod-extra.list` ||: + if [ -n "$match2" ] + then + continue + #echo $mod2 >> notreq.list + else + echo $mod.ko >> req.list + fi + fi + done +done + +sort -u req.list > req2.list +sort -u mod-extra.list > mod-extra2.list +join -v 1 mod-extra2.list req2.list > mod-extra3.list + +for mod in `cat mod-extra3.list` +do + # get the path for the module + modpath=`grep /$mod modnames` ||: + [ -z "$modpath" ] && continue; + echo $modpath >> dep.list +done + +sort -u dep.list > dep2.list + +# now move the modules into the extra/ directory +for mod in `cat dep2.list` +do + newpath=`dirname $mod | sed -e 's/kernel\//extra\//'` + mkdir -p $newpath + mv $mod $newpath +done + +rm modnames dep.list dep2.list req.list req2.list +rm mod-extra.list mod-extra2.list mod-extra3.list +popd From bb764e80a3a73738aedadb8e53fda68aaf1d88b6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 14 Sep 2012 12:32:41 -0400 Subject: [PATCH 042/492] Prep mod-extra.sh for signed modules --- kernel.spec | 3 ++- mod-extra.sh | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index ed6ce13c7..129178605 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2262,6 +2262,7 @@ fi %changelog * Tue Sep 25 2012 Josh Boyer - Move the modules-extra processing to a script +- Prep mod-extra.sh for signed modules * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.2 - Update team driver from net-next from Jiri Pirko diff --git a/mod-extra.sh b/mod-extra.sh index 115950b16..d121bd0b1 100755 --- a/mod-extra.sh +++ b/mod-extra.sh @@ -61,6 +61,20 @@ do mv $mod $newpath done +popd + +# If we're signing modules, we can't leave the .mod files for the .ko files +# we've moved in .tmp_versions/. Remove them so the Kbuild 'modules_sign' +# target doesn't try to sign a non-existent file. This is kinda ugly, but +# so is modules-extra. + +for mod in `cat ${Dir}/dep2.list` +do + modfile=`basename $mod | sed -e 's/.ko/.mod/'` + rm .tmp_versions/$modfile +done + +pushd $Dir rm modnames dep.list dep2.list req.list req2.list rm mod-extra.list mod-extra2.list mod-extra3.list popd From 8febe3d66bab94c4542e55e1e47b5929a04c626d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Sep 2012 12:02:24 -0400 Subject: [PATCH 043/492] Switch to using modsign-post-KS upstream with x509 certs --- genkey | 10 - kernel.spec | 76 +- mod-extra-sign.sh | 28 + modsign-20120816.patch | 10434 ---------------- modsign-post-KS-jwb.patch | 9153 ++++++++++++++ ...120809.patch => secure-boot-20120924.patch | 484 +- x509.genkey | 16 + 7 files changed, 9497 insertions(+), 10704 deletions(-) delete mode 100644 genkey create mode 100755 mod-extra-sign.sh delete mode 100644 modsign-20120816.patch create mode 100644 modsign-post-KS-jwb.patch rename secure-boot-20120809.patch => secure-boot-20120924.patch (70%) create mode 100644 x509.genkey diff --git a/genkey b/genkey deleted file mode 100644 index fdb7d1f64..000000000 --- a/genkey +++ /dev/null @@ -1,10 +0,0 @@ -%pubring modsign.pub -%secring modsign.sec -%no-protection: yes -%transient-key: yes -Key-Type: RSA -Key-Length: 2048 -Name-Real: Fedora Project -Name-Comment: Kernel Module GPG key -%commit - diff --git a/kernel.spec b/kernel.spec index 129178605..3a0206fc7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -551,19 +551,20 @@ BuildRequires: rpm-build >= 4.9.0-1, elfutils >= elfutils-0.153-1 %endif %if %{signmodules} -BuildRequires: gnupg +BuildRequires: openssl BuildRequires: pesign >= 0.10-4 %endif Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.xz %if %{signmodules} -Source11: genkey +Source11: x509.genkey %endif Source15: merge.pl Source16: mod-extra.list Source17: mod-extra.sh +Source18: mod-extra-sign.sh Source19: Makefile.release Source20: Makefile.config @@ -680,10 +681,10 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-20120816.patch +Patch900: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20120809.patch +Patch1000: secure-boot-20120924.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -1393,10 +1394,10 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ -ApplyPatch modsign-20120816.patch +ApplyPatch modsign-post-KS-jwb.patch # secure boot -ApplyPatch secure-boot-20120809.patch +ApplyPatch secure-boot-20120924.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1623,13 +1624,6 @@ BuildKernel() { # we'll get it from the linux-firmware package and we don't want conflicts make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw= -%if %{signmodules} - if [ -z "$(readelf -n $(find fs/ -name \*.ko | head -n 1) | grep module.sig)" ]; then - echo "ERROR: modules are NOT signed" >&2; - exit 1; - fi -%endif - %ifarch %{vdso_arches} make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=$KernelVer if [ ! -s ldconfig-kernel.conf ]; then @@ -1753,6 +1747,12 @@ BuildKernel() { # Call the modules-extra script to move things around %{SOURCE17} $RPM_BUILD_ROOT/lib/modules/$KernelVer %{SOURCE16} +%if %{signmodules} + # Save off the .tmp_versions/ directory. We'll use it in the + # __debug_install_post macro below to sign the right things + cp -r .tmp_versions .tmp_versions.sign${Flavour:+.${Flavour}} +%endif + # remove files that will be auto generated by depmod at rpm -i time for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap devname softdep do @@ -1875,9 +1875,56 @@ find Documentation -type d | xargs chmod u+w # This macro is used by %%install, so we must redefine it before that. %define debug_package %{nil} +# In the modsign case, we do 3 things. 1) We check the "flavour" and hard +# code the value in the following invocations. This is somewhat sub-optimal +# but we're doing this inside of an RPM macro and it isn't as easy as it +# could be because of that. 2) We restore the .tmp_versions/ directory from +# the one we saved off in BuildKernel above. This is to make sure we're +# signing the modules we actually built/installed in that flavour. 3) We +# grab the arch and invoke 'make modules_sign' and the mod-extra-sign.sh +# commands to actually sign the modules. +# +# We have to do all of those things _after_ find-debuginfo runs, otherwise +# that will strip the signature off of the modules. + %if %{with_debuginfo} %define __debug_install_post \ /usr/lib/rpm/find-debuginfo.sh %{debuginfo_args} %{_builddir}/%{?buildsubdir}\ + if [ "%{signmodules}" == "1" ]; \ + then \ + if [ "%{with_pae}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAE.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.PAE .tmp_versions \ + make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAE \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAE/extra/ \ + fi \ + if [ "%{with_debug}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-debug.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.debug .tmp_versions \ + make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.debug \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.debug/extra/ \ + fi \ + if [ "%{with_pae_debug}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAEdebug.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.PAEdebug .tmp_versions \ + make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAEdebug \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAEdebug/extra/ \ + fi \ + if [ "%{with_up}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign .tmp_versions \ + make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL} \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}/extra/ \ + fi \ + fi \ %{nil} %ifnarch noarch @@ -2263,6 +2310,7 @@ fi * Tue Sep 25 2012 Josh Boyer - Move the modules-extra processing to a script - Prep mod-extra.sh for signed modules +- Switch to using modsign-post-KS upstream with x509 certs * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.2 - Update team driver from net-next from Jiri Pirko diff --git a/mod-extra-sign.sh b/mod-extra-sign.sh new file mode 100755 index 000000000..a4b2c8cf7 --- /dev/null +++ b/mod-extra-sign.sh @@ -0,0 +1,28 @@ +#! /bin/bash + +# We need to sign modules we've moved from /kernel/ to /extra/ +# during mod-extra processing by hand. The 'modules_sign' Kbuild target can +# "handle" out-of-tree modules, but it does that by not signing them. Plus, +# the modules we've moved aren't actually out-of-tree. We've just shifted +# them to a different location behind Kbuild's back because we are mean. + +# This essentially duplicates the 'modules_sign' Kbuild target and runs the +# same commands for those modules. + +moddir=$1 + +modules=`find $moddir -name *.ko` + +MODSECKEY="./signing_key.priv" +MODPUBKEY="./signing_key.x509" + +for mod in $modules +do + dir=`dirname $mod` + file=`basename $mod` + + sh ./scripts/sign-file ${MODSECKEY} ${MODPUBKEY} ${dir}/${file} \ + ${dir}/${file}.signed + mv ${dir}/${file}.signed ${dir}/${file} + rm -f ${dir}/${file}.{sig,dig} +done diff --git a/modsign-20120816.patch b/modsign-20120816.patch deleted file mode 100644 index 3c679558d..000000000 --- a/modsign-20120816.patch +++ /dev/null @@ -1,10434 +0,0 @@ -From bcb9a5e7e8108872ec9fd7083209cbf3a47ef952 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:14 +0100 -Subject: [PATCH 01/32] KEYS: Add payload preparsing opportunity prior to key - instantiate or update - -Give the key type the opportunity to preparse the payload prior to the -instantiation and update routines being called. This is done with the -provision of two new key type operations: - - int (*preparse)(struct key_preparsed_payload *prep); - void (*free_preparse)(struct key_preparsed_payload *prep); - -If the first operation is present, then it is called before key creation (in -the add/update case) or before the key semaphore is taken (in the update and -instantiate cases). The second operation is called to clean up if the first -was called. - -preparse() is given the opportunity to fill in the following structure: - - struct key_preparsed_payload { - char *description; - void *type_data[2]; - void *payload; - const void *data; - size_t datalen; - size_t quotalen; - }; - -Before the preparser is called, the first three fields will have been cleared, -the payload pointer and size will be stored in data and datalen and the default -quota size from the key_type struct will be stored into quotalen. - -The preparser may parse the payload in any way it likes and may store data in -the type_data[] and payload fields for use by the instantiate() and update() -ops. - -The preparser may also propose a description for the key by attaching it as a -string to the description field. This can be used by passing a NULL or "" -description to the add_key() system call or the key_create_or_update() -function. This cannot work with request_key() as that required the description -to tell the upcall about the key to be created. - -This, for example permits keys that store PGP public keys to generate their own -name from the user ID and public key fingerprint in the key. - -The instantiate() and update() operations are then modified to look like this: - - int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - int (*update)(struct key *key, struct key_preparsed_payload *prep); - -and the new payload data is passed in *prep, whether or not it was preparsed. - -Signed-off-by: David Howells ---- - Documentation/security/keys.txt | 50 +++++++++++++- - fs/cifs/cifs_spnego.c | 6 +- - fs/cifs/cifsacl.c | 8 +-- - include/keys/user-type.h | 6 +- - include/linux/key-type.h | 35 +++++++++- - net/ceph/crypto.c | 9 +-- - net/dns_resolver/dns_key.c | 6 +- - net/rxrpc/ar-key.c | 40 ++++++------ - security/keys/encrypted-keys/encrypted.c | 16 +++-- - security/keys/key.c | 108 ++++++++++++++++++++++--------- - security/keys/keyctl.c | 18 ++++-- - security/keys/keyring.c | 6 +- - security/keys/request_key_auth.c | 8 +-- - security/keys/trusted.c | 16 +++-- - security/keys/user_defined.c | 14 ++-- - 15 files changed, 245 insertions(+), 101 deletions(-) - -diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt -index aa0dbd7..7d9ca92 100644 ---- a/Documentation/security/keys.txt -+++ b/Documentation/security/keys.txt -@@ -412,6 +412,10 @@ The main syscalls are: - to the keyring. In this case, an error will be generated if the process - does not have permission to write to the keyring. - -+ If the key type supports it, if the description is NULL or an empty -+ string, the key type will try and generate a description from the content -+ of the payload. -+ - The payload is optional, and the pointer can be NULL if not required by - the type. The payload is plen in size, and plen can be zero for an empty - payload. -@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: - it should return 0. - - -- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ (*) int (*preparse)(struct key_preparsed_payload *prep); -+ -+ This optional method permits the key type to attempt to parse payload -+ before a key is created (add key) or the key semaphore is taken (update or -+ instantiate key). The structure pointed to by prep looks like: -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ Before calling the method, the caller will fill in data and datalen with -+ the payload blob parameters; quotalen will be filled in with the default -+ quota size from the key type and the rest will be cleared. -+ -+ If a description can be proposed from the payload contents, that should be -+ attached as a string to the description field. This will be used for the -+ key description if the caller of add_key() passes NULL or "". -+ -+ The method can attach anything it likes to type_data[] and payload. These -+ are merely passed along to the instantiate() or update() operations. -+ -+ The method should return 0 if success ful or a negative error code -+ otherwise. -+ -+ -+ (*) void (*free_preparse)(struct key_preparsed_payload *prep); -+ -+ This method is only required if the preparse() method is provided, -+ otherwise it is unused. It cleans up anything attached to the -+ description, type_data and payload fields of the key_preparsed_payload -+ struct as filled in by the preparse() method. -+ -+ -+ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - This method is called to attach a payload to a key during construction. - The payload attached need not bear any relation to the data passed to this - function. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - If the amount of data attached to the key differs from the size in - keytype->def_datalen, then key_payload_reserve() should be called. - -@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: - If this type of key can be updated, then this method should be provided. - It is called to update a key's payload from the blob of data provided. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - key_payload_reserve() should be called if the data length might change - before any changes are actually made. Note that if this succeeds, the type - is committed to changing the key because it's already been altered, so all -diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c -index e622863..086f381 100644 ---- a/fs/cifs/cifs_spnego.c -+++ b/fs/cifs/cifs_spnego.c -@@ -31,18 +31,18 @@ - - /* create a new cifs key */ - static int --cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - int ret; - - ret = -ENOMEM; -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - goto error; - - /* attach the data */ -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; - ret = 0; - -diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c -index 05f4dc2..f3c60e2 100644 ---- a/fs/cifs/cifsacl.c -+++ b/fs/cifs/cifsacl.c -@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { - }; - - static int --cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - return -ENOMEM; - -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; -- key->datalen = datalen; -+ key->datalen = prep->datalen; - return 0; - } - -diff --git a/include/keys/user-type.h b/include/keys/user-type.h -index bc9ec1d..5e452c8 100644 ---- a/include/keys/user-type.h -+++ b/include/keys/user-type.h -@@ -35,8 +35,10 @@ struct user_key_payload { - extern struct key_type key_type_user; - extern struct key_type key_type_logon; - --extern int user_instantiate(struct key *key, const void *data, size_t datalen); --extern int user_update(struct key *key, const void *data, size_t datalen); -+struct key_preparsed_payload; -+ -+extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); -+extern int user_update(struct key *key, struct key_preparsed_payload *prep); - extern int user_match(const struct key *key, const void *criterion); - extern void user_revoke(struct key *key); - extern void user_destroy(struct key *key); -diff --git a/include/linux/key-type.h b/include/linux/key-type.h -index f0c651c..518a53a 100644 ---- a/include/linux/key-type.h -+++ b/include/linux/key-type.h -@@ -26,6 +26,27 @@ struct key_construction { - struct key *authkey;/* authorisation for key being constructed */ - }; - -+/* -+ * Pre-parsed payload, used by key add, update and instantiate. -+ * -+ * This struct will be cleared and data and datalen will be set with the data -+ * and length parameters from the caller and quotalen will be set from -+ * def_datalen from the key type. Then if the preparse() op is provided by the -+ * key type, that will be called. Then the struct will be passed to the -+ * instantiate() or the update() op. -+ * -+ * If the preparse() op is given, the free_preparse() op will be called to -+ * clear the contents. -+ */ -+struct key_preparsed_payload { -+ char *description; /* Proposed key description (or NULL) */ -+ void *type_data[2]; /* Private key-type data */ -+ void *payload; /* Proposed payload */ -+ const void *data; /* Raw data */ -+ size_t datalen; /* Raw datalen */ -+ size_t quotalen; /* Quota length for proposed payload */ -+}; -+ - typedef int (*request_key_actor_t)(struct key_construction *key, - const char *op, void *aux); - -@@ -45,18 +66,28 @@ struct key_type { - /* vet a description */ - int (*vet_description)(const char *description); - -+ /* Preparse the data blob from userspace that is to be the payload, -+ * generating a proposed description and payload that will be handed to -+ * the instantiate() and update() ops. -+ */ -+ int (*preparse)(struct key_preparsed_payload *prep); -+ -+ /* Free a preparse data structure. -+ */ -+ void (*free_preparse)(struct key_preparsed_payload *prep); -+ - /* instantiate a key of this type - * - this method should call key_payload_reserve() to determine if the - * user's quota will hold the payload - */ -- int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - /* update a key of this type (optional) - * - this method should call key_payload_reserve() to recalculate the - * quota consumption - * - the key must be locked against read when modifying - */ -- int (*update)(struct key *key, const void *data, size_t datalen); -+ int (*update)(struct key *key, struct key_preparsed_payload *prep); - - /* match a key against a description */ - int (*match)(const struct key *key, const void *desc); -diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c -index 9da7fdd..af14cb4 100644 ---- a/net/ceph/crypto.c -+++ b/net/ceph/crypto.c -@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, - } - } - --int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) -+int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct ceph_crypto_key *ckey; -+ size_t datalen = prep->datalen; - int ret; - void *p; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto err; - - ret = key_payload_reserve(key, datalen); -@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) - goto err; - - /* TODO ceph_crypto_key_decode should really take const input */ -- p = (void *)data; -- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); -+ p = (void *)prep->data; -+ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); - if (ret < 0) - goto err_ckey; - -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index d9507dd..859ab8b 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; - * "ip1,ip2,...#foo=bar" - */ - static int --dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) -+dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; - unsigned long derrno; - int ret; -- size_t result_len = 0; -- const char *data = _data, *end, *opt; -+ size_t datalen = prep->datalen, result_len = 0; -+ const char *data = prep->data, *end, *opt; - - kenter("%%%d,%s,'%*.*s',%zu", - key->serial, key->description, -diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c -index 8b1f9f4..106c5a6 100644 ---- a/net/rxrpc/ar-key.c -+++ b/net/rxrpc/ar-key.c -@@ -26,8 +26,8 @@ - #include "ar-internal.h" - - static int rxrpc_vet_description_s(const char *); --static int rxrpc_instantiate(struct key *, const void *, size_t); --static int rxrpc_instantiate_s(struct key *, const void *, size_t); -+static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); -+static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); - static void rxrpc_destroy(struct key *); - static void rxrpc_destroy_s(struct key *); - static void rxrpc_describe(const struct key *, struct seq_file *); -@@ -678,7 +678,7 @@ error: - * - * if no data is provided, then a no-security key is made - */ --static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) -+static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - const struct rxrpc_key_data_v1 *v1; - struct rxrpc_key_token *token, **pp; -@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - u32 kver; - int ret; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - - /* handle a no-security key */ -- if (!data && datalen == 0) -+ if (!prep->data && prep->datalen == 0) - return 0; - - /* determine if the XDR payload format is being used */ -- if (datalen > 7 * 4) { -- ret = rxrpc_instantiate_xdr(key, data, datalen); -+ if (prep->datalen > 7 * 4) { -+ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); - if (ret != -EPROTO) - return ret; - } - - /* get the key interface version number */ - ret = -EINVAL; -- if (datalen <= 4 || !data) -+ if (prep->datalen <= 4 || !prep->data) - goto error; -- memcpy(&kver, data, sizeof(kver)); -- data += sizeof(kver); -- datalen -= sizeof(kver); -+ memcpy(&kver, prep->data, sizeof(kver)); -+ prep->data += sizeof(kver); -+ prep->datalen -= sizeof(kver); - - _debug("KEY I/F VERSION: %u", kver); - -@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - - /* deal with a version 1 key */ - ret = -EINVAL; -- if (datalen < sizeof(*v1)) -+ if (prep->datalen < sizeof(*v1)) - goto error; - -- v1 = data; -- if (datalen != sizeof(*v1) + v1->ticket_length) -+ v1 = prep->data; -+ if (prep->datalen != sizeof(*v1) + v1->ticket_length) - goto error; - - _debug("SCIX: %u", v1->security_index); -@@ -784,17 +784,17 @@ error: - * instantiate a server secret key - * data should be a pointer to the 8-byte secret key - */ --static int rxrpc_instantiate_s(struct key *key, const void *data, -- size_t datalen) -+static int rxrpc_instantiate_s(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct crypto_blkcipher *ci; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - -- if (datalen != 8) -+ if (prep->datalen != 8) - return -EINVAL; - -- memcpy(&key->type_data, data, 8); -+ memcpy(&key->type_data, prep->data, 8); - - ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(ci)) { -@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, - return PTR_ERR(ci); - } - -- if (crypto_blkcipher_setkey(ci, data, 8) < 0) -+ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) - BUG(); - - key->payload.data = ci; -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 2d1bb8a..9e1e005 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int encrypted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = NULL; - char *datablob = NULL; -@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, - char *master_desc = NULL; - char *decrypted_datalen = NULL; - char *hex_encoded_iv = NULL; -+ size_t datalen = prep->datalen; - int ret; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; - datablob[datalen] = 0; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - ret = datablob_parse(datablob, &format, &master_desc, - &decrypted_datalen, &hex_encoded_iv); - if (ret < 0) -@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_update(struct key *key, const void *data, size_t datalen) -+static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = key->payload.data; - struct encrypted_key_payload *new_epayload; - char *buf; - char *new_master_desc = NULL; - const char *format = NULL; -+ size_t datalen = prep->datalen; - int ret = 0; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - buf = kmalloc(datalen + 1, GFP_KERNEL); -@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) - return -ENOMEM; - - buf[datalen] = 0; -- memcpy(buf, data, datalen); -+ memcpy(buf, prep->data, datalen); - ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); - if (ret < 0) - goto out; -diff --git a/security/keys/key.c b/security/keys/key.c -index 50d96d4..732a53e 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); - * key_construction_mutex. - */ - static int __key_instantiate_and_link(struct key *key, -- const void *data, -- size_t datalen, -+ struct key_preparsed_payload *prep, - struct key *keyring, - struct key *authkey, - unsigned long *_prealloc) -@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, - /* can't instantiate twice */ - if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { - /* instantiate the key */ -- ret = key->type->instantiate(key, data, datalen); -+ ret = key->type->instantiate(key, prep); - - if (ret == 0) { - /* mark the key as being instantiated */ -@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, - struct key *keyring, - struct key *authkey) - { -+ struct key_preparsed_payload prep; - unsigned long prealloc; - int ret; - -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = data; -+ prep.datalen = datalen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; -+ } -+ - if (keyring) { - ret = __key_link_begin(keyring, key->type, key->description, - &prealloc); - if (ret < 0) -- return ret; -+ goto error_free_preparse; - } - -- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, -+ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, - &prealloc); - - if (keyring) - __key_link_end(keyring, key->type, prealloc); - -+error_free_preparse: -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - -@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) - * if we get an error. - */ - static inline key_ref_t __key_update(key_ref_t key_ref, -- const void *payload, size_t plen) -+ struct key_preparsed_payload *prep) - { - struct key *key = key_ref_to_ptr(key_ref); - int ret; -@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, - - down_write(&key->sem); - -- ret = key->type->update(key, payload, plen); -+ ret = key->type->update(key, prep); - if (ret == 0) - /* updating a negative key instantiates it */ - clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - unsigned long flags) - { - unsigned long prealloc; -+ struct key_preparsed_payload prep; - const struct cred *cred = current_cred(); - struct key_type *ktype; - struct key *keyring, *key = NULL; -@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - } - - key_ref = ERR_PTR(-EINVAL); -- if (!ktype->match || !ktype->instantiate) -- goto error_2; -+ if (!ktype->match || !ktype->instantiate || -+ (!description && !ktype->preparse)) -+ goto error_put_type; - - keyring = key_ref_to_ptr(keyring_ref); - -@@ -798,18 +814,33 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - - key_ref = ERR_PTR(-ENOTDIR); - if (keyring->type != &key_type_keyring) -- goto error_2; -+ goto error_put_type; -+ -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = ktype->def_datalen; -+ if (ktype->preparse) { -+ ret = ktype->preparse(&prep); -+ if (ret < 0) -+ goto error_put_type; -+ if (!description) -+ description = prep.description; -+ ret = -EINVAL; -+ if (!description) -+ goto error_free_prep; -+ } - - ret = __key_link_begin(keyring, ktype, description, &prealloc); - if (ret < 0) -- goto error_2; -+ goto error_free_prep; - - /* if we're going to allocate a new key, we're going to have - * to modify the keyring */ - ret = key_permission(keyring_ref, KEY_WRITE); - if (ret < 0) { - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - /* if it's possible to update this type of key, search for an existing -@@ -840,25 +871,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - perm, flags); - if (IS_ERR(key)) { - key_ref = ERR_CAST(key); -- goto error_3; -+ goto error_link_end; - } - - /* instantiate it and link it into the target keyring */ -- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, -- &prealloc); -+ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); - if (ret < 0) { - key_put(key); - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); - -- error_3: -+error_link_end: - __key_link_end(keyring, ktype, prealloc); -- error_2: -+error_free_prep: -+ if (ktype->preparse) -+ ktype->free_preparse(&prep); -+error_put_type: - key_type_put(ktype); -- error: -+error: - return key_ref; - - found_matching_key: -@@ -866,10 +899,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - * - we can drop the locks first as we have the key pinned - */ - __key_link_end(keyring, ktype, prealloc); -- key_type_put(ktype); - -- key_ref = __key_update(key_ref, payload, plen); -- goto error; -+ key_ref = __key_update(key_ref, &prep); -+ goto error_free_prep; - } - EXPORT_SYMBOL(key_create_or_update); - -@@ -888,6 +920,7 @@ EXPORT_SYMBOL(key_create_or_update); - */ - int key_update(key_ref_t key_ref, const void *payload, size_t plen) - { -+ struct key_preparsed_payload prep; - struct key *key = key_ref_to_ptr(key_ref); - int ret; - -@@ -900,18 +933,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - - /* attempt to update it if supported */ - ret = -EOPNOTSUPP; -- if (key->type->update) { -- down_write(&key->sem); -- -- ret = key->type->update(key, payload, plen); -- if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ if (!key->type->update) -+ goto error; - -- up_write(&key->sem); -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; - } - -- error: -+ down_write(&key->sem); -+ -+ ret = key->type->update(key, &prep); -+ if (ret == 0) -+ /* updating a negative key instantiates it */ -+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ -+ up_write(&key->sem); -+ -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - EXPORT_SYMBOL(key_update); -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 3364fbf..505d40b 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, - * Extract the description of a new key from userspace and either add it as a - * new key to the specified keyring or update a matching key in that keyring. - * -+ * If the description is NULL or an empty string, the key type is asked to -+ * generate one from the payload. -+ * - * The keyring must be writable so that we can attach the key to it. - * - * If successful, the new key's serial number is returned, otherwise an error -@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, - if (ret < 0) - goto error; - -- description = strndup_user(_description, PAGE_SIZE); -- if (IS_ERR(description)) { -- ret = PTR_ERR(description); -- goto error; -+ description = NULL; -+ if (_description) { -+ description = strndup_user(_description, PAGE_SIZE); -+ if (IS_ERR(description)) { -+ ret = PTR_ERR(description); -+ goto error; -+ } -+ if (!*description) { -+ kfree(description); -+ description = NULL; -+ } - } - - /* pull the payload in if one was supplied */ -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index 81e7852..f04d8cf 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) - * operations. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen); -+ struct key_preparsed_payload *prep); - static int keyring_match(const struct key *keyring, const void *criterion); - static void keyring_revoke(struct key *keyring); - static void keyring_destroy(struct key *keyring); -@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) - * Returns 0 on success, -EINVAL if given any data. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen) -+ struct key_preparsed_payload *prep) - { - int ret; - - ret = -EINVAL; -- if (datalen == 0) { -+ if (prep->datalen == 0) { - /* make the keyring available by name if it has one */ - keyring_publish_name(keyring); - ret = 0; -diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c -index 60d4e3f..85730d5 100644 ---- a/security/keys/request_key_auth.c -+++ b/security/keys/request_key_auth.c -@@ -19,7 +19,8 @@ - #include - #include "internal.h" - --static int request_key_auth_instantiate(struct key *, const void *, size_t); -+static int request_key_auth_instantiate(struct key *, -+ struct key_preparsed_payload *); - static void request_key_auth_describe(const struct key *, struct seq_file *); - static void request_key_auth_revoke(struct key *); - static void request_key_auth_destroy(struct key *); -@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { - * Instantiate a request-key authorisation key. - */ - static int request_key_auth_instantiate(struct key *key, -- const void *data, -- size_t datalen) -+ struct key_preparsed_payload *prep) - { -- key->payload.data = (struct request_key_auth *) data; -+ key->payload.data = (struct request_key_auth *)prep->data; - return 0; - } - -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 2d5d041..42036c7 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) - * - * On success, return 0. Otherwise return errno. - */ --static int trusted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int trusted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct trusted_key_payload *payload = NULL; - struct trusted_key_options *options = NULL; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - int key_cmd; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - - options = trusted_options_alloc(); -@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) - /* - * trusted_update - reseal an existing key with new PCR values - */ --static int trusted_update(struct key *key, const void *data, size_t datalen) -+static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct trusted_key_payload *p = key->payload.data; - struct trusted_key_payload *new_p; - struct trusted_key_options *new_o; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - - if (!p->migratable) - return -EPERM; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); -@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) - goto out; - } - -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { -diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c -index c7660a2..55dc889 100644 ---- a/security/keys/user_defined.c -+++ b/security/keys/user_defined.c -@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); - /* - * instantiate a user defined key - */ --int user_instantiate(struct key *key, const void *data, size_t datalen) -+int user_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - ret = key_payload_reserve(key, datalen); -@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) - - /* attach the data */ - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - rcu_assign_keypointer(key, upayload); - ret = 0; - -@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); - * update a user defined key - * - the key's semaphore is write-locked - */ --int user_update(struct key *key, const void *data, size_t datalen) -+int user_update(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload, *zap; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - /* construct a replacement payload */ -@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) - goto error; - - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - - /* check the quota and attach the new data */ - zap = upayload; --- -1.7.11.4 - - -From 2f5f2d483565648dbe050fda8767edd5d65b1d98 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:17 +0100 -Subject: [PATCH 02/32] MPILIB: Provide count_leading/trailing_zeros() based - on arch functions - -Provide count_leading/trailing_zeros() macros based on extant arch bit scanning -functions rather than reimplementing from scratch in MPILIB. - -Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). - -Also move the definition to asm-generic as other people may be interested in -using it. - -Signed-off-by: David Howells -Cc: David S. Miller -Cc: Dmitry Kasatkin -Cc: Arnd Bergmann ---- - include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ - lib/mpi/longlong.h | 138 +------------------------------ - lib/mpi/mpi-bit.c | 2 +- - lib/mpi/mpi-pow.c | 4 +- - 4 files changed, 62 insertions(+), 139 deletions(-) - create mode 100644 include/asm-generic/bitops/count_zeros.h - -diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h -new file mode 100644 -index 0000000..97520d2 ---- /dev/null -+++ b/include/asm-generic/bitops/count_zeros.h -@@ -0,0 +1,57 @@ -+/* Count leading and trailing zeros functions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+ -+#include -+ -+/** -+ * count_leading_zeros - Count the number of zeros from the MSB back -+ * @x: The value -+ * -+ * Count the number of leading zeros from the MSB going towards the LSB in @x. -+ * -+ * If the MSB of @x is set, the result is 0. -+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. -+ */ -+static inline int count_leading_zeros(unsigned long x) -+{ -+ if (sizeof(x) == 4) -+ return BITS_PER_LONG - fls(x); -+ else -+ return BITS_PER_LONG - fls64(x); -+} -+ -+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG -+ -+/** -+ * count_trailing_zeros - Count the number of zeros from the LSB forwards -+ * @x: The value -+ * -+ * Count the number of trailing zeros from the LSB going towards the MSB in @x. -+ * -+ * If the LSB of @x is set, the result is 0. -+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. -+ */ -+static inline int count_trailing_zeros(unsigned long x) -+{ -+#define COUNT_TRAILING_ZEROS_0 (-1) -+ -+ if (sizeof(x) == 4) -+ return ffs(x); -+ else -+ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; -+} -+ -+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ -diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h -index 29f9862..678ce4f 100644 ---- a/lib/mpi/longlong.h -+++ b/lib/mpi/longlong.h -@@ -19,6 +19,8 @@ - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. */ - -+#include -+ - /* You have to define the following before including this file: - * - * UWtype -- An unsigned type, default type for operations (typically a "word") -@@ -146,12 +148,6 @@ do { \ - : "1" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))) -- --#define count_leading_zeros(count, x) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #endif /* __a29k__ */ - - #if defined(__alpha) && W_TYPE_SIZE == 64 -@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); - : "1" ((USItype)(nh)), \ - "0" ((USItype)(nl)), \ - "g" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bsch/1 %1,%0" \ -- : "=g" (count) \ -- : "g" ((USItype)(x)), \ -- "0" ((USItype)0)) - #endif - - /*************************************** -@@ -354,27 +345,6 @@ do { USItype __r; \ - } while (0) - extern USItype __udiv_qrnnd(); - #endif /* LONGLONG_STANDALONE */ --#define count_leading_zeros(count, x) \ --do { \ -- USItype __tmp; \ -- __asm__ ( \ -- "ldi 1,%0\n" \ -- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ -- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ -- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ -- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ -- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ -- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ -- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ -- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ -- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ -- "extru %1,30,1,%1 ; Extract bit 1.\n" \ -- "sub %0,%1,%0 ; Subtract it. " \ -- : "=r" (count), "=r" (__tmp) : "1" (x)); \ --} while (0) - #endif /* hppa */ - - /*************************************** -@@ -457,15 +427,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "rm" ((USItype)(d))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("bsrl %1,%0" \ -- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define count_trailing_zeros(count, x) \ -- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) - #ifndef UMUL_TIME - #define UMUL_TIME 40 - #endif -@@ -536,15 +497,6 @@ do { \ - "dI" ((USItype)(d))); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("scanbit %1,%0" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ - #if defined(__i960mx) /* what is the proper symbol to test??? */ - #define rshift_rhlc(r, h, l, c) \ - do { \ -@@ -603,11 +555,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bfffo %1{%b2:%b2},%0" \ -- : "=d" ((USItype)(count)) \ -- : "od" ((USItype)(x)), "n" (0)) --#define COUNT_LEADING_ZEROS_0 32 - #else /* not mc68020 */ - #define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ -@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ - "rJ" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("ff1 %0,%1" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 63 /* sic */ - #if defined(__m88110__) - #define umul_ppmm(wh, wl, u, v) \ - do { \ -@@ -779,12 +717,6 @@ do { \ - : "0" (__xx.__ll), \ - "g" ((USItype)(d))); \ - (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) --#define count_trailing_zeros(count, x) \ --do { \ -- __asm__("ffsd %2,%0" \ -- : "=r"((USItype) (count)) \ -- : "0"((USItype) 0), "r"((USItype) (x))); \ -- } while (0) - #endif /* __ns32000__ */ - - /*************************************** -@@ -855,11 +787,6 @@ do { \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - } while (0) --#define count_leading_zeros(count, x) \ -- __asm__ ("{cntlz|cntlzw} %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #if defined(_ARCH_PPC) - #define umul_ppmm(ph, pl, m0, m1) \ - do { \ -@@ -1001,19 +928,6 @@ do { \ - } while (0) - #define UMUL_TIME 20 - #define UDIV_TIME 200 --#define count_leading_zeros(count, x) \ --do { \ -- if ((x) >= 0x10000) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x) >> 16)); \ -- else { \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))); \ -- (count) += 16; \ -- } \ --} while (0) - #endif /* RT/ROMP */ - - /*************************************** -@@ -1142,13 +1056,6 @@ do { \ - "rI" ((USItype)(d)) \ - : "%g1" __AND_CLOBBER_CC) - #define UDIV_TIME 37 --#define count_leading_zeros(count, x) \ -- __asm__ ("scan %1,0,%0" \ -- : "=r" ((USItype)(x)) \ -- : "r" ((USItype)(count))) --/* Early sparclites return 63 for an argument of 0, but they warn that future -- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 -- undefined. */ - #endif /* __sparclite__ */ - #endif /* __sparc_v8__ */ - /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -@@ -1454,47 +1361,6 @@ do { \ - #define udiv_qrnnd __udiv_qrnnd_c - #endif - --#undef count_leading_zeros --#if !defined(count_leading_zeros) -- extern --#ifdef __STDC__ -- const --#endif -- unsigned char __clz_tab[]; --#define count_leading_zeros(count, x) \ --do { \ -- UWtype __xr = (x); \ -- UWtype __a; \ -- \ -- if (W_TYPE_SIZE <= 32) { \ -- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ -- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ -- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ -- } \ -- else { \ -- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ -- if (((__xr >> __a) & 0xff) != 0) \ -- break; \ -- } \ -- \ -- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ --} while (0) -- /* This version gives a well-defined value for zero. */ --#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE --#endif -- --#if !defined(count_trailing_zeros) --/* Define count_trailing_zeros using count_leading_zeros. The latter might be -- defined in asm, but if it is not, the C version above is good enough. */ --#define count_trailing_zeros(count, x) \ --do { \ -- UWtype __ctz_x = (x); \ -- UWtype __ctz_c; \ -- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ -- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ --} while (0) --#endif -- - #ifndef UDIV_NEEDS_NORMALIZATION - #define UDIV_NEEDS_NORMALIZATION 0 - #endif -diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c -index 5687248..503537e 100644 ---- a/lib/mpi/mpi-bit.c -+++ b/lib/mpi/mpi-bit.c -@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) - if (a->nlimbs) { - mpi_limb_t alimb = a->d[a->nlimbs - 1]; - if (alimb) -- count_leading_zeros(n, alimb); -+ n = count_leading_zeros(alimb); - else - n = BITS_PER_MPI_LIMB; - n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index 67f3e79..5464c87 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - mp = mp_marker = mpi_alloc_limb_space(msize); - if (!mp) - goto enomem; -- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); -+ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); - if (mod_shift_cnt) - mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); - else -@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - - i = esize - 1; - e = ep[i]; -- count_leading_zeros(c, e); -+ c = count_leading_zeros(e); - e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ - c = BITS_PER_MPI_LIMB - 1 - c; - --- -1.7.11.4 - - -From 15b76403afcc626b91e5fcee8b6a950a51f284ef Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:18 +0100 -Subject: [PATCH 03/32] KEYS: Create a key type that can be used for general - cryptographic operations - -Create a key type that can be used for general cryptographic operations, such -as encryption, decryption, signature generation and signature verification. - -The key type is "crypto" and can provide access to a variety of cryptographic -algorithms. - -Signed-off-by: David Howells ---- - Documentation/security/keys-crypto.txt | 181 ++++++++++++++++++++++ - include/keys/crypto-subtype.h | 57 +++++++ - include/keys/crypto-type.h | 25 +++ - security/keys/Kconfig | 2 + - security/keys/Makefile | 1 + - security/keys/crypto/Kconfig | 7 + - security/keys/crypto/Makefile | 7 + - security/keys/crypto/crypto_keys.h | 28 ++++ - security/keys/crypto/crypto_type.c | 272 +++++++++++++++++++++++++++++++++ - 9 files changed, 580 insertions(+) - create mode 100644 Documentation/security/keys-crypto.txt - create mode 100644 include/keys/crypto-subtype.h - create mode 100644 include/keys/crypto-type.h - create mode 100644 security/keys/crypto/Kconfig - create mode 100644 security/keys/crypto/Makefile - create mode 100644 security/keys/crypto/crypto_keys.h - create mode 100644 security/keys/crypto/crypto_type.c - -diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt -new file mode 100644 -index 0000000..97dee80 ---- /dev/null -+++ b/Documentation/security/keys-crypto.txt -@@ -0,0 +1,181 @@ -+ ====================== -+ CRYPTOGRAPHIC KEY TYPE -+ ====================== -+ -+Contents: -+ -+ - Overview. -+ - Key identification. -+ - Accessing crypto keys. -+ - Implementing crypto parsers. -+ - Implementing crypto subtypes. -+ -+ -+======== -+OVERVIEW -+======== -+ -+The "crypto" key type is designed to be a container for cryptographic keys, -+without imposing any particular restrictions on the form of the cryptography or -+the key. -+ -+The crypto key is given a subtype that defines what sort of data is associated -+with the key and provides operations to describe and destroy it. However, no -+requirement is made that the key data actually be loaded into the key. -+ -+The crypto key also has a number of data parsers registered with it. The data -+parsers are responsible for extracing information the blobs of data passed to -+the instantiator function. The first data parser that recognises the blob gets -+to set the subtype of the key and define the operations that can be done on -+that key. -+ -+Completely in-kernel key retention and operation subtypes and parsers can be -+defined, but it would also be possible to provide access to cryptographic -+hardware (such as a TPM) that might be used to both retain the relevant key and -+perform operations using that key. In such a case, the crypto key would then -+merely be an interface to the TPM driver. -+ -+ -+================== -+KEY IDENTIFICATION -+================== -+ -+Because the identity of a key is not necessarily known and may not be easily -+calculated when a crypto key is allocated, it may not be a simple matter to set -+a key description to something that's useful for determining whether this is -+the key you're looking for. Furthermore, it may be necessary to perform a -+partial match upon the key identity. -+ -+To help with this, when a key is loaded, the parser calculates the key -+fingerprint and stores a copy in the key structure. -+ -+The crypto key type's key matching function then performs more checks than just -+the straightforward comparison of the description with the criterion string: -+ -+ (1) If the criterion string is of the form "id:" then the match -+ function will examine a key's fingerprint to see if the hex digits given -+ after the "id:" match the tail. For instance: -+ -+ keyctl search @s crypto id:5acc2142 -+ -+ will match a key with fingerprint: -+ -+ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 -+ -+ (2) If the criterion string is of the form ":" then the -+ match will match the ID as in (1), but with the added restriction that -+ only keys of the specified subtype (e.g. dsa or rsa) will be matched. For -+ instance: -+ -+ keyctl search @s crypto dsa:5acc2142 -+ -+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are -+displayed, along with the subtype: -+ -+ 1a39e171 I----- 1 perm 3f010000 0 0 crypto modsign.0: DSA 5acc2142 [] -+ -+ -+===================== -+ACCESSING CRYPTO KEYS -+===================== -+ -+To access crypto keys from within the kernel, the following inclusion is -+required: -+ -+ #include -+ -+This gives access to the key type: -+ -+ struct key_type key_type_crypto; -+ -+ -+=========================== -+IMPLEMENTING CRYPTO PARSERS -+=========================== -+ -+The crypto key type keeps a list of registered data parsers. An example of -+such a parser is one that parses OpenPGP packet formatted data [RFC 4880]. -+ -+During key instantiation each parser in the list is tried until one doesn't -+return -EBADMSG. -+ -+The parser definition structure looks like the following: -+ -+ struct crypto_key_parser { -+ struct module *owner; -+ const char *name; -+ -+ int (*instantiate)(struct key *key, -+ const void *data, size_t datalen); -+ }; -+ -+The owner and name fields should be set to the owning module and the name of -+the parser. -+ -+There are a number of operations defined by the parser. They are all optional, -+but it is expected that at least one will be defined. -+ -+ (1) instantiate(). -+ -+ The arguments are the same as for the instantiate function in the key -+ type. 'key' is the crypto key being instantiated; data and datalen are -+ the instantiation data, presumably containing cryptographic key data, and -+ the length of that data. -+ -+ If the data format is not recognised, -EBADMSG should be returned. If it -+ is recognised, but the key cannot for some reason be set up, some other -+ negative error code should be returned. -+ -+ If the key can be successfully set up, then key->payload should be set to -+ point to the retained data, key->type_data.p[0] should be set to point to -+ the subtype chosen and key->type_data.p[1] should be set to point to a -+ copy of the key's identity string and 0 should be returned. -+ -+ The key's identity string may be partially matched upon. For a public-key -+ algorithm such as RSA and DSA this will likely be a printable hex version -+ of the key's fingerprint. -+ -+Functions are provided to register and unregister parsers: -+ -+ int register_crypto_key_parser(struct crypto_key_parser *parser); -+ void unregister_crypto_key_parser(struct crypto_key_parser *subtype); -+ -+Parsers may not have the same name. The names are only used for displaying in -+debugging messages. -+ -+ -+============================ -+IMPLEMENTING CRYPTO SUBTYPES -+============================ -+ -+The parser selects the appropriate subtype directly and sets it on the key; the -+crypto key then retains a reference on the subtype module (which means the -+parser can be removed thereafter). -+ -+The subtype definition structure looks like the following: -+ -+ struct crypto_key_subtype { -+ struct module *owner; -+ const char *name; -+ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ void (*destroy)(void *payload); -+ }; -+ -+The owner and name fields should be set to the owning module and the name of -+the subtype. -+ -+There are a number of operations defined by the subtype: -+ -+ (1) describe(). -+ -+ Mandatory. This allows the subtype to display something in /proc/keys -+ against the key. For instance the name of the public key algorithm type -+ could be displayed. The key type will display the tail of the key -+ identity string after this. -+ -+ (2) destroy(). -+ -+ Mandatory. This should free the memory associated with the key. The -+ crypto key will look after freeing the fingerprint and releasing the -+ reference on the subtype module. -diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h -new file mode 100644 -index 0000000..1f546e6 ---- /dev/null -+++ b/include/keys/crypto-subtype.h -@@ -0,0 +1,57 @@ -+/* Cryptographic key subtype -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ * -+ * See Documentation/security/keys-crypto.txt -+ */ -+ -+#ifndef _KEYS_CRYPTO_SUBTYPE_H -+#define _KEYS_CRYPTO_SUBTYPE_H -+ -+#include -+#include -+ -+extern struct key_type key_type_crypto; -+ -+/* -+ * Keys of this type declare a subtype that indicates the handlers and -+ * capabilities. -+ */ -+struct crypto_key_subtype { -+ struct module *owner; -+ const char *name; -+ unsigned short name_len; /* length of name */ -+ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ -+ void (*destroy)(void *payload); -+}; -+ -+/* -+ * Data parser. Called during instantiation and signature verification -+ * initiation. -+ */ -+struct crypto_key_parser { -+ struct list_head link; -+ struct module *owner; -+ const char *name; -+ -+ /* Attempt to parse a key from the data blob passed to add_key() or -+ * keyctl_instantiate(). Should also generate a proposed description -+ * that the caller can optionally use for the key. -+ * -+ * Return EBADMSG if not recognised. -+ */ -+ int (*preparse)(struct key_preparsed_payload *prep); -+}; -+ -+extern int register_crypto_key_parser(struct crypto_key_parser *); -+extern void unregister_crypto_key_parser(struct crypto_key_parser *); -+ -+#endif /* _KEYS_CRYPTO_SUBTYPE_H */ -diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h -new file mode 100644 -index 0000000..47c00c7 ---- /dev/null -+++ b/include/keys/crypto-type.h -@@ -0,0 +1,25 @@ -+/* Cryptographic key type interface -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ * -+ * See Documentation/security/keys-crypto.txt -+ */ -+ -+#ifndef _KEYS_CRYPTO_TYPE_H -+#define _KEYS_CRYPTO_TYPE_H -+ -+#include -+ -+extern struct key_type key_type_crypto; -+ -+/* -+ * The payload is at the discretion of the subtype. -+ */ -+ -+#endif /* _KEYS_CRYPTO_TYPE_H */ -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index a90d6d3..992fe52 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -69,3 +69,5 @@ config KEYS_DEBUG_PROC_KEYS - the resulting table. - - If you are unsure as to whether this is required, answer N. -+ -+source security/keys/crypto/Kconfig -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 504aaa0..67dae73 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -24,3 +24,4 @@ obj-$(CONFIG_SYSCTL) += sysctl.o - # - obj-$(CONFIG_TRUSTED_KEYS) += trusted.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ -+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto/ -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -new file mode 100644 -index 0000000..3d15710 ---- /dev/null -+++ b/security/keys/crypto/Kconfig -@@ -0,0 +1,7 @@ -+config CRYPTO_KEY_TYPE -+ tristate "Cryptographic key type" -+ depends on KEYS -+ help -+ This option provides support for a type of key that holds the keys -+ required for cryptographic operations such as encryption, decryption, -+ signature generation and signature verification. -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -new file mode 100644 -index 0000000..36db1d5 ---- /dev/null -+++ b/security/keys/crypto/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for cryptographic keys -+# -+ -+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o -+ -+crypto_keys-y := crypto_type.o -diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h -new file mode 100644 -index 0000000..eb11788 ---- /dev/null -+++ b/security/keys/crypto/crypto_keys.h -@@ -0,0 +1,28 @@ -+/* Internal crypto type stuff -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+static inline -+struct crypto_key_subtype *crypto_key_subtype(const struct key *key) -+{ -+ return key->type_data.p[0]; -+} -+ -+static inline const char *crypto_key_id(const struct key *key) -+{ -+ return key->type_data.p[1]; -+} -+ -+ -+/* -+ * crypto_type.c -+ */ -+extern struct list_head crypto_key_parsers; -+extern struct rw_semaphore crypto_key_parsers_sem; -diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c -new file mode 100644 -index 0000000..e8f83a6 ---- /dev/null -+++ b/security/keys/crypto/crypto_type.c -@@ -0,0 +1,272 @@ -+/* Cryptographic key type -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ * -+ * See Documentation/security/keys-crypto.txt -+ */ -+#include -+#include -+#include -+#include -+#include "crypto_keys.h" -+ -+MODULE_LICENSE("GPL"); -+ -+LIST_HEAD(crypto_key_parsers); -+DECLARE_RWSEM(crypto_key_parsers_sem); -+ -+/* -+ * Match crypto_keys on (part of) their name -+ * We have some shorthand methods for matching keys. We allow: -+ * -+ * "" - request a key by description -+ * "id:" - request a key matching the ID -+ * ":" - request a key of a subtype -+ */ -+static int crypto_key_match(const struct key *key, const void *description) -+{ -+ const struct crypto_key_subtype *subtype = crypto_key_subtype(key); -+ const char *spec = description; -+ const char *id, *kid; -+ ptrdiff_t speclen; -+ size_t idlen, kidlen; -+ -+ if (!subtype || !spec || !*spec) -+ return 0; -+ -+ /* See if the full key description matches as is */ -+ if (key->description && strcmp(key->description, description) == 0) -+ return 1; -+ -+ /* All tests from here on break the criterion description into a -+ * specifier, a colon and then an identifier. -+ */ -+ id = strchr(spec, ':'); -+ if (!id) -+ return 0; -+ -+ speclen = id - spec; -+ id++; -+ -+ /* Anything after here requires a partial match on the ID string */ -+ kid = crypto_key_id(key); -+ if (!kid) -+ return 0; -+ -+ idlen = strlen(id); -+ kidlen = strlen(kid); -+ if (idlen > kidlen) -+ return 0; -+ -+ kid += kidlen - idlen; -+ if (strcasecmp(id, kid) != 0) -+ return 0; -+ -+ if (speclen == 2 && -+ memcmp(spec, "id", 2) == 0) -+ return 1; -+ -+ if (speclen == subtype->name_len && -+ memcmp(spec, subtype->name, speclen) == 0) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Describe the crypto key -+ */ -+static void crypto_key_describe(const struct key *key, struct seq_file *m) -+{ -+ const struct crypto_key_subtype *subtype = crypto_key_subtype(key); -+ const char *kid = crypto_key_id(key); -+ size_t n; -+ -+ seq_puts(m, key->description); -+ -+ if (subtype) { -+ seq_puts(m, ": "); -+ subtype->describe(key, m); -+ -+ if (kid) { -+ seq_putc(m, ' '); -+ n = strlen(kid); -+ if (n <= 8) -+ seq_puts(m, kid); -+ else -+ seq_puts(m, kid + n - 8); -+ } -+ -+ seq_puts(m, " ["); -+ /* put something here to indicate the key's capabilities */ -+ seq_putc(m, ']'); -+ } -+} -+ -+/* -+ * Preparse a crypto payload to get format the contents appropriately for the -+ * internal payload to cut down on the number of scans of the data performed. -+ * -+ * We also generate a proposed description from the contents of the key that -+ * can be used to name the key if the user doesn't want to provide one. -+ */ -+static int crypto_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct crypto_key_parser *parser; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (prep->datalen == 0) -+ return -EINVAL; -+ -+ down_read(&crypto_key_parsers_sem); -+ -+ ret = -EBADMSG; -+ list_for_each_entry(parser, &crypto_key_parsers, link) { -+ pr_debug("Trying parser '%s'\n", parser->name); -+ -+ ret = parser->preparse(prep); -+ if (ret != -EBADMSG) { -+ pr_debug("Parser recognised the format (ret %d)\n", -+ ret); -+ break; -+ } -+ } -+ -+ up_read(&crypto_key_parsers_sem); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Clean up the preparse data -+ */ -+static void crypto_key_free_preparse(struct key_preparsed_payload *prep) -+{ -+ struct crypto_key_subtype *subtype = prep->type_data[0]; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (subtype) { -+ subtype->destroy(prep->payload); -+ module_put(subtype->owner); -+ } -+ kfree(prep->type_data[1]); -+ kfree(prep->description); -+} -+ -+/* -+ * Instantiate a crypto_key defined key -+ */ -+static int crypto_key_instantiate(struct key *key, struct key_preparsed_payload *prep) -+{ -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ ret = key_payload_reserve(key, prep->quotalen); -+ if (ret == 0) { -+ key->type_data.p[0] = prep->type_data[0]; -+ key->type_data.p[1] = prep->type_data[1]; -+ key->payload.data = prep->payload; -+ prep->type_data[0] = NULL; -+ prep->type_data[1] = NULL; -+ prep->payload = NULL; -+ } -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * dispose of the data dangling from the corpse of a crypto key -+ */ -+static void crypto_key_destroy(struct key *key) -+{ -+ struct crypto_key_subtype *subtype = crypto_key_subtype(key); -+ if (subtype) { -+ subtype->destroy(key->payload.data); -+ module_put(subtype->owner); -+ key->type_data.p[0] = NULL; -+ } -+ kfree(key->type_data.p[1]); -+ key->type_data.p[1] = NULL; -+} -+ -+struct key_type key_type_crypto = { -+ .name = "crypto", -+ .preparse = crypto_key_preparse, -+ .free_preparse = crypto_key_free_preparse, -+ .instantiate = crypto_key_instantiate, -+ .match = crypto_key_match, -+ .destroy = crypto_key_destroy, -+ .describe = crypto_key_describe, -+}; -+EXPORT_SYMBOL_GPL(key_type_crypto); -+ -+/** -+ * register_crypto_key_parser - Register a crypto key blob parser -+ * @parser: The parser to register -+ */ -+int register_crypto_key_parser(struct crypto_key_parser *parser) -+{ -+ struct crypto_key_parser *cursor; -+ int ret; -+ -+ down_write(&crypto_key_parsers_sem); -+ -+ list_for_each_entry(cursor, &crypto_key_parsers, link) { -+ if (strcmp(cursor->name, parser->name) == 0) { -+ pr_err("Crypto key parser '%s' already registered\n", -+ parser->name); -+ ret = -EEXIST; -+ goto out; -+ } -+ } -+ -+ list_add_tail(&parser->link, &crypto_key_parsers); -+ -+ pr_notice("Crypto key parser '%s' registered\n", parser->name); -+ ret = 0; -+ -+out: -+ up_write(&crypto_key_parsers_sem); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(register_crypto_key_parser); -+ -+/** -+ * unregister_crypto_key_parser - Unregister a crypto key blob parser -+ * @parser: The parser to unregister -+ */ -+void unregister_crypto_key_parser(struct crypto_key_parser *parser) -+{ -+ down_write(&crypto_key_parsers_sem); -+ list_del(&parser->link); -+ up_write(&crypto_key_parsers_sem); -+ -+ pr_notice("Crypto key parser '%s' unregistered\n", parser->name); -+} -+EXPORT_SYMBOL_GPL(unregister_crypto_key_parser); -+ -+/* -+ * Module stuff -+ */ -+static int __init crypto_key_init(void) -+{ -+ return register_key_type(&key_type_crypto); -+} -+ -+static void __exit crypto_key_cleanup(void) -+{ -+ unregister_key_type(&key_type_crypto); -+} -+ -+module_init(crypto_key_init); -+module_exit(crypto_key_cleanup); --- -1.7.11.4 - - -From a4e8ef15db9c013c4d3141424120c5ba74376483 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:18 +0100 -Subject: [PATCH 04/32] KEYS: Add signature verification facility - -Add a facility whereby a key subtype may be asked to verify a signature against -the data it is purported to have signed. - -This adds four routines: - - (1) struct crypto_key_verify_context * - verify_sig_begin(struct key *keyring, const void *sig, size_t siglen); - - This sets up a verification context for the given signature using - information in that signature to select a key from the specified keyring - and to request a hash algorithm from the crypto layer. - - (2) int verify_sig_add_data(struct crypto_key_verify_context *ctx, - const void *data, size_t datalen); - - Incrementally supply data to be signed. May be called multiple times. - - (3) int verify_sig_end(struct crypto_key_verify_context *ctx, - const void *sig, size_t siglen); - - Complete the verification process and return the result. -EKEYREJECTED - will indicate that the verification failed and 0 will indicate success. - Other errors are also possible. - - (4) void verify_sig_cancel(struct crypto_key_verify_context *ctx); - - Cancel the verification process. - -Signed-off-by: David Howells ---- - Documentation/security/keys-crypto.txt | 100 +++++++++++++++++++++ - include/keys/crypto-subtype.h | 36 +++++++- - include/keys/crypto-type.h | 9 ++ - security/keys/crypto/Makefile | 2 +- - security/keys/crypto/crypto_keys.h | 1 - - security/keys/crypto/crypto_type.c | 2 +- - security/keys/crypto/crypto_verify.c | 159 +++++++++++++++++++++++++++++++++ - 7 files changed, 304 insertions(+), 5 deletions(-) - create mode 100644 security/keys/crypto/crypto_verify.c - -diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt -index 97dee80..0a886ec 100644 ---- a/Documentation/security/keys-crypto.txt -+++ b/Documentation/security/keys-crypto.txt -@@ -7,6 +7,7 @@ Contents: - - Overview. - - Key identification. - - Accessing crypto keys. -+ - Signature verification. - - Implementing crypto parsers. - - Implementing crypto subtypes. - -@@ -89,6 +90,65 @@ This gives access to the key type: - struct key_type key_type_crypto; - - -+SIGNATURE VERIFICATION -+---------------------- -+ -+The four operations that can perform cryptographic signature verification, -+using one of a set of keys to provide the public key: -+ -+ (1) Begin verification procedure. -+ -+ struct crypto_key_verify_context * -+ verify_sig_begin(struct key *keyring, const void *sig, size_t siglen); -+ -+ This function sets up a verification context from the information in the -+ signature and looks for a suitable key in the keyring. The signature blob -+ must be presented again at the end of the procedure. The keys will be -+ checked against parameters in the signature, and if the matching one is -+ not found then -ENOKEY will be returned. -+ -+ The hashing algorithm, if such a thing applies, will be determined from -+ information in the signature and the appropriate crypto module will be -+ used. -ENOPKG will be returned if the hash algorithm is unavailable. -+ -+ The return value is an opaque pointer to be passed to the other functions, -+ or a negative error code. -+ -+ (2) Indicate data to be verified. -+ -+ int verify_sig_add_data(struct crypto_key_verify_context *ctx, -+ const void *data, size_t datalen); -+ -+ This function is used to shovel data to the verification procedure so that -+ it can load it into the hash, pass it to hardware or whatever is -+ appropriate for the algorithm being employed. -+ -+ The data is not canonicalised for the document type specified in the -+ signature. The caller must do that. -+ -+ It will return 0 if successful and a negative error code if not. -+ -+ (3) Complete the verification process. -+ -+ int verify_sig_end(struct crypto_key_verify_context *ctx, -+ const void *sig, size_t siglen); -+ -+ This function performs the actual signature verification step and cleans -+ up the resources allocated at the beginning. The signature must be -+ presented again as some of the data therein may need to be added to the -+ internal hash. -+ -+ It will return -EKEYREJECTED if the signature didn't match, 0 if -+ successful and may return other errors as appropriate. -+ -+ (4) Cancel the verification process. -+ -+ void verify_sig_cancel(struct crypto_key_verify_context *ctx); -+ -+ This function cleans up the resources allocated at the beginning. This is -+ not necessary if verify_sig_end() was called. -+ -+ - =========================== - IMPLEMENTING CRYPTO PARSERS - =========================== -@@ -107,6 +167,8 @@ The parser definition structure looks like the following: - - int (*instantiate)(struct key *key, - const void *data, size_t datalen); -+ struct crypto_key_verify_context *(*verify_sig_begin)( -+ struct key *keyring, const u8 *sig, size_t siglen); - }; - - The owner and name fields should be set to the owning module and the name of -@@ -135,6 +197,44 @@ but it is expected that at least one will be defined. - algorithm such as RSA and DSA this will likely be a printable hex version - of the key's fingerprint. - -+ (2) verify_sig_begin(). -+ -+ This is similar in concept to the instantiate() function, except that it -+ is given a signature blob to parse rather than a key data blob. -+ -+ If the data format is not recognised, -EBADMSG should be returned. If it -+ is recognised, but the signature verification process cannot for some -+ reason be set up, some other negative error code should be returned. -+ -ENOKEY should be used to indicate that no matching key is available and -+ -ENOPKG should be returned if the hash algorithm or the verification -+ algorithm are unavailable. -+ -+ If successful, the parser should allocate a verification context and embed -+ the following struct in it: -+ -+ struct crypto_key_verify_context { -+ struct key *key; -+ int (*add_data)(struct crypto_key_verify_context *ctx, -+ const void *data, size_t datalen); -+ int (*end)(struct crypto_key_verify_context *ctx, -+ const u8 *sig, size_t siglen); -+ void (*cancel)(struct crypto_key_verify_context *ctx); -+ }; -+ -+ and return a pointer to this to the caller, who will then pass it to the -+ verification operation wrappers described in the "Signature Verification" -+ section. The three operation pointers here correspond exactly to those -+ wrappers and are all mandatory. container_of() should be used to retrieve -+ the actual context. -+ -+ Note that the crypto key type retains a reference on the parser module for -+ the lifetime of this context, though the operation pointers need not point -+ into this module. -+ -+ The parser should also record a pointer to the key selected and take a -+ reference on that key with key_get(). -+ -+ - Functions are provided to register and unregister parsers: - - int register_crypto_key_parser(struct crypto_key_parser *parser); -diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h -index 1f546e6..61a5338 100644 ---- a/include/keys/crypto-subtype.h -+++ b/include/keys/crypto-subtype.h -@@ -34,8 +34,7 @@ struct crypto_key_subtype { - }; - - /* -- * Data parser. Called during instantiation and signature verification -- * initiation. -+ * Key data parser. Called during key instantiation. - */ - struct crypto_key_parser { - struct list_head link; -@@ -54,4 +53,37 @@ struct crypto_key_parser { - extern int register_crypto_key_parser(struct crypto_key_parser *); - extern void unregister_crypto_key_parser(struct crypto_key_parser *); - -+/* -+ * Context base for signature verification methods. Allocated by the subtype -+ * and presumably embedded in something appropriate. -+ */ -+struct crypto_sig_verify_context { -+ struct key *key; -+ struct crypto_sig_parser *parser; -+ int (*add_data)(struct crypto_sig_verify_context *ctx, -+ const void *data, size_t datalen); -+ int (*end)(struct crypto_sig_verify_context *ctx, -+ const u8 *sig, size_t siglen); -+ void (*cancel)(struct crypto_sig_verify_context *ctx); -+}; -+ -+/* -+ * Signature data parser. Called during signature verification initiation. -+ */ -+struct crypto_sig_parser { -+ struct list_head link; -+ struct module *owner; -+ const char *name; -+ -+ /* Attempt to recognise a signature blob and find a matching key. -+ * -+ * Return EBADMSG if not recognised. -+ */ -+ struct crypto_sig_verify_context *(*verify_sig_begin)( -+ struct key *keyring, const u8 *sig, size_t siglen); -+}; -+ -+extern int register_crypto_sig_parser(struct crypto_sig_parser *); -+extern void unregister_crypto_sig_parser(struct crypto_sig_parser *); -+ - #endif /* _KEYS_CRYPTO_SUBTYPE_H */ -diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h -index 47c00c7..0fb362a 100644 ---- a/include/keys/crypto-type.h -+++ b/include/keys/crypto-type.h -@@ -18,6 +18,15 @@ - - extern struct key_type key_type_crypto; - -+struct crypto_sig_verify_context; -+extern struct crypto_sig_verify_context *verify_sig_begin( -+ struct key *key, const void *sig, size_t siglen); -+extern int verify_sig_add_data(struct crypto_sig_verify_context *ctx, -+ const void *data, size_t datalen); -+extern int verify_sig_end(struct crypto_sig_verify_context *ctx, -+ const void *sig, size_t siglen); -+extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx); -+ - /* - * The payload is at the discretion of the subtype. - */ -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 36db1d5..67001bc 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -4,4 +4,4 @@ - - obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o - --crypto_keys-y := crypto_type.o -+crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h -index eb11788..ab9b381 100644 ---- a/security/keys/crypto/crypto_keys.h -+++ b/security/keys/crypto/crypto_keys.h -@@ -24,5 +24,4 @@ static inline const char *crypto_key_id(const struct key *key) - /* - * crypto_type.c - */ --extern struct list_head crypto_key_parsers; - extern struct rw_semaphore crypto_key_parsers_sem; -diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c -index e8f83a6..821db37 100644 ---- a/security/keys/crypto/crypto_type.c -+++ b/security/keys/crypto/crypto_type.c -@@ -18,7 +18,7 @@ - - MODULE_LICENSE("GPL"); - --LIST_HEAD(crypto_key_parsers); -+static LIST_HEAD(crypto_key_parsers); - DECLARE_RWSEM(crypto_key_parsers_sem); - - /* -diff --git a/security/keys/crypto/crypto_verify.c b/security/keys/crypto/crypto_verify.c -new file mode 100644 -index 0000000..d64f1c7 ---- /dev/null -+++ b/security/keys/crypto/crypto_verify.c -@@ -0,0 +1,159 @@ -+/* Signature verification with a crypto key -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ * -+ * See Documentation/security/keys-crypto.txt -+ */ -+ -+#include -+#include -+#include -+#include "crypto_keys.h" -+ -+static LIST_HEAD(crypto_sig_parsers); -+ -+/** -+ * verify_sig_begin - Initiate the use of a crypto key to verify a signature -+ * @keyring: The public keys to verify against -+ * @sig: The signature data -+ * @siglen: The signature length -+ * -+ * Returns a context or an error. -+ */ -+struct crypto_sig_verify_context *verify_sig_begin( -+ struct key *keyring, const void *sig, size_t siglen) -+{ -+ struct crypto_sig_verify_context *ret; -+ struct crypto_sig_parser *parser; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (siglen == 0 || !sig) -+ return ERR_PTR(-EINVAL); -+ -+ down_read(&crypto_key_parsers_sem); -+ -+ ret = ERR_PTR(-EBADMSG); -+ list_for_each_entry(parser, &crypto_sig_parsers, link) { -+ if (parser->verify_sig_begin) { -+ if (!try_module_get(parser->owner)) -+ continue; -+ -+ pr_debug("Trying parser '%s'\n", parser->name); -+ -+ ret = parser->verify_sig_begin(keyring, sig, siglen); -+ if (IS_ERR(ret)) -+ module_put(parser->owner); -+ else -+ ret->parser = parser; -+ if (ret != ERR_PTR(-EBADMSG)) { -+ pr_debug("Parser recognised the format" -+ " (ret %ld)\n", -+ PTR_ERR(ret)); -+ break; -+ } -+ } -+ } -+ -+ up_read(&crypto_key_parsers_sem); -+ pr_devel("<==%s() = %p\n", __func__, ret); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(verify_sig_begin); -+ -+/** -+ * verify_sig_add_data - Incrementally provide data to be verified -+ * @ctx: The context from verify_sig_begin() -+ * @data: Data -+ * @datalen: The amount of @data -+ * -+ * This may be called multiple times. -+ */ -+int verify_sig_add_data(struct crypto_sig_verify_context *ctx, -+ const void *data, size_t datalen) -+{ -+ return ctx->add_data(ctx, data, datalen); -+} -+EXPORT_SYMBOL_GPL(verify_sig_add_data); -+ -+/** -+ * verify_sig_end - Finalise signature verification and return result -+ * @ctx: The context from verify_sig_begin() -+ * @sig: The signature data -+ * @siglen: The signature length -+ */ -+int verify_sig_end(struct crypto_sig_verify_context *ctx, -+ const void *sig, size_t siglen) -+{ -+ struct crypto_sig_parser *parser = ctx->parser; -+ int ret; -+ -+ ret = ctx->end(ctx, sig, siglen); -+ module_put(parser->owner); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(verify_sig_end); -+ -+/** -+ * verify_sig_end - Cancel signature verification -+ * @ctx: The context from verify_sig_begin() -+ */ -+void verify_sig_cancel(struct crypto_sig_verify_context *ctx) -+{ -+ struct crypto_sig_parser *parser = ctx->parser; -+ -+ ctx->cancel(ctx); -+ module_put(parser->owner); -+} -+EXPORT_SYMBOL_GPL(verify_sig_cancel); -+ -+/** -+ * register_crypto_sig_parser - Register a crypto sig blob parser -+ * @parser: The parser to register -+ */ -+int register_crypto_sig_parser(struct crypto_sig_parser *parser) -+{ -+ struct crypto_sig_parser *cursor; -+ int ret; -+ -+ down_write(&crypto_key_parsers_sem); -+ -+ list_for_each_entry(cursor, &crypto_sig_parsers, link) { -+ if (strcmp(cursor->name, parser->name) == 0) { -+ pr_err("Crypto signature parser '%s' already registered\n", -+ parser->name); -+ ret = -EEXIST; -+ goto out; -+ } -+ } -+ -+ list_add_tail(&parser->link, &crypto_sig_parsers); -+ -+ pr_notice("Crypto signature parser '%s' registered\n", parser->name); -+ ret = 0; -+ -+out: -+ up_write(&crypto_key_parsers_sem); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(register_crypto_sig_parser); -+ -+/** -+ * unregister_crypto_sig_parser - Unregister a crypto sig blob parser -+ * @parser: The parser to unregister -+ */ -+void unregister_crypto_sig_parser(struct crypto_sig_parser *parser) -+{ -+ down_write(&crypto_key_parsers_sem); -+ list_del(&parser->link); -+ up_write(&crypto_key_parsers_sem); -+ -+ pr_notice("Crypto signature parser '%s' unregistered\n", parser->name); -+} -+EXPORT_SYMBOL_GPL(unregister_crypto_sig_parser); --- -1.7.11.4 - - -From d8cb66a6f69869c8c2992f67915a7c238066f2fb Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:18 +0100 -Subject: [PATCH 05/32] KEYS: Asymmetric public-key algorithm crypto key - subtype - -Add a subtype for supporting asymmetric public-key encryption algorithms such -as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). - -Signed-off-by: David Howells ---- - security/keys/crypto/Kconfig | 10 ++++ - security/keys/crypto/Makefile | 3 +- - security/keys/crypto/public_key.c | 82 +++++++++++++++++++++++++ - security/keys/crypto/public_key.h | 123 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 217 insertions(+), 1 deletion(-) - create mode 100644 security/keys/crypto/public_key.c - create mode 100644 security/keys/crypto/public_key.h - -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -index 3d15710..5f2b8ac 100644 ---- a/security/keys/crypto/Kconfig -+++ b/security/keys/crypto/Kconfig -@@ -5,3 +5,13 @@ config CRYPTO_KEY_TYPE - This option provides support for a type of key that holds the keys - required for cryptographic operations such as encryption, decryption, - signature generation and signature verification. -+ -+config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE -+ tristate "Asymmetric public-key crypto algorithm subtype" -+ depends on CRYPTO_KEY_TYPE -+ select MPILIB -+ help -+ This option provides support for asymmetric public key type handling. -+ If signature generation and/or verification are to be used, -+ appropriate hash algorithms (such as SHA-1) must be available. -+ ENOPKG will be reported if the requisite algorithm is unavailable. -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 67001bc..6384306 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -3,5 +3,6 @@ - # - - obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o -- - crypto_keys-y := crypto_type.o crypto_verify.o -+ -+obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c -new file mode 100644 -index 0000000..ebb31ec ---- /dev/null -+++ b/security/keys/crypto/public_key.c -@@ -0,0 +1,82 @@ -+/* Asymmetric public key crypto subtype -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PKEY: "fmt -+#include -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+ -+const char *const pkey_algo[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = "DSA", -+ [PKEY_ALGO_RSA] = "RSA", -+}; -+EXPORT_SYMBOL_GPL(pkey_algo); -+ -+const char *const pkey_hash_algo[PKEY_HASH__LAST] = { -+ [PKEY_HASH_MD4] = "md4", -+ [PKEY_HASH_MD5] = "md5", -+ [PKEY_HASH_SHA1] = "sha1", -+ [PKEY_HASH_RIPE_MD_160] = "rmd160", -+ [PKEY_HASH_SHA256] = "sha256", -+ [PKEY_HASH_SHA384] = "sha384", -+ [PKEY_HASH_SHA512] = "sha512", -+ [PKEY_HASH_SHA224] = "sha224", -+}; -+EXPORT_SYMBOL_GPL(pkey_hash_algo); -+ -+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { -+ [PKEY_ID_PGP] = "PGP", -+ [PKEY_ID_X509] = "X509", -+}; -+EXPORT_SYMBOL_GPL(pkey_id_type); -+ -+/* -+ * Provide a part of a description of the key for /proc/keys. -+ */ -+static void public_key_describe(const struct key *crypto_key, -+ struct seq_file *m) -+{ -+ struct public_key *key = crypto_key->payload.data; -+ -+ if (key) -+ seq_printf(m, "%s.%s", -+ pkey_id_type[key->id_type], key->algo->name); -+} -+ -+/* -+ * Destroy a public key algorithm key -+ */ -+void public_key_destroy(void *payload) -+{ -+ struct public_key *key = payload; -+ int i; -+ -+ if (key) { -+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) -+ mpi_free(key->mpi[i]); -+ kfree(key); -+ } -+} -+EXPORT_SYMBOL_GPL(public_key_destroy); -+ -+/* -+ * Public key algorithm crypto key subtype -+ */ -+struct crypto_key_subtype public_key_crypto_key_subtype = { -+ .owner = THIS_MODULE, -+ .name = "public_key", -+ .describe = public_key_describe, -+ .destroy = public_key_destroy, -+}; -+EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype); -diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h -new file mode 100644 -index 0000000..228090d ---- /dev/null -+++ b/security/keys/crypto/public_key.h -@@ -0,0 +1,123 @@ -+/* Asymmetric public-key algorithm definitions -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_PUBLIC_KEY_H -+#define _LINUX_PUBLIC_KEY_H -+ -+#include -+#include -+#include -+ -+struct public_key; -+struct public_key_signature; -+ -+enum pkey_algo { -+ PKEY_ALGO_DSA, -+ PKEY_ALGO_RSA, -+ PKEY_ALGO__LAST -+}; -+ -+extern const char *const pkey_algo[PKEY_ALGO__LAST]; -+ -+enum pkey_hash_algo { -+ PKEY_HASH_MD4, -+ PKEY_HASH_MD5, -+ PKEY_HASH_SHA1, -+ PKEY_HASH_RIPE_MD_160, -+ PKEY_HASH_SHA256, -+ PKEY_HASH_SHA384, -+ PKEY_HASH_SHA512, -+ PKEY_HASH_SHA224, -+ PKEY_HASH__LAST -+}; -+ -+extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; -+ -+enum pkey_id_type { -+ PKEY_ID_PGP, /* OpenPGP generated key ID */ -+ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ -+ PKEY_ID_TYPE__LAST -+}; -+ -+extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; -+ -+/* -+ * Public key type definition -+ */ -+struct public_key_algorithm { -+ const char *name; -+ u8 n_pub_mpi; /* Number of MPIs in public key */ -+ u8 n_sec_mpi; /* Number of MPIs in secret key */ -+ u8 n_sig_mpi; /* Number of MPIs in a signature */ -+ int (*verify)(const struct public_key *key, -+ const struct public_key_signature *sig); -+}; -+ -+/* -+ * Asymmetric public key data -+ */ -+struct public_key { -+ const struct public_key_algorithm *algo; -+ u8 capabilities; -+#define PKEY_CAN_ENCRYPT 0x01 -+#define PKEY_CAN_DECRYPT 0x02 -+#define PKEY_CAN_ENCDEC (PKEY_CAN_ENCRYPT | PKEY_CAN_DECRYPT) -+#define PKEY_CAN_SIGN 0x04 -+#define PKEY_CAN_VERIFY 0x08 -+#define PKEY_CAN_SIGVER (PKEY_CAN_SIGN | PKEY_CAN_VERIFY) -+ enum pkey_id_type id_type : 8; -+ union { -+ MPI mpi[5]; -+ struct { -+ MPI p; /* DSA prime */ -+ MPI q; /* DSA group order */ -+ MPI g; /* DSA group generator */ -+ MPI y; /* DSA public-key value = g^x mod p */ -+ MPI x; /* DSA secret exponent (if present) */ -+ } dsa; -+ struct { -+ MPI n; /* RSA public modulus */ -+ MPI e; /* RSA public encryption exponent */ -+ MPI d; /* RSA secret encryption exponent (if present) */ -+ MPI p; /* RSA secret prime (if present) */ -+ MPI q; /* RSA secret prime (if present) */ -+ } rsa; -+ }; -+ -+ u8 key_id[8]; /* ID of this key pair */ -+ u8 key_id_size; /* Number of bytes in key_id */ -+}; -+ -+/* -+ * Asymmetric public key algorithm signature data -+ */ -+struct public_key_signature { -+ struct crypto_sig_verify_context base; -+ u8 *digest; -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ u8 signed_hash_msw[2]; -+ u8 digest_size; /* Number of bytes in digest */ -+ union { -+ MPI mpi[2]; -+ struct { -+ MPI s; /* m^d mod n */ -+ } rsa; -+ struct { -+ MPI r; -+ MPI s; -+ } dsa; -+ }; -+ struct shash_desc hash; /* This must go last! */ -+}; -+ -+extern struct crypto_key_subtype public_key_crypto_key_subtype; -+ -+#endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.11.4 - - -From 76b6843d2be046bd5ab8fbae8a1cc5b5d2d48a80 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:18 +0100 -Subject: [PATCH 06/32] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA - signature verification - -Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by -RSA signature verification as per RFC3447 section 5.2.2 step 1. - -Signed-off-by: David Howells ---- - lib/mpi/Makefile | 1 + - lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) - create mode 100644 lib/mpi/mpi-cmp.c - -diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile -index 45ca90a..019a68c 100644 ---- a/lib/mpi/Makefile -+++ b/lib/mpi/Makefile -@@ -14,6 +14,7 @@ mpi-y = \ - generic_mpih-add1.o \ - mpicoder.o \ - mpi-bit.o \ -+ mpi-cmp.o \ - mpih-cmp.o \ - mpih-div.o \ - mpih-mul.o \ -diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c -new file mode 100644 -index 0000000..1871e7b ---- /dev/null -+++ b/lib/mpi/mpi-cmp.c -@@ -0,0 +1,70 @@ -+/* mpi-cmp.c - MPI functions -+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. -+ * -+ * This file is part of GnuPG. -+ * -+ * GnuPG is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * GnuPG 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ */ -+ -+#include "mpi-internal.h" -+ -+int mpi_cmp_ui(MPI u, unsigned long v) -+{ -+ mpi_limb_t limb = v; -+ -+ mpi_normalize(u); -+ if (!u->nlimbs && !limb) -+ return 0; -+ if (u->sign) -+ return -1; -+ if (u->nlimbs > 1) -+ return 1; -+ -+ if (u->d[0] == limb) -+ return 0; -+ else if (u->d[0] > limb) -+ return 1; -+ else -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp_ui); -+ -+int mpi_cmp(MPI u, MPI v) -+{ -+ mpi_size_t usize, vsize; -+ int cmp; -+ -+ mpi_normalize(u); -+ mpi_normalize(v); -+ usize = u->nlimbs; -+ vsize = v->nlimbs; -+ if (!u->sign && v->sign) -+ return 1; -+ if (u->sign && !v->sign) -+ return -1; -+ if (usize != vsize && !u->sign && !v->sign) -+ return usize - vsize; -+ if (usize != vsize && u->sign && v->sign) -+ return vsize + usize; -+ if (!usize) -+ return 0; -+ cmp = mpihelp_cmp(u->d, v->d, usize); -+ if (!cmp) -+ return 0; -+ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) -+ return 1; -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp); --- -1.7.11.4 - - -From 48c4be1c886e51edbbbebdb65421a7ca120a8d21 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:18 +0100 -Subject: [PATCH 07/32] KEYS: RSA: Implement signature verification algorithm - [PKCS#1 / RFC3447] - -Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only -the signature verification algorithm is supported. This uses the asymmetric -public key subtype to hold its key data. - -Signed-off-by: David Howells ---- - security/keys/crypto/Kconfig | 7 + - security/keys/crypto/Makefile | 1 + - security/keys/crypto/crypto_rsa.c | 267 ++++++++++++++++++++++++++++++++++++++ - security/keys/crypto/public_key.h | 2 + - 4 files changed, 277 insertions(+) - create mode 100644 security/keys/crypto/crypto_rsa.c - -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -index 5f2b8ac..4e3777e 100644 ---- a/security/keys/crypto/Kconfig -+++ b/security/keys/crypto/Kconfig -@@ -15,3 +15,10 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE - If signature generation and/or verification are to be used, - appropriate hash algorithms (such as SHA-1) must be available. - ENOPKG will be reported if the requisite algorithm is unavailable. -+ -+config CRYPTO_KEY_PKEY_ALGO_RSA -+ tristate "RSA public-key algorithm" -+ depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE -+ select MPILIB_EXTRA -+ help -+ This option enables support for the RSA algorithm (PKCS#1, RFC3447). -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 6384306..b6b1a5a 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o - crypto_keys-y := crypto_type.o crypto_verify.o - - obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o -+obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o -diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c -new file mode 100644 -index 0000000..6e95e60 ---- /dev/null -+++ b/security/keys/crypto/crypto_rsa.c -@@ -0,0 +1,267 @@ -+/* RSA asymmetric public-key algorithm [RFC3447] -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "RSA: "fmt -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+ -+#define kenter(FMT, ...) \ -+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -+#define kleave(FMT, ...) \ -+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) -+ -+/* -+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. -+ */ -+static const u8 RSA_digest_info_MD5[] = { -+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, -+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ -+ 0x05, 0x00, 0x04, 0x10 -+}; -+ -+static const u8 RSA_digest_info_SHA1[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_RIPE_MD_160[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x24, 0x03, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_SHA224[] = { -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C -+}; -+ -+static const u8 RSA_digest_info_SHA256[] = { -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20 -+}; -+ -+static const u8 RSA_digest_info_SHA384[] = { -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30 -+}; -+ -+static const u8 RSA_digest_info_SHA512[] = { -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40 -+}; -+ -+static const struct { -+ const u8 *data; -+ size_t size; -+} RSA_ASN1_templates[PKEY_HASH__LAST] = { -+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } -+ [PKEY_HASH_MD5] = _(MD5), -+ [PKEY_HASH_SHA1] = _(SHA1), -+ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), -+ [PKEY_HASH_SHA256] = _(SHA256), -+ [PKEY_HASH_SHA384] = _(SHA384), -+ [PKEY_HASH_SHA512] = _(SHA512), -+ [PKEY_HASH_SHA224] = _(SHA224), -+#undef _ -+}; -+ -+/* -+ * RSAVP1() function [RFC3447 sec 5.2.2] -+ */ -+static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) -+{ -+ MPI m; -+ int ret; -+ -+ /* (1) Validate 0 <= s < n */ -+ if (mpi_cmp_ui(s, 0) < 0) { -+ kleave(" = -EBADMSG [s < 0]"); -+ return -EBADMSG; -+ } -+ if (mpi_cmp(s, key->rsa.n) >= 0) { -+ kleave(" = -EBADMSG [s >= n]"); -+ return -EBADMSG; -+ } -+ -+ m = mpi_alloc(0); -+ if (!m) -+ return -ENOMEM; -+ -+ /* (2) m = s^e mod n */ -+ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); -+ if (ret < 0) { -+ mpi_free(m); -+ return ret; -+ } -+ -+ *_m = m; -+ return 0; -+} -+ -+/* -+ * Integer to Octet String conversion [RFC3447 sec 4.1] -+ */ -+static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) -+{ -+ unsigned X_size, x_size; -+ int X_sign; -+ u8 *X; -+ -+ /* Make sure the string is the right length. The number should begin -+ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero -+ * bits not being reported by MPI. -+ */ -+ x_size = mpi_get_nbits(x); -+ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); -+ if (x_size != xLen * 8 - 15) -+ return -ERANGE; -+ -+ X = mpi_get_buffer(x, &X_size, &X_sign); -+ if (!X) -+ return -ENOMEM; -+ if (X_sign < 0) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ if (X_size != xLen - 1) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ -+ *_X = X; -+ return 0; -+} -+ -+/* -+ * Perform the RSA signature verification. -+ * @H: Value of hash of data and metadata -+ * @EM: The computed signature value -+ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) -+ * @hash_size: The size of H -+ * @asn1_template: The DigestInfo ASN.1 template -+ * @asn1_size: Size of asm1_template[] -+ */ -+static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, -+ const u8 *asn1_template, size_t asn1_size) -+{ -+ unsigned PS_end, T_offset, i; -+ -+ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); -+ -+ if (k < 2 + 1 + asn1_size + hash_size) -+ return -EBADMSG; -+ -+ /* Decode the EMSA-PKCS1-v1_5 */ -+ if (EM[1] != 0x01) { -+ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); -+ return -EBADMSG; -+ } -+ -+ T_offset = k - (asn1_size + hash_size); -+ PS_end = T_offset - 1; -+ if (EM[PS_end] != 0x00) { -+ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); -+ return -EBADMSG; -+ } -+ -+ for (i = 2; i < PS_end; i++) { -+ if (EM[i] != 0xff) { -+ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); -+ return -EBADMSG; -+ } -+ } -+ -+ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { -+ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); -+ return -EBADMSG; -+ } -+ -+ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { -+ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); -+ return -EKEYREJECTED; -+ } -+ -+ kleave(" = 0"); -+ return 0; -+} -+ -+/* -+ * Perform the verification step [RFC3447 sec 8.2.2]. -+ */ -+static int RSA_verify_signature(const struct public_key *key, -+ const struct public_key_signature *sig) -+{ -+ size_t tsize; -+ int ret; -+ -+ /* Variables as per RFC3447 sec 8.2.2 */ -+ const u8 *H = sig->digest; -+ u8 *EM = NULL; -+ MPI m = NULL; -+ size_t k; -+ -+ kenter(""); -+ -+ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) -+ return -ENOTSUPP; -+ -+ /* (1) Check the signature size against the public key modulus size */ -+ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ -+ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -+ if (tsize != k) { -+ ret = -EBADMSG; -+ goto error; -+ } -+ -+ /* (2b) Apply the RSAVP1 verification primitive to the public key */ -+ ret = RSAVP1(key, sig->rsa.s, &m); -+ if (ret < 0) -+ goto error; -+ -+ /* (2c) Convert the message representative (m) to an encoded message -+ * (EM) of length k octets. -+ * -+ * NOTE! The leading zero byte is suppressed by MPI, so we pass a -+ * pointer to the _preceding_ byte to RSA_verify()! -+ */ -+ ret = RSA_I2OSP(m, k, &EM); -+ if (ret < 0) -+ goto error; -+ -+ ret = RSA_verify(H, EM - 1, k, sig->digest_size, -+ RSA_ASN1_templates[sig->pkey_hash_algo].data, -+ RSA_ASN1_templates[sig->pkey_hash_algo].size); -+ -+error: -+ kfree(EM); -+ mpi_free(m); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+const struct public_key_algorithm RSA_public_key_algorithm = { -+ .name = "RSA", -+ .n_pub_mpi = 2, -+ .n_sec_mpi = 3, -+ .n_sig_mpi = 1, -+ .verify = RSA_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); -diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h -index 228090d..947817b 100644 ---- a/security/keys/crypto/public_key.h -+++ b/security/keys/crypto/public_key.h -@@ -61,6 +61,8 @@ struct public_key_algorithm { - const struct public_key_signature *sig); - }; - -+extern const struct public_key_algorithm RSA_public_key_algorithm; -+ - /* - * Asymmetric public key data - */ --- -1.7.11.4 - - -From 311305a6e970236bd30d8942552a26e6f93730ce Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:19 +0100 -Subject: [PATCH 08/32] KEYS: RSA: Fix signature verification for shorter - signatures - -gpg can produce a signature file where length of signature is less than the -modulus size because the amount of space an MPI takes up is kept as low as -possible by discarding leading zeros. This regularly happens for several -modules during the build. - -Fix it by relaxing check in RSA verification code. - -Thanks to Tomas Mraz and Miloslav Trmac for help. - -Signed-off-by: Milan Broz -Signed-off-by: David Howells ---- - security/keys/crypto/crypto_rsa.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c -index 6e95e60..796ed1d 100644 ---- a/security/keys/crypto/crypto_rsa.c -+++ b/security/keys/crypto/crypto_rsa.c -@@ -222,15 +222,23 @@ static int RSA_verify_signature(const struct public_key *key, - return -ENOTSUPP; - - /* (1) Check the signature size against the public key modulus size */ -- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ k = mpi_get_nbits(key->rsa.n); -+ tsize = mpi_get_nbits(sig->rsa.s); - -- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ /* According to RFC 4880 sec 3.2, length of MPI is computed starting -+ * from most significant bit. So the RFC 3447 sec 8.2.2 size check -+ * must be relaxed to conform with shorter signatures - so we fail here -+ * only if signature length is longer than modulus size. -+ */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -- if (tsize != k) { -+ if (k < tsize) { - ret = -EBADMSG; - goto error; - } - -+ /* Round up and convert to octets */ -+ k = (k + 7) / 8; -+ - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); - if (ret < 0) --- -1.7.11.4 - - -From a9b954d2c225dc99ecc319ea760576f525f0a623 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 00:14:19 +0100 -Subject: [PATCH 09/32] PGPLIB: PGP definitions (RFC 4880) - -Provide some useful PGP definitions from RFC 4880. These describe details of -public key crypto as used by crypto keys for things like signature -verification. - -Signed-off-by: David Howells ---- - include/linux/pgp.h | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 206 insertions(+) - create mode 100644 include/linux/pgp.h - -diff --git a/include/linux/pgp.h b/include/linux/pgp.h -new file mode 100644 -index 0000000..1359f64 ---- /dev/null -+++ b/include/linux/pgp.h -@@ -0,0 +1,206 @@ -+/* PGP definitions (RFC 4880) -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_PGP_H -+#define _LINUX_PGP_H -+ -+#include -+ -+struct pgp_key_ID { -+ u8 id[8]; -+}; -+ -+struct pgp_time { -+ u8 time[4]; -+}; -+ -+/* -+ * PGP public-key algorithm identifiers [RFC4880: 9.1] -+ */ -+enum pgp_pubkey_algo { -+ PGP_PUBKEY_RSA_ENC_OR_SIG = 1, -+ PGP_PUBKEY_RSA_ENC_ONLY = 2, -+ PGP_PUBKEY_RSA_SIG_ONLY = 3, -+ PGP_PUBKEY_ELGAMAL = 16, -+ PGP_PUBKEY_DSA = 17, -+ PGP_PUBKEY__LAST -+}; -+ -+/* -+ * PGP symmetric-key algorithm identifiers [RFC4880: 9.2] -+ */ -+enum pgp_symkey_algo { -+ PGP_SYMKEY_PLAINTEXT = 0, -+ PGP_SYMKEY_IDEA = 1, -+ PGP_SYMKEY_3DES = 2, -+ PGP_SYMKEY_CAST5 = 3, -+ PGP_SYMKEY_BLOWFISH = 4, -+ PGP_SYMKEY_AES_128KEY = 7, -+ PGP_SYMKEY_AES_192KEY = 8, -+ PGP_SYMKEY_AES_256KEY = 9, -+ PGP_SYMKEY_TWOFISH_256KEY = 10, -+}; -+ -+/* -+ * PGP compression algorithm identifiers [RFC4880: 9.3] -+ */ -+enum pgp_compr_algo { -+ PGP_COMPR_UNCOMPRESSED = 0, -+ PGP_COMPR_ZIP = 1, -+ PGP_COMPR_ZLIB = 2, -+ PGP_COMPR_BZIP2 = 3, -+}; -+ -+/* -+ * PGP hash algorithm identifiers [RFC4880: 9.4] -+ */ -+enum pgp_hash_algo { -+ PGP_HASH_MD5 = 1, -+ PGP_HASH_SHA1 = 2, -+ PGP_HASH_RIPE_MD_160 = 3, -+ PGP_HASH_SHA256 = 8, -+ PGP_HASH_SHA384 = 9, -+ PGP_HASH_SHA512 = 10, -+ PGP_HASH_SHA224 = 11, -+ PGP_HASH__LAST -+}; -+ -+extern const char *const pgp_hash_algorithms[PGP_HASH__LAST]; -+ -+/* -+ * PGP packet type tags [RFC4880: 4.3]. -+ */ -+enum pgp_packet_tag { -+ PGP_PKT_RESERVED = 0, -+ PGP_PKT_PUBKEY_ENC_SESSION_KEY = 1, -+ PGP_PKT_SIGNATURE = 2, -+ PGP_PKT_SYMKEY_ENC_SESSION_KEY = 3, -+ PGP_PKT_ONEPASS_SIGNATURE = 4, -+ PGP_PKT_SECRET_KEY = 5, -+ PGP_PKT_PUBLIC_KEY = 6, -+ PGP_PKT_SECRET_SUBKEY = 7, -+ PGP_PKT_COMPRESSED_DATA = 8, -+ PGP_PKT_SYM_ENC_DATA = 9, -+ PGP_PKT_MARKER = 10, -+ PGP_PKT_LITERAL_DATA = 11, -+ PGP_PKT_TRUST = 12, -+ PGP_PKT_USER_ID = 13, -+ PGP_PKT_PUBLIC_SUBKEY = 14, -+ PGP_PKT_USER_ATTRIBUTE = 17, -+ PGP_PKT_SYM_ENC_AND_INTEG_DATA = 18, -+ PGP_PKT_MODIFY_DETECT_CODE = 19, -+ PGP_PKT_PRIVATE_0 = 60, -+ PGP_PKT_PRIVATE_3 = 63, -+ PGP_PKT__HIGHEST = 63 -+}; -+ -+/* -+ * Signature (tag 2) packet [RFC4880: 5.2]. -+ */ -+enum pgp_signature_version { -+ PGP_SIG_VERSION_3 = 3, -+ PGP_SIG_VERSION_4 = 4, -+}; -+ -+enum pgp_signature_type { -+ PGP_SIG_BINARY_DOCUMENT_SIG = 0x00, -+ PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG = 0x01, -+ PGP_SIG_STANDALONE_SIG = 0x02, -+ PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY = 0x10, -+ PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY = 0x11, -+ PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY = 0x12, -+ PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY = 0x13, -+ PGP_SIG_SUBKEY_BINDING_SIG = 0x18, -+ PGP_SIG_PRIMARY_KEY_BINDING_SIG = 0x19, -+ PGP_SIG_DIRECTLY_ON_KEY = 0x1F, -+ PGP_SIG_KEY_REVOCATION_SIG = 0x20, -+ PGP_SIG_SUBKEY_REVOCATION_SIG = 0x28, -+ PGP_SIG_CERT_REVOCATION_SIG = 0x30, -+ PGP_SIG_TIMESTAMP_SIG = 0x40, -+ PGP_SIG_THIRD_PARTY_CONFIRM_SIG = 0x50, -+}; -+ -+struct pgp_signature_v3_packet { -+ enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_3 */ -+ u8 length_of_hashed; /* == 5 */ -+ struct { -+ enum pgp_signature_type signature_type : 8; -+ struct pgp_time creation_time; -+ } hashed; -+ struct pgp_key_ID issuer; -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ enum pgp_hash_algo hash_algo : 8; -+} __packed; -+ -+struct pgp_signature_v4_packet { -+ enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_4 */ -+ enum pgp_signature_type signature_type : 8; -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ enum pgp_hash_algo hash_algo : 8; -+} __packed; -+ -+/* -+ * V4 signature subpacket types [RFC4880: 5.2.3.1]. -+ */ -+enum pgp_sig_subpkt_type { -+ PGP_SIG_CREATION_TIME = 2, -+ PGP_SIG_EXPIRATION_TIME = 3, -+ PGP_SIG_EXPORTABLE_CERT = 4, -+ PGP_SIG_TRUST_SIG = 5, -+ PGP_SIG_REGEXP = 6, -+ PGP_SIG_REVOCABLE = 7, -+ PGP_SIG_KEY_EXPIRATION_TIME = 9, -+ PGP_SIG_PREF_SYM_ALGO = 11, -+ PGP_SIG_REVOCATION_KEY = 12, -+ PGP_SIG_ISSUER = 16, -+ PGP_SIG_NOTATION_DATA = 20, -+ PGP_SIG_PREF_HASH_ALGO = 21, -+ PGP_SIG_PREF_COMPR_ALGO = 22, -+ PGP_SIG_KEY_SERVER_PREFS = 23, -+ PGP_SIG_PREF_KEY_SERVER = 24, -+ PGP_SIG_PRIMARY_USER_ID = 25, -+ PGP_SIG_POLICY_URI = 26, -+ PGP_SIG_KEY_FLAGS = 27, -+ PGP_SIG_SIGNERS_USER_ID = 28, -+ PGP_SIG_REASON_FOR_REVOCATION = 29, -+ PGP_SIG_FEATURES = 30, -+ PGP_SIG_TARGET = 31, -+ PGP_SIG_EMBEDDED_SIG = 32, -+ PGP_SIG__LAST -+}; -+ -+#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK 0x80 -+ -+/* -+ * Key (tag 5, 6, 7 and 14) packet -+ */ -+enum pgp_key_version { -+ PGP_KEY_VERSION_2 = 2, -+ PGP_KEY_VERSION_3 = 3, -+ PGP_KEY_VERSION_4 = 4, -+}; -+ -+struct pgp_key_v3_packet { -+ enum pgp_key_version version : 8; -+ struct pgp_time creation_time; -+ u8 expiry[2]; /* 0 or time in days till expiry */ -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ u8 key_material[0]; -+} __packed; -+ -+struct pgp_key_v4_packet { -+ enum pgp_key_version version : 8; -+ struct pgp_time creation_time; -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ u8 key_material[0]; -+} __packed; -+ -+#endif /* _LINUX_PGP_H */ --- -1.7.11.4 - - -From 1937e5a7e8ae1abdb7f1dc72f7b128e33c31d644 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:13 +0100 -Subject: [PATCH 10/32] PGPLIB: Basic packet parser - -Provide a simple parser that extracts the packets from a PGP packet blob and -passes the desirous ones to the given processor function: - - struct pgp_parse_context { - u64 types_of_interest; - int (*process_packet)(struct pgp_parse_context *context, - enum pgp_packet_tag type, - u8 headerlen, - const u8 *data, - size_t datalen); - }; - - int pgp_parse_packets(const u8 *data, size_t datalen, - struct pgp_parse_context *ctx); - -This is configured on with CONFIG_PGP_LIBRARY. - -Signed-off-by: David Howells ---- - include/linux/pgplib.h | 47 +++++++ - security/keys/crypto/Kconfig | 6 + - security/keys/crypto/Makefile | 1 + - security/keys/crypto/pgp_library.c | 268 +++++++++++++++++++++++++++++++++++++ - 4 files changed, 322 insertions(+) - create mode 100644 include/linux/pgplib.h - create mode 100644 security/keys/crypto/pgp_library.c - -diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h -new file mode 100644 -index 0000000..a045b3a ---- /dev/null -+++ b/include/linux/pgplib.h -@@ -0,0 +1,47 @@ -+/* PGP library definitions (RFC 4880) -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_PGPLIB_H -+#define _LINUX_PGPLIB_H -+ -+#if defined(CONFIG_PGP_LIBRARY) || defined(CONFIG_PGP_LIBRARY_MODULE) -+ -+#include -+ -+/* -+ * PGP library packet parser -+ */ -+struct pgp_parse_context { -+ u64 types_of_interest; -+ int (*process_packet)(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, -+ u8 headerlen, -+ const u8 *data, -+ size_t datalen); -+}; -+ -+extern int pgp_parse_packets(const u8 *data, size_t datalen, -+ struct pgp_parse_context *ctx); -+ -+struct pgp_parse_pubkey { -+ enum pgp_key_version version : 8; -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ time_t creation_time; -+ time_t expires_at; -+}; -+ -+extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen, -+ struct pgp_parse_pubkey *pk); -+ -+ -+#endif /* CONFIG_PGP_LIBRARY */ -+ -+#endif /* _LINUX_PGPLIB_H */ -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -index 4e3777e..88ce0e2 100644 ---- a/security/keys/crypto/Kconfig -+++ b/security/keys/crypto/Kconfig -@@ -22,3 +22,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA - select MPILIB_EXTRA - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). -+ -+config PGP_LIBRARY -+ tristate "PGP parsing library" -+ help -+ This option enables a library that provides a number of simple -+ utility functions for parsing PGP (RFC 4880) packet-based messages. -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index b6b1a5a..5fbe54e 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -7,3 +7,4 @@ crypto_keys-y := crypto_type.o crypto_verify.o - - obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o -+obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o -diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c -new file mode 100644 -index 0000000..39d2878 ---- /dev/null -+++ b/security/keys/crypto/pgp_library.c -@@ -0,0 +1,268 @@ -+/* PGP packet parser (RFC 4880) -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+#define pr_fmt(fmt) "PGP: "fmt -+#include -+#include -+#include -+#include -+ -+MODULE_LICENSE("GPL"); -+ -+const char *const pgp_hash_algorithms[PGP_HASH__LAST] = { -+ [PGP_HASH_MD5] = "md5", -+ [PGP_HASH_SHA1] = "sha1", -+ [PGP_HASH_RIPE_MD_160] = "rmd160", -+ [PGP_HASH_SHA256] = "sha256", -+ [PGP_HASH_SHA384] = "sha384", -+ [PGP_HASH_SHA512] = "sha512", -+ [PGP_HASH_SHA224] = "sha224", -+}; -+EXPORT_SYMBOL_GPL(pgp_hash_algorithms); -+ -+/** -+ * pgp_parse_packet_header - Parse a PGP packet header -+ * @_data: Start of the PGP packet (updated to PGP packet data) -+ * @_datalen: Amount of data remaining in buffer (decreased) -+ * @_type: Where the packet type will be returned -+ * @_headerlen: Where the header length will be returned -+ * -+ * Parse a set of PGP packet header [RFC 4880: 4.2]. -+ * -+ * Returns packet data size on success; non-zero on error. If successful, -+ * *_data and *_datalen will have been updated and *_headerlen will be set to -+ * hold the length of the packet header. -+ */ -+static ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, -+ enum pgp_packet_tag *_type, -+ u8 *_headerlen) -+{ -+ enum pgp_packet_tag type; -+ const u8 *data = *_data; -+ size_t size, datalen = *_datalen; -+ -+ pr_devel("-->pgp_parse_packet_header(,%zu,,)\n", datalen); -+ -+ if (datalen < 2) -+ goto short_packet; -+ -+ pr_devel("pkthdr %02x, %02x\n", data[0], data[1]); -+ -+ type = *data++; -+ datalen--; -+ if (!(type & 0x80)) { -+ pr_debug("Packet type does not have MSB set\n"); -+ return -EBADMSG; -+ } -+ type &= ~0x80; -+ -+ if (type & 0x40) { -+ /* New packet length format */ -+ type &= ~0x40; -+ pr_devel("new format: t=%u\n", type); -+ switch (data[0]) { -+ case 0x00 ... 0xbf: -+ /* One-byte length */ -+ size = data[0]; -+ data++; -+ datalen--; -+ *_headerlen = 2; -+ break; -+ case 0xc0 ... 0xdf: -+ /* Two-byte length */ -+ if (datalen < 2) -+ goto short_packet; -+ size = (data[0] - 192) * 256; -+ size += data[1] + 192; -+ data += 2; -+ datalen -= 2; -+ *_headerlen = 3; -+ break; -+ case 0xff: -+ /* Five-byte length */ -+ if (datalen < 5) -+ goto short_packet; -+ size = data[1] << 24; -+ size |= data[2] << 16; -+ size |= data[3] << 8; -+ size |= data[4]; -+ data += 5; -+ datalen -= 5; -+ *_headerlen = 6; -+ break; -+ default: -+ pr_debug("Partial body length packet not supported\n"); -+ return -EBADMSG; -+ } -+ } else { -+ /* Old packet length format */ -+ u8 length_type = type & 0x03; -+ type >>= 2; -+ pr_devel("old format: t=%u lt=%u\n", type, length_type); -+ -+ switch (length_type) { -+ case 0: -+ /* One-byte length */ -+ size = data[0]; -+ data++; -+ datalen--; -+ *_headerlen = 2; -+ break; -+ case 1: -+ /* Two-byte length */ -+ if (datalen < 2) -+ goto short_packet; -+ size = data[0] << 8; -+ size |= data[1]; -+ data += 2; -+ datalen -= 2; -+ *_headerlen = 3; -+ break; -+ case 2: -+ /* Four-byte length */ -+ if (datalen < 4) -+ goto short_packet; -+ size = data[0] << 24; -+ size |= data[1] << 16; -+ size |= data[2] << 8; -+ size |= data[3]; -+ data += 4; -+ datalen -= 4; -+ *_headerlen = 5; -+ break; -+ default: -+ pr_debug("Indefinite length packet not supported\n"); -+ return -EBADMSG; -+ } -+ } -+ -+ pr_devel("datalen=%zu size=%zu", datalen, size); -+ if (datalen < size) -+ goto short_packet; -+ if ((int)size < 0) -+ goto too_big; -+ -+ *_data = data; -+ *_datalen = datalen; -+ *_type = type; -+ pr_devel("Found packet type=%u size=%zd\n", type, size); -+ return size; -+ -+short_packet: -+ pr_debug("Attempt to parse short packet\n"); -+ return -EBADMSG; -+too_big: -+ pr_debug("Signature subpacket size >2G\n"); -+ return -EMSGSIZE; -+} -+ -+/** -+ * pgp_parse_packets - Parse a set of PGP packets -+ * @_data: Data to be parsed (updated) -+ * @_datalen: Amount of data (updated) -+ * @ctx: Parsing context -+ * -+ * Parse a set of PGP packets [RFC 4880: 4]. -+ */ -+int pgp_parse_packets(const u8 *data, size_t datalen, -+ struct pgp_parse_context *ctx) -+{ -+ enum pgp_packet_tag type; -+ ssize_t pktlen; -+ u8 headerlen; -+ int ret; -+ -+ while (datalen > 2) { -+ pktlen = pgp_parse_packet_header(&data, &datalen, &type, -+ &headerlen); -+ if (pktlen < 0) -+ return pktlen; -+ -+ if ((ctx->types_of_interest >> type) & 1) { -+ ret = ctx->process_packet(ctx, type, headerlen, -+ data, pktlen); -+ if (ret < 0) -+ return ret; -+ } -+ data += pktlen; -+ datalen -= pktlen; -+ } -+ -+ if (datalen != 0) { -+ pr_debug("Excess octets in packet stream\n"); -+ return -EBADMSG; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(pgp_parse_packets); -+ -+/** -+ * pgp_parse_public_key - Parse the common part of a PGP pubkey packet -+ * @_data: Content of packet (updated) -+ * @_datalen: Length of packet remaining (updated) -+ * @pk: Public key data -+ * -+ * Parse the common data struct for a PGP pubkey packet [RFC 4880: 5.5.2]. -+ */ -+int pgp_parse_public_key(const u8 **_data, size_t *_datalen, -+ struct pgp_parse_pubkey *pk) -+{ -+ const u8 *data = *_data; -+ size_t datalen = *_datalen; -+ __be32 tmp; -+ -+ if (datalen < 12) { -+ pr_debug("Public key packet too short\n"); -+ return -EBADMSG; -+ } -+ -+ pk->version = *data++; -+ switch (pk->version) { -+ case PGP_KEY_VERSION_2: -+ case PGP_KEY_VERSION_3: -+ case PGP_KEY_VERSION_4: -+ break; -+ default: -+ pr_debug("Public key packet with unhandled version %d\n", -+ pk->version); -+ return -EBADMSG; -+ } -+ -+ tmp = *data++ << 24; -+ tmp |= *data++ << 16; -+ tmp |= *data++ << 8; -+ tmp |= *data++; -+ pk->creation_time = tmp; -+ if (pk->version == PGP_KEY_VERSION_4) { -+ pk->expires_at = 0; /* Have to get it from the selfsignature */ -+ } else { -+ unsigned short ndays; -+ ndays = *data++ << 8; -+ ndays |= *data++; -+ if (ndays) -+ pk->expires_at = pk->creation_time + ndays * 86400UL; -+ else -+ pk->expires_at = 0; -+ datalen -= 2; -+ } -+ -+ pk->pubkey_algo = *data++; -+ datalen -= 6; -+ -+ pr_devel("%x,%x,%lx,%lx", -+ pk->version, pk->pubkey_algo, pk->creation_time, -+ pk->expires_at); -+ -+ *_data = data; -+ *_datalen = datalen; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(pgp_parse_public_key); --- -1.7.11.4 - - -From 3379efc21d2ecc93de135e3265baabbe1f326d5a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:17 +0100 -Subject: [PATCH 11/32] PGPLIB: Signature parser - -Provide some PGP signature parsing helpers: - - (1) A function to parse V4 signature subpackets and pass the desired ones to - a processor function: - - int pgp_parse_sig_subpkts(const u8 *data, size_t datalen, - struct pgp_parse_sig_context *ctx); - - (2) A function to parse out basic signature parameters from any PGP signature - such that the algorithms and public key can be selected: - - int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, - struct pgp_sig_parameters *p); - -Signed-off-by: David Howells ---- - include/linux/pgplib.h | 25 ++++ - security/keys/crypto/pgp_library.c | 280 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 305 insertions(+) - -diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h -index a045b3a..34594a9 100644 ---- a/include/linux/pgplib.h -+++ b/include/linux/pgplib.h -@@ -41,6 +41,31 @@ struct pgp_parse_pubkey { - extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen, - struct pgp_parse_pubkey *pk); - -+struct pgp_parse_sig_context { -+ unsigned long types_of_interest[128 / BITS_PER_LONG]; -+ int (*process_packet)(struct pgp_parse_sig_context *context, -+ enum pgp_sig_subpkt_type type, -+ const u8 *data, -+ size_t datalen); -+}; -+ -+extern int pgp_parse_sig_packets(const u8 *data, size_t datalen, -+ struct pgp_parse_sig_context *ctx); -+ -+struct pgp_sig_parameters { -+ enum pgp_signature_version version : 8; -+ enum pgp_signature_type signature_type : 8; -+ enum pgp_pubkey_algo pubkey_algo : 8; -+ enum pgp_hash_algo hash_algo : 8; -+ union { -+ struct pgp_key_ID issuer; -+ __be32 issuer32[2]; -+ }; -+}; -+ -+extern int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, -+ struct pgp_sig_parameters *p); -+ - - #endif /* CONFIG_PGP_LIBRARY */ - -diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c -index 39d2878..50b7fa0 100644 ---- a/security/keys/crypto/pgp_library.c -+++ b/security/keys/crypto/pgp_library.c -@@ -266,3 +266,283 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen, - return 0; - } - EXPORT_SYMBOL_GPL(pgp_parse_public_key); -+ -+/** -+ * pgp_parse_sig_subpkt_header - Parse a PGP V4 signature subpacket header -+ * @_data: Start of the subpacket (updated to subpacket data) -+ * @_datalen: Amount of data remaining in buffer (decreased) -+ * @_type: Where the subpacket type will be returned -+ * -+ * Parse a PGP V4 signature subpacket header [RFC 4880: 5.2.3.1]. -+ * -+ * Returns packet data size on success; non-zero on error. If successful, -+ * *_data and *_datalen will have been updated and *_headerlen will be set to -+ * hold the length of the packet header. -+ */ -+static ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen, -+ enum pgp_sig_subpkt_type *_type) -+{ -+ enum pgp_sig_subpkt_type type; -+ const u8 *data = *_data; -+ size_t size, datalen = *_datalen; -+ -+ pr_devel("-->pgp_parse_sig_subpkt_header(,%zu,,)", datalen); -+ -+ if (datalen < 2) -+ goto short_subpacket; -+ -+ pr_devel("subpkt hdr %02x, %02x\n", data[0], data[1]); -+ -+ switch (data[0]) { -+ case 0x00 ... 0xbf: -+ /* One-byte length */ -+ size = data[0]; -+ data++; -+ datalen--; -+ break; -+ case 0xc0 ... 0xfe: -+ /* Two-byte length */ -+ if (datalen < 3) -+ goto short_subpacket; -+ size = (data[0] - 192) * 256; -+ size += data[1] + 192; -+ data += 2; -+ datalen -= 2; -+ break; -+ case 0xff: -+ if (datalen < 6) -+ goto short_subpacket; -+ size = data[1] << 24; -+ size |= data[2] << 16; -+ size |= data[3] << 8; -+ size |= data[4]; -+ data += 5; -+ datalen -= 5; -+ break; -+ } -+ -+ /* The type octet is included in the size */ -+ pr_devel("datalen=%zu size=%zu", datalen, size); -+ if (datalen < size) -+ goto short_subpacket; -+ if (size == 0) -+ goto very_short_subpacket; -+ if ((int)size < 0) -+ goto too_big; -+ -+ type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK; -+ datalen--; -+ size--; -+ -+ *_data = data; -+ *_datalen = datalen; -+ *_type = type; -+ pr_devel("Found subpkt type=%u size=%zd\n", type, size); -+ return size; -+ -+very_short_subpacket: -+ pr_debug("Signature subpacket size can't be zero\n"); -+ return -EBADMSG; -+short_subpacket: -+ pr_debug("Attempt to parse short signature subpacket\n"); -+ return -EBADMSG; -+too_big: -+ pr_debug("Signature subpacket size >2G\n"); -+ return -EMSGSIZE; -+} -+ -+/** -+ * pgp_parse_sig_subpkts - Parse a set of PGP V4 signatute subpackets -+ * @_data: Data to be parsed (updated) -+ * @_datalen: Amount of data (updated) -+ * @ctx: Parsing context -+ * -+ * Parse a set of PGP signature subpackets [RFC 4880: 5.2.3]. -+ */ -+static int pgp_parse_sig_subpkts(const u8 *data, size_t datalen, -+ struct pgp_parse_sig_context *ctx) -+{ -+ enum pgp_sig_subpkt_type type; -+ ssize_t pktlen; -+ int ret; -+ -+ pr_devel("-->pgp_parse_sig_subpkts(,%zu,,)", datalen); -+ -+ while (datalen > 2) { -+ pktlen = pgp_parse_sig_subpkt_header(&data, &datalen, &type); -+ if (pktlen < 0) -+ return pktlen; -+ if (test_bit(type, ctx->types_of_interest)) { -+ ret = ctx->process_packet(ctx, type, data, pktlen); -+ if (ret < 0) -+ return ret; -+ } -+ data += pktlen; -+ datalen -= pktlen; -+ } -+ -+ if (datalen != 0) { -+ pr_debug("Excess octets in signature subpacket stream\n"); -+ return -EBADMSG; -+ } -+ -+ return 0; -+} -+ -+struct pgp_parse_sig_params_ctx { -+ struct pgp_parse_sig_context base; -+ struct pgp_sig_parameters *params; -+ bool got_the_issuer; -+}; -+ -+/* -+ * Process a V4 signature subpacket. -+ */ -+static int pgp_process_sig_params_subpkt(struct pgp_parse_sig_context *context, -+ enum pgp_sig_subpkt_type type, -+ const u8 *data, -+ size_t datalen) -+{ -+ struct pgp_parse_sig_params_ctx *ctx = -+ container_of(context, struct pgp_parse_sig_params_ctx, base); -+ -+ if (ctx->got_the_issuer) { -+ pr_debug("V4 signature packet has multiple issuers\n"); -+ return -EBADMSG; -+ } -+ -+ if (datalen != 8) { -+ pr_debug("V4 signature issuer subpkt not 8 long (%zu)\n", -+ datalen); -+ return -EBADMSG; -+ } -+ -+ memcpy(&ctx->params->issuer, data, 8); -+ ctx->got_the_issuer = true; -+ return 0; -+} -+ -+/** -+ * pgp_parse_sig_params - Parse basic parameters from a PGP signature packet -+ * @_data: Content of packet (updated) -+ * @_datalen: Length of packet remaining (updated) -+ * @p: The basic parameters -+ * -+ * Parse the basic parameters from a PGP signature packet [RFC 4880: 5.2] that -+ * are needed to start off a signature verification operation. The only ones -+ * actually necessary are the signature type (which affects how the data is -+ * transformed) and the hash algorithm. -+ * -+ * We also extract the public key algorithm and the issuer's key ID as we'll -+ * need those to determine if we actually have the public key available. If -+ * not, then we can't verify the signature anyway. -+ * -+ * Returns 0 if successful or a negative error code. *_data and *_datalen are -+ * updated to point to the 16-bit subset of the hash value and the set of MPIs. -+ */ -+int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, -+ struct pgp_sig_parameters *p) -+{ -+ const u8 *data = *_data; -+ size_t datalen = *_datalen; -+ int ret; -+ -+ pr_devel("-->pgp_parse_sig_params(,%zu,,)", datalen); -+ -+ if (datalen < 1) -+ return -EBADMSG; -+ p->version = *data; -+ -+ if (p->version == PGP_SIG_VERSION_3) { -+ const struct pgp_signature_v3_packet *v3 = (const void *)data; -+ -+ if (datalen < sizeof(*v3)) { -+ pr_debug("Short V3 signature packet\n"); -+ return -EBADMSG; -+ } -+ datalen -= sizeof(*v3); -+ data += sizeof(*v3); -+ -+ /* V3 has everything we need in the header */ -+ p->signature_type = v3->hashed.signature_type; -+ p->issuer = v3->issuer; -+ p->pubkey_algo = v3->pubkey_algo; -+ p->hash_algo = v3->hash_algo; -+ -+ } else if (p->version == PGP_SIG_VERSION_4) { -+ const struct pgp_signature_v4_packet *v4 = (const void *)data; -+ struct pgp_parse_sig_params_ctx ctx = { -+ .base.process_packet = pgp_process_sig_params_subpkt, -+ .params = p, -+ .got_the_issuer = false, -+ }; -+ size_t subdatalen; -+ -+ if (datalen < sizeof(*v4) + 2 + 2 + 2) { -+ pr_debug("Short V4 signature packet\n"); -+ return -EBADMSG; -+ } -+ datalen -= sizeof(*v4); -+ data += sizeof(*v4); -+ -+ /* V4 has most things in the header... */ -+ p->signature_type = v4->signature_type; -+ p->pubkey_algo = v4->pubkey_algo; -+ p->hash_algo = v4->hash_algo; -+ -+ /* ... but we have to get the key ID from the subpackets, of -+ * which there are two sets. */ -+ __set_bit(PGP_SIG_ISSUER, ctx.base.types_of_interest); -+ -+ subdatalen = *data++ << 8; -+ subdatalen |= *data++; -+ datalen -= 2; -+ if (subdatalen) { -+ /* Hashed subpackets */ -+ pr_devel("hashed data: %zu (after %zu)\n", -+ subdatalen, sizeof(*v4)); -+ if (subdatalen > datalen + 2 + 2) { -+ pr_debug("Short V4 signature packet [hdata]\n"); -+ return -EBADMSG; -+ } -+ ret = pgp_parse_sig_subpkts(data, subdatalen, -+ &ctx.base); -+ if (ret < 0) -+ return ret; -+ data += subdatalen; -+ datalen -= subdatalen; -+ } -+ -+ subdatalen = *data++ << 8; -+ subdatalen |= *data++; -+ datalen -= 2; -+ if (subdatalen) { -+ /* Unhashed subpackets */ -+ pr_devel("unhashed data: %zu\n", subdatalen); -+ if (subdatalen > datalen + 2) { -+ pr_debug("Short V4 signature packet [udata]\n"); -+ return -EBADMSG; -+ } -+ ret = pgp_parse_sig_subpkts(data, subdatalen, -+ &ctx.base); -+ if (ret < 0) -+ return ret; -+ data += subdatalen; -+ datalen -= subdatalen; -+ } -+ -+ if (!ctx.got_the_issuer) { -+ pr_debug("V4 signature packet lacks issuer\n"); -+ return -EBADMSG; -+ } -+ } else { -+ pr_debug("Signature packet with unhandled version %d\n", -+ p->version); -+ return -EBADMSG; -+ } -+ -+ *_data = data; -+ *_datalen = datalen; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(pgp_parse_sig_params); --- -1.7.11.4 - - -From 39b6dd66338812a1e1806489d3fed50620011b14 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:17 +0100 -Subject: [PATCH 12/32] KEYS: PGP data parser - -Implement a PGP data parser for the crypto key type to use when instantiating a -key. - -This parser attempts to parse the instantiation data as a PGP packet sequence -(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm -key or subkey from it. - -If it finds such a key, it will set up a public_key subtype payload with -appropriate handler routines (DSA or RSA) and attach it to the key. - -Thanks to Tetsuo Handa for pointing out -some errors. - -Signed-off-by: David Howells ---- - security/keys/crypto/Kconfig | 12 ++ - security/keys/crypto/Makefile | 4 + - security/keys/crypto/pgp_parser.h | 23 +++ - security/keys/crypto/pgp_public_key.c | 344 ++++++++++++++++++++++++++++++++++ - 4 files changed, 383 insertions(+) - create mode 100644 security/keys/crypto/pgp_parser.h - create mode 100644 security/keys/crypto/pgp_public_key.c - -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -index 88ce0e2..1c2ae55 100644 ---- a/security/keys/crypto/Kconfig -+++ b/security/keys/crypto/Kconfig -@@ -28,3 +28,15 @@ config PGP_LIBRARY - help - This option enables a library that provides a number of simple - utility functions for parsing PGP (RFC 4880) packet-based messages. -+ -+config CRYPTO_KEY_PGP_PARSER -+ tristate "PGP key blob parser" -+ depends on CRYPTO_KEY_TYPE -+ select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE -+ select PGP_LIBRARY -+ select MD5 # V3 fingerprint generation -+ select SHA1 # V4 fingerprint generation -+ help -+ This option provides support for parsing PGP (RFC 4880) format blobs -+ for key data and provides the ability to instantiate a crypto key -+ from a public key packet found inside the blob. -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 5fbe54e..35733fc 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o - obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o - obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o -+ -+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o -+pgp_key_parser-y := \ -+ pgp_public_key.o -diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h -new file mode 100644 -index 0000000..1cda231 ---- /dev/null -+++ b/security/keys/crypto/pgp_parser.h -@@ -0,0 +1,23 @@ -+/* PGP crypto data parser internal definitions -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+ -+#define kenter(FMT, ...) \ -+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -+#define kleave(FMT, ...) \ -+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) -+ -+/* -+ * pgp_key_parser.c -+ */ -+extern const -+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; -diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c -new file mode 100644 -index 0000000..c260e02 ---- /dev/null -+++ b/security/keys/crypto/pgp_public_key.c -@@ -0,0 +1,344 @@ -+/* Instantiate a public key crypto key from PGP format data [RFC 4880] -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PGP: "fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "public_key.h" -+#include "pgp_parser.h" -+ -+MODULE_LICENSE("GPL"); -+ -+const -+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = { -+#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \ -+ defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE) -+ [PGP_PUBKEY_RSA_ENC_OR_SIG] = &RSA_public_key_algorithm, -+ [PGP_PUBKEY_RSA_ENC_ONLY] = &RSA_public_key_algorithm, -+ [PGP_PUBKEY_RSA_SIG_ONLY] = &RSA_public_key_algorithm, -+#endif -+ [PGP_PUBKEY_ELGAMAL] = NULL, -+ [PGP_PUBKEY_DSA] = NULL, -+}; -+ -+static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = { -+ [PGP_PUBKEY_RSA_ENC_OR_SIG] = PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER, -+ [PGP_PUBKEY_RSA_ENC_ONLY] = PKEY_CAN_ENCDEC, -+ [PGP_PUBKEY_RSA_SIG_ONLY] = PKEY_CAN_SIGVER, -+ [PGP_PUBKEY_ELGAMAL] = 0, -+ [PGP_PUBKEY_DSA] = 0, -+}; -+ -+static inline void digest_putc(struct shash_desc *digest, uint8_t ch) -+{ -+ crypto_shash_update(digest, &ch, 1); -+} -+ -+struct pgp_key_data_parse_context { -+ struct pgp_parse_context pgp; -+ struct crypto_key_subtype *subtype; -+ char *fingerprint; -+ void *payload; -+}; -+ -+/* -+ * Calculate the public key ID (RFC4880 12.2) -+ */ -+static int pgp_calc_pkey_keyid(struct shash_desc *digest, -+ struct pgp_parse_pubkey *pgp, -+ struct public_key *key) -+{ -+ unsigned nb[ARRAY_SIZE(key->mpi)]; -+ unsigned nn[ARRAY_SIZE(key->mpi)]; -+ unsigned n; -+ u8 *pp[ARRAY_SIZE(key->mpi)]; -+ u32 a32; -+ int npkey = key->algo->n_pub_mpi; -+ int i, ret = -ENOMEM; -+ -+ kenter(""); -+ -+ for (i = 0; i < ARRAY_SIZE(pp); i++) -+ pp[i] = NULL; -+ -+ n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6; -+ for (i = 0; i < npkey; i++) { -+ nb[i] = mpi_get_nbits(key->mpi[i]); -+ pp[i] = mpi_get_buffer(key->mpi[i], nn + i, NULL); -+ if (!pp[i]) -+ goto error; -+ n += 2 + nn[i]; -+ } -+ -+ digest_putc(digest, 0x99); /* ctb */ -+ digest_putc(digest, n >> 8); /* 16-bit header length */ -+ digest_putc(digest, n); -+ digest_putc(digest, pgp->version); -+ -+ a32 = pgp->creation_time; -+ digest_putc(digest, a32 >> 24); -+ digest_putc(digest, a32 >> 16); -+ digest_putc(digest, a32 >> 8); -+ digest_putc(digest, a32 >> 0); -+ -+ if (pgp->version < PGP_KEY_VERSION_4) { -+ u16 a16; -+ -+ if (pgp->expires_at) -+ a16 = (pgp->expires_at - pgp->creation_time) / 86400UL; -+ else -+ a16 = 0; -+ digest_putc(digest, a16 >> 8); -+ digest_putc(digest, a16 >> 0); -+ } -+ -+ digest_putc(digest, pgp->pubkey_algo); -+ -+ for (i = 0; i < npkey; i++) { -+ digest_putc(digest, nb[i] >> 8); -+ digest_putc(digest, nb[i]); -+ crypto_shash_update(digest, pp[i], nn[i]); -+ } -+ ret = 0; -+ -+error: -+ for (i = 0; i < npkey; i++) -+ kfree(pp[i]); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+/* -+ * Calculate the public key ID fingerprint -+ */ -+static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx, -+ struct pgp_parse_pubkey *pgp, -+ struct public_key *key) -+{ -+ struct crypto_shash *tfm; -+ struct shash_desc *digest; -+ char *fingerprint; -+ u8 *raw_fingerprint; -+ int digest_size, offset; -+ int ret, i; -+ -+ ret = -ENOMEM; -+ tfm = crypto_alloc_shash(pgp->version < PGP_KEY_VERSION_4 ? -+ "md5" : "sha1", 0, 0); -+ if (!tfm) -+ goto cleanup; -+ -+ digest = kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm), -+ GFP_KERNEL); -+ if (!digest) -+ goto cleanup_tfm; -+ -+ digest->tfm = tfm; -+ digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ ret = crypto_shash_init(digest); -+ if (ret < 0) -+ goto cleanup_hash; -+ -+ ret = pgp_calc_pkey_keyid(digest, pgp, key); -+ if (ret < 0) -+ goto cleanup_hash; -+ -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ raw_fingerprint = kmalloc(digest_size, GFP_KERNEL); -+ if (!raw_fingerprint) -+ goto cleanup_hash; -+ -+ ret = crypto_shash_final(digest, raw_fingerprint); -+ if (ret < 0) -+ goto cleanup_raw_fingerprint; -+ -+ fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL); -+ if (!fingerprint) -+ goto cleanup_raw_fingerprint; -+ -+ offset = digest_size - 8; -+ pr_debug("offset %u/%u\n", offset, digest_size); -+ -+ for (i = 0; i < digest_size; i++) -+ sprintf(fingerprint + i * 2, "%02x", raw_fingerprint[i]); -+ pr_debug("fingerprint %s\n", fingerprint); -+ -+ memcpy(&key->key_id, raw_fingerprint + offset, 8); -+ key->key_id_size = 8; -+ key->id_type = PKEY_ID_PGP; -+ -+ ctx->fingerprint = fingerprint; -+ ret = 0; -+cleanup_raw_fingerprint: -+ kfree(raw_fingerprint); -+cleanup_hash: -+ kfree(digest); -+cleanup_tfm: -+ crypto_free_shash(tfm); -+cleanup: -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+/* -+ * Extract a public key or public subkey from the PGP stream. -+ */ -+static int pgp_process_public_key(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, -+ u8 headerlen, -+ const u8 *data, -+ size_t datalen) -+{ -+ const struct public_key_algorithm *algo; -+ struct pgp_key_data_parse_context *ctx = -+ container_of(context, struct pgp_key_data_parse_context, pgp); -+ struct pgp_parse_pubkey pgp; -+ struct public_key *key; -+ int i, ret; -+ -+ kenter(",%u,%u,,%zu", type, headerlen, datalen); -+ -+ if (ctx->subtype) { -+ kleave(" = -ENOKEY [already]"); -+ return -EBADMSG; -+ } -+ -+ key = kzalloc(sizeof(struct public_key), GFP_KERNEL); -+ if (!key) -+ return -ENOMEM; -+ -+ ret = pgp_parse_public_key(&data, &datalen, &pgp); -+ if (ret < 0) -+ goto cleanup; -+ -+ if (pgp.pubkey_algo >= PGP_PUBKEY__LAST || -+ !pgp_public_key_algorithms[pgp.pubkey_algo]) { -+ pr_debug("Unsupported public key algorithm %u\n", -+ pgp.pubkey_algo); -+ ret = -ENOPKG; -+ goto cleanup; -+ } -+ -+ algo = key->algo = pgp_public_key_algorithms[pgp.pubkey_algo]; -+ -+ /* It's a public key, so that only gives us encrypt and verify -+ * capabilities. -+ */ -+ key->capabilities = pgp_public_key_capabilities[pgp.pubkey_algo] & -+ (PKEY_CAN_ENCRYPT | PKEY_CAN_VERIFY); -+ -+ for (i = 0; i < algo->n_pub_mpi; i++) { -+ unsigned int remaining = datalen; -+ if (remaining == 0) { -+ pr_debug("short %zu mpi %d\n", datalen, i); -+ goto cleanup_badmsg; -+ } -+ key->mpi[i] = mpi_read_from_buffer(data, &remaining); -+ if (!key->mpi[i]) -+ goto cleanup_nomem; -+ data += remaining; -+ datalen -= remaining; -+ } -+ -+ if (datalen != 0) { -+ pr_debug("excess %zu\n", datalen); -+ goto cleanup_badmsg; -+ } -+ -+ ret = pgp_generate_fingerprint(ctx, &pgp, key); -+ if (ret < 0) -+ goto cleanup; -+ -+ /* We're pinning the module by being linked against it */ -+ __module_get(public_key_crypto_key_subtype.owner); -+ ctx->subtype = &public_key_crypto_key_subtype; -+ ctx->payload = key; -+ kleave(" = 0 [use]"); -+ return 0; -+ -+cleanup_nomem: -+ ret = -ENOMEM; -+ goto cleanup; -+cleanup_badmsg: -+ ret = -EBADMSG; -+cleanup: -+ pr_devel("cleanup"); -+ if (key) { -+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) -+ mpi_free(key->mpi[i]); -+ kfree(key); -+ } -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+/* -+ * Attempt to parse the instantiation data blob for a key as a PGP packet -+ * message holding a key. -+ */ -+static int pgp_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct pgp_key_data_parse_context ctx; -+ int ret; -+ -+ kenter(""); -+ -+ ctx.pgp.types_of_interest = -+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); -+ ctx.pgp.process_packet = pgp_process_public_key; -+ ctx.subtype = NULL; -+ ctx.fingerprint = NULL; -+ ctx.payload = NULL; -+ -+ ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp); -+ if (ret < 0) { -+ if (ctx.payload) -+ ctx.subtype->destroy(ctx.payload); -+ if (ctx.subtype) -+ module_put(ctx.subtype->owner); -+ kfree(ctx.fingerprint); -+ return ret; -+ } -+ -+ prep->type_data[0] = ctx.subtype; -+ prep->type_data[1] = ctx.fingerprint; -+ prep->payload = ctx.payload; -+ prep->quotalen = prep->datalen; -+ return 0; -+} -+ -+static struct crypto_key_parser pgp_key_parser = { -+ .owner = THIS_MODULE, -+ .name = "pgp", -+ .preparse = pgp_key_preparse, -+}; -+ -+/* -+ * Module stuff -+ */ -+static int __init pgp_key_init(void) -+{ -+ return register_crypto_key_parser(&pgp_key_parser); -+} -+ -+static void __exit pgp_key_exit(void) -+{ -+ unregister_crypto_key_parser(&pgp_key_parser); -+} -+ -+module_init(pgp_key_init); -+module_exit(pgp_key_exit); --- -1.7.11.4 - - -From 1095ff02a49868cf8f3706dd2c83474bcf2081f8 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:17 +0100 -Subject: [PATCH 13/32] KEYS: PGP-based public key signature verification - -Provide handlers for PGP-based public-key algorithm signature verification. -This does most of the work involved in signature verification as most of it is -public-key algorithm agnostic. The public-key verification algorithm itself -is just the last little bit and is supplied the complete hash data to process. - -This requires glue logic putting on top to make use of it - something the next -patch provides. - -Signed-off-by: David Howells ---- - security/keys/crypto/Makefile | 3 +- - security/keys/crypto/pgp_parser.h | 6 + - security/keys/crypto/pgp_sig_verify.c | 325 ++++++++++++++++++++++++++++++++++ - 3 files changed, 333 insertions(+), 1 deletion(-) - create mode 100644 security/keys/crypto/pgp_sig_verify.c - -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 35733fc..0c8b8a1 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -11,4 +11,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o - - obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o - pgp_key_parser-y := \ -- pgp_public_key.o -+ pgp_public_key.o \ -+ pgp_sig_verify.o -diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h -index 1cda231..6f5b3af 100644 ---- a/security/keys/crypto/pgp_parser.h -+++ b/security/keys/crypto/pgp_parser.h -@@ -21,3 +21,9 @@ - */ - extern const - struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; -+ -+/* -+ * pgp_pubkey_sig.c -+ */ -+extern struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin( -+ struct key *crypto_key, const u8 *sigdata, size_t siglen); -diff --git a/security/keys/crypto/pgp_sig_verify.c b/security/keys/crypto/pgp_sig_verify.c -new file mode 100644 -index 0000000..f9bb949 ---- /dev/null -+++ b/security/keys/crypto/pgp_sig_verify.c -@@ -0,0 +1,325 @@ -+/* PGP public key signature verification [RFC 4880] -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PGPSIG: "fmt -+#include -+#include -+#include -+#include -+#include -+#include "public_key.h" -+#include "pgp_parser.h" -+ -+static const struct { -+ enum pkey_hash_algo algo : 8; -+} pgp_pubkey_hash[PGP_HASH__LAST] = { -+ [PGP_HASH_MD5].algo = PKEY_HASH_MD5, -+ [PGP_HASH_SHA1].algo = PKEY_HASH_SHA1, -+ [PGP_HASH_RIPE_MD_160].algo = PKEY_HASH_RIPE_MD_160, -+ [PGP_HASH_SHA256].algo = PKEY_HASH_SHA256, -+ [PGP_HASH_SHA384].algo = PKEY_HASH_SHA384, -+ [PGP_HASH_SHA512].algo = PKEY_HASH_SHA512, -+ [PGP_HASH_SHA224].algo = PKEY_HASH_SHA224, -+}; -+ -+static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx, -+ const void *data, size_t datalen); -+static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx, -+ const u8 *sig, size_t siglen); -+static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx); -+ -+struct pgp_pkey_sig_parse_context { -+ struct pgp_parse_context pgp; -+ struct pgp_sig_parameters params; -+}; -+ -+static int pgp_pkey_parse_signature(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, -+ u8 headerlen, -+ const u8 *data, -+ size_t datalen) -+{ -+ struct pgp_pkey_sig_parse_context *ctx = -+ container_of(context, struct pgp_pkey_sig_parse_context, pgp); -+ -+ return pgp_parse_sig_params(&data, &datalen, &ctx->params); -+} -+ -+/* -+ * Begin the process of verifying a DSA signature. -+ * -+ * This involves allocating the hash into which first the data and then the -+ * metadata will be put, and parsing the signature to check that it matches the -+ * key. -+ */ -+struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin( -+ struct key *crypto_key, const u8 *sigdata, size_t siglen) -+{ -+ struct pgp_pkey_sig_parse_context p; -+ struct public_key_signature *sig; -+ struct crypto_shash *tfm; -+ const struct public_key *key = crypto_key->payload.data; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ kenter("{%d},,%zu", key_serial(crypto_key), siglen); -+ -+ if (!key) { -+ kleave(" = -ENOKEY [no public key]"); -+ return ERR_PTR(-ENOKEY); -+ } -+ -+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE); -+ p.pgp.process_packet = pgp_pkey_parse_signature; -+ ret = pgp_parse_packets(sigdata, siglen, &p.pgp); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ -+ if (p.params.pubkey_algo >= PGP_PUBKEY__LAST || -+ !pgp_public_key_algorithms[p.params.pubkey_algo]) { -+ pr_debug("Unsupported public key algorithm %u\n", -+ p.params.pubkey_algo); -+ return ERR_PTR(-ENOPKG); -+ } -+ -+ if (pgp_public_key_algorithms[p.params.pubkey_algo] != key->algo) { -+ kleave(" = -EKEYREJECTED [wrong pk algo]"); -+ return ERR_PTR(-EKEYREJECTED); -+ } -+ -+ if (!(key->capabilities & PKEY_CAN_VERIFY)) { -+ kleave(" = -EKEYREJECTED [key can't verify]"); -+ return ERR_PTR(-EKEYREJECTED); -+ } -+ -+ if (p.params.hash_algo >= PGP_HASH__LAST || -+ !pgp_hash_algorithms[p.params.hash_algo]) { -+ pr_debug("Unsupported hash algorithm %u\n", -+ p.params.hash_algo); -+ return ERR_PTR(-ENOPKG); -+ } -+ -+ pr_debug("Signature generated with %s hash\n", -+ pgp_hash_algorithms[p.params.hash_algo]); -+ -+ if (memcmp(&p.params.issuer, key->key_id, 8) != 0) { -+ kleave(" = -ENOKEY [wrong key ID]"); -+ return ERR_PTR(-ENOKEY); -+ } -+ -+ if (p.params.signature_type != PGP_SIG_BINARY_DOCUMENT_SIG && -+ p.params.signature_type != PGP_SIG_STANDALONE_SIG) { -+ /* We don't want to canonicalise */ -+ kleave(" = -EOPNOTSUPP [canon]"); -+ return ERR_PTR(-EOPNOTSUPP); -+ } -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pgp_hash_algorithms[p.params.hash_algo], 0, 0); -+ if (IS_ERR(tfm)) -+ return PTR_ERR(tfm) == -ENOENT ? -+ ERR_PTR(-ENOPKG) : ERR_CAST(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data. -+ */ -+ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -+ if (!sig) { -+ crypto_free_shash(tfm); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ sig->base.key = crypto_key; -+ sig->base.add_data = pgp_pkey_verify_sig_add_data; -+ sig->base.end = pgp_pkey_verify_sig_end; -+ sig->base.cancel = pgp_pkey_verify_sig_cancel; -+ sig->pkey_hash_algo = pgp_pubkey_hash[p.params.hash_algo].algo; -+ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; -+ sig->digest_size = digest_size; -+ sig->hash.tfm = tfm; -+ sig->hash.flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(&sig->hash); -+ if (ret < 0) { -+ crypto_free_shash(sig->hash.tfm); -+ kfree(sig); -+ return ERR_PTR(ret); -+ } -+ -+ key_get(sig->base.key); -+ kleave(" = %p", sig); -+ return &sig->base; -+} -+ -+/* -+ * Load data into the hash -+ */ -+static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx, -+ const void *data, size_t datalen) -+{ -+ struct public_key_signature *sig = -+ container_of(ctx, struct public_key_signature, base); -+ -+ return crypto_shash_update(&sig->hash, data, datalen); -+} -+ -+struct pgp_pkey_sig_digest_context { -+ struct pgp_parse_context pgp; -+ const struct public_key *key; -+ struct public_key_signature *sig; -+}; -+ -+/* -+ * Extract required metadata from the signature packet and add what we need to -+ * to the hash. -+ */ -+static int pgp_pkey_digest_signature(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, -+ u8 headerlen, -+ const u8 *data, -+ size_t datalen) -+{ -+ struct pgp_pkey_sig_digest_context *ctx = -+ container_of(context, struct pgp_pkey_sig_digest_context, pgp); -+ enum pgp_signature_version version; -+ int i; -+ -+ kenter(",%u,%u,,%zu", type, headerlen, datalen); -+ -+ version = *data; -+ if (version == PGP_SIG_VERSION_3) { -+ /* We just include an excerpt of the metadata from a V3 -+ * signature. -+ */ -+ crypto_shash_update(&ctx->sig->hash, data + 1, 5); -+ data += sizeof(struct pgp_signature_v3_packet); -+ datalen -= sizeof(struct pgp_signature_v3_packet); -+ } else if (version == PGP_SIG_VERSION_4) { -+ /* We add the whole metadata header and some of the hashed data -+ * for a V4 signature, plus a trailer. -+ */ -+ size_t hashedsz, unhashedsz; -+ u8 trailer[6]; -+ -+ hashedsz = 4 + 2 + (data[4] << 8) + data[5]; -+ crypto_shash_update(&ctx->sig->hash, data, hashedsz); -+ -+ trailer[0] = version; -+ trailer[1] = 0xffU; -+ trailer[2] = hashedsz >> 24; -+ trailer[3] = hashedsz >> 16; -+ trailer[4] = hashedsz >> 8; -+ trailer[5] = hashedsz; -+ -+ crypto_shash_update(&ctx->sig->hash, trailer, 6); -+ data += hashedsz; -+ datalen -= hashedsz; -+ -+ unhashedsz = 2 + (data[0] << 8) + data[1]; -+ data += unhashedsz; -+ datalen -= unhashedsz; -+ } -+ -+ if (datalen <= 2) { -+ kleave(" = -EBADMSG"); -+ return -EBADMSG; -+ } -+ -+ /* There's a quick check on the hash available. */ -+ ctx->sig->signed_hash_msw[0] = *data++; -+ ctx->sig->signed_hash_msw[1] = *data++; -+ datalen -= 2; -+ -+ /* And then the cryptographic data, which we'll need for the -+ * algorithm. -+ */ -+ for (i = 0; i < ctx->key->algo->n_sig_mpi; i++) { -+ unsigned int remaining = datalen; -+ if (remaining == 0) { -+ pr_debug("short %zu mpi %d\n", datalen, i); -+ return -EBADMSG; -+ } -+ ctx->sig->mpi[i] = mpi_read_from_buffer(data, &remaining); -+ if (!ctx->sig->mpi[i]) -+ return -ENOMEM; -+ data += remaining; -+ datalen -= remaining; -+ } -+ -+ if (datalen != 0) { -+ kleave(" = -EBADMSG [trailer %zu]", datalen); -+ return -EBADMSG; -+ } -+ -+ kleave(" = 0"); -+ return 0; -+} -+ -+/* -+ * The data is now all loaded into the hash; load the metadata, finalise the -+ * hash and perform the verification step. -+ */ -+static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx, -+ const u8 *sigdata, size_t siglen) -+{ -+ struct public_key_signature *sig = -+ container_of(ctx, struct public_key_signature, base); -+ const struct public_key *key = sig->base.key->payload.data; -+ struct pgp_pkey_sig_digest_context p; -+ int ret; -+ -+ kenter(""); -+ -+ /* Firstly we add metadata, starting with some of the data from the -+ * signature packet */ -+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE); -+ p.pgp.process_packet = pgp_pkey_digest_signature; -+ p.key = key; -+ p.sig = sig; -+ ret = pgp_parse_packets(sigdata, siglen, &p.pgp); -+ if (ret < 0) -+ goto error_free_ctx; -+ -+ crypto_shash_final(&sig->hash, sig->digest); -+ -+ ret = key->algo->verify(key, sig); -+ -+error_free_ctx: -+ pgp_pkey_verify_sig_cancel(ctx); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+/* -+ * Cancel an in-progress data loading -+ */ -+static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx) -+{ -+ struct public_key_signature *sig = -+ container_of(ctx, struct public_key_signature, base); -+ int i; -+ -+ kenter(""); -+ -+ /* !!! Do we need to tell the crypto layer to cancel too? */ -+ crypto_free_shash(sig->hash.tfm); -+ key_put(sig->base.key); -+ for (i = 0; i < ARRAY_SIZE(sig->mpi); i++) -+ mpi_free(sig->mpi[i]); -+ kfree(sig); -+ -+ kleave(""); -+} --- -1.7.11.4 - - -From 69d9f31b888090b5705b7148760143a6b706a116 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:17 +0100 -Subject: [PATCH 14/32] KEYS: PGP format signature parser - -Implement a signature parser that will attempt to parse a signature blob as a -PGP packet format message. If it can, it will find an appropriate crypto key -and set the public-key algorithm according to the data in the signature. - -Signed-off-by: David Howells ---- - security/keys/crypto/Makefile | 1 + - security/keys/crypto/pgp_sig_parser.c | 136 ++++++++++++++++++++++++++++++++++ - 2 files changed, 137 insertions(+) - create mode 100644 security/keys/crypto/pgp_sig_parser.c - -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index 0c8b8a1..a9a34c6 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -12,4 +12,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o - obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o - pgp_key_parser-y := \ - pgp_public_key.o \ -+ pgp_sig_parser.o \ - pgp_sig_verify.o -diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c -new file mode 100644 -index 0000000..683eb53 ---- /dev/null -+++ b/security/keys/crypto/pgp_sig_parser.c -@@ -0,0 +1,136 @@ -+/* Handling for PGP public key signature data [RFC 4880] -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PGPSIG: "fmt -+#include -+#include -+#include -+#include -+#include "public_key.h" -+#include "pgp_parser.h" -+ -+struct PGP_sig_parse_context { -+ struct pgp_parse_context pgp; -+ struct pgp_sig_parameters params; -+ bool found_sig; -+}; -+ -+/* -+ * Look inside signature sections for a key ID -+ */ -+static int pgp_process_signature(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, -+ u8 headerlen, -+ const u8 *data, -+ size_t datalen) -+{ -+ struct PGP_sig_parse_context *ctx = -+ container_of(context, struct PGP_sig_parse_context, pgp); -+ -+ ctx->found_sig = true; -+ return pgp_parse_sig_params(&data, &datalen, &ctx->params); -+} -+ -+/* -+ * Attempt to find a key to use for PGP signature verification, starting off by -+ * looking in the supplied keyring. -+ * -+ * The function may also look for other key sources such as a TPM. If an -+ * alternative key is found it can be added to the keyring for future -+ * reference. -+ */ -+static struct key *find_key_for_pgp_sig(struct key *keyring, -+ const u8 *sig, size_t siglen) -+{ -+ struct PGP_sig_parse_context p; -+ key_ref_t key; -+ char criterion[3 + 8 * 2 + 1]; -+ int ret; -+ -+ if (!keyring) -+ return ERR_PTR(-ENOKEY); -+ -+ /* Need to find the key ID */ -+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE); -+ p.pgp.process_packet = pgp_process_signature; -+ p.found_sig = false; -+ ret = pgp_parse_packets(sig, siglen, &p.pgp); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ -+ if (!p.found_sig) -+ return ERR_PTR(-ENOMSG); -+ -+ sprintf(criterion, "id:%08x%08x", -+ be32_to_cpu(p.params.issuer32[0]), -+ be32_to_cpu(p.params.issuer32[1])); -+ -+ pr_debug("Look up: %s\n", criterion); -+ -+ key = keyring_search(make_key_ref(keyring, 1), -+ &key_type_crypto, criterion); -+ if (IS_ERR(key)) { -+ switch (PTR_ERR(key)) { -+ /* Hide some search errors */ -+ case -EACCES: -+ case -ENOTDIR: -+ case -EAGAIN: -+ return ERR_PTR(-ENOKEY); -+ default: -+ return ERR_CAST(key); -+ } -+ } -+ -+ pr_debug("Found key %x\n", key_serial(key_ref_to_ptr(key))); -+ return key_ref_to_ptr(key); -+} -+ -+/* -+ * Attempt to parse a signature as a PGP packet format blob and find a -+ * matching key. -+ */ -+static struct crypto_sig_verify_context *pgp_verify_sig_begin( -+ struct key *keyring, const u8 *sig, size_t siglen) -+{ -+ struct crypto_sig_verify_context *ctx; -+ struct key *key; -+ -+ key = find_key_for_pgp_sig(keyring, sig, siglen); -+ if (IS_ERR(key)) -+ return ERR_CAST(key); -+ -+ /* We only handle in-kernel public key signatures for the moment */ -+ ctx = pgp_pkey_verify_sig_begin(key, sig, siglen); -+ key_put(key); -+ return ctx; -+} -+ -+static struct crypto_sig_parser pgp_sig_parser = { -+ .owner = THIS_MODULE, -+ .name = "pgp", -+ .verify_sig_begin = pgp_verify_sig_begin, -+}; -+ -+/* -+ * Module stuff -+ */ -+static int __init pgp_sig_init(void) -+{ -+ return register_crypto_sig_parser(&pgp_sig_parser); -+} -+ -+static void __exit pgp_sig_exit(void) -+{ -+ unregister_crypto_sig_parser(&pgp_sig_parser); -+} -+ -+module_init(pgp_sig_init); -+module_exit(pgp_sig_exit); --- -1.7.11.4 - - -From fe109b5adbb22b3503cb1f72f5585543218ba990 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:17 +0100 -Subject: [PATCH 15/32] KEYS: Provide PGP key description autogeneration - -Provide a facility to autogenerate the name of PGP keys from the contents of -the payload. If add_key() is given a blank description, a description is -constructed from the last user ID packet in the payload data plus the last 8 -hex digits of the key ID. For instance: - - keyctl padd crypto "" @s ---- - security/keys/crypto/pgp_public_key.c | 64 +++++++++++++++++++++++++++++------ - 1 file changed, 53 insertions(+), 11 deletions(-) - -diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c -index c260e02..2347ecd 100644 ---- a/security/keys/crypto/pgp_public_key.c -+++ b/security/keys/crypto/pgp_public_key.c -@@ -52,6 +52,9 @@ struct pgp_key_data_parse_context { - struct crypto_key_subtype *subtype; - char *fingerprint; - void *payload; -+ const char *user_id; -+ size_t user_id_len; -+ size_t fingerprint_len; - }; - - /* -@@ -166,6 +169,7 @@ static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx, - if (ret < 0) - goto cleanup_raw_fingerprint; - -+ ctx->fingerprint_len = digest_size * 2; - fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL); - if (!fingerprint) - goto cleanup_raw_fingerprint; -@@ -212,6 +216,13 @@ static int pgp_process_public_key(struct pgp_parse_context *context, - - kenter(",%u,%u,,%zu", type, headerlen, datalen); - -+ if (type == PGP_PKT_USER_ID) { -+ ctx->user_id = data; -+ ctx->user_id_len = datalen; -+ kleave(" = 0 [user ID]"); -+ return 0; -+ } -+ - if (ctx->subtype) { - kleave(" = -ENOKEY [already]"); - return -EBADMSG; -@@ -297,21 +308,44 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep) - - kenter(""); - -+ memset(&ctx, 0, sizeof(ctx)); - ctx.pgp.types_of_interest = -- (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); -+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY) | -+ (1 << PGP_PKT_USER_ID); - ctx.pgp.process_packet = pgp_process_public_key; -- ctx.subtype = NULL; -- ctx.fingerprint = NULL; -- ctx.payload = NULL; - - ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp); -- if (ret < 0) { -- if (ctx.payload) -- ctx.subtype->destroy(ctx.payload); -- if (ctx.subtype) -- module_put(ctx.subtype->owner); -- kfree(ctx.fingerprint); -- return ret; -+ if (ret < 0) -+ goto error; -+ -+ if (ctx.user_id && ctx.user_id_len > 0) { -+ /* Propose a description for the key (user ID without the comment) */ -+ size_t ulen = ctx.user_id_len, flen = ctx.fingerprint_len; -+ const char *p; -+ -+ p = memchr(ctx.user_id, '(', ulen); -+ if (p) { -+ /* Remove the comment */ -+ do { -+ p--; -+ } while (*p == ' ' && p > ctx.user_id); -+ if (*p != ' ') -+ p++; -+ ulen = p - ctx.user_id; -+ } -+ -+ if (ulen > 255 - 9) -+ ulen = 255 - 9; -+ prep->description = kmalloc(ulen + 1 + 8 + 1, GFP_KERNEL); -+ ret = -ENOMEM; -+ if (!prep->description) -+ goto error; -+ memcpy(prep->description, ctx.user_id, ulen); -+ prep->description[ulen] = ' '; -+ memcpy(prep->description + ulen + 1, -+ ctx.fingerprint + flen - 8, 8); -+ prep->description[ulen + 9] = 0; -+ pr_debug("desc '%s'\n", prep->description); - } - - prep->type_data[0] = ctx.subtype; -@@ -319,6 +353,14 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep) - prep->payload = ctx.payload; - prep->quotalen = prep->datalen; - return 0; -+ -+error: -+ if (ctx.payload) -+ ctx.subtype->destroy(ctx.payload); -+ if (ctx.subtype) -+ module_put(ctx.subtype->owner); -+ kfree(ctx.fingerprint); -+ return ret; - } - - static struct crypto_key_parser pgp_key_parser = { --- -1.7.11.4 - - -From 77b00423d002eb013293177310644c8284b6ea2f Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:18 +0100 -Subject: [PATCH 16/32] KEYS: Provide a function to load keys from a PGP - keyring blob - -Provide a function to load keys from a PGP keyring blob for use in initialising -the module signing key keyring: - - int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen, - struct key *keyring, const char *descprefix); - -The keys are labelled with descprefix plus a number to uniquify them. The keys -will actually be identified by the ID calculated from the PGP data rather than -by the description, so this shouldn't be a problem. - -The keys are attached to the keyring supplied. - -Looking as root in /proc/keys after the module signing keyring has been loaded: - -24460d1c I----- 1 perm 3f010000 0 0 crypto modsign.0: dsa 5acc2142 [] -3ca85723 I----- 1 perm 1f010000 0 0 keyring .module_sign: 1/4 - -Thanks to Tetsuo Handa for some pointing -out some errors. - -Signed-off-by: David Howells ---- - Documentation/security/keys-crypto.txt | 20 ++++++ - include/keys/crypto-type.h | 3 + - security/keys/crypto/Kconfig | 9 +++ - security/keys/crypto/Makefile | 1 + - security/keys/crypto/pgp_preload.c | 115 +++++++++++++++++++++++++++++++++ - 5 files changed, 148 insertions(+) - create mode 100644 security/keys/crypto/pgp_preload.c - -diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt -index 0a886ec..be5067e 100644 ---- a/Documentation/security/keys-crypto.txt -+++ b/Documentation/security/keys-crypto.txt -@@ -10,6 +10,7 @@ Contents: - - Signature verification. - - Implementing crypto parsers. - - Implementing crypto subtypes. -+ - Initial PGP key preloading. - - - ======== -@@ -279,3 +280,22 @@ There are a number of operations defined by the subtype: - Mandatory. This should free the memory associated with the key. The - crypto key will look after freeing the fingerprint and releasing the - reference on the subtype module. -+ -+ -+======================= -+INITIAL PGP KEY LOADING -+======================= -+ -+A function is provided to perform an initial load of a set of public keys bound -+into a PGP packet format blob: -+ -+ int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring); -+ -+This takes the blob of data defined by pgpdata and pgpdatalen, extracts keys -+from them and adds them to the specified keyring. The keys are labelled with a -+description generated from the fingerprint and last user ID of each key. The -+description is required to prevent all but the last key being discarded when -+the keys are linked into the keyring. -+ -+This function is only available during initial kernel set up. -diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h -index 0fb362a..ed9b203 100644 ---- a/include/keys/crypto-type.h -+++ b/include/keys/crypto-type.h -@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx); - * The payload is at the discretion of the subtype. - */ - -+extern __init int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring); -+ - #endif /* _KEYS_CRYPTO_TYPE_H */ -diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig -index 1c2ae55..8af0155 100644 ---- a/security/keys/crypto/Kconfig -+++ b/security/keys/crypto/Kconfig -@@ -40,3 +40,12 @@ config CRYPTO_KEY_PGP_PARSER - This option provides support for parsing PGP (RFC 4880) format blobs - for key data and provides the ability to instantiate a crypto key - from a public key packet found inside the blob. -+ -+config PGP_PRELOAD -+ bool "PGP public key preloading facility" -+ select PGP_LIBRARY -+ select CRYPTO_KEY_PGP_PARSER -+ help -+ This option provides a facility for the kernel to preload PGP-wrapped -+ bundles of keys during boot. It is used by module signing to load -+ the module signing keys for example. -diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile -index a9a34c6..c873674 100644 ---- a/security/keys/crypto/Makefile -+++ b/security/keys/crypto/Makefile -@@ -8,6 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o - obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o - obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o -+obj-$(CONFIG_PGP_PRELOAD) += pgp_preload.o - - obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o - pgp_key_parser-y := \ -diff --git a/security/keys/crypto/pgp_preload.c b/security/keys/crypto/pgp_preload.c -new file mode 100644 -index 0000000..ca4cfe6 ---- /dev/null -+++ b/security/keys/crypto/pgp_preload.c -@@ -0,0 +1,115 @@ -+/* Cryptographic key request handling -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ * -+ * See Documentation/security/keys-crypto.txt -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "crypto_keys.h" -+ -+struct preload_pgp_keys_context { -+ struct pgp_parse_context pgp; -+ key_ref_t keyring; -+ const u8 *key_start; -+ const u8 *key_end; -+ bool found_key; -+}; -+ -+/* -+ * Create a key. -+ */ -+static int __init create_pgp_key(struct preload_pgp_keys_context *ctx) -+{ -+ key_ref_t key; -+ -+ key = key_create_or_update(ctx->keyring, "crypto", NULL, -+ ctx->key_start, -+ ctx->key_end - ctx->key_start, -+ KEY_POS_ALL | KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(key)) -+ return PTR_ERR(key); -+ -+ pr_notice("Loaded %s key: %s\n", -+ key_ref_to_ptr(key)->description, -+ crypto_key_id(key_ref_to_ptr(key))); -+ -+ key_ref_put(key); -+ return 0; -+} -+ -+/* -+ * Extract a public key or subkey from the PGP stream. -+ */ -+static int __init found_pgp_key(struct pgp_parse_context *context, -+ enum pgp_packet_tag type, u8 headerlen, -+ const u8 *data, size_t datalen) -+{ -+ struct preload_pgp_keys_context *ctx = -+ container_of(context, struct preload_pgp_keys_context, pgp); -+ int ret; -+ -+ if (ctx->found_key) { -+ ctx->key_end = data - headerlen; -+ ret = create_pgp_key(ctx); -+ if (ret < 0) -+ return ret; -+ } -+ -+ ctx->key_start = data - headerlen; -+ ctx->found_key = true; -+ return 0; -+} -+ -+/** -+ * preload_pgp_keys - Load keys from a PGP keyring blob -+ * @pgpdata: The PGP keyring blob containing the keys. -+ * @pgpdatalen: The size of the @pgpdata blob. -+ * @keyring: The keyring to add the new keys to. -+ * -+ * Preload a pack of keys from a PGP keyring blob. -+ * -+ * The keys have their descriptions generated from the user ID and fingerprint -+ * in the PGP stream. Since keys can be matched on their key IDs independently -+ * of the key description, the description is mostly irrelevant apart from the -+ * fact that keys of the same description displace one another from a keyring. -+ * -+ * The caller should override the current creds if they want the keys to be -+ * owned by someone other than the current process's owner. Keys will not be -+ * accounted towards the owner's quota. -+ * -+ * This function may only be called whilst the kernel is booting. -+ */ -+int __init preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, -+ struct key *keyring) -+{ -+ struct preload_pgp_keys_context ctx; -+ int ret; -+ -+ ctx.pgp.types_of_interest = -+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY); -+ ctx.pgp.process_packet = found_pgp_key; -+ ctx.keyring = make_key_ref(keyring, 1); -+ ctx.found_key = false; -+ -+ ret = pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp); -+ if (ret < 0) -+ return ret; -+ -+ if (ctx.found_key) { -+ ctx.key_end = pgpdata + pgpdatalen; -+ return create_pgp_key(&ctx); -+ } -+ return 0; -+} --- -1.7.11.4 - - -From d569964b0037289f291f5ac48df54a6b90b3435a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:33:48 +0100 -Subject: [PATCH 17/32] Make most arch asm/module.h files use - asm-generic/module.h - -Use the mapping of Elf_[SPE]hdr, Elf_Addr, Elf_Sym, Elf_Dyn, Elf_Rel/Rela, -ELF_R_TYPE() and ELF_R_SYM() to either the 32-bit version or the 64-bit version -into asm-generic/module.h for all arches bar MIPS. - -Also, use the generic definition mod_arch_specific where possible. - -To this end, I've defined three new config bools: - - (*) HAVE_MOD_ARCH_SPECIFIC - - Arches define this if they don't want to use the empty generic - mod_arch_specific struct. - - (*) MODULES_USE_ELF_RELA - - Arches define this if their modules can contain RELA records. This causes - the Elf_Rela mapping to be emitted and allows apply_relocate_add() to be - defined by the arch rather than have the core emit an error message. - - (*) MODULES_USE_ELF_REL - - Arches define this if their modules can contain REL records. This causes - the Elf_Rel mapping to be emitted and allows apply_relocate() to be - defined by the arch rather than have the core emit an error message. - -Note that it is possible to allow both REL and RELA records: m68k and mips are -two arches that do this. - -With this, some arch asm/module.h files can be deleted entirely and replaced -with a generic-y marker in the arch Kbuild file. - -Additionally, I have removed the bits from m32r and score that handle the -unsupported type of relocation record as that's now handled centrally. - -Thanks to Jonas Gorski for some MIPS fixes. - -Signed-off-by: David Howells -Acked-by: Sam Ravnborg ---- - arch/Kconfig | 19 ++++++++++++++++++ - arch/alpha/Kconfig | 2 ++ - arch/alpha/include/asm/module.h | 10 ++-------- - arch/arm/Kconfig | 2 ++ - arch/arm/include/asm/module.h | 8 ++------ - arch/avr32/Kconfig | 2 ++ - arch/avr32/include/asm/module.h | 6 ++---- - arch/blackfin/Kconfig | 2 ++ - arch/blackfin/include/asm/module.h | 4 +--- - arch/c6x/Kconfig | 1 + - arch/c6x/include/asm/module.h | 12 +----------- - arch/cris/Kconfig | 1 + - arch/cris/include/asm/Kbuild | 2 ++ - arch/cris/include/asm/module.h | 9 --------- - arch/frv/include/asm/module.h | 8 +------- - arch/h8300/Kconfig | 1 + - arch/h8300/include/asm/Kbuild | 2 ++ - arch/h8300/include/asm/module.h | 11 ----------- - arch/hexagon/Kconfig | 1 + - arch/ia64/Kconfig | 2 ++ - arch/ia64/include/asm/module.h | 6 ++---- - arch/m32r/Kconfig | 1 + - arch/m32r/include/asm/Kbuild | 2 ++ - arch/m32r/include/asm/module.h | 10 ---------- - arch/m32r/kernel/module.c | 15 -------------- - arch/m68k/Kconfig | 3 +++ - arch/m68k/include/asm/module.h | 6 ++---- - arch/microblaze/Kconfig | 1 + - arch/mips/Kconfig | 3 +++ - arch/mips/include/asm/module.h | 10 ++++++++-- - arch/mips/kernel/module.c | 2 ++ - arch/mn10300/Kconfig | 1 + - arch/mn10300/include/asm/module.h | 7 +------ - arch/openrisc/Kconfig | 1 + - arch/parisc/Kconfig | 2 ++ - arch/parisc/include/asm/module.h | 16 +++------------ - arch/powerpc/Kconfig | 2 ++ - arch/powerpc/include/asm/module.h | 7 +------ - arch/s390/Kconfig | 2 ++ - arch/s390/include/asm/module.h | 18 +++-------------- - arch/score/Kconfig | 2 ++ - arch/score/include/asm/module.h | 6 +----- - arch/score/kernel/module.c | 10 ---------- - arch/sh/Kconfig | 2 ++ - arch/sh/include/asm/module.h | 14 +++---------- - arch/sparc/Kconfig | 1 + - arch/sparc/include/asm/Kbuild | 1 + - arch/sparc/include/asm/module.h | 24 ----------------------- - arch/tile/Kconfig | 1 + - arch/unicore32/Kconfig | 1 + - arch/x86/Kconfig | 2 ++ - arch/x86/um/Kconfig | 2 ++ - arch/xtensa/Kconfig | 1 + - arch/xtensa/include/asm/module.h | 9 +-------- - include/asm-generic/module.h | 40 +++++++++++++++++++++++++++++++------- - include/linux/moduleloader.h | 36 ++++++++++++++++++++++++++++++---- - kernel/module.c | 20 ------------------- - 57 files changed, 169 insertions(+), 223 deletions(-) - delete mode 100644 arch/cris/include/asm/module.h - delete mode 100644 arch/h8300/include/asm/module.h - delete mode 100644 arch/m32r/include/asm/module.h - delete mode 100644 arch/sparc/include/asm/module.h - -diff --git a/arch/Kconfig b/arch/Kconfig -index 72f2fa1..3450115 100644 ---- a/arch/Kconfig -+++ b/arch/Kconfig -@@ -281,4 +281,23 @@ config SECCOMP_FILTER - - See Documentation/prctl/seccomp_filter.txt for details. - -+config HAVE_MOD_ARCH_SPECIFIC -+ bool -+ help -+ The arch uses struct mod_arch_specific to store data. Many arches -+ just need a simple module loader without arch specific data - those -+ should not enable this. -+ -+config MODULES_USE_ELF_RELA -+ bool -+ help -+ Modules only use ELF RELA relocations. Modules with ELF REL -+ relocations will give an error. -+ -+config MODULES_USE_ELF_REL -+ bool -+ help -+ Modules only use ELF REL relocations. Modules with ELF RELA -+ relocations will give an error. -+ - source "kernel/gcov/Kconfig" -diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig -index 9944ded..7e3710c 100644 ---- a/arch/alpha/Kconfig -+++ b/arch/alpha/Kconfig -@@ -20,6 +20,8 @@ config ALPHA - select GENERIC_CMOS_UPDATE - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - help - The Alpha is a 64-bit general-purpose processor designed and - marketed by the Digital Equipment Corporation of blessed memory, -diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h -index 7b63743..9cd13b5 100644 ---- a/arch/alpha/include/asm/module.h -+++ b/arch/alpha/include/asm/module.h -@@ -1,19 +1,13 @@ - #ifndef _ALPHA_MODULE_H - #define _ALPHA_MODULE_H - -+#include -+ - struct mod_arch_specific - { - unsigned int gotsecindex; - }; - --#define Elf_Sym Elf64_Sym --#define Elf_Shdr Elf64_Shdr --#define Elf_Ehdr Elf64_Ehdr --#define Elf_Phdr Elf64_Phdr --#define Elf_Dyn Elf64_Dyn --#define Elf_Rel Elf64_Rel --#define Elf_Rela Elf64_Rela -- - #define ARCH_SHF_SMALL SHF_ALPHA_GPREL - - #ifdef MODULE -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index e91c7cd..c75c217 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -50,6 +50,8 @@ config ARM - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER - select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN -+ select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND -+ select MODULES_USE_ELF_REL - help - The ARM series is a line of low-power-consumption RISC chip designs - licensed by ARM Ltd and targeted at embedded applications and -diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h -index 6c6809f..0d3a28d 100644 ---- a/arch/arm/include/asm/module.h -+++ b/arch/arm/include/asm/module.h -@@ -1,9 +1,7 @@ - #ifndef _ASM_ARM_MODULE_H - #define _ASM_ARM_MODULE_H - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#include - - struct unwind_table; - -@@ -16,13 +14,11 @@ enum { - ARM_SEC_DEVEXIT, - ARM_SEC_MAX, - }; --#endif - - struct mod_arch_specific { --#ifdef CONFIG_ARM_UNWIND - struct unwind_table *unwind[ARM_SEC_MAX]; --#endif - }; -+#endif - - /* - * Add the ARM architecture version to the version magic string -diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig -index 5ade51c..06e73bf 100644 ---- a/arch/avr32/Kconfig -+++ b/arch/avr32/Kconfig -@@ -15,6 +15,8 @@ config AVR32 - select ARCH_WANT_IPC_PARSE_VERSION - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select GENERIC_CLOCKEVENTS -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - help - AVR32 is a high-performance 32-bit RISC microprocessor core, - designed for cost-sensitive embedded applications, with particular -diff --git a/arch/avr32/include/asm/module.h b/arch/avr32/include/asm/module.h -index 4514445..3f083d3 100644 ---- a/arch/avr32/include/asm/module.h -+++ b/arch/avr32/include/asm/module.h -@@ -1,6 +1,8 @@ - #ifndef __ASM_AVR32_MODULE_H - #define __ASM_AVR32_MODULE_H - -+#include -+ - struct mod_arch_syminfo { - unsigned long got_offset; - int got_initialized; -@@ -17,10 +19,6 @@ struct mod_arch_specific { - struct mod_arch_syminfo *syminfo; - }; - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -- - #define MODULE_PROC_FAMILY "AVR32v1" - - #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY -diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig -index f348619..a48d8be 100644 ---- a/arch/blackfin/Kconfig -+++ b/arch/blackfin/Kconfig -@@ -41,6 +41,8 @@ config BLACKFIN - select HAVE_NMI_WATCHDOG if NMI_WATCHDOG - select GENERIC_SMP_IDLE_THREAD - select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - - config GENERIC_CSUM - def_bool y -diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h -index ed5689b..231a149 100644 ---- a/arch/blackfin/include/asm/module.h -+++ b/arch/blackfin/include/asm/module.h -@@ -7,9 +7,7 @@ - #ifndef _ASM_BFIN_MODULE_H - #define _ASM_BFIN_MODULE_H - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#include - - struct mod_arch_specific { - Elf_Shdr *text_l1; -diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig -index 052f81a..8f3a304 100644 ---- a/arch/c6x/Kconfig -+++ b/arch/c6x/Kconfig -@@ -16,6 +16,7 @@ config C6X - select OF - select OF_EARLY_FLATTREE - select GENERIC_CLOCKEVENTS -+ select MODULES_USE_ELF_RELA - - config MMU - def_bool n -diff --git a/arch/c6x/include/asm/module.h b/arch/c6x/include/asm/module.h -index a453f97..5c7269c 100644 ---- a/arch/c6x/include/asm/module.h -+++ b/arch/c6x/include/asm/module.h -@@ -13,17 +13,7 @@ - #ifndef _ASM_C6X_MODULE_H - #define _ASM_C6X_MODULE_H - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr --#define Elf_Addr Elf32_Addr --#define Elf_Word Elf32_Word -- --/* -- * This file contains the C6x architecture specific module code. -- */ --struct mod_arch_specific { --}; -+#include - - struct loaded_sections { - unsigned int new_vaddr; -diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig -index e922154..7bb8cf9 100644 ---- a/arch/cris/Kconfig -+++ b/arch/cris/Kconfig -@@ -47,6 +47,7 @@ config CRIS - select GENERIC_IOMAP - select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 - select GENERIC_CMOS_UPDATE -+ select MODULES_USE_ELF_RELA - - config HZ - int -diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild -index 04d02a5..28b690d 100644 ---- a/arch/cris/include/asm/Kbuild -+++ b/arch/cris/include/asm/Kbuild -@@ -7,3 +7,5 @@ header-y += ethernet.h - header-y += etraxgpio.h - header-y += rs485.h - header-y += sync_serial.h -+ -+generic-y += module.h -diff --git a/arch/cris/include/asm/module.h b/arch/cris/include/asm/module.h -deleted file mode 100644 -index 7ee7231..0000000 ---- a/arch/cris/include/asm/module.h -+++ /dev/null -@@ -1,9 +0,0 @@ --#ifndef _ASM_CRIS_MODULE_H --#define _ASM_CRIS_MODULE_H --/* cris is simple */ --struct mod_arch_specific { }; -- --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr --#endif /* _ASM_CRIS_MODULE_H */ -diff --git a/arch/frv/include/asm/module.h b/arch/frv/include/asm/module.h -index 3d5c636..a8848f0 100644 ---- a/arch/frv/include/asm/module.h -+++ b/arch/frv/include/asm/module.h -@@ -11,13 +11,7 @@ - #ifndef _ASM_MODULE_H - #define _ASM_MODULE_H - --struct mod_arch_specific --{ --}; -- --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#include - - /* - * Include the architecture version. -diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig -index 5e8a0d9..c149d3b29 100644 ---- a/arch/h8300/Kconfig -+++ b/arch/h8300/Kconfig -@@ -6,6 +6,7 @@ config H8300 - select ARCH_WANT_IPC_PARSE_VERSION - select GENERIC_IRQ_SHOW - select GENERIC_CPU_DEVICES -+ select MODULES_USE_ELF_RELA - - config SYMBOL_PREFIX - string -diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild -index c68e168..871382d 100644 ---- a/arch/h8300/include/asm/Kbuild -+++ b/arch/h8300/include/asm/Kbuild -@@ -1 +1,3 @@ - include include/asm-generic/Kbuild.asm -+ -+generic-y += module.h -diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h -deleted file mode 100644 -index 8e46724..0000000 ---- a/arch/h8300/include/asm/module.h -+++ /dev/null -@@ -1,11 +0,0 @@ --#ifndef _ASM_H8300_MODULE_H --#define _ASM_H8300_MODULE_H --/* -- * This file contains the H8/300 architecture specific module code. -- */ --struct mod_arch_specific { }; --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -- --#endif /* _ASM_H8/300_MODULE_H */ -diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig -index b2fdfb7..0744f7d 100644 ---- a/arch/hexagon/Kconfig -+++ b/arch/hexagon/Kconfig -@@ -30,6 +30,7 @@ config HEXAGON - select KTIME_SCALAR - select GENERIC_CLOCKEVENTS - select GENERIC_CLOCKEVENTS_BROADCAST -+ select MODULES_USE_ELF_RELA - ---help--- - Qualcomm Hexagon is a processor architecture designed for high - performance and low power across a wide variety of applications. -diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig -index 310cf57..6881464 100644 ---- a/arch/ia64/Kconfig -+++ b/arch/ia64/Kconfig -@@ -39,6 +39,8 @@ config IA64 - select ARCH_THREAD_INFO_ALLOCATOR - select ARCH_CLOCKSOURCE_DATA - select GENERIC_TIME_VSYSCALL -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - default y - help - The Itanium Processor Family is Intel's 64-bit successor to -diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h -index 908eaef..dfba22a 100644 ---- a/arch/ia64/include/asm/module.h -+++ b/arch/ia64/include/asm/module.h -@@ -1,6 +1,8 @@ - #ifndef _ASM_IA64_MODULE_H - #define _ASM_IA64_MODULE_H - -+#include -+ - /* - * IA-64-specific support for kernel module loader. - * -@@ -29,10 +31,6 @@ struct mod_arch_specific { - unsigned int next_got_entry; /* index of next available got entry */ - }; - --#define Elf_Shdr Elf64_Shdr --#define Elf_Sym Elf64_Sym --#define Elf_Ehdr Elf64_Ehdr -- - #define MODULE_PROC_FAMILY "ia64" - #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \ - "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) -diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig -index 49498bb..fc61533 100644 ---- a/arch/m32r/Kconfig -+++ b/arch/m32r/Kconfig -@@ -13,6 +13,7 @@ config M32R - select GENERIC_IRQ_SHOW - select GENERIC_ATOMIC64 - select ARCH_USES_GETTIMEOFFSET -+ select MODULES_USE_ELF_RELA - - config SBUS - bool -diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild -index c68e168..871382d 100644 ---- a/arch/m32r/include/asm/Kbuild -+++ b/arch/m32r/include/asm/Kbuild -@@ -1 +1,3 @@ - include include/asm-generic/Kbuild.asm -+ -+generic-y += module.h -diff --git a/arch/m32r/include/asm/module.h b/arch/m32r/include/asm/module.h -deleted file mode 100644 -index eb73ee0..0000000 ---- a/arch/m32r/include/asm/module.h -+++ /dev/null -@@ -1,10 +0,0 @@ --#ifndef _ASM_M32R_MODULE_H --#define _ASM_M32R_MODULE_H -- --struct mod_arch_specific { }; -- --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -- --#endif /* _ASM_M32R_MODULE_H */ -diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c -index 3071fe8..38233b6 100644 ---- a/arch/m32r/kernel/module.c -+++ b/arch/m32r/kernel/module.c -@@ -201,18 +201,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, - } - return 0; - } -- --int apply_relocate(Elf32_Shdr *sechdrs, -- const char *strtab, -- unsigned int symindex, -- unsigned int relsec, -- struct module *me) --{ --#if 0 -- printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", -- me->name); -- return -ENOEXEC; --#endif -- return 0; -- --} -diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig -index 4a46990..714a850 100644 ---- a/arch/m68k/Kconfig -+++ b/arch/m68k/Kconfig -@@ -12,6 +12,9 @@ config M68K - select FPU if MMU - select ARCH_WANT_IPC_PARSE_VERSION - select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_REL -+ select MODULES_USE_ELF_RELA - - config RWSEM_GENERIC_SPINLOCK - bool -diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h -index edffe66..8b58fce 100644 ---- a/arch/m68k/include/asm/module.h -+++ b/arch/m68k/include/asm/module.h -@@ -1,6 +1,8 @@ - #ifndef _ASM_M68K_MODULE_H - #define _ASM_M68K_MODULE_H - -+#include -+ - enum m68k_fixup_type { - m68k_fixup_memoffset, - m68k_fixup_vnode_shift, -@@ -36,8 +38,4 @@ struct module; - extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, - struct m68k_fixup_info *end); - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -- - #endif /* _ASM_M68K_MODULE_H */ -diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig -index ab9afca..b4f409f 100644 ---- a/arch/microblaze/Kconfig -+++ b/arch/microblaze/Kconfig -@@ -24,6 +24,7 @@ config MICROBLAZE - select GENERIC_CPU_DEVICES - select GENERIC_ATOMIC64 - select GENERIC_CLOCKEVENTS -+ select MODULES_USE_ELF_RELA - - config SWAP - def_bool n -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index 331d574..5ff52db 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -36,6 +36,9 @@ config MIPS - select BUILDTIME_EXTABLE_SORT - select GENERIC_CLOCKEVENTS - select GENERIC_CMOS_UPDATE -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_REL -+ select MODULES_USE_ELF_RELA if 64BIT - - menu "Machine selection" - -diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h -index 7531ecd..c93b62b 100644 ---- a/arch/mips/include/asm/module.h -+++ b/arch/mips/include/asm/module.h -@@ -34,11 +34,14 @@ typedef struct { - } Elf64_Mips_Rela; - - #ifdef CONFIG_32BIT -- - #define Elf_Shdr Elf32_Shdr - #define Elf_Sym Elf32_Sym - #define Elf_Ehdr Elf32_Ehdr - #define Elf_Addr Elf32_Addr -+#define Elf_Rel Elf32_Rel -+#define Elf_Rela Elf32_Rela -+#define ELF_R_TYPE(X) ELF32_R_TYPE(X) -+#define ELF_R_SYM(X) ELF32_R_SYM(X) - - #define Elf_Mips_Rel Elf32_Rel - #define Elf_Mips_Rela Elf32_Rela -@@ -49,11 +52,14 @@ typedef struct { - #endif - - #ifdef CONFIG_64BIT -- - #define Elf_Shdr Elf64_Shdr - #define Elf_Sym Elf64_Sym - #define Elf_Ehdr Elf64_Ehdr - #define Elf_Addr Elf64_Addr -+#define Elf_Rel Elf64_Rel -+#define Elf_Rela Elf64_Rela -+#define ELF_R_TYPE(X) ELF64_R_TYPE(X) -+#define ELF_R_SYM(X) ELF64_R_SYM(X) - - #define Elf_Mips_Rel Elf64_Mips_Rel - #define Elf_Mips_Rela Elf64_Mips_Rela -diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c -index 4f8c3cb..9f102cf 100644 ---- a/arch/mips/kernel/module.c -+++ b/arch/mips/kernel/module.c -@@ -324,6 +324,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, - return 0; - } - -+#ifdef CONFIG_MODULES_USE_ELF_RELA - int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relsec, - struct module *me) -@@ -363,6 +364,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, - - return 0; - } -+#endif - - /* Given an address, look for it in the module exception tables. */ - const struct exception_table_entry *search_module_dbetables(unsigned long addr) -diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig -index 5cfb086..aa03f2e 100644 ---- a/arch/mn10300/Kconfig -+++ b/arch/mn10300/Kconfig -@@ -8,6 +8,7 @@ config MN10300 - select HAVE_ARCH_KGDB - select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER - select GENERIC_CLOCKEVENTS -+ select MODULES_USE_ELF_RELA - - config AM33_2 - def_bool n -diff --git a/arch/mn10300/include/asm/module.h b/arch/mn10300/include/asm/module.h -index 5d7057d..6571103 100644 ---- a/arch/mn10300/include/asm/module.h -+++ b/arch/mn10300/include/asm/module.h -@@ -12,12 +12,7 @@ - #ifndef _ASM_MODULE_H - #define _ASM_MODULE_H - --struct mod_arch_specific { --}; -- --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#include - - /* - * Include the MN10300 architecture version. -diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig -index 49765b5..05f2ba4 100644 ---- a/arch/openrisc/Kconfig -+++ b/arch/openrisc/Kconfig -@@ -21,6 +21,7 @@ config OPENRISC - select GENERIC_CLOCKEVENTS - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select MODULES_USE_ELF_RELA - - config MMU - def_bool y -diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig -index 3ff21b5..166d991 100644 ---- a/arch/parisc/Kconfig -+++ b/arch/parisc/Kconfig -@@ -19,6 +19,8 @@ config PARISC - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select GENERIC_SMP_IDLE_THREAD - select GENERIC_STRNCPY_FROM_USER -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - - help - The PA-RISC microprocessor is designed by Hewlett-Packard and used -diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h -index 1f41234..bab37e9 100644 ---- a/arch/parisc/include/asm/module.h -+++ b/arch/parisc/include/asm/module.h -@@ -1,21 +1,11 @@ - #ifndef _ASM_PARISC_MODULE_H - #define _ASM_PARISC_MODULE_H -+ -+#include -+ - /* - * This file contains the parisc architecture specific module code. - */ --#ifdef CONFIG_64BIT --#define Elf_Shdr Elf64_Shdr --#define Elf_Sym Elf64_Sym --#define Elf_Ehdr Elf64_Ehdr --#define Elf_Addr Elf64_Addr --#define Elf_Rela Elf64_Rela --#else --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr --#define Elf_Addr Elf32_Addr --#define Elf_Rela Elf32_Rela --#endif - - struct unwind_table; - -diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig -index 352f416..74f8478 100644 ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -139,6 +139,8 @@ config PPC - select GENERIC_CLOCKEVENTS - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - - config EARLY_PRINTK - bool -diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h -index 0192a4e..c1df590 100644 ---- a/arch/powerpc/include/asm/module.h -+++ b/arch/powerpc/include/asm/module.h -@@ -11,6 +11,7 @@ - - #include - #include -+#include - - - #ifndef __powerpc64__ -@@ -60,16 +61,10 @@ struct mod_arch_specific { - */ - - #ifdef __powerpc64__ --# define Elf_Shdr Elf64_Shdr --# define Elf_Sym Elf64_Sym --# define Elf_Ehdr Elf64_Ehdr - # ifdef MODULE - asm(".section .stubs,\"ax\",@nobits; .align 3; .previous"); - # endif - #else --# define Elf_Shdr Elf32_Shdr --# define Elf_Sym Elf32_Sym --# define Elf_Ehdr Elf32_Ehdr - # ifdef MODULE - asm(".section .plt,\"ax\",@nobits; .align 3; .previous"); - asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous"); -diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig -index 107610e..c76a052 100644 ---- a/arch/s390/Kconfig -+++ b/arch/s390/Kconfig -@@ -125,6 +125,8 @@ config S390 - select GENERIC_CLOCKEVENTS - select KTIME_SCALAR if 32BIT - select HAVE_ARCH_SECCOMP_FILTER -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_RELA - - config SCHED_OMIT_FRAME_POINTER - def_bool y -diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h -index f0b6b26..df1f861 100644 ---- a/arch/s390/include/asm/module.h -+++ b/arch/s390/include/asm/module.h -@@ -1,5 +1,8 @@ - #ifndef _ASM_S390_MODULE_H - #define _ASM_S390_MODULE_H -+ -+#include -+ - /* - * This file contains the s390 architecture specific module code. - */ -@@ -28,19 +31,4 @@ struct mod_arch_specific - struct mod_arch_syminfo *syminfo; - }; - --#ifdef CONFIG_64BIT --#define ElfW(x) Elf64_ ## x --#define ELFW(x) ELF64_ ## x --#else --#define ElfW(x) Elf32_ ## x --#define ELFW(x) ELF32_ ## x --#endif -- --#define Elf_Addr ElfW(Addr) --#define Elf_Rela ElfW(Rela) --#define Elf_Shdr ElfW(Shdr) --#define Elf_Sym ElfW(Sym) --#define Elf_Ehdr ElfW(Ehdr) --#define ELF_R_SYM ELFW(R_SYM) --#define ELF_R_TYPE ELFW(R_TYPE) - #endif /* _ASM_S390_MODULE_H */ -diff --git a/arch/score/Kconfig b/arch/score/Kconfig -index ba0f412..e2c8db4 100644 ---- a/arch/score/Kconfig -+++ b/arch/score/Kconfig -@@ -10,6 +10,8 @@ config SCORE - select ARCH_DISCARD_MEMBLOCK - select GENERIC_CPU_DEVICES - select GENERIC_CLOCKEVENTS -+ select HAVE_MOD_ARCH_SPECIFIC -+ select MODULES_USE_ELF_REL - - choice - prompt "System type" -diff --git a/arch/score/include/asm/module.h b/arch/score/include/asm/module.h -index f0b5dc0..abf395b 100644 ---- a/arch/score/include/asm/module.h -+++ b/arch/score/include/asm/module.h -@@ -3,6 +3,7 @@ - - #include - #include -+#include - - struct mod_arch_specific { - /* Data Bus Error exception tables */ -@@ -13,11 +14,6 @@ struct mod_arch_specific { - - typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr --#define Elf_Addr Elf32_Addr -- - /* Given an address, look for it in the exception tables. */ - #ifdef CONFIG_MODULES - const struct exception_table_entry *search_module_dbetables(unsigned long addr); -diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c -index 469e3b6..1378d99 100644 ---- a/arch/score/kernel/module.c -+++ b/arch/score/kernel/module.c -@@ -125,16 +125,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, - return 0; - } - --int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, -- unsigned int symindex, unsigned int relsec, -- struct module *me) --{ -- /* Non-standard return value... most other arch's return -ENOEXEC -- * for an unsupported relocation variant -- */ -- return 0; --} -- - /* Given an address, look for it in the module exception tables. */ - const struct exception_table_entry *search_module_dbetables(unsigned long addr) - { -diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig -index 36f5141..656329a 100644 ---- a/arch/sh/Kconfig -+++ b/arch/sh/Kconfig -@@ -35,6 +35,8 @@ config SUPERH - select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER -+ select MODULES_USE_ELF_RELA - help - The SuperH is a RISC processor targeted for use in embedded systems - and consumer electronics; it was also used in the Sega Dreamcast -diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h -index b7927de..81300d8b 100644 ---- a/arch/sh/include/asm/module.h -+++ b/arch/sh/include/asm/module.h -@@ -1,21 +1,13 @@ - #ifndef _ASM_SH_MODULE_H - #define _ASM_SH_MODULE_H - --struct mod_arch_specific { -+#include -+ - #ifdef CONFIG_DWARF_UNWINDER -+struct mod_arch_specific { - struct list_head fde_list; - struct list_head cie_list; --#endif - }; -- --#ifdef CONFIG_64BIT --#define Elf_Shdr Elf64_Shdr --#define Elf_Sym Elf64_Sym --#define Elf_Ehdr Elf64_Ehdr --#else --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr - #endif - - #ifdef CONFIG_CPU_LITTLE_ENDIAN -diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig -index 67f1f6f..a244e70 100644 ---- a/arch/sparc/Kconfig -+++ b/arch/sparc/Kconfig -@@ -37,6 +37,7 @@ config SPARC - select GENERIC_CLOCKEVENTS - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select MODULES_USE_ELF_RELA - - config SPARC32 - def_bool !64BIT -diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild -index 67f83e0..fbe1cb5 100644 ---- a/arch/sparc/include/asm/Kbuild -+++ b/arch/sparc/include/asm/Kbuild -@@ -21,4 +21,5 @@ generic-y += div64.h - generic-y += local64.h - generic-y += irq_regs.h - generic-y += local.h -+generic-y += module.h - generic-y += word-at-a-time.h -diff --git a/arch/sparc/include/asm/module.h b/arch/sparc/include/asm/module.h -deleted file mode 100644 -index ff8e02d..0000000 ---- a/arch/sparc/include/asm/module.h -+++ /dev/null -@@ -1,24 +0,0 @@ --#ifndef __SPARC_MODULE_H --#define __SPARC_MODULE_H --struct mod_arch_specific { }; -- --/* -- * Use some preprocessor magic to define the correct symbol -- * for sparc32 and sparc64. -- * Elf_Addr becomes Elf32_Addr for sparc32 and Elf64_Addr for sparc64 -- */ --#define ___ELF(a, b, c) a##b##c --#define __ELF(a, b, c) ___ELF(a, b, c) --#define _Elf(t) __ELF(Elf, CONFIG_BITS, t) --#define _ELF(t) __ELF(ELF, CONFIG_BITS, t) -- --#define Elf_Shdr _Elf(_Shdr) --#define Elf_Sym _Elf(_Sym) --#define Elf_Ehdr _Elf(_Ehdr) --#define Elf_Rela _Elf(_Rela) --#define Elf_Addr _Elf(_Addr) -- --#define ELF_R_SYM _ELF(_R_SYM) --#define ELF_R_TYPE _ELF(_R_TYPE) -- --#endif /* __SPARC_MODULE_H */ -diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig -index 932e443..1603f30 100644 ---- a/arch/tile/Kconfig -+++ b/arch/tile/Kconfig -@@ -17,6 +17,7 @@ config TILE - select SYS_HYPERVISOR - select ARCH_HAVE_NMI_SAFE_CMPXCHG - select GENERIC_CLOCKEVENTS -+ select MODULES_USE_ELF_RELA - - # FIXME: investigate whether we need/want these options. - # select HAVE_IOREMAP_PROT -diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig -index b0a4743..5ef0814 100644 ---- a/arch/unicore32/Kconfig -+++ b/arch/unicore32/Kconfig -@@ -14,6 +14,7 @@ config UNICORE32 - select GENERIC_IRQ_SHOW - select ARCH_WANT_FRAME_POINTERS - select GENERIC_IOMAP -+ select MODULES_USE_ELF_REL - help - UniCore-32 is 32-bit Instruction Set Architecture, - including a series of low-power-consumption RISC chip -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index 8ec3a1a..01726cb 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -97,6 +97,8 @@ config X86 - select KTIME_SCALAR if X86_32 - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER -+ select MODULES_USE_ELF_REL if X86_32 -+ select MODULES_USE_ELF_RELA if X86_64 - - config INSTRUCTION_DECODER - def_bool (KPROBES || PERF_EVENTS || UPROBES) -diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig -index 9926e11..a4b0c10 100644 ---- a/arch/x86/um/Kconfig -+++ b/arch/x86/um/Kconfig -@@ -21,9 +21,11 @@ config 64BIT - config X86_32 - def_bool !64BIT - select HAVE_AOUT -+ select MODULES_USE_ELF_REL - - config X86_64 - def_bool 64BIT -+ select MODULES_USE_ELF_RELA - - config RWSEM_XCHGADD_ALGORITHM - def_bool X86_XADD && 64BIT -diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig -index 8ed64cf..4816e44 100644 ---- a/arch/xtensa/Kconfig -+++ b/arch/xtensa/Kconfig -@@ -11,6 +11,7 @@ config XTENSA - select HAVE_GENERIC_HARDIRQS - select GENERIC_IRQ_SHOW - select GENERIC_CPU_DEVICES -+ select MODULES_USE_ELF_RELA - help - Xtensa processors are 32-bit RISC machines designed by Tensilica - primarily for embedded systems. These processors are both -diff --git a/arch/xtensa/include/asm/module.h b/arch/xtensa/include/asm/module.h -index d9b34be..488b40c 100644 ---- a/arch/xtensa/include/asm/module.h -+++ b/arch/xtensa/include/asm/module.h -@@ -13,15 +13,8 @@ - #ifndef _XTENSA_MODULE_H - #define _XTENSA_MODULE_H - --struct mod_arch_specific --{ -- /* No special elements, yet. */ --}; -- - #define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " - --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#include - - #endif /* _XTENSA_MODULE_H */ -diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h -index ed5b44d..14dc41d 100644 ---- a/include/asm-generic/module.h -+++ b/include/asm-generic/module.h -@@ -5,18 +5,44 @@ - * Many architectures just need a simple module - * loader without arch specific data. - */ -+#ifndef CONFIG_HAVE_MOD_ARCH_SPECIFIC - struct mod_arch_specific - { - }; -+#endif - - #ifdef CONFIG_64BIT --#define Elf_Shdr Elf64_Shdr --#define Elf_Sym Elf64_Sym --#define Elf_Ehdr Elf64_Ehdr --#else --#define Elf_Shdr Elf32_Shdr --#define Elf_Sym Elf32_Sym --#define Elf_Ehdr Elf32_Ehdr -+#define Elf_Shdr Elf64_Shdr -+#define Elf_Phdr Elf64_Phdr -+#define Elf_Sym Elf64_Sym -+#define Elf_Dyn Elf64_Dyn -+#define Elf_Ehdr Elf64_Ehdr -+#define Elf_Addr Elf64_Addr -+#ifdef CONFIG_MODULES_USE_ELF_REL -+#define Elf_Rel Elf64_Rel -+#endif -+#ifdef CONFIG_MODULES_USE_ELF_RELA -+#define Elf_Rela Elf64_Rela -+#endif -+#define ELF_R_TYPE(X) ELF64_R_TYPE(X) -+#define ELF_R_SYM(X) ELF64_R_SYM(X) -+ -+#else /* CONFIG_64BIT */ -+ -+#define Elf_Shdr Elf32_Shdr -+#define Elf_Phdr Elf32_Phdr -+#define Elf_Sym Elf32_Sym -+#define Elf_Dyn Elf32_Dyn -+#define Elf_Ehdr Elf32_Ehdr -+#define Elf_Addr Elf32_Addr -+#ifdef CONFIG_MODULES_USE_ELF_REL -+#define Elf_Rel Elf32_Rel -+#endif -+#ifdef CONFIG_MODULES_USE_ELF_RELA -+#define Elf_Rela Elf32_Rela -+#endif -+#define ELF_R_TYPE(X) ELF32_R_TYPE(X) -+#define ELF_R_SYM(X) ELF32_R_SYM(X) - #endif - - #endif /* __ASM_GENERIC_MODULE_H */ -diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h -index b2be02e..560ca53 100644 ---- a/include/linux/moduleloader.h -+++ b/include/linux/moduleloader.h -@@ -28,21 +28,49 @@ void *module_alloc(unsigned long size); - /* Free memory returned from module_alloc. */ - void module_free(struct module *mod, void *module_region); - --/* Apply the given relocation to the (simplified) ELF. Return -error -- or 0. */ -+/* -+ * Apply the given relocation to the (simplified) ELF. Return -error -+ * or 0. -+ */ -+#ifdef CONFIG_MODULES_USE_ELF_REL - int apply_relocate(Elf_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *mod); -+#else -+static inline int apply_relocate(Elf_Shdr *sechdrs, -+ const char *strtab, -+ unsigned int symindex, -+ unsigned int relsec, -+ struct module *me) -+{ -+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); -+ return -ENOEXEC; -+} -+#endif - --/* Apply the given add relocation to the (simplified) ELF. Return -- -error or 0 */ -+/* -+ * Apply the given add relocation to the (simplified) ELF. Return -+ * -error or 0 -+ */ -+#ifdef CONFIG_MODULES_USE_ELF_RELA - int apply_relocate_add(Elf_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *mod); -+#else -+static inline int apply_relocate_add(Elf_Shdr *sechdrs, -+ const char *strtab, -+ unsigned int symindex, -+ unsigned int relsec, -+ struct module *me) -+{ -+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); -+ return -ENOEXEC; -+} -+#endif - - /* Any final processing of module before access. Return -error or 0. */ - int module_finalize(const Elf_Ehdr *hdr, -diff --git a/kernel/module.c b/kernel/module.c -index 4edbd9c..087aeed 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -1949,26 +1949,6 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) - return ret; - } - --int __weak apply_relocate(Elf_Shdr *sechdrs, -- const char *strtab, -- unsigned int symindex, -- unsigned int relsec, -- struct module *me) --{ -- pr_err("module %s: REL relocation unsupported\n", me->name); -- return -ENOEXEC; --} -- --int __weak apply_relocate_add(Elf_Shdr *sechdrs, -- const char *strtab, -- unsigned int symindex, -- unsigned int relsec, -- struct module *me) --{ -- pr_err("module %s: RELA relocation unsupported\n", me->name); -- return -ENOEXEC; --} -- - static int apply_relocations(struct module *mod, const struct load_info *info) - { - unsigned int i; --- -1.7.11.4 - - -From c6cfa3260f1e2961e69a2e3240695954aed24976 Mon Sep 17 00:00:00 2001 -From: Ralf Baechle -Date: Thu, 16 Aug 2012 01:38:43 +0100 -Subject: [PATCH 18/32] MIPS: Fix module.c build for 32 bit - -Fixes build failure introduced by "Make most arch asm/module.h files use -asm-generic/module.h" by moving all the RELA processing code to a -separate file to be used only for RELA processing on 64-bit kernels. - - CC arch/mips/kernel/module.o -arch/mips/kernel/module.c:250:14: error: 'reloc_handlers_rela' defined but not -used [-Werror=unused-variable] -cc1: all warnings being treated as errors - -make[6]: *** [arch/mips/kernel/module.o] Error 1 - -Signed-off-by: Ralf Baechle -Signed-off-by: David Howells ---- - arch/mips/kernel/Makefile | 1 + - arch/mips/kernel/module-rela.c | 144 +++++++++++++++++++++++++++++++++++++++++ - arch/mips/kernel/module.c | 124 +---------------------------------- - arch/mips/kernel/module.h | 12 ++++ - 4 files changed, 159 insertions(+), 122 deletions(-) - create mode 100644 arch/mips/kernel/module-rela.c - create mode 100644 arch/mips/kernel/module.h - -diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c -new file mode 100644 -index 0000000..4e784a8 ---- /dev/null -+++ b/arch/mips/kernel/module-rela.c -@@ -0,0 +1,144 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Copyright (C) 2001 Rusty Russell. -+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) -+ * Copyright (C) 2005 Thiemo Seufer -+ */ -+ -+#include -+#include -+#include -+#include -+#include "module.h" -+ -+static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ *location = v; -+ -+ return 0; -+} -+ -+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ if (v % 4) { -+ pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", -+ me->name); -+ return -ENOEXEC; -+ } -+ -+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -+ printk(KERN_ERR -+ "module %s: relocation overflow\n", -+ me->name); -+ return -ENOEXEC; -+ } -+ -+ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); -+ -+ return 0; -+} -+ -+static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ *location = (*location & 0xffff0000) | -+ ((((long long) v + 0x8000LL) >> 16) & 0xffff); -+ -+ return 0; -+} -+ -+static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ *location = (*location & 0xffff0000) | (v & 0xffff); -+ -+ return 0; -+} -+ -+static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ *(Elf_Addr *)location = v; -+ -+ return 0; -+} -+ -+static int apply_r_mips_higher_rela(struct module *me, u32 *location, -+ Elf_Addr v) -+{ -+ *location = (*location & 0xffff0000) | -+ ((((long long) v + 0x80008000LL) >> 32) & 0xffff); -+ -+ return 0; -+} -+ -+static int apply_r_mips_highest_rela(struct module *me, u32 *location, -+ Elf_Addr v) -+{ -+ *location = (*location & 0xffff0000) | -+ ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); -+ -+ return 0; -+} -+ -+static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, -+ Elf_Addr v) = { -+ [R_MIPS_NONE] = apply_r_mips_none, -+ [R_MIPS_32] = apply_r_mips_32_rela, -+ [R_MIPS_26] = apply_r_mips_26_rela, -+ [R_MIPS_HI16] = apply_r_mips_hi16_rela, -+ [R_MIPS_LO16] = apply_r_mips_lo16_rela, -+ [R_MIPS_64] = apply_r_mips_64_rela, -+ [R_MIPS_HIGHER] = apply_r_mips_higher_rela, -+ [R_MIPS_HIGHEST] = apply_r_mips_highest_rela -+}; -+ -+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, -+ unsigned int symindex, unsigned int relsec, -+ struct module *me) -+{ -+ Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; -+ Elf_Sym *sym; -+ u32 *location; -+ unsigned int i; -+ Elf_Addr v; -+ int res; -+ -+ pr_debug("Applying relocate section %u to %u\n", relsec, -+ sechdrs[relsec].sh_info); -+ -+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { -+ /* This is where to make the change */ -+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr -+ + rel[i].r_offset; -+ /* This is the symbol it is referring to */ -+ sym = (Elf_Sym *)sechdrs[symindex].sh_addr -+ + ELF_MIPS_R_SYM(rel[i]); -+ if (IS_ERR_VALUE(sym->st_value)) { -+ /* Ignore unresolved weak symbol */ -+ if (ELF_ST_BIND(sym->st_info) == STB_WEAK) -+ continue; -+ printk(KERN_WARNING "%s: Unknown symbol %s\n", -+ me->name, strtab + sym->st_name); -+ return -ENOENT; -+ } -+ -+ v = sym->st_value + rel[i].r_addend; -+ -+ res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); -+ if (res) -+ return res; -+ } -+ -+ return 0; -+} -diff --git a/arch/mips/kernel/module.h b/arch/mips/kernel/module.h -new file mode 100644 -index 0000000..675d091 ---- /dev/null -+++ b/arch/mips/kernel/module.h -@@ -0,0 +1,12 @@ -+/* Internal definitions for MIPS module code -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+/* -+ * module.c -+ */ -+extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v); -diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile -index fdaf65e..cd1e6c2 100644 ---- a/arch/mips/kernel/Makefile -+++ b/arch/mips/kernel/Makefile -@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o - - obj-$(CONFIG_STACKTRACE) += stacktrace.o - obj-$(CONFIG_MODULES) += mips_ksyms.o module.o -+obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o - - obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o - -diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c -index 9f102cf..e7dc80b 100644 ---- a/arch/mips/kernel/module.c -+++ b/arch/mips/kernel/module.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include "module.h" - - #include /* MODULE_START */ - -@@ -51,7 +52,7 @@ void *module_alloc(unsigned long size) - } - #endif - --static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) -+int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) - { - return 0; - } -@@ -63,13 +64,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) - return 0; - } - --static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- *location = v; -- -- return 0; --} -- - static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) - { - if (v % 4) { -@@ -91,26 +85,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) - return 0; - } - --static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- if (v % 4) { -- pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", -- me->name); -- return -ENOEXEC; -- } -- -- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -- printk(KERN_ERR -- "module %s: relocation overflow\n", -- me->name); -- return -ENOEXEC; -- } -- -- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); -- -- return 0; --} -- - static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) - { - struct mips_hi16 *n; -@@ -132,14 +106,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) - return 0; - } - --static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- *location = (*location & 0xffff0000) | -- ((((long long) v + 0x8000LL) >> 16) & 0xffff); -- -- return 0; --} -- - static void free_relocation_chain(struct mips_hi16 *l) - { - struct mips_hi16 *next; -@@ -217,38 +183,6 @@ out_danger: - return -ENOEXEC; - } - --static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- *location = (*location & 0xffff0000) | (v & 0xffff); -- -- return 0; --} -- --static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- *(Elf_Addr *)location = v; -- -- return 0; --} -- --static int apply_r_mips_higher_rela(struct module *me, u32 *location, -- Elf_Addr v) --{ -- *location = (*location & 0xffff0000) | -- ((((long long) v + 0x80008000LL) >> 32) & 0xffff); -- -- return 0; --} -- --static int apply_r_mips_highest_rela(struct module *me, u32 *location, -- Elf_Addr v) --{ -- *location = (*location & 0xffff0000) | -- ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); -- -- return 0; --} -- - static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, - Elf_Addr v) = { - [R_MIPS_NONE] = apply_r_mips_none, -@@ -258,18 +192,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, - [R_MIPS_LO16] = apply_r_mips_lo16_rel - }; - --static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, -- Elf_Addr v) = { -- [R_MIPS_NONE] = apply_r_mips_none, -- [R_MIPS_32] = apply_r_mips_32_rela, -- [R_MIPS_26] = apply_r_mips_26_rela, -- [R_MIPS_HI16] = apply_r_mips_hi16_rela, -- [R_MIPS_LO16] = apply_r_mips_lo16_rela, -- [R_MIPS_64] = apply_r_mips_64_rela, -- [R_MIPS_HIGHER] = apply_r_mips_higher_rela, -- [R_MIPS_HIGHEST] = apply_r_mips_highest_rela --}; -- - int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relsec, - struct module *me) -@@ -324,48 +246,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, - return 0; - } - --#ifdef CONFIG_MODULES_USE_ELF_RELA --int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, -- unsigned int symindex, unsigned int relsec, -- struct module *me) --{ -- Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; -- Elf_Sym *sym; -- u32 *location; -- unsigned int i; -- Elf_Addr v; -- int res; -- -- pr_debug("Applying relocate section %u to %u\n", relsec, -- sechdrs[relsec].sh_info); -- -- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { -- /* This is where to make the change */ -- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr -- + rel[i].r_offset; -- /* This is the symbol it is referring to */ -- sym = (Elf_Sym *)sechdrs[symindex].sh_addr -- + ELF_MIPS_R_SYM(rel[i]); -- if (IS_ERR_VALUE(sym->st_value)) { -- /* Ignore unresolved weak symbol */ -- if (ELF_ST_BIND(sym->st_info) == STB_WEAK) -- continue; -- printk(KERN_WARNING "%s: Unknown symbol %s\n", -- me->name, strtab + sym->st_name); -- return -ENOENT; -- } -- -- v = sym->st_value + rel[i].r_addend; -- -- res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); -- if (res) -- return res; -- } -- -- return 0; --} --#endif -- - /* Given an address, look for it in the module exception tables. */ - const struct exception_table_entry *search_module_dbetables(unsigned long addr) - { --- -1.7.11.4 - - -From 661f0147e9414fb2237f56d88d1f92d8a42345c9 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 19/32] Provide macros for forming the name of an ELF note and - its section - -Provide macros for stringifying the name of an ELF note and its section -appropriately so that the macro can be used in both C and assembly. - -Signed-off-by: David Howells ---- - include/linux/elfnote.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h -index 278e3ef..949d494 100644 ---- a/include/linux/elfnote.h -+++ b/include/linux/elfnote.h -@@ -58,6 +58,7 @@ - ELFNOTE_END - - #else /* !__ASSEMBLER__ */ -+#include - #include - /* - * Use an anonymous structure which matches the shape of -@@ -93,6 +94,9 @@ - - #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc) - #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc) -+ -+#define ELFNOTE_NAME(name) __stringify(name) -+#define ELFNOTE_SECTION(name) ".note."ELFNOTE_NAME(name) - #endif /* __ASSEMBLER__ */ - - #endif /* _LINUX_ELFNOTE_H */ --- -1.7.11.4 - - -From 544f02e192a8a38153d7dedc61bc107545666c0d Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 20/32] MODSIGN: Provide gitignore and make clean rules for - extra files - -Provide gitignore and make clean rules for extra files to hide and clean up the -extra files produced by module signing stuff once it is added. Also add a -clean up rule for the module content extractor program used to extract the data -to be signed. - -Signed-off-by: David Howells ---- - .gitignore | 12 ++++++++++++ - Makefile | 1 + - scripts/mod/.gitignore | 1 + - 3 files changed, 14 insertions(+) - -diff --git a/.gitignore b/.gitignore -index 57af07c..7948eeb 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,6 +14,9 @@ - *.o.* - *.a - *.s -+*.ko.unsigned -+*.ko.digest -+*.ko.digest.sig - *.ko - *.so - *.so.dbg -@@ -84,3 +87,12 @@ GTAGS - *.orig - *~ - \#*# -+ -+# -+# GPG leavings from module signing -+# -+genkey -+modsign.pub -+modsign.sec -+random_seed -+trustdb.gpg -diff --git a/Makefile b/Makefile -index ddf5be9..70a6b5b 100644 ---- a/Makefile -+++ b/Makefile -@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -+ -o -name '*.ko.*' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ - -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ -diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore -index e9b7abe..223dfd6 100644 ---- a/scripts/mod/.gitignore -+++ b/scripts/mod/.gitignore -@@ -1,4 +1,5 @@ - elfconfig.h - mk_elfconfig - modpost -+mod-extract - --- -1.7.11.4 - - -From 6e21809168e7b45a830ec354ec9fc1582fcffe4f Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 21/32] MODSIGN: Provide Documentation and Kconfig options - -Provide documentation and kernel configuration options for module signing. - -The documentation can be found in: - - Documentation/module-signing.txt - -The following configuration options are added: - - (1) CONFIG_MODULE_SIG - - Enable module signing. This will both cause the build process to sign - modules and the kernel to check modules when they're loaded. - - (2) CONFIG_MODULE_SIG_SHA1 - CONFIG_MODULE_SIG_SHA224 - CONFIG_MODULE_SIG_SHA256 - CONFIG_MODULE_SIG_SHA384 - CONFIG_MODULE_SIG_SHA512 - - Select the cryptographic hash used to digest the data prior to signing. - Additionally, the crypto module selected will be built into the kernel as - it won't be possible to load it as a module without incurring a circular - dependency when the kernel tries to check its signature. - - (3) CONFIG_MODULE_SIG_FORCE - - Require that any module loaded must be signed with a key compiled into - the kernel. All other modules are rejected with EKEYREJECTED. - -Signed-off-by: David Howells ---- - Documentation/module-signing.txt | 194 +++++++++++++++++++++++++++++++++++++++ - include/linux/modsign.h | 27 ++++++ - init/Kconfig | 54 +++++++++++ - 3 files changed, 275 insertions(+) - create mode 100644 Documentation/module-signing.txt - create mode 100644 include/linux/modsign.h - -diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt -new file mode 100644 -index 0000000..d75d473 ---- /dev/null -+++ b/Documentation/module-signing.txt -@@ -0,0 +1,194 @@ -+ ============================== -+ KERNEL MODULE SIGNING FACILITY -+ ============================== -+ -+The module signing facility applies cryptographic signature checking to modules -+on module load, checking the signature against a ring of public keys compiled -+into the kernel. GPG is used to do the cryptographic work and determines the -+format of the signature and key data. The facility uses GPG's MPI library to -+handle the huge numbers involved. -+ -+This facility is enabled through CONFIG_MODULE_SIG. Turning on signature -+checking will also force the module's ELF metadata to be verified before the -+signature is checked. -+ -+The signature checker in the kernel is capable of handling multiple keys of -+either DSA or RSA type, and can support any of MD5, RIPE-MD-160, SHA-1, -+SHA-224, SHA-256, SHA-384 and SHA-512 hashes - PROVIDED(!) the requisite -+algorithms are compiled into the kernel. -+ -+(!) NOTE: Modules may only be verified initially with algorithms compiled into -+the kernel. Further algorithm modules may be loaded and used - but these must -+first pass a verification step using already loaded/compiled-in algorithms. -+ -+ -+===================== -+SUPPLYING PUBLIC KEYS -+===================== -+ -+A set of public keys must be supplied at kernel image build time. This is done -+by taking a GPG public key file and placing it in the base of the kernel -+directory in a file called modsign.pub. -+ -+For example, a throwaway key could be generated automatically by something like -+the following: -+ -+ cat >genkey < -+ -+ This indicates the whereabouts of the GPG keyring that is the source of -+ the public key to be used. The default is "./modsign.pub". -+ -+ (*) MODKEYNAME= -+ -+ The name of the key pair to be used from the aforementioned keyrings. -+ This defaults to being unset, thus leaving the choice of default key to -+ gpg. -+ -+ (*) KEYFLAGS="gpg-options" -+ -+ Override the complete gpg command line, including the preceding three -+ options. The default options supplied to gpg are: -+ -+ --no-default-keyring -+ --secret-keyring $(MODSECKEY) -+ --keyring $(MODPUBKEY) -+ --no-default-keyring -+ --homedir . -+ --no-options -+ --no-auto-check-trustdb -+ --no-permission-warning -+ --digest-algo= -+ -+ with: -+ -+ --default-key $(MODKEYNAME) -+ -+ being added if requested. -+ -+The resulting module.ko file will be the signed module. -+ -+ -+======================== -+STRIPPING SIGNED MODULES -+======================== -+ -+Signed modules may be safely stripped with any of the following: -+ -+ strip -x -+ strip -g -+ eu-strip -+ -+as the signature only covers those parts of the module the kernel actually uses -+and any ELF metadata required to deal with them. Any necessary ELF metadata -+that is affected by stripping is canonicalised by the sig generator and the sig -+checker to hide strip effects. -+ -+This permits the debuginfo to be detached from the module and placed in another -+spot so that gdb can find it when referring to that module without the need for -+multiple signed versions of the module. Such is done by rpmbuild when -+producing RPMs. -+ -+It also permits the module to be stripped as far as possible for when modules -+are being reduced prior to being included in an initial ramdisk composition. -+ -+Note that "strip" and "strip -s" may not be used on a module, signed or -+otherwise, as they remove the symbol table and render the relocation tables -+unusable. -+ -+ -+====================== -+LOADING SIGNED MODULES -+====================== -+ -+Modules are loaded with insmod, exactly as for unsigned modules. The signature -+is inserted into the module object file during the build process as an ELF note -+called "module.sig" in an ELF section called ".note.module.sig". The signature -+checker will detect it and apply signature checking. -+ -+ -+========================================= -+NON-VALID SIGNATURES AND UNSIGNED MODULES -+========================================= -+ -+If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on -+the kernel command line, the kernel will _only_ load validly signed modules -+for which it has a public key. Otherwise, it will also load modules that are -+unsigned. Any module for which the kernel has a key, but which proves to have -+a signature mismatch will not be permitted to load (returning EKEYREJECTED). -+ -+This table indicates the behaviours of the various situations: -+ -+ MODULE STATE PERMISSIVE MODE ENFORCING MODE -+ ======================================= =============== =============== -+ Unsigned Ok EKEYREJECTED -+ Signed, no public key ENOKEY ENOKEY -+ Validly signed, public key Ok Ok -+ Invalidly signed, public key EKEYREJECTED EKEYREJECTED -+ Validly signed, expired key EKEYEXPIRED EKEYEXPIRED -+ Signed, hash algorithm unavailable ENOPKG ENOPKG -+ Corrupt signature EBADMSG EBADMSG -+ Corrupt ELF ELIBBAD ELIBBAD -diff --git a/include/linux/modsign.h b/include/linux/modsign.h -new file mode 100644 -index 0000000..c5ac87a ---- /dev/null -+++ b/include/linux/modsign.h -@@ -0,0 +1,27 @@ -+/* Module signing definitions -+ * -+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_MODSIGN_H -+#define _LINUX_MODSIGN_H -+ -+#ifdef CONFIG_MODULE_SIG -+ -+#include -+ -+/* -+ * The parameters of the ELF note used to carry the signature -+ */ -+#define MODSIGN_NOTE_NAME module.sig -+#define MODSIGN_NOTE_TYPE 100 -+ -+#endif -+ -+#endif /* _LINUX_MODSIGN_H */ -diff --git a/init/Kconfig b/init/Kconfig -index af6c7f8..e23ed83 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1585,6 +1585,60 @@ config MODULE_SRCVERSION_ALL - the version). With this option, such a "srcversion" field - will be created for all modules. If unsure, say N. - -+config MODULE_SIG -+ bool "Module signature verification" -+ depends on MODULES -+ select KEYS -+ select CRYPTO_KEY_TYPE -+ select CRYPTO_KEY_PKEY_ALGO_DSA -+ select CRYPTO_KEY_PKEY_ALGO_RSA -+ select PGP_PARSER -+ select PGP_PRELOAD -+ help -+ Check modules for valid signatures upon load. For more information -+ see: -+ -+ Documentation/module-signing.txt -+ -+choice -+ prompt "Which hash algorithm should modules be signed with?" -+ depends on MODULE_SIG -+ help -+ This determines which sort of hashing algorithm will be used during -+ signature generation. This algorithm _must_ be built into the kernel -+ directly so that signature verification can take place. It is not -+ possible to load a signed module containing the algorithm to check -+ the signature on that module. -+ -+config MODULE_SIG_SHA1 -+ bool "Sign modules with SHA-1" -+ select CRYPTO_SHA1 -+ -+config MODULE_SIG_SHA224 -+ bool "Sign modules with SHA-224" -+ select CRYPTO_SHA224 -+ -+config MODULE_SIG_SHA256 -+ bool "Sign modules with SHA-256" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA384 -+ bool "Sign modules with SHA-384" -+ select CRYPTO_SHA384 -+ -+config MODULE_SIG_SHA512 -+ bool "Sign modules with SHA-512" -+ select CRYPTO_SHA512 -+ -+endchoice -+ -+config MODULE_SIG_FORCE -+ bool "Required modules to be validly signed (EXPERIMENTAL)" -+ depends on MODULE_SIG -+ help -+ Reject unsigned modules or signed modules for which we don't have a -+ key. -+ - endif # MODULES - - config INIT_ALL_POSSIBLE --- -1.7.11.4 - - -From 7733934d34b7f03574b4578edfad4a60d6fe3d56 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 22/32] MODSIGN: Sign modules during the build process - -If CONFIG_MODULE_SIG is set, then this patch will cause the module to get a -signature installed. The following steps will occur: - - (1) The module will be linked to foo.ko.unsigned instead of foo.ko - - (2) The module's signable content will be extracted to foo.ko.digest by the - mod-extract program. - - (3) The signature will be generated on foo.ko.digest by gpg and placed in - foo.ko.digest.sig - - (4) The signature will be encapsulated into an ELF note and placed into a file - called foo.ko.note.o using the output from modsign-note.sh piped into the - assembler. - - (5) The unsigned module from (1) and the signature ELF note from (4) will be - linked together to produce foo.ko - -Step (3) requires private and public keys to be available. By default these -are expected to be found in PGP keyring files called modsign.sec (the secret -key) and modsign.pub (the public key) in the build root. - -If the secret key is not found then signing will be skipped and the unsigned -module from (1) will just be copied to foo.ko. - -If signing occurs, lines like the following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - SIGN [M] fs/foo/foo.ko - -will appear in the build log. If it is skipped, the following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - NO SIGN [M] fs/foo/foo.ko - -Signed-off-by: David Howells ---- - scripts/Makefile.modpost | 87 ++++- - scripts/mod/Makefile | 2 +- - scripts/mod/mod-extract.c | 913 ++++++++++++++++++++++++++++++++++++++++++++ - scripts/mod/modsign-note.sh | 16 + - 4 files changed, 1016 insertions(+), 2 deletions(-) - create mode 100644 scripts/mod/mod-extract.c - create mode 100644 scripts/mod/modsign-note.sh - -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 08dce14..17465d8 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -14,7 +14,8 @@ - # 3) create one .mod.c file pr. module - # 4) create one Module.symvers file with CRC for all exported symbols - # 5) compile all .mod.c files --# 6) final link of the module to a file -+# 6) final link of the module to a (or ) file -+# 7) signs the modules to a file - - # Step 3 is used to place certain information in the module's ELF - # section, including information such as: -@@ -32,6 +33,8 @@ - # Step 4 is solely used to allow module versioning in external modules, - # where the CRC of each module is retrieved from the Module.symvers file. - -+# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. -+ - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined - # symbols in the final module linking stage - # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE - targets += $(modules:.ko=.mod.o) - - # Step 6), final link of the modules -+ifneq ($(CONFIG_MODULE_SIG),y) - quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -125,7 +129,88 @@ $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) - - targets += $(modules) -+else -+quiet_cmd_ld_ko_unsigned_o = LD [M] $@ -+ cmd_ld_ko_unsigned_o = \ -+ $(LD) -r $(LDFLAGS) \ -+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -+ -o $@ $(filter-out FORCE,$^) \ -+ $(if $(AFTER_LINK),; $(AFTER_LINK)) -+ -+$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE -+ $(call if_changed,ld_ko_unsigned_o) -+ -+targets += $(modules:.ko=.ko.unsigned) -+ -+# Step 7), sign the modules -+MODSECKEY = ./modsign.sec -+MODPUBKEY = ./modsign.pub -+KEYFLAGS = --no-default-keyring --secret-keyring $(MODSECKEY) --keyring $(MODPUBKEY) --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning -+ -+ifdef CONFIG_MODULE_SIG_SHA1 -+KEYFLAGS += --digest-algo=SHA1 -+else -+ifdef CONFIG_MODULE_SIG_SHA224 -+KEYFLAGS += --digest-algo=SHA224 -+else -+ifdef CONFIG_MODULE_SIG_SHA256 -+KEYFLAGS += --digest-algo=SHA256 -+else -+ifdef CONFIG_MODULE_SIG_SHA384 -+KEYFLAGS += --digest-algo=SHA384 -+else -+ifdef CONFIG_MODULE_SIG_SHA512 -+KEYFLAGS += --digest-algo=SHA512 -+else -+endif -+endif -+endif -+endif -+endif -+ -+ifdef MODKEYNAME -+KEYFLAGS += --default-key $(MODKEYNAME) -+endif - -+ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) -+ifeq ($(KBUILD_SRC),) -+ # no O= is being used -+ SCRIPTS_DIR := scripts -+else -+ SCRIPTS_DIR := $(KBUILD_SRC)/scripts -+endif -+SIGN_MODULES := 1 -+else -+SIGN_MODULES := 0 -+endif -+ -+# only sign if it's an in-tree module -+ifneq ($(KBUILD_EXTMOD),) -+SIGN_MODULES := 0 -+endif -+ -+ifeq ($(SIGN_MODULES),1) -+KEYRING_DEP := modsign.sec modsign.pub -+quiet_cmd_sign_ko_ko_unsigned = SIGN [M] $@ -+ cmd_sign_ko_ko_unsigned = \ -+ scripts/mod/mod-extract $< $@.digest && \ -+ rm -f $@.digest.sig && \ -+ gpg --batch --no-greeting $(KEYFLAGS) -b $@.digest && \ -+ sh $(SCRIPTS_DIR)/mod/modsign-note.sh $@.digest.sig | \ -+ $(CC) -x assembler-with-cpp $(c_flags) $(CFLAGS_MODULE) -c -o $@.note.o - && \ -+ $(LD) -r $(LDFLAGS) -o $@ $< $@.note.o -+else -+KEYRING_DEP := -+quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ -+ cmd_sign_ko_ko_unsigned = \ -+ cp $< $@ -+endif -+ -+$(modules): %.ko :%.ko.unsigned $(KEYRING_DEP) FORCE -+ $(call if_changed,sign_ko_ko_unsigned) -+ -+targets += $(modules) -+endif - - # Add FORCE to the prequisites of a target to force it to be always rebuilt. - # --------------------------------------------------------------------------- -diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile -index ff954f8..4654e3b 100644 ---- a/scripts/mod/Makefile -+++ b/scripts/mod/Makefile -@@ -1,4 +1,4 @@ --hostprogs-y := modpost mk_elfconfig -+hostprogs-y := modpost mk_elfconfig mod-extract - always := $(hostprogs-y) empty.o - - modpost-objs := modpost.o file2alias.o sumversion.o -diff --git a/scripts/mod/mod-extract.c b/scripts/mod/mod-extract.c -new file mode 100644 -index 0000000..0c0e3e3 ---- /dev/null -+++ b/scripts/mod/mod-extract.c -@@ -0,0 +1,913 @@ -+/* mod-extract.c: module extractor for signing -+ * -+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static void extract_elf64(void *buffer, size_t size, Elf64_Ehdr *hdr); -+static void extract_elf32(void *buffer, size_t size, Elf32_Ehdr *hdr); -+ -+struct byteorder { -+ uint16_t (*get16)(const uint16_t *); -+ uint32_t (*get32)(const uint32_t *); -+ uint64_t (*get64)(const uint64_t *); -+ void (*set16)(uint16_t *, uint16_t); -+ void (*set32)(uint32_t *, uint32_t); -+ void (*set64)(uint64_t *, uint64_t); -+}; -+ -+static uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); } -+static uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); } -+static uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); } -+static uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); } -+static uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); } -+static uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); } -+ -+static void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); } -+static void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); } -+static void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); } -+static void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); } -+static void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); } -+static void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); } -+ -+static const struct byteorder byteorder_le = { -+ get16_le, get32_le, get64_le, -+ set16_le, set32_le, set64_le -+}; -+static const struct byteorder byteorder_be = { -+ get16_be, get32_be, get64_be, -+ set16_be, set32_be, set64_be -+}; -+static const struct byteorder *order; -+ -+static inline uint16_t get16(const uint16_t *p) { return order->get16(p); } -+static inline uint32_t get32(const uint32_t *p) { return order->get32(p); } -+static inline uint64_t get64(const uint64_t *p) { return order->get64(p); } -+static inline void set16(uint16_t *p, uint16_t n) { order->set16(p, n); } -+static inline void set32(uint32_t *p, uint32_t n) { order->set32(p, n); } -+static inline void set64(uint64_t *p, uint64_t n) { order->set64(p, n); } -+ -+static FILE *outfd; -+static uint8_t csum, xcsum; -+ -+static void write_out(const void *data, size_t size) -+{ -+ const uint8_t *p = data; -+ size_t loop; -+ -+ for (loop = 0; loop < size; loop++) { -+ csum += p[loop]; -+ xcsum += p[loop]; -+ } -+ -+ if (fwrite(data, 1, size, outfd) != size) { -+ perror("write"); -+ exit(1); -+ } -+} -+ -+#define write_out_val(VAL) write_out(&(VAL), sizeof(VAL)) -+ -+static int is_verbose; -+ -+static __attribute__((format(printf, 1, 2))) -+void verbose(const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (is_verbose) { -+ va_start(va, fmt); -+ vprintf(fmt, va); -+ va_end(va); -+ } -+} -+ -+static __attribute__((noreturn)) -+void usage(void) -+{ -+ fprintf(stderr, "Usage: mod-extract [-v] \n"); -+ exit(2); -+} -+ -+/* -+ * -+ */ -+int main(int argc, char **argv) -+{ -+ struct stat st; -+ Elf32_Ehdr *hdr32; -+ Elf64_Ehdr *hdr64; -+ size_t len; -+ void *buffer; -+ int fd, be, b64; -+ -+ while (argc > 1 && strcmp("-v", argv[1]) == 0) { -+ argv++; -+ argc--; -+ is_verbose++; -+ } -+ -+ if (argc != 3) -+ usage(); -+ -+ /* map the module into memory */ -+ fd = open(argv[1], O_RDONLY); -+ if (fd < 0) { -+ perror("open input"); -+ exit(1); -+ } -+ -+ if (fstat(fd, &st) < 0) { -+ perror("fstat"); -+ exit(1); -+ } -+ -+ len = st.st_size; -+ -+ buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); -+ if (buffer == MAP_FAILED) { -+ perror("mmap"); -+ exit(1); -+ } -+ -+ if (close(fd) < 0) { -+ perror("close input"); -+ exit(1); -+ } -+ -+ /* check it's an ELF object */ -+ hdr32 = buffer; -+ hdr64 = buffer; -+ -+ if (hdr32->e_ident[EI_MAG0] != ELFMAG0 || -+ hdr32->e_ident[EI_MAG1] != ELFMAG1 || -+ hdr32->e_ident[EI_MAG2] != ELFMAG2 || -+ hdr32->e_ident[EI_MAG3] != ELFMAG3 -+ ) { -+ fprintf(stderr, "Module does not appear to be ELF\n"); -+ exit(3); -+ } -+ -+ /* determine endianness and word size */ -+ b64 = (hdr32->e_ident[EI_CLASS] == ELFCLASS64); -+ be = (hdr32->e_ident[EI_DATA] == ELFDATA2MSB); -+ order = be ? &byteorder_be : &byteorder_le; -+ -+ verbose("Module is %s-bit %s-endian\n", -+ b64 ? "64" : "32", -+ be ? "big" : "little"); -+ -+ /* open the output file */ -+ outfd = fopen(argv[2], "w"); -+ if (!outfd) { -+ perror("open output"); -+ exit(1); -+ } -+ -+ /* perform the extraction */ -+ if (b64) -+ extract_elf64(buffer, len, hdr64); -+ else -+ extract_elf32(buffer, len, hdr32); -+ -+ /* done */ -+ if (fclose(outfd) == EOF) { -+ perror("close output"); -+ exit(1); -+ } -+ -+ return 0; -+} -+ -+/* -+ * extract a RELA table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static void extract_elf64_rela(const void *buffer, int secix, int targetix, -+ const Elf64_Rela *relatab, size_t nrels, -+ const Elf64_Sym *symbols, size_t nsyms, -+ const Elf64_Shdr *sections, size_t nsects, int *canonmap, -+ const char *strings, size_t nstrings, -+ const char *sh_name) -+{ -+ struct { -+ uint64_t r_offset; -+ uint64_t r_addend; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+ -+ } __attribute__((packed)) relocation; -+ -+ const Elf64_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ Elf64_Section st_shndx; -+ Elf64_Xword r_info; -+ -+ /* decode the relocation */ -+ r_info = get64(&relatab[loop].r_info); -+ relocation.r_offset = relatab[loop].r_offset; -+ relocation.r_addend = relatab[loop].r_addend; -+ set32(&relocation.r_type, ELF64_R_TYPE(r_info)); -+ -+ if (ELF64_R_SYM(r_info) >= nsyms) { -+ fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n", -+ (size_t)ELF64_R_SYM(r_info), loop); -+ exit(1); -+ } -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &symbols[ELF64_R_SYM(r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = get16(&symbol->st_shndx); -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < nsects) -+ set16(&relocation.st_shndx, canonmap[st_shndx]); -+ -+ write_out_val(relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + get32(&symbol->st_name); -+ write_out(name, strlen(name) + 1); -+ } -+ } -+ -+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name); -+} -+ -+/* -+ * extract a REL table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static void extract_elf64_rel(const void *buffer, int secix, int targetix, -+ const Elf64_Rel *relatab, size_t nrels, -+ const Elf64_Sym *symbols, size_t nsyms, -+ const Elf64_Shdr *sections, size_t nsects, int *canonmap, -+ const char *strings, size_t nstrings, -+ const char *sh_name) -+{ -+ struct { -+ uint64_t r_offset; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+ -+ } __attribute__((packed)) relocation; -+ -+ const Elf64_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ Elf64_Section st_shndx; -+ Elf64_Xword r_info; -+ -+ /* decode the relocation */ -+ r_info = get64(&relatab[loop].r_info); -+ relocation.r_offset = relatab[loop].r_offset; -+ set32(&relocation.r_type, ELF64_R_TYPE(r_info)); -+ -+ if (ELF64_R_SYM(r_info) >= nsyms) { -+ fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n", -+ (size_t)ELF64_R_SYM(r_info), loop); -+ exit(1); -+ } -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &symbols[ELF64_R_SYM(r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = get16(&symbol->st_shndx); -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < nsects) -+ set16(&relocation.st_shndx, canonmap[st_shndx]); -+ -+ write_out_val(relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + get32(&symbol->st_name); -+ write_out(name, strlen(name) + 1); -+ } -+ } -+ -+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name); -+} -+ -+/* -+ * extract the data from a 64-bit module -+ */ -+static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr) -+{ -+ const Elf64_Sym *symbols; -+ Elf64_Shdr *sections; -+ const char *secstrings, *strings; -+ size_t nsyms, nstrings; -+ int loop, shnum, *canonlist, *canonmap, canon, changed, tmp; -+ -+ sections = buffer + get64(&hdr->e_shoff); -+ secstrings = buffer + get64(§ions[get16(&hdr->e_shstrndx)].sh_offset); -+ shnum = get16(&hdr->e_shnum); -+ -+ /* find the symbol table and the string table and produce a list of -+ * index numbers of sections that contribute to the kernel's module -+ * image -+ */ -+ canonlist = calloc(sizeof(int), shnum * 2); -+ if (!canonlist) { -+ perror("calloc"); -+ exit(1); -+ } -+ canonmap = canonlist + shnum; -+ canon = 0; -+ -+ symbols = NULL; -+ strings = NULL; -+ nstrings = 0; -+ nsyms = 0; -+ -+ for (loop = 1; loop < shnum; loop++) { -+ const char *sh_name = secstrings + get32(§ions[loop].sh_name); -+ Elf64_Word sh_type = get32(§ions[loop].sh_type); -+ Elf64_Xword sh_size = get64(§ions[loop].sh_size); -+ Elf64_Xword sh_flags = get64(§ions[loop].sh_flags); -+ Elf64_Word sh_info = get32(§ions[loop].sh_info); -+ Elf64_Off sh_offset = get64(§ions[loop].sh_offset); -+ void *data = buffer + sh_offset; -+ -+ /* quick sanity check */ -+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) { -+ fprintf(stderr, "Section goes beyond EOF\n"); -+ exit(3); -+ } -+ -+ /* we only need to canonicalise allocatable sections */ -+ if (sh_flags & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ else if ((sh_type == SHT_REL || sh_type == SHT_RELA) && -+ get64(§ions[sh_info].sh_flags) & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ -+ /* keep track of certain special sections */ -+ switch (sh_type) { -+ case SHT_SYMTAB: -+ if (strcmp(sh_name, ".symtab") == 0) { -+ symbols = data; -+ nsyms = sh_size / sizeof(Elf64_Sym); -+ } -+ break; -+ -+ case SHT_STRTAB: -+ if (strcmp(sh_name, ".strtab") == 0) { -+ strings = data; -+ nstrings = sh_size; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ if (!symbols) { -+ fprintf(stderr, "Couldn't locate symbol table\n"); -+ exit(3); -+ } -+ -+ if (!strings) { -+ fprintf(stderr, "Couldn't locate strings table\n"); -+ exit(3); -+ } -+ -+ /* canonicalise the index numbers of the contributing section */ -+ do { -+ changed = 0; -+ -+ for (loop = 0; loop < canon - 1; loop++) { -+ const char *x = secstrings + get32(§ions[canonlist[loop + 0]].sh_name); -+ const char *y = secstrings + get32(§ions[canonlist[loop + 1]].sh_name); -+ if (strcmp(x, y) > 0) { -+ tmp = canonlist[loop + 0]; -+ canonlist[loop + 0] = canonlist[loop + 1]; -+ canonlist[loop + 1] = tmp; -+ changed = 1; -+ } -+ } -+ -+ } while (changed); -+ -+ for (loop = 0; loop < canon; loop++) -+ canonmap[canonlist[loop]] = loop + 1; -+ -+ if (is_verbose > 1) { -+ printf("\nSection canonicalisation map:\n"); -+ for (loop = 1; loop < shnum; loop++) { -+ const char *x = secstrings + get32(§ions[loop].sh_name); -+ printf("%4d %s\n", canonmap[loop], x); -+ } -+ -+ printf("\nAllocated section list in canonical order:\n"); -+ for (loop = 0; loop < canon; loop++) { -+ const char *x = secstrings + get32(§ions[canonlist[loop]].sh_name); -+ printf("%4d %s\n", canonlist[loop], x); -+ } -+ } -+ -+ /* iterate through the section table looking for sections we want to -+ * contribute to the signature */ -+ verbose("\n"); -+ verbose("CAN FILE POS CS SECT NAME\n"); -+ verbose("=== ======== == ==== ==============================\n"); -+ -+ for (loop = 0; loop < canon; loop++) { -+ int sect = canonlist[loop]; -+ const char *sh_name = secstrings + get32(§ions[sect].sh_name); -+ Elf64_Word sh_type = get32(§ions[sect].sh_type); -+ Elf64_Xword sh_size = get64(§ions[sect].sh_size); -+ Elf64_Xword sh_flags = get64(§ions[sect].sh_flags); -+ Elf64_Word sh_info = get32(§ions[sect].sh_info); -+ Elf64_Off sh_offset = get64(§ions[sect].sh_offset); -+ void *data = buffer + sh_offset; -+ -+ csum = 0; -+ -+ /* include canonicalised relocation sections */ -+ if (sh_type == SHT_REL || sh_type == SHT_RELA) { -+ Elf32_Word canon_sh_info; -+ -+ if (sh_info <= 0 && sh_info >= hdr->e_shnum) { -+ fprintf(stderr, -+ "Invalid ELF - REL/RELA sh_info does" -+ " not refer to a valid section\n"); -+ exit(3); -+ } -+ -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ set32(&canon_sh_info, canonmap[sh_info]); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ write_out_val(canon_sh_info); -+ -+ if (sh_type == SHT_RELA) -+ extract_elf64_rela(buffer, sect, sh_info, -+ data, sh_size / sizeof(Elf64_Rela), -+ symbols, nsyms, -+ sections, shnum, canonmap, -+ strings, nstrings, -+ sh_name); -+ else -+ extract_elf64_rel(buffer, sect, sh_info, -+ data, sh_size / sizeof(Elf64_Rel), -+ symbols, nsyms, -+ sections, shnum, canonmap, -+ strings, nstrings, -+ sh_name); -+ continue; -+ } -+ -+ /* include the headers of BSS sections */ -+ if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) { -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ -+ verbose("%02x %4d %s\n", csum, sect, sh_name); -+ } -+ -+ /* include allocatable loadable sections */ -+ if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC) -+ goto include_section; -+ -+ /* not this section */ -+ continue; -+ -+ include_section: -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ -+ /* write out the section data */ -+ write_out(data, sh_size); -+ -+ verbose("%02x %4d %s\n", csum, sect, sh_name); -+ } -+ -+ verbose("%08lx (%lu bytes csum 0x%02x)\n", -+ ftell(outfd), ftell(outfd), xcsum); -+} -+ -+/* -+ * extract a RELA table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static void extract_elf32_rela(const void *buffer, int secix, int targetix, -+ const Elf32_Rela *relatab, size_t nrels, -+ const Elf32_Sym *symbols, size_t nsyms, -+ const Elf32_Shdr *sections, size_t nsects, -+ int *canonmap, -+ const char *strings, size_t nstrings, -+ const char *sh_name) -+{ -+ struct { -+ uint32_t r_offset; -+ uint32_t r_addend; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+ -+ } __attribute__((packed)) relocation; -+ -+ const Elf32_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ Elf32_Section st_shndx; -+ Elf32_Word r_info; -+ -+ /* decode the relocation */ -+ r_info = get32(&relatab[loop].r_info); -+ relocation.r_offset = relatab[loop].r_offset; -+ relocation.r_addend = relatab[loop].r_addend; -+ relocation.r_type = ELF32_R_TYPE(r_info); -+ -+ if (ELF32_R_SYM(r_info) >= nsyms) { -+ fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n", -+ ELF32_R_SYM(r_info), loop); -+ exit(1); -+ } -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &symbols[ELF32_R_SYM(r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = get16(&symbol->st_shndx); -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < nsects) -+ set16(&relocation.st_shndx, canonmap[st_shndx]); -+ -+ write_out_val(relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + get32(&symbol->st_name); -+ write_out(name, strlen(name) + 1); -+ } -+ } -+ -+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name); -+} -+ -+/* -+ * extract a REL table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static void extract_elf32_rel(const void *buffer, int secix, int targetix, -+ const Elf32_Rel *relatab, size_t nrels, -+ const Elf32_Sym *symbols, size_t nsyms, -+ const Elf32_Shdr *sections, size_t nsects, -+ int *canonmap, -+ const char *strings, size_t nstrings, -+ const char *sh_name) -+{ -+ struct { -+ uint32_t r_offset; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+ -+ } __attribute__((packed)) relocation; -+ -+ const Elf32_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ Elf32_Section st_shndx; -+ Elf32_Word r_info; -+ -+ /* decode the relocation */ -+ r_info = get32(&relatab[loop].r_info); -+ relocation.r_offset = relatab[loop].r_offset; -+ relocation.r_type = ELF32_R_TYPE(r_info); -+ -+ if (ELF32_R_SYM(r_info) >= nsyms) { -+ fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n", -+ ELF32_R_SYM(r_info), loop); -+ exit(1); -+ } -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &symbols[ELF32_R_SYM(r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = get16(&symbol->st_shndx); -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < nsects) -+ set16(&relocation.st_shndx, canonmap[st_shndx]); -+ -+ write_out_val(relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + get32(&symbol->st_name); -+ write_out(name, strlen(name) + 1); -+ } -+ } -+ -+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name); -+} -+ -+/* -+ * extract the data from a 32-bit module -+ */ -+static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr) -+{ -+ const Elf32_Sym *symbols; -+ Elf32_Shdr *sections; -+ const char *secstrings, *strings; -+ size_t nsyms, nstrings; -+ int loop, shnum, *canonlist, *canonmap, canon, changed, tmp; -+ -+ sections = buffer + get32(&hdr->e_shoff); -+ secstrings = buffer + get32(§ions[get16(&hdr->e_shstrndx)].sh_offset); -+ shnum = get16(&hdr->e_shnum); -+ -+ /* find the symbol table and the string table and produce a list of -+ * index numbers of sections that contribute to the kernel's module -+ * image -+ */ -+ canonlist = calloc(sizeof(int), shnum * 2); -+ if (!canonlist) { -+ perror("calloc"); -+ exit(1); -+ } -+ canonmap = canonlist + shnum; -+ canon = 0; -+ -+ symbols = NULL; -+ strings = NULL; -+ nstrings = 0; -+ nsyms = 0; -+ -+ for (loop = 1; loop < shnum; loop++) { -+ const char *sh_name = secstrings + get32(§ions[loop].sh_name); -+ Elf32_Word sh_type = get32(§ions[loop].sh_type); -+ Elf32_Xword sh_size = get32(§ions[loop].sh_size); -+ Elf32_Xword sh_flags = get32(§ions[loop].sh_flags); -+ Elf64_Word sh_info = get32(§ions[loop].sh_info); -+ Elf32_Off sh_offset = get32(§ions[loop].sh_offset); -+ void *data = buffer + sh_offset; -+ -+ /* quick sanity check */ -+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) { -+ fprintf(stderr, "Section goes beyond EOF\n"); -+ exit(3); -+ } -+ -+ /* we only need to canonicalise allocatable sections */ -+ if (sh_flags & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ else if ((sh_type == SHT_REL || sh_type == SHT_RELA) && -+ get32(§ions[sh_info].sh_flags) & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ -+ /* keep track of certain special sections */ -+ switch (sh_type) { -+ case SHT_SYMTAB: -+ if (strcmp(sh_name, ".symtab") == 0) { -+ symbols = data; -+ nsyms = sh_size / sizeof(Elf32_Sym); -+ } -+ break; -+ -+ case SHT_STRTAB: -+ if (strcmp(sh_name, ".strtab") == 0) { -+ strings = data; -+ nstrings = sh_size; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ if (!symbols) { -+ fprintf(stderr, "Couldn't locate symbol table\n"); -+ exit(3); -+ } -+ -+ if (!strings) { -+ fprintf(stderr, "Couldn't locate strings table\n"); -+ exit(3); -+ } -+ -+ /* canonicalise the index numbers of the contributing section */ -+ do { -+ changed = 0; -+ -+ for (loop = 0; loop < canon - 1; loop++) { -+ const char *x = secstrings + get32(§ions[canonlist[loop + 0]].sh_name); -+ const char *y = secstrings + get32(§ions[canonlist[loop + 1]].sh_name); -+ if (strcmp(x, y) > 0) { -+ tmp = canonlist[loop + 0]; -+ canonlist[loop + 0] = canonlist[loop + 1]; -+ canonlist[loop + 1] = tmp; -+ changed = 1; -+ } -+ } -+ -+ } while (changed); -+ -+ for (loop = 0; loop < canon; loop++) -+ canonmap[canonlist[loop]] = loop + 1; -+ -+ if (is_verbose > 1) { -+ printf("\nSection canonicalisation map:\n"); -+ for (loop = 1; loop < shnum; loop++) { -+ const char *x = secstrings + get32(§ions[loop].sh_name); -+ printf("%4d %s\n", canonmap[loop], x); -+ } -+ -+ printf("\nAllocated section list in canonical order:\n"); -+ for (loop = 0; loop < canon; loop++) { -+ const char *x = secstrings + get32(§ions[canonlist[loop]].sh_name); -+ printf("%4d %s\n", canonlist[loop], x); -+ } -+ } -+ -+ /* iterate through the section table looking for sections we want to -+ * contribute to the signature */ -+ verbose("\n"); -+ verbose("CAN FILE POS CS SECT NAME\n"); -+ verbose("=== ======== == ==== ==============================\n"); -+ -+ for (loop = 0; loop < canon; loop++) { -+ int sect = canonlist[loop]; -+ const char *sh_name = secstrings + get32(§ions[sect].sh_name); -+ Elf32_Word sh_type = get32(§ions[sect].sh_type); -+ Elf32_Xword sh_size = get32(§ions[sect].sh_size); -+ Elf32_Xword sh_flags = get32(§ions[sect].sh_flags); -+ Elf32_Word sh_info = get32(§ions[sect].sh_info); -+ Elf32_Off sh_offset = get32(§ions[sect].sh_offset); -+ void *data = buffer + sh_offset; -+ -+ csum = 0; -+ -+ /* quick sanity check */ -+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) { -+ fprintf(stderr, "section goes beyond EOF\n"); -+ exit(3); -+ } -+ -+ /* include canonicalised relocation sections */ -+ if (sh_type == SHT_REL || sh_type == SHT_RELA) { -+ Elf32_Word canon_sh_info; -+ -+ if (sh_info <= 0 && sh_info >= hdr->e_shnum) { -+ fprintf(stderr, -+ "Invalid ELF - REL/RELA sh_info does" -+ " not refer to a valid section\n"); -+ exit(3); -+ } -+ -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ set32(&canon_sh_info, canonmap[sh_info]); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ write_out_val(canon_sh_info); -+ -+ if (sh_type == SHT_RELA) -+ extract_elf32_rela(buffer, sect, sh_info, -+ data, sh_size / sizeof(Elf32_Rela), -+ symbols, nsyms, -+ sections, shnum, canonmap, -+ strings, nstrings, -+ sh_name); -+ else -+ extract_elf32_rel(buffer, sect, sh_info, -+ data, sh_size / sizeof(Elf32_Rel), -+ symbols, nsyms, -+ sections, shnum, canonmap, -+ strings, nstrings, -+ sh_name); -+ continue; -+ } -+ -+ /* include the headers of BSS sections */ -+ if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) { -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ -+ verbose("%02x %4d %s\n", csum, sect, sh_name); -+ } -+ -+ /* include allocatable loadable sections */ -+ if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC) -+ goto include_section; -+ -+ /* not this section */ -+ continue; -+ -+ include_section: -+ verbose("%3u %08lx ", loop, ftell(outfd)); -+ -+ /* write out selected portions of the section header */ -+ write_out(sh_name, strlen(sh_name)); -+ write_out_val(sections[sect].sh_type); -+ write_out_val(sections[sect].sh_flags); -+ write_out_val(sections[sect].sh_size); -+ write_out_val(sections[sect].sh_addralign); -+ -+ /* write out the section data */ -+ write_out(data, sh_size); -+ -+ verbose("%02x %4d %s\n", csum, sect, sh_name); -+ } -+ -+ verbose("%08lx (%lu bytes csum 0x%02x)\n", -+ ftell(outfd), ftell(outfd), xcsum); -+} -diff --git a/scripts/mod/modsign-note.sh b/scripts/mod/modsign-note.sh -new file mode 100644 -index 0000000..bca67c0 ---- /dev/null -+++ b/scripts/mod/modsign-note.sh -@@ -0,0 +1,16 @@ -+#!/bin/sh -+# -+# Generate a module signature note source file -+# -+# mod-sign.sh > -+# -+ -+SIG=$1 -+ -+cat < -+ -+ELFNOTE(MODSIGN_NOTE_NAME, MODSIGN_NOTE_TYPE, .incbin "$SIG") -+EOF -+ -+exit 0 --- -1.7.11.4 - - -From ee3ca99bcf972f0d072d91f9256c39a197153b8e Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 23/32] MODSIGN: Module signature verification stub - -Create a stub for the module signature verifier and link it into module.c so -that it gets called. A field is added to struct module to record whether or -not a valid module signature was detected. - -The stub also implements the policy for handling unsigned modules and the -printing of error messages to indicate various problems with the module. - -If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on -the kernel command line, the kernel will _only_ load validly signed modules -for which it has a public key. Otherwise, it will also load modules that are -unsigned. Any module for which the kernel has a key, but which proves to have -a signature mismatch will not be permitted to load. - -This table indicates the behaviours in the various situations: - - MODULE STATE PERMISSIVE MODE ENFORCING MODE - ======================================= =============== =============== - Unsigned Ok EKEYREJECTED - Signed, no public key ENOKEY ENOKEY - Validly signed, public key Ok Ok - Invalidly signed, public key EKEYREJECTED EKEYREJECTED - Validly signed, expired key EKEYEXPIRED EKEYEXPIRED - Signed, hash algorithm unavailable ENOPKG ENOPKG - Corrupt signature EBADMSG EBADMSG - Corrupt ELF ELIBBAD ELIBBAD - -Signed-off-by: David Howells ---- - include/linux/module.h | 3 ++ - kernel/Makefile | 1 + - kernel/module-verify-defs.h | 77 +++++++++++++++++++++++++++++++ - kernel/module-verify.c | 110 ++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-verify.h | 20 ++++++++ - kernel/module.c | 26 +++++++++-- - 6 files changed, 232 insertions(+), 5 deletions(-) - create mode 100644 kernel/module-verify-defs.h - create mode 100644 kernel/module-verify.c - create mode 100644 kernel/module-verify.h - -diff --git a/include/linux/module.h b/include/linux/module.h -index fbcafe2..7391833 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -227,6 +227,9 @@ struct module - /* Unique handle for this module */ - char name[MODULE_NAME_LEN]; - -+ /* Is this module GPG signed */ -+ bool gpgsig_ok; -+ - /* Sysfs stuff. */ - struct module_kobject mkobj; - struct module_attribute *modinfo_attrs; -diff --git a/kernel/Makefile b/kernel/Makefile -index c0cc67a..cec222a 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o -+obj-$(CONFIG_MODULE_SIG) += module-verify.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h -new file mode 100644 -index 0000000..141ddab ---- /dev/null -+++ b/kernel/module-verify-defs.h -@@ -0,0 +1,77 @@ -+/* Module verification internal definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifdef CONFIG_MODULE_SIG -+ -+/* -+ * Internal state -+ */ -+struct module_verify_data { -+ struct crypto_key_verify_context *mod_sig; /* Module signing context */ -+ union { -+ const void *buffer; /* module buffer */ -+ const Elf_Ehdr *hdr; /* ELF header */ -+ }; -+ const Elf_Shdr *sections; /* ELF section table */ -+ const char *secstrings; /* ELF section string table */ -+ const void *sig; /* Signature note content */ -+ size_t size; /* module object size */ -+ size_t nsects; /* number of sections */ -+ size_t sig_size; /* Size of signature */ -+ size_t signed_size; /* count of bytes contributed to digest */ -+ unsigned *canonlist; /* list of canonicalised sections */ -+ unsigned *canonmap; /* section canonicalisation map */ -+ unsigned ncanon; /* number of canonicalised sections */ -+ unsigned sig_index; /* module signature section index */ -+ uint8_t xcsum; /* checksum of bytes contributed to digest */ -+ uint8_t csum; /* checksum of bytes representing a section */ -+}; -+ -+/* -+ * Whether or not we support various types of ELF relocation record -+ */ -+#if defined(MODULE_HAS_ELF_REL_ONLY) -+#define is_elf_rel(sh_type) ((sh_type) == SHT_REL) -+#define is_elf_rela(sh_type) (0) -+#elif defined(MODULE_HAS_ELF_RELA_ONLY) -+#define is_elf_rel(sh_type) (0) -+#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) -+#else -+#define is_elf_rel(sh_type) ((sh_type) == SHT_REL) -+#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) -+#endif -+ -+/* -+ * Debugging. Define DEBUG to enable. -+ */ -+#define _debug(FMT, ...) \ -+ do { \ -+ if (unlikely(modsign_debug)) \ -+ pr_debug(FMT, ##__VA_ARGS__); \ -+ } while (0) -+ -+#ifdef DEBUG -+#define count_and_csum(C, __p, __n) \ -+ do { \ -+ int __loop; \ -+ for (__loop = 0; __loop < __n; __loop++) { \ -+ (C)->csum += __p[__loop]; \ -+ (C)->xcsum += __p[__loop]; \ -+ } \ -+ (C)->signed_size += __n; \ -+ } while (0) -+#else -+#define count_and_csum(C, __p, __n) \ -+ do { \ -+ } while (0) -+#endif -+ -+#endif /* CONFIG_MODULE_SIG */ -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -new file mode 100644 -index 0000000..4bf857e ---- /dev/null -+++ b/kernel/module-verify.c -@@ -0,0 +1,110 @@ -+/* Module signature verification -+ * -+ * The code in this file examines a signed kernel module and attempts to -+ * determine if the PGP signature inside the module matches a digest of the -+ * allocatable sections and the canonicalised relocation tables for those -+ * allocatable sections. -+ * -+ * The module signature is included in an ELF note within the ELF structure of -+ * the module blob. This, combined with the minimal canonicalisation performed -+ * here, permits the module to pass through "strip -x", "strip -g" and -+ * "eu-strip" without becoming corrupt. "strip" and "strip -s" will render a -+ * module unusable by removing the symbol table. -+ * -+ * Copyright (C) 2004, 2011, 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * - Derived from GregKH's RSA module signer -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#undef DEBUG -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "module-verify.h" -+#include "module-verify-defs.h" -+ -+#ifdef DEBUG -+static int modsign_debug; -+core_param(modsign_debug, modsign_debug, int, 0644); -+#else -+#define modsign_debug false -+#endif -+ -+#ifdef CONFIG_MODULE_SIG_FORCE -+#define modsign_signedonly true -+#else -+static bool modsign_signedonly; -+#endif -+ -+static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); -+static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); -+ -+/* -+ * Verify a module's integrity -+ */ -+int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) -+{ -+ struct module_verify_data mvdata; -+ int ret; -+ -+ memset(&mvdata, 0, sizeof(mvdata)); -+ mvdata.buffer = hdr; -+ mvdata.size = size; -+ -+ if (mvdata.sig_index <= 0) { -+ /* Deal with an unsigned module */ -+ if (modsign_signedonly) { -+ pr_err("An attempt to load unsigned module was rejected\n"); -+ return -EKEYREJECTED; -+ } else { -+ return 0; -+ } -+ goto out; -+ } -+ -+ ret = 0; -+ -+out: -+ switch (ret) { -+ case 0: /* Good signature */ -+ *_gpgsig_ok = true; -+ break; -+ case -ELIBBAD: -+ pr_err("Module format error encountered\n"); -+ break; -+ case -EBADMSG: -+ pr_err("Module signature error encountered\n"); -+ break; -+ case -EKEYREJECTED: /* Signature mismatch or number format error */ -+ pr_err("Module signature verification failed\n"); -+ break; -+ case -ENOKEY: /* Signed, but we don't have the public key */ -+ pr_err("Module signed with unknown public key\n"); -+ break; -+ default: /* Other error (probably ENOMEM) */ -+ break; -+ } -+ return ret; -+} -+ -+static int __init sign_setup(char *str) -+{ -+#ifndef CONFIG_MODULE_SIG_FORCE -+ modsign_signedonly = true; -+#endif -+ return 0; -+} -+__setup("enforcemodulesig", sign_setup); -diff --git a/kernel/module-verify.h b/kernel/module-verify.h -new file mode 100644 -index 0000000..c640634 ---- /dev/null -+++ b/kernel/module-verify.h -@@ -0,0 +1,20 @@ -+/* Module verification definitions -+ * -+ * Copyright (C) 2004, 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#ifdef CONFIG_MODULE_SIG -+extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok); -+#else -+static inline int module_verify(const Elf_Ehdr *hdr, size_t size, -+ bool *_gpgsig_ok) -+{ -+ return 0; -+} -+#endif -diff --git a/kernel/module.c b/kernel/module.c -index 087aeed..a59a9da 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include "module-verify.h" - - #define CREATE_TRACE_POINTS - #include -@@ -2382,7 +2383,8 @@ static inline void kmemleak_load_module(const struct module *mod, - /* Sets info->hdr and info->len. */ - static int copy_and_check(struct load_info *info, - const void __user *umod, unsigned long len, -- const char __user *uargs) -+ const char __user *uargs, -+ bool *_gpgsig_ok) - { - int err; - Elf_Ehdr *hdr; -@@ -2415,6 +2417,12 @@ static int copy_and_check(struct load_info *info, - goto free_hdr; - } - -+ /* Verify the module's contents */ -+ *_gpgsig_ok = false; -+ err = module_verify(hdr, len, _gpgsig_ok); -+ if (err < 0) -+ goto free_hdr; -+ - info->hdr = hdr; - info->len = len; - return 0; -@@ -2757,7 +2765,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, - return 0; - } - --static struct module *layout_and_allocate(struct load_info *info) -+static struct module *layout_and_allocate(struct load_info *info, -+ bool gpgsig_ok) - { - /* Module within temporary copy. */ - struct module *mod; -@@ -2767,6 +2776,7 @@ static struct module *layout_and_allocate(struct load_info *info) - mod = setup_load_info(info); - if (IS_ERR(mod)) - return mod; -+ mod->gpgsig_ok = gpgsig_ok; - - err = check_modinfo(mod, info); - if (err) -@@ -2850,17 +2860,18 @@ static struct module *load_module(void __user *umod, - struct load_info info = { NULL, }; - struct module *mod; - long err; -+ bool gpgsig_ok; - - pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", - umod, len, uargs); - - /* Copy in the blobs from userspace, check they are vaguely sane. */ -- err = copy_and_check(&info, umod, len, uargs); -+ err = copy_and_check(&info, umod, len, uargs, &gpgsig_ok); - if (err) - return ERR_PTR(err); - - /* Figure out module layout, and allocate all the memory. */ -- mod = layout_and_allocate(&info); -+ mod = layout_and_allocate(&info, gpgsig_ok); - if (IS_ERR(mod)) { - err = PTR_ERR(mod); - goto free_copy; -@@ -3497,8 +3508,13 @@ void print_modules(void) - printk(KERN_DEFAULT "Modules linked in:"); - /* Most callers should already have preempt disabled, but make sure */ - preempt_disable(); -- list_for_each_entry_rcu(mod, &modules, list) -+ list_for_each_entry_rcu(mod, &modules, list) { - printk(" %s%s", mod->name, module_flags(mod, buf)); -+#ifdef CONFIG_MODULE_SIG -+ if (!mod->gpgsig_ok) -+ printk("(U)"); -+#endif -+ } - preempt_enable(); - if (last_unloaded_module[0]) - printk(" [last unloaded: %s]", last_unloaded_module); --- -1.7.11.4 - - -From 0f8f372047d8220e1d918797972746bb9fe345d9 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 24/32] MODSIGN: Automatically generate module signing keys if - missing - -Automatically generate keys for module signing if they're absent so that -allyesconfig doesn't break. The builder should consider generating their own -keyrings, however, so that the keys are appropriately named and any extra keys -required get imported. - -Also change the names of the keyring files to modsign.pub and modsign.sec so -that they are then a more obvious what they're about and add a dependency for -the signing rules on the keyring files so that the signatures get regenerated -if the keyrings change. - -Signed-off-by: David Howells ---- - kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index cec222a..28cd248 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ - targets += timeconst.h - $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) -+ -+############################################################################### -+# -+# If module signing is requested, say by allyesconfig, but a key has not been -+# supplied, then one will need to be generated to make sure the build does not -+# fail and that the kernel may be used afterwards. -+# -+############################################################################### -+ifeq ($(CONFIG_MODULE_SIG),y) -+modsign.pub modsign.sec: genkey -+ @echo "###" -+ @echo "### Now generating a PGP key pair to be used for signing modules." -+ @echo "###" -+ @echo "### If this takes a long time, you might wish to run rngd in the" -+ @echo "### background to keep the supply of entropy topped up. It" -+ @echo "### needs to be run as root and should use a hardware random" -+ @echo "### number generator if one is available, eg:" -+ @echo "###" -+ @echo "### rngd -r /dev/hwrandom" -+ @echo "###" -+ gpg --homedir . --batch --gen-key genkey -+ @echo "###" -+ @echo "### Key pair generated." -+ @echo "###" -+ rm -f pubring.gpg secring.gpg trustdb.gpg -+ -+genkey: -+ @echo "###" >&2 -+ @echo "### Now generating a sample key generation script." >&2 -+ @echo "###" >&2 -+ @echo "### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2 -+ @echo "### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2 -+ @echo "###" >&2 -+ @echo "### If you have a hardware random number generator feeding" >&2 -+ @echo "### into /dev/random, you should drop the %no-protection" >&2 -+ @echo "### and %transient-key lines from the script." >&2 -+ @echo "###" >&2 -+ echo "%pubring modsign.pub" >genkey -+ echo "%secring modsign.sec" >>genkey -+ echo "%no-protection: yes" >> genkey -+ echo "%transient-key: yes" >>genkey -+ echo "Key-Type: RSA" >>genkey -+ echo "Key-Length: 4096" >>genkey -+ echo "Name-Real: Sample kernel key" >>genkey -+ echo "Name-Comment: Sample kernel module signing key" >>genkey -+ echo "%commit" >>genkey -+ -+endif -+CLEAN_FILES += modsign.pub modsign.sec genkey random_seed --- -1.7.11.4 - - -From be5544dce081ccb49fd452a6273c5024208b2f06 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 25/32] MODSIGN: Provide module signing public keys to the - kernel - -Include a PGP keyring containing the public keys required to perform module -verification in the kernel image during build and create a special keyring -during boot which is then populated with keys of crypto type holding the public -keys found in the PGP keyring. - -These can be seen by root: - -[root@andromeda ~]# cat /proc/keys -07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] -15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 -... - -It is probably worth permitting root to invalidate these keys, resulting in -their removal and preventing further modules from being loaded with that key. - -Signed-off-by: David Howells ---- - kernel/Makefile | 25 ++++++++------- - kernel/modsign-pubkey.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-verify-defs.h | 4 +++ - kernel/module-verify.c | 2 -- - 4 files changed, 93 insertions(+), 13 deletions(-) - create mode 100644 kernel/modsign-pubkey.c - -diff --git a/kernel/Makefile b/kernel/Makefile -index 28cd248..1d20704 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,7 +55,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o --obj-$(CONFIG_MODULE_SIG) += module-verify.o -+obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o -+kernel/modsign-pubkey.o: modsign.pub - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -159,16 +160,18 @@ modsign.pub modsign.sec: genkey - rm -f pubring.gpg secring.gpg trustdb.gpg - - genkey: -- @echo "###" >&2 -- @echo "### Now generating a sample key generation script." >&2 -- @echo "###" >&2 -- @echo "### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2 -- @echo "### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2 -- @echo "###" >&2 -- @echo "### If you have a hardware random number generator feeding" >&2 -- @echo "### into /dev/random, you should drop the %no-protection" >&2 -- @echo "### and %transient-key lines from the script." >&2 -- @echo "###" >&2 -+ @echo "kernel/Makefile:163: ###" >&2 -+ @echo "kernel/Makefile:163: ### CONFIG_MODULE_SIG is enabled so a public key is needed." >&2 -+ @echo "kernel/Makefile:163: ###" >&2 -+ @echo "kernel/Makefile:163: ### Now generating a sample key generation script." >&2 -+ @echo "kernel/Makefile:163: ###" >&2 -+ @echo "kernel/Makefile:163: ### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2 -+ @echo "kernel/Makefile:163: ### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2 -+ @echo "kernel/Makefile:163: ###" >&2 -+ @echo "kernel/Makefile:163: ### If you have a hardware random number generator feeding" >&2 -+ @echo "kernel/Makefile:163: ### into /dev/random, you should drop the %no-protection" >&2 -+ @echo "kernel/Makefile:163: ### and %transient-key lines from the script." >&2 -+ @echo "kernel/Makefile:163: ###" >&2 - echo "%pubring modsign.pub" >genkey - echo "%secring modsign.sec" >>genkey - echo "%no-protection: yes" >> genkey -diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c -new file mode 100644 -index 0000000..5fdb082 ---- /dev/null -+++ b/kernel/modsign-pubkey.c -@@ -0,0 +1,75 @@ -+/* Public keys for module signature verification -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "module-verify-defs.h" -+ -+struct key *modsign_keyring; -+ -+extern __initdata const u8 modsign_public_keys[]; -+extern __initdata const u8 modsign_public_keys_end[]; -+asm(".section .init.data,\"aw\"\n" -+ "modsign_public_keys:\n" -+ ".incbin \"modsign.pub\"\n" -+ "modsign_public_keys_end:" -+ ); -+ -+/* -+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice -+ * if modsign.pub changes. -+ */ -+static __initdata const char annoy_ccache[] = __TIME__ "foo"; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int module_verify_init(void) -+{ -+ pr_notice("Initialise module verification\n"); -+ -+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", -+ 0, 0, current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_keyring)) -+ panic("Can't allocate module signing keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(module_verify_init); -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int modsign_pubkey_init(void) -+{ -+ pr_notice("Load module verification keys\n"); -+ -+ if (preload_pgp_keys(modsign_public_keys, -+ modsign_public_keys_end - modsign_public_keys, -+ modsign_keyring) < 0) -+ panic("Can't load module signing keys\n"); -+ -+ return 0; -+} -+late_initcall(modsign_pubkey_init); -diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h -index 141ddab..2fe31e1 100644 ---- a/kernel/module-verify-defs.h -+++ b/kernel/module-verify-defs.h -@@ -11,6 +11,10 @@ - - #ifdef CONFIG_MODULE_SIG - -+#include -+ -+extern struct key *modsign_keyring; -+ - /* - * Internal state - */ -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 4bf857e..05473e6 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -28,8 +28,6 @@ - #include - #include - #include --#include --#include - #include - #include - #include --- -1.7.11.4 - - -From 34c918aacc002f8a7226a26a0d8af614c6f4430e Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:45 +0100 -Subject: [PATCH 26/32] MODSIGN: Check the ELF container - -Check the ELF container of the kernel module to prevent the kernel from -crashing or getting corrupted whilst trying to use it and locate the module -signature note if present. - -We try to check as little as possible. We check the metadata that the -signature checker actually has to use, and leave anything that it doesn't -actually need to the signature to catch. - -The stuff we need to check is: - - (1) The locations and offsets in the ELF header of important parts like the - section table. - - (2) The section table. Note that we only check sh_info for section types that - we're actually interested in (string, symbol and relocation tables). We - also check that alignments are what we expect for those tables. - - (3) That non-empty string tables have the required NUL at the end so that we - can be sure that all strings therein are NUL-terminated. We don't bother - checking for the required NUL at the beginning as it shouldn't cause a - problem to us. - - (4) The name offset and section index in each symbol. We could defer this to - when we deal with the relocation tables so that we only check symbols that - are used by relocations - but we would then end up checking some symbols - multiple times. - - (5) The module signature note section and the first note in it if present. - - (6) That relocations applied to an allocatable section only refer to - symbols in allocatable sections and absolute symbols (done in the module - signing code rather than here). - -Note that these checks survive "strip -x", "strip -g" and "eu-strip" being -applied to a module and detect if the module was given to "strip" or "strip -s" -and report an error. - -We can skip some direct checks that turn out unnecessary or redundant: - - (1) That sh_link has a greater than 0 value for symbol tables and relocation - tables. These require the index of a string table and a symbol table - respectively - and since we have already checked section 0 is of SHT_NULL - type, checking the symbol type renders the sh_link > 0 check redundant. - - (2) That a non-empty string table begins with a NUL. Since we check the - string table ends with a NUL, any string in there will be NUL-terminated - and shouldn't cause us to transgress beyond the bounds of the string table - when using strlen(). - - (3) That strings in a string table actually make sense. We don't care, so - long as it is NUL terminated. Any string that refers to an undefined - symbol is added to the crypto digest and will be checked that way. - Strings that we directly look for (such as ".modinfo") will be validated - by that. - - (4) That sections don't overlap. We don't actually care if sections overlap - in the file, provided we don't see bad metadata. If the sections holding - the allocatable content overlap, then the signature check is likely to - fail. - - (5) That symbol values and relocation offsets and addends make sense. We just - add this data to the digest if it pertains to an allocatable section. - - (6) That allocatable note sections, other than the signature note, make sense. - The contents of these get added to the digest in their entirety, so we - don't need to check them manually. - -If bad ELF is detected, ELIBBAD is indicated. - -Note! The "noinline" attribute on the module_verify_elf() function results in -somewhat smaller code. Similarly, having separate loops to check basic section -parameters and to check type-specific features of sections results in smaller -code, presumably because some local variables can be discarded. - -Signed-off-by: David Howells ---- - kernel/module-verify.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 230 insertions(+) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 05473e6..2161d11 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -51,6 +51,228 @@ static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); - static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); - - /* -+ * Verify the minimum amount of ELF structure of a module needed to check the -+ * module's signature without bad ELF crashing the kernel. -+ */ -+static noinline int module_verify_elf(struct module_verify_data *mvdata) -+{ -+ const struct elf_note *note; -+ const Elf_Ehdr *hdr = mvdata->hdr; -+ const Elf_Shdr *section, *secstop; -+ const Elf_Sym *symbols, *symbol, *symstop; -+ const char *strtab; -+ size_t size, secstrsize, strsize, notesize, notemetasize; -+ unsigned line; -+ -+ size = mvdata->size; -+ -+#define elfcheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while (0) -+ -+#define seccheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while (0) -+ -+#define symcheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0) -+ -+ /* Validate the ELF header */ -+ elfcheck(size > sizeof(Elf_Ehdr)); -+ elfcheck(hdr->e_ehsize < size); -+ -+ elfcheck(hdr->e_shnum < SHN_LORESERVE); -+ elfcheck(hdr->e_shstrndx < hdr->e_shnum); -+ elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); -+ elfcheck(hdr->e_shoff < size); -+ elfcheck(hdr->e_shoff >= hdr->e_ehsize); -+ elfcheck(hdr->e_shoff % sizeof(long) == 0); -+ elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); -+ -+ /* Validate the section table contents */ -+ mvdata->nsects = hdr->e_shnum; -+ mvdata->sections = mvdata->buffer + hdr->e_shoff; -+ secstop = mvdata->sections + mvdata->nsects; -+ -+ /* Section 0 is special, usually indicating an undefined symbol */ -+ section = &mvdata->sections[SHN_UNDEF]; -+ seccheck(section->sh_type == SHT_NULL); -+ -+ /* We also want access to the section name table */ -+ section = &mvdata->sections[hdr->e_shstrndx]; -+ seccheck(section->sh_type == SHT_STRTAB); -+ secstrsize = mvdata->sections[hdr->e_shstrndx].sh_size; -+ -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ seccheck(section->sh_name < secstrsize); -+ seccheck(section->sh_link < hdr->e_shnum); -+ -+ /* Section file offsets must reside within the file, though -+ * they don't have to actually consume file space (.bss for -+ * example). -+ */ -+ seccheck(section->sh_offset >= hdr->e_ehsize); -+ if (section->sh_addralign > 1) -+ seccheck((section->sh_offset & -+ (section->sh_addralign - 1)) == 0); -+ seccheck(section->sh_offset <= size); -+ if (section->sh_type != SHT_NOBITS) -+ seccheck(section->sh_size <= size - section->sh_offset); -+ -+ /* Some types of section should contain arrays of fixed-length -+ * records of a predetermined size and mustn't contain partial -+ * records. Also, records we're going to access directly must -+ * have appropriate alignment that we don't get a misalignment -+ * exception. -+ */ -+ if (section->sh_entsize > 1) -+ seccheck(section->sh_size % section->sh_entsize == 0); -+ -+ switch (section->sh_type) { -+ case SHT_SYMTAB: -+ seccheck(section->sh_entsize == sizeof(Elf_Sym)); -+ seccheck(section->sh_addralign % sizeof(long) == 0); -+ break; -+ case SHT_REL: -+#ifdef Elf_Rel -+ seccheck(section->sh_entsize == sizeof(Elf_Rel)); -+ seccheck(section->sh_addralign % sizeof(long) == 0); -+ break; -+#else -+ seccheck(false); -+ break; -+#endif -+ case SHT_RELA: -+#ifdef Elf_Rela -+ seccheck(section->sh_entsize == sizeof(Elf_Rela)); -+ seccheck(section->sh_addralign % sizeof(long) == 0); -+ break; -+#else -+ seccheck(false); -+ break; -+#endif -+ case SHT_NOTE: -+ seccheck(section->sh_addralign % 4 == 0); -+ break; -+ case SHT_STRTAB: -+ /* We require all string tables to be non-empty. If -+ * not empty, a string table must end in a NUL (it -+ * should also begin with a NUL, but it's not a problem -+ * for us if it doesn't). -+ */ -+ seccheck(section->sh_size >= 2); -+ strtab = mvdata->buffer + section->sh_offset; -+ seccheck(strtab[section->sh_size - 1] == '\0'); -+ break; -+ } -+ } -+ -+ /* Check features specific to the type of each section. -+ * -+ * Note that having a separate loop here allows the compiler to discard -+ * some local variables used in the above loop thus making the code -+ * smaller. -+ */ -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ switch (section->sh_type) { -+ case SHT_SYMTAB: -+ /* Symbol tables nominate a string table. */ -+ seccheck(mvdata->sections[section->sh_link].sh_type == -+ SHT_STRTAB); -+ -+ /* Validate the symbols in the table. The first symbol -+ * (STN_UNDEF) is special. -+ */ -+ symbol = symbols = mvdata->buffer + section->sh_offset; -+ symstop = mvdata->buffer + -+ (section->sh_offset + section->sh_size); -+ -+ symcheck(ELF_ST_TYPE(symbols[0].st_info) == STT_NOTYPE); -+ symcheck(symbol[0].st_shndx == SHN_UNDEF); -+ -+ strsize = mvdata->sections[section->sh_link].sh_size; -+ for (symbol++; symbol < symstop; symbol++) { -+ symcheck(symbol->st_name < strsize); -+ symcheck(symbol->st_shndx < hdr->e_shnum || -+ symbol->st_shndx >= SHN_LORESERVE); -+ } -+ break; -+ -+#ifdef Elf_Rel -+ case SHT_REL: -+#endif -+#ifdef Elf_Rela -+ case SHT_RELA: -+#endif -+ /* Relocation tables nominate a symbol table and a -+ * target section to which the relocations will be -+ * applied. -+ */ -+ seccheck(mvdata->sections[section->sh_link].sh_type == -+ SHT_SYMTAB); -+ seccheck(section->sh_info > 0); -+ seccheck(section->sh_info < hdr->e_shnum); -+ break; -+ } -+ } -+ -+ /* We can now use section name string table section as we checked its -+ * bounds in the loop above. -+ * -+ * Each name is NUL-terminated, and the table as a whole should have a -+ * NUL at either end as there to be at least one named section for the -+ * module information. -+ */ -+ section = &mvdata->sections[hdr->e_shstrndx]; -+ mvdata->secstrings = mvdata->buffer + section->sh_offset; -+ -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ const char *name = mvdata->secstrings + section->sh_name; -+ -+ switch (section->sh_type) { -+ case SHT_NOTE: -+ if (strcmp(name, modsign_note_section) != 0) -+ continue; -+ -+ /* We've found a note purporting to contain a signature -+ * so we should check the structure of that. -+ */ -+ notemetasize = sizeof(struct elf_note) + -+ roundup(sizeof(modsign_note_name), 4); -+ -+ seccheck(mvdata->sig_index == 0); -+ seccheck(section->sh_size > notemetasize); -+ note = mvdata->buffer + section->sh_offset; -+ seccheck(note->n_type == MODSIGN_NOTE_TYPE); -+ seccheck(note->n_namesz == sizeof(modsign_note_name)); -+ -+ notesize = section->sh_size - notemetasize; -+ seccheck(note->n_descsz <= notesize); -+ -+ seccheck(memcmp(note + 1, modsign_note_name, -+ note->n_namesz) == 0); -+ -+ mvdata->sig_size = note->n_descsz; -+ mvdata->sig = (void *)note + notemetasize; -+ mvdata->sig_index = section - mvdata->sections; -+ break; -+ } -+ } -+ -+ return 0; -+ -+elfcheck_error: -+ _debug("Verify ELF error (check %u)\n", line); -+ return -ELIBBAD; -+seccheck_error: -+ _debug("Verify ELF error [sec %ld] (check %u)\n", -+ (long)(section - mvdata->sections), line); -+ return -ELIBBAD; -+symcheck_error: -+ _debug("Verify ELF error [sym %ld] (check %u)\n", -+ (long)(symbol - symbols), line); -+ return -ELIBBAD; -+} -+ -+/* - * Verify a module's integrity - */ - int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) -@@ -62,6 +284,14 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) - mvdata.buffer = hdr; - mvdata.size = size; - -+ /* Minimally check the ELF to make sure building the signature digest -+ * won't crash the kernel. -+ */ -+ ret = module_verify_elf(&mvdata); -+ if (ret < 0) -+ goto out; -+ -+ /* The ELF checker found the sig for us if it exists */ - if (mvdata.sig_index <= 0) { - /* Deal with an unsigned module */ - if (modsign_signedonly) { --- -1.7.11.4 - - -From 2de4559e24c416e6813c10edbe3cc433ecd0dd50 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 27/32] MODSIGN: Produce a filtered and canonicalised section - list - -Build a list of the sections in which we're interested and canonicalise the -section indices to avoid the problems of the section table being altered by ld -when the signature is linked into the binary and by strip. - -The only sections in which we're actually interested are those that are marked -allocatable (which will be kept in memory) and relocation tables that are -applicable to those sections. - -Canonicalisation is done by sorting the filtered list in order of section name. - -Signed-off-by: David Howells ---- - kernel/module-verify.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 80 insertions(+) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 2161d11..646b104 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -273,6 +273,80 @@ symcheck_error: - } - - /* -+ * Canonicalise the section table index numbers. -+ * -+ * We build a list of the sections we want to add to the digest and sort it by -+ * name. We're only interested in adding two types of section: -+ * -+ * (1) Allocatable sections. These should have no references to other -+ * sections. -+ * -+ * (2) Relocation tables for allocatable sections. The section table entry -+ * has a reference to the target section to which the relocations will be -+ * applied. The relocation entries have references to symbols in -+ * non-allocatable sections. Symbols can be replaced by their contents, -+ * but do include a further reference to a section - which must be -+ * canonicalised. -+ * -+ * We also build a map of raw section index to canonical section index. -+ */ -+static int module_verify_canonicalise(struct module_verify_data *mvdata) -+{ -+ const Elf_Shdr *sechdrs = mvdata->sections; -+ unsigned *canonlist, canon, loop, tmp; -+ bool changed; -+ -+ canonlist = kmalloc(sizeof(unsigned) * mvdata->nsects * 2, GFP_KERNEL); -+ if (!canonlist) -+ return -ENOMEM; -+ -+ mvdata->canonlist = canonlist; -+ mvdata->canonmap = canonlist + mvdata->nsects; -+ canon = 0; -+ -+ for (loop = 1; loop < mvdata->nsects; loop++) { -+ const Elf_Shdr *section = mvdata->sections + loop; -+ -+ if (loop == mvdata->sig_index) -+ continue; -+ -+ /* We only want allocatable sections and relocation tables */ -+ if (section->sh_flags & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ else if ((is_elf_rel(section->sh_type) || -+ is_elf_rela(section->sh_type)) && -+ mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC) -+ canonlist[canon++] = loop; -+ } -+ -+ /* Sort the canonicalisation list */ -+ do { -+ changed = false; -+ -+ for (loop = 0; loop < canon - 1; loop++) { -+ const char *x, *y; -+ -+ x = mvdata->secstrings + sechdrs[canonlist[loop + 0]].sh_name; -+ y = mvdata->secstrings + sechdrs[canonlist[loop + 1]].sh_name; -+ -+ if (strcmp(x, y) > 0) { -+ tmp = canonlist[loop + 0]; -+ canonlist[loop + 0] = canonlist[loop + 1]; -+ canonlist[loop + 1] = tmp; -+ changed = true; -+ } -+ } -+ } while (changed); -+ -+ /* What we really want is a raw-to-canon lookup table */ -+ memset(mvdata->canonmap, 0xff, mvdata->nsects * sizeof(unsigned)); -+ for (loop = 0; loop < canon; loop++) -+ mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1; -+ mvdata->ncanon = canon; -+ return 0; -+} -+ -+/* - * Verify a module's integrity - */ - int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) -@@ -303,7 +377,13 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) - goto out; - } - -+ /* Produce a canonicalisation map for the sections */ -+ ret = module_verify_canonicalise(&mvdata); -+ if (ret < 0) -+ goto out; -+ - ret = 0; -+ kfree(mvdata.canonlist); - - out: - switch (ret) { --- -1.7.11.4 - - -From 3c8e71a46663f1fc3ee49fe3f6fa5c3bb85b704c Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 28/32] MODSIGN: Create digest of module content and check - signature - -Apply signature checking to modules on module load, checking the signature -against the ring of public keys compiled into the kernel (if enabled by -CONFIG_MODULE_SIG). Turning on signature checking will also force the module's -ELF metadata to be verified first. - -There are several reasons why these patches are useful, amongst which are: - - (1) to prevent accidentally corrupted modules from causing damage; - - (2) to prevent maliciously modified modules from causing damage; - - (3) to allow a sysadmin (or more likely an IT department) to enforce a policy - that only known and approved modules shall be loaded onto machines which - they're expected to support; - - (4) to allow other support providers to do likewise, or at least to _detect_ - the fact that unsupported modules are loaded; - - (5) to allow the detection of modules replaced by a second-order distro or a - preloaded Linux purveyor. - -These patches have two main appeals: (a) preventing malicious modules from -being loaded, and (b) reducing support workload by pointing out modules on a -crashing box that aren't what they're expected to be. - -Note that this is not a complete solution by any means: the core kernel is not -protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least -controls) one relatively simple attack vector. To protect the kernel image -would be the responsibility of the boot loader or the system BIOS. - -This facility is optional: the builder of a kernel is by no means under any -requirement to actually enable it, let alone force the set of loadable modules -to be restricted to just those that the builder provides (there are degrees of -restriction available). - -Note! The "noinline" attribute on module_verify_signature() results in -somewhat smaller code. - -Signed-off-by: David Howells ---- - kernel/module-verify-defs.h | 13 +- - kernel/module-verify.c | 332 +++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 338 insertions(+), 7 deletions(-) - -diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h -index 2fe31e1..cb477a2 100644 ---- a/kernel/module-verify-defs.h -+++ b/kernel/module-verify-defs.h -@@ -19,7 +19,7 @@ extern struct key *modsign_keyring; - * Internal state - */ - struct module_verify_data { -- struct crypto_key_verify_context *mod_sig; /* Module signing context */ -+ struct crypto_sig_verify_context *mod_sig; /* Module signing context */ - union { - const void *buffer; /* module buffer */ - const Elf_Ehdr *hdr; /* ELF header */ -@@ -42,15 +42,16 @@ struct module_verify_data { - /* - * Whether or not we support various types of ELF relocation record - */ --#if defined(MODULE_HAS_ELF_REL_ONLY) -+#ifdef Elf_Rel - #define is_elf_rel(sh_type) ((sh_type) == SHT_REL) --#define is_elf_rela(sh_type) (0) --#elif defined(MODULE_HAS_ELF_RELA_ONLY) -+#else - #define is_elf_rel(sh_type) (0) -+#endif -+ -+#ifdef Elf_Rela - #define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) - #else --#define is_elf_rel(sh_type) ((sh_type) == SHT_REL) --#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) -+#define is_elf_rela(sh_type) (0) - #endif - - /* -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 646b104..bee7e04 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -50,6 +50,22 @@ static bool modsign_signedonly; - static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); - static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); - -+#define crypto_digest_update_data(C, PTR, N) \ -+do { \ -+ uint8_t *__p = (uint8_t *)(PTR); \ -+ size_t __n = (N); \ -+ count_and_csum((C), __p, __n); \ -+ verify_sig_add_data((C)->mod_sig, __p, __n); \ -+} while (0) -+ -+#define crypto_digest_update_val(C, VAL) \ -+do { \ -+ uint8_t *__p = (uint8_t *)&(VAL); \ -+ size_t __n = sizeof(VAL); \ -+ count_and_csum((C), __p, __n); \ -+ verify_sig_add_data((C)->mod_sig, __p, __n); \ -+} while (0) -+ - /* - * Verify the minimum amount of ELF structure of a module needed to check the - * module's signature without bad ELF crashing the kernel. -@@ -346,6 +362,320 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata) - return 0; - } - -+#ifdef Elf_Rel -+/* -+ * Extract an ELF REL table -+ * -+ * We need to canonicalise the entries in case section/symbol addition/removal -+ * has rearranged the symbol table and the section table. -+ */ -+static int extract_elf_rel(struct module_verify_data *mvdata, -+ unsigned secix, -+ const Elf_Rel *reltab, size_t nrels, -+ const char *sh_name) -+{ -+ struct { -+#ifdef CONFIG_64BIT -+ uint64_t r_offset; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+#else -+ uint32_t r_offset; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+#endif -+ } __packed relocation; -+ -+ const Elf_Shdr *relsec, *symsec, *strsec; -+ const Elf_Rel *reloc; -+ const Elf_Sym *symbols, *symbol; -+ const char *strings; -+ unsigned long r_sym; -+ size_t nsyms, loop; -+ -+ relsec = &mvdata->sections[secix]; -+ symsec = &mvdata->sections[relsec->sh_link]; -+ strsec = &mvdata->sections[symsec->sh_link]; -+ nsyms = symsec->sh_size / sizeof(Elf_Sym); -+ symbols = mvdata->buffer + symsec->sh_offset; -+ strings = mvdata->buffer + strsec->sh_offset; -+ -+ /* Contribute the relevant bits from a join of -+ * { REL, SYMBOL, SECTION } -+ */ -+ for (loop = 0; loop < nrels; loop++) { -+ unsigned st_shndx; -+ -+ reloc = &reltab[loop]; -+ -+ /* Decode the relocation */ -+ relocation.r_offset = reloc->r_offset; -+ relocation.r_type = ELF_R_TYPE(reloc->r_info); -+ -+ /* Decode the symbol referenced by the relocation */ -+ r_sym = ELF_R_SYM(reloc->r_info); -+ if (r_sym >= nsyms) -+ return -ELIBBAD; -+ symbol = &symbols[r_sym]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = symbol->st_shndx; -+ -+ /* Canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) { -+ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC)) -+ return -ELIBBAD; -+ relocation.st_shndx = mvdata->canonmap[st_shndx]; -+ } -+ -+ crypto_digest_update_val(mvdata, relocation); -+ -+ /* Undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + symbol->st_name; -+ crypto_digest_update_data(mvdata, -+ name, strlen(name) + 1); -+ } -+ } -+ -+ _debug("%08zx %02x digested the %s section, nrels %zu\n", -+ mvdata->signed_size, mvdata->csum, sh_name, nrels); -+ -+ return 0; -+} -+#endif -+ -+#ifdef Elf_Rela -+/* -+ * Extract an ELF RELA table -+ * -+ * We need to canonicalise the entries in case section/symbol addition/removal -+ * has rearranged the symbol table and the section table. -+ */ -+static int extract_elf_rela(struct module_verify_data *mvdata, -+ unsigned secix, -+ const Elf_Rela *relatab, size_t nrels, -+ const char *sh_name) -+{ -+ struct { -+#ifdef CONFIG_64BIT -+ uint64_t r_offset; -+ uint64_t r_addend; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+#else -+ uint32_t r_offset; -+ uint32_t r_addend; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+#endif -+ } __packed relocation; -+ -+ const Elf_Shdr *relsec, *symsec, *strsec; -+ const Elf_Rela *reloc; -+ const Elf_Sym *symbols, *symbol; -+ unsigned long r_sym; -+ const char *strings; -+ size_t nsyms, loop; -+ -+ relsec = &mvdata->sections[secix]; -+ symsec = &mvdata->sections[relsec->sh_link]; -+ strsec = &mvdata->sections[symsec->sh_link]; -+ nsyms = symsec->sh_size / sizeof(Elf_Sym); -+ symbols = mvdata->buffer + symsec->sh_offset; -+ strings = mvdata->buffer + strsec->sh_offset; -+ -+ /* Contribute the relevant bits from a join of -+ * { RELA, SYMBOL, SECTION } -+ */ -+ for (loop = 0; loop < nrels; loop++) { -+ unsigned st_shndx; -+ -+ reloc = &relatab[loop]; -+ -+ /* Decode the relocation */ -+ relocation.r_offset = reloc->r_offset; -+ relocation.r_addend = reloc->r_addend; -+ relocation.r_type = ELF_R_TYPE(reloc->r_info); -+ -+ /* Decode the symbol referenced by the relocation */ -+ r_sym = ELF_R_SYM(reloc->r_info); -+ if (r_sym >= nsyms) -+ return -ELIBBAD; -+ symbol = &symbols[r_sym]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = 0; -+ st_shndx = symbol->st_shndx; -+ -+ /* Canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) { -+ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC)) -+ return -ELIBBAD; -+ relocation.st_shndx = mvdata->canonmap[st_shndx]; -+ } -+ -+ crypto_digest_update_val(mvdata, relocation); -+ -+ /* Undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = strings + symbol->st_name; -+ crypto_digest_update_data(mvdata, -+ name, strlen(name) + 1); -+ } -+ } -+ -+ _debug("%08zx %02x digested the %s section, nrels %zu\n", -+ mvdata->signed_size, mvdata->csum, sh_name, nrels); -+ -+ return 0; -+} -+#endif -+ -+/* -+ * Verify a module's signature -+ */ -+static noinline int module_verify_signature(struct module_verify_data *mvdata) -+{ -+ struct crypto_sig_verify_context *mod_sig; -+ const Elf_Shdr *sechdrs = mvdata->sections; -+ const char *secstrings = mvdata->secstrings; -+ const u8 *sig = mvdata->sig; -+ size_t sig_size = mvdata->sig_size; -+ int loop, ret; -+ -+ _debug("sig in section %u (size %zu)\n", -+ mvdata->sig_index, mvdata->sig_size); -+ _debug("%02x%02x%02x%02x%02x%02x%02x%02x\n", -+ sig[0], sig[1], sig[2], sig[3], -+ sig[4], sig[5], sig[6], sig[7]); -+ -+ /* Find the crypto key for the module signature -+ * - !!! if this tries to load the required hash algorithm module, -+ * we will deadlock!!! -+ */ -+ mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size); -+ if (IS_ERR(mod_sig)) { -+ pr_err("Couldn't initiate module signature verification: %ld\n", -+ PTR_ERR(mod_sig)); -+ return PTR_ERR(mod_sig); -+ } -+ -+ mvdata->mod_sig = mod_sig; -+#ifdef DEBUG -+ mvdata->xcsum = 0; -+#endif -+ -+ /* Load data from each relevant section into the digest. Note that -+ * canonlist[] is a filtered list and only contains the sections we -+ * actually want. -+ */ -+ for (loop = 0; loop < mvdata->ncanon; loop++) { -+ int sect = mvdata->canonlist[loop]; -+ unsigned long sh_type = sechdrs[sect].sh_type; -+ unsigned long sh_info = sechdrs[sect].sh_info; -+ unsigned long sh_size = sechdrs[sect].sh_size; -+ const char *sh_name = secstrings + sechdrs[sect].sh_name; -+ const void *data = mvdata->buffer + sechdrs[sect].sh_offset; -+ -+#ifdef DEBUG -+ mvdata->csum = 0; -+#endif -+ -+ /* Digest the headers of any section we include. */ -+ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name)); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign); -+ -+ /* Relocation record sections refer to the section to be -+ * relocated, but this needs to be canonicalised to survive -+ * stripping. -+ */ -+ if (is_elf_rel(sh_type) || is_elf_rela(sh_type)) -+ crypto_digest_update_val(mvdata, -+ mvdata->canonmap[sh_info]); -+ -+ /* Since relocation records give details of how we have to -+ * alter the allocatable sections, we need to digest these too. -+ * -+ * These, however, refer to metadata (symbols and sections) -+ * that may have been altered by the process of adding the -+ * signature section or the process of being stripped. -+ * -+ * To deal with this, we substitute the referenced metadata for -+ * the references to that metadata. So, for instance, the -+ * symbol ref from the relocation record is replaced with the -+ * contents of the symbol to which it refers, and the symbol's -+ * section ref is replaced with a canonicalised section number. -+ */ -+#ifdef Elf_Rel -+ if (is_elf_rel(sh_type)) { -+ ret = extract_elf_rel(mvdata, sect, -+ data, -+ sh_size / sizeof(Elf_Rel), -+ sh_name); -+ if (ret < 0) -+ goto format_error; -+ continue; -+ } -+#endif -+ -+#ifdef Elf_Rela -+ if (is_elf_rela(sh_type)) { -+ ret = extract_elf_rela(mvdata, sect, -+ data, -+ sh_size / sizeof(Elf_Rela), -+ sh_name); -+ if (ret < 0) -+ goto format_error; -+ continue; -+ } -+#endif -+ -+ /* Include allocatable loadable sections */ -+ if (sh_type != SHT_NOBITS) -+ crypto_digest_update_data(mvdata, data, sh_size); -+ -+ _debug("%08zx %02x digested the %s section, size %ld\n", -+ mvdata->signed_size, mvdata->csum, sh_name, sh_size); -+ } -+ -+ _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n", -+ mvdata->signed_size, mvdata->xcsum); -+ -+ /* Do the actual signature verification */ -+ ret = verify_sig_end(mvdata->mod_sig, sig, sig_size); -+ _debug("verify-sig : %d\n", ret); -+ return ret; -+ -+format_error: -+ verify_sig_cancel(mvdata->mod_sig); -+ return -ELIBBAD; -+} -+ - /* - * Verify a module's integrity - */ -@@ -382,7 +712,7 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) - if (ret < 0) - goto out; - -- ret = 0; -+ ret = module_verify_signature(&mvdata); - kfree(mvdata.canonlist); - - out: --- -1.7.11.4 - - -From 53142a9c74e2922885d03555d26213fc38553b90 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 29/32] MODSIGN: Suppress some redundant ELF checks - -Suppress some redundant ELF checks in module_verify_elf() that are also done -by copy_and_check() in the core module loader code prior to calling -module_verify(). - -Signed-off-by: David Howells ---- - kernel/module-verify.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index bee7e04..f3a694f 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -97,11 +97,11 @@ do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0) - - elfcheck(hdr->e_shnum < SHN_LORESERVE); - elfcheck(hdr->e_shstrndx < hdr->e_shnum); -- elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); -- elfcheck(hdr->e_shoff < size); -+ /* elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); */ -+ /* elfcheck(hdr->e_shoff < size); */ - elfcheck(hdr->e_shoff >= hdr->e_ehsize); - elfcheck(hdr->e_shoff % sizeof(long) == 0); -- elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); -+ /* elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); */ - - /* Validate the section table contents */ - mvdata->nsects = hdr->e_shnum; --- -1.7.11.4 - - -From 14d36171021b1c16f6c664bd4ab31e1d989ab282 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 30/32] MODSIGN: Panic the kernel if FIPS is enabled upon - module signing failure - -If module signing fails when the kernel is running with FIPS enabled then the -kernel should panic lest the crypto layer be compromised. Possibly a panic -shouldn't happen on cases like ENOMEM. - -Reported-by: Stephan Mueller -Signed-off-by: David Howells ---- - kernel/module-verify.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index f3a694f..896c0ff 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include "module-verify.h" - #include "module-verify-defs.h" -@@ -716,6 +717,10 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) - kfree(mvdata.canonlist); - - out: -+ if (ret < 0 && fips_enabled) -+ panic("Module verification failed with error %d in FIPS mode\n", -+ ret); -+ - switch (ret) { - case 0: /* Good signature */ - *_gpgsig_ok = true; --- -1.7.11.4 - - -From 1e8e625508f013acfb8ade3b5c30dcc7ff710ce9 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 31/32] MODSIGN: Allow modules to be signed with an unknown - key unless enforcing - -Currently we fail the loading of modules that are signed with a public key -that is not in the modsign keyring even if we are not in enforcing mode. -This is somewhat at odds with the fact that we allow a completely unsigned -module to load in such a case. - -We should allow modules signed with an unknown key to load in cases -where we are not enforcing and not in FIPS mode. - -Signed-off-by: Josh Boyer -Signed-off-by: David Howells ---- - kernel/module-verify.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 896c0ff..041506f 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -736,6 +736,13 @@ out: - break; - case -ENOKEY: /* Signed, but we don't have the public key */ - pr_err("Module signed with unknown public key\n"); -+ if (!modsign_signedonly) { -+ /* Allow a module to be signed with an unknown public -+ * key unless we're enforcing. -+ */ -+ pr_info("Allowing\n"); -+ ret = 0; -+ } - break; - default: /* Other error (probably ENOMEM) */ - break; --- -1.7.11.4 - - -From 7ac7095ee6624789c6a971d16f5ca823ebbde3c7 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 16 Aug 2012 01:38:46 +0100 -Subject: [PATCH 32/32] MODSIGN: Fix documentation of signed-nokey behavior - when not enforcing. - -jwboyer's previous commit changes the behavior of module signing when -there's a valid signature but we don't know the public key and are in -permissive mode. This updates the documentation to match. - -Signed-off-by: Peter Jones -Acked-by: Josh Boyer -Signed-off-by: David Howells ---- - Documentation/module-signing.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt -index d75d473..8c4bef9 100644 ---- a/Documentation/module-signing.txt -+++ b/Documentation/module-signing.txt -@@ -185,7 +185,7 @@ This table indicates the behaviours of the various situations: - MODULE STATE PERMISSIVE MODE ENFORCING MODE - ======================================= =============== =============== - Unsigned Ok EKEYREJECTED -- Signed, no public key ENOKEY ENOKEY -+ Signed, no public key Ok ENOKEY - Validly signed, public key Ok Ok - Invalidly signed, public key EKEYREJECTED EKEYREJECTED - Validly signed, expired key EKEYEXPIRED EKEYEXPIRED --- -1.7.11.4 - diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch new file mode 100644 index 000000000..6dd81ffa0 --- /dev/null +++ b/modsign-post-KS-jwb.patch @@ -0,0 +1,9153 @@ +From 2cdfd353ac1a5b9f62398ef59b4a08b5b55ac089 Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Wed, 5 Sep 2012 12:32:17 +0930 +Subject: [PATCH 01/26] module: signature checking hook + +We do a very simple search for a particular string appended to the module +(which is cache-hot and about to be SHA'd anyway). There's both a config +option and a boot parameter which control whether we accept (and taint) or +fail with unsigned modules. + +Signed-off-by: Rusty Russell +--- + Documentation/kernel-parameters.txt | 6 +++ + include/linux/module.h | 8 ++++ + init/Kconfig | 14 ++++++ + kernel/module.c | 88 ++++++++++++++++++++++++++++++++++++- + 4 files changed, 115 insertions(+), 1 deletion(-) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index ad7e2e5..9b2b8d3 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + log everything. Information is printed at KERN_DEBUG + so loglevel=8 may also need to be specified. + ++ module.sig_enforce ++ [KNL] When CONFIG_MODULE_SIG is set, this means that ++ modules without (valid) signatures will fail to load. ++ Note that if CONFIG_MODULE_SIG_ENFORCE is set, that ++ is always true, so this option does nothing. ++ + mousedev.tap_time= + [MOUSE] Maximum time between finger touching and + leaving touchpad surface for touch to be considered +diff --git a/include/linux/module.h b/include/linux/module.h +index fbcafe2..7760c6d 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -21,6 +21,9 @@ + #include + #include + ++/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ ++#define MODULE_SIG_STRING "~Module signature appended~\n" ++ + /* Not Yet Implemented */ + #define MODULE_SUPPORTED_DEVICE(name) + +@@ -260,6 +263,11 @@ struct module + const unsigned long *unused_gpl_crcs; + #endif + ++#ifdef CONFIG_MODULE_SIG ++ /* Signature was verified. */ ++ bool sig_ok; ++#endif ++ + /* symbols that will be GPL-only in the near future. */ + const struct kernel_symbol *gpl_future_syms; + const unsigned long *gpl_future_crcs; +diff --git a/init/Kconfig b/init/Kconfig +index af6c7f8..7452e19 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL + the version). With this option, such a "srcversion" field + will be created for all modules. If unsure, say N. + ++config MODULE_SIG ++ bool "Module signature verification" ++ depends on MODULES ++ help ++ Check modules for valid signatures upon load: the signature ++ is simply appended to the module. For more information see ++ Documentation/module-signing.txt. ++ ++config MODULE_SIG_FORCE ++ bool "Require modules to be validly signed" ++ depends on MODULE_SIG ++ help ++ Reject unsigned modules or signed modules for which we don't have a ++ key. Without this, such modules will simply taint the kernel. + endif # MODULES + + config INIT_ALL_POSSIBLE +diff --git a/kernel/module.c b/kernel/module.c +index 4edbd9c..5c6f65c 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -102,6 +102,43 @@ static LIST_HEAD(modules); + struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ + #endif /* CONFIG_KGDB_KDB */ + ++#ifdef CONFIG_MODULE_SIG ++#ifdef CONFIG_MODULE_SIG_FORCE ++static bool sig_enforce = true; ++#else ++static bool sig_enforce = false; ++ ++static int param_set_bool_enable_only(const char *val, ++ const struct kernel_param *kp) ++{ ++ int err; ++ bool test; ++ struct kernel_param dummy_kp = *kp; ++ ++ dummy_kp.arg = &test; ++ ++ err = param_set_bool(val, &dummy_kp); ++ if (err) ++ return err; ++ ++ /* Don't let them unset it once it's set! */ ++ if (!test && sig_enforce) ++ return -EROFS; ++ ++ if (test) ++ sig_enforce = true; ++ return 0; ++} ++ ++static const struct kernel_param_ops param_ops_bool_enable_only = { ++ .set = param_set_bool_enable_only, ++ .get = param_get_bool, ++}; ++#define param_check_bool_enable_only param_check_bool ++ ++module_param(sig_enforce, bool_enable_only, 0644); ++#endif /* !CONFIG_MODULE_SIG_FORCE */ ++#endif /* CONFIG_MODULE_SIG */ + + /* Block module loading/unloading? */ + int modules_disabled = 0; +@@ -136,6 +173,7 @@ struct load_info { + unsigned long symoffs, stroffs; + struct _ddebug *debug; + unsigned int num_debug; ++ bool sig_ok; + struct { + unsigned int sym, str, mod, vers, info, pcpu; + } index; +@@ -2399,7 +2437,45 @@ static inline void kmemleak_load_module(const struct module *mod, + } + #endif + +-/* Sets info->hdr and info->len. */ ++#ifdef CONFIG_MODULE_SIG ++static int module_sig_check(struct load_info *info, ++ const void *mod, unsigned long *len) ++{ ++ int err = 0; ++ const unsigned long markerlen = strlen(MODULE_SIG_STRING); ++ const void *p = mod, *end = mod + *len; ++ ++ /* Poor man's memmem. */ ++ while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { ++ if (p + markerlen > end) ++ break; ++ ++ if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { ++ const void *sig = p + markerlen; ++ /* Truncate module up to signature. */ ++ *len = p - mod; ++ err = mod_verify_sig(mod, *len, ++ sig, end - sig, ++ &info->sig_ok); ++ break; ++ } ++ p++; ++ } ++ ++ /* Not having a signature is only an error if we're strict. */ ++ if (!err && !info->sig_ok && sig_enforce) ++ err = -EKEYREJECTED; ++ return err; ++} ++#else /* !CONFIG_MODULE_SIG */ ++static int module_sig_check(struct load_info *info, ++ void *mod, unsigned long *len) ++{ ++ return 0; ++} ++#endif /* !CONFIG_MODULE_SIG */ ++ ++/* Sets info->hdr, info->len and info->sig_ok. */ + static int copy_and_check(struct load_info *info, + const void __user *umod, unsigned long len, + const char __user *uargs) +@@ -2419,6 +2495,10 @@ static int copy_and_check(struct load_info *info, + goto free_hdr; + } + ++ err = module_sig_check(info, hdr, &len); ++ if (err) ++ goto free_hdr; ++ + /* Sanity checks against insmoding binaries or wrong arch, + weird elf version */ + if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 +@@ -2886,6 +2966,12 @@ static struct module *load_module(void __user *umod, + goto free_copy; + } + ++#ifdef CONFIG_MODULE_SIG ++ mod->sig_ok = info.sig_ok; ++ if (!mod->sig_ok) ++ add_taint_module(mod, TAINT_FORCED_MODULE); ++#endif ++ + /* Now module is in final location, initialize linked lists, etc. */ + err = module_unload_init(mod); + if (err) +-- +1.7.11.4 + + +From d4f65b5d2497b2fd9c45f06b71deb4ab084a5b66 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 13:06:29 +0100 +Subject: [PATCH 02/26] KEYS: Add payload preparsing opportunity prior to key + instantiate or update + +Give the key type the opportunity to preparse the payload prior to the +instantiation and update routines being called. This is done with the +provision of two new key type operations: + + int (*preparse)(struct key_preparsed_payload *prep); + void (*free_preparse)(struct key_preparsed_payload *prep); + +If the first operation is present, then it is called before key creation (in +the add/update case) or before the key semaphore is taken (in the update and +instantiate cases). The second operation is called to clean up if the first +was called. + +preparse() is given the opportunity to fill in the following structure: + + struct key_preparsed_payload { + char *description; + void *type_data[2]; + void *payload; + const void *data; + size_t datalen; + size_t quotalen; + }; + +Before the preparser is called, the first three fields will have been cleared, +the payload pointer and size will be stored in data and datalen and the default +quota size from the key_type struct will be stored into quotalen. + +The preparser may parse the payload in any way it likes and may store data in +the type_data[] and payload fields for use by the instantiate() and update() +ops. + +The preparser may also propose a description for the key by attaching it as a +string to the description field. This can be used by passing a NULL or "" +description to the add_key() system call or the key_create_or_update() +function. This cannot work with request_key() as that required the description +to tell the upcall about the key to be created. + +This, for example permits keys that store PGP public keys to generate their own +name from the user ID and public key fingerprint in the key. + +The instantiate() and update() operations are then modified to look like this: + + int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + int (*update)(struct key *key, struct key_preparsed_payload *prep); + +and the new payload data is passed in *prep, whether or not it was preparsed. + +Signed-off-by: David Howells +--- + Documentation/security/keys.txt | 50 +++++++++++++- + fs/cifs/cifs_spnego.c | 6 +- + fs/cifs/cifsacl.c | 8 +-- + include/keys/user-type.h | 6 +- + include/linux/key-type.h | 35 +++++++++- + net/ceph/crypto.c | 9 +-- + net/dns_resolver/dns_key.c | 6 +- + net/rxrpc/ar-key.c | 40 +++++------ + security/keys/encrypted-keys/encrypted.c | 16 +++-- + security/keys/key.c | 114 ++++++++++++++++++++++--------- + security/keys/keyctl.c | 18 +++-- + security/keys/keyring.c | 6 +- + security/keys/request_key_auth.c | 8 +-- + security/keys/trusted.c | 16 +++-- + security/keys/user_defined.c | 14 ++-- + 15 files changed, 250 insertions(+), 102 deletions(-) + +diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt +index aa0dbd7..7d9ca92 100644 +--- a/Documentation/security/keys.txt ++++ b/Documentation/security/keys.txt +@@ -412,6 +412,10 @@ The main syscalls are: + to the keyring. In this case, an error will be generated if the process + does not have permission to write to the keyring. + ++ If the key type supports it, if the description is NULL or an empty ++ string, the key type will try and generate a description from the content ++ of the payload. ++ + The payload is optional, and the pointer can be NULL if not required by + the type. The payload is plen in size, and plen can be zero for an empty + payload. +@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: + it should return 0. + + +- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ (*) int (*preparse)(struct key_preparsed_payload *prep); ++ ++ This optional method permits the key type to attempt to parse payload ++ before a key is created (add key) or the key semaphore is taken (update or ++ instantiate key). The structure pointed to by prep looks like: ++ ++ struct key_preparsed_payload { ++ char *description; ++ void *type_data[2]; ++ void *payload; ++ const void *data; ++ size_t datalen; ++ size_t quotalen; ++ }; ++ ++ Before calling the method, the caller will fill in data and datalen with ++ the payload blob parameters; quotalen will be filled in with the default ++ quota size from the key type and the rest will be cleared. ++ ++ If a description can be proposed from the payload contents, that should be ++ attached as a string to the description field. This will be used for the ++ key description if the caller of add_key() passes NULL or "". ++ ++ The method can attach anything it likes to type_data[] and payload. These ++ are merely passed along to the instantiate() or update() operations. ++ ++ The method should return 0 if success ful or a negative error code ++ otherwise. ++ ++ ++ (*) void (*free_preparse)(struct key_preparsed_payload *prep); ++ ++ This method is only required if the preparse() method is provided, ++ otherwise it is unused. It cleans up anything attached to the ++ description, type_data and payload fields of the key_preparsed_payload ++ struct as filled in by the preparse() method. ++ ++ ++ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + This method is called to attach a payload to a key during construction. + The payload attached need not bear any relation to the data passed to this + function. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + If the amount of data attached to the key differs from the size in + keytype->def_datalen, then key_payload_reserve() should be called. + +@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: + If this type of key can be updated, then this method should be provided. + It is called to update a key's payload from the blob of data provided. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + key_payload_reserve() should be called if the data length might change + before any changes are actually made. Note that if this succeeds, the type + is committed to changing the key because it's already been altered, so all +diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c +index e622863..086f381 100644 +--- a/fs/cifs/cifs_spnego.c ++++ b/fs/cifs/cifs_spnego.c +@@ -31,18 +31,18 @@ + + /* create a new cifs key */ + static int +-cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + int ret; + + ret = -ENOMEM; +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + goto error; + + /* attach the data */ +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; + ret = 0; + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 05f4dc2..f3c60e2 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { + }; + + static int +-cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + return -ENOMEM; + +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; +- key->datalen = datalen; ++ key->datalen = prep->datalen; + return 0; + } + +diff --git a/include/keys/user-type.h b/include/keys/user-type.h +index bc9ec1d..5e452c8 100644 +--- a/include/keys/user-type.h ++++ b/include/keys/user-type.h +@@ -35,8 +35,10 @@ struct user_key_payload { + extern struct key_type key_type_user; + extern struct key_type key_type_logon; + +-extern int user_instantiate(struct key *key, const void *data, size_t datalen); +-extern int user_update(struct key *key, const void *data, size_t datalen); ++struct key_preparsed_payload; ++ ++extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); ++extern int user_update(struct key *key, struct key_preparsed_payload *prep); + extern int user_match(const struct key *key, const void *criterion); + extern void user_revoke(struct key *key); + extern void user_destroy(struct key *key); +diff --git a/include/linux/key-type.h b/include/linux/key-type.h +index f0c651c..518a53a 100644 +--- a/include/linux/key-type.h ++++ b/include/linux/key-type.h +@@ -26,6 +26,27 @@ struct key_construction { + struct key *authkey;/* authorisation for key being constructed */ + }; + ++/* ++ * Pre-parsed payload, used by key add, update and instantiate. ++ * ++ * This struct will be cleared and data and datalen will be set with the data ++ * and length parameters from the caller and quotalen will be set from ++ * def_datalen from the key type. Then if the preparse() op is provided by the ++ * key type, that will be called. Then the struct will be passed to the ++ * instantiate() or the update() op. ++ * ++ * If the preparse() op is given, the free_preparse() op will be called to ++ * clear the contents. ++ */ ++struct key_preparsed_payload { ++ char *description; /* Proposed key description (or NULL) */ ++ void *type_data[2]; /* Private key-type data */ ++ void *payload; /* Proposed payload */ ++ const void *data; /* Raw data */ ++ size_t datalen; /* Raw datalen */ ++ size_t quotalen; /* Quota length for proposed payload */ ++}; ++ + typedef int (*request_key_actor_t)(struct key_construction *key, + const char *op, void *aux); + +@@ -45,18 +66,28 @@ struct key_type { + /* vet a description */ + int (*vet_description)(const char *description); + ++ /* Preparse the data blob from userspace that is to be the payload, ++ * generating a proposed description and payload that will be handed to ++ * the instantiate() and update() ops. ++ */ ++ int (*preparse)(struct key_preparsed_payload *prep); ++ ++ /* Free a preparse data structure. ++ */ ++ void (*free_preparse)(struct key_preparsed_payload *prep); ++ + /* instantiate a key of this type + * - this method should call key_payload_reserve() to determine if the + * user's quota will hold the payload + */ +- int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + /* update a key of this type (optional) + * - this method should call key_payload_reserve() to recalculate the + * quota consumption + * - the key must be locked against read when modifying + */ +- int (*update)(struct key *key, const void *data, size_t datalen); ++ int (*update)(struct key *key, struct key_preparsed_payload *prep); + + /* match a key against a description */ + int (*match)(const struct key *key, const void *desc); +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 9da7fdd..af14cb4 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, + } + } + +-int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) ++int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct ceph_crypto_key *ckey; ++ size_t datalen = prep->datalen; + int ret; + void *p; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto err; + + ret = key_payload_reserve(key, datalen); +@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) + goto err; + + /* TODO ceph_crypto_key_decode should really take const input */ +- p = (void *)data; +- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); ++ p = (void *)prep->data; ++ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); + if (ret < 0) + goto err_ckey; + +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index d9507dd..859ab8b 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; + * "ip1,ip2,...#foo=bar" + */ + static int +-dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) ++dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; + unsigned long derrno; + int ret; +- size_t result_len = 0; +- const char *data = _data, *end, *opt; ++ size_t datalen = prep->datalen, result_len = 0; ++ const char *data = prep->data, *end, *opt; + + kenter("%%%d,%s,'%*.*s',%zu", + key->serial, key->description, +diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c +index 8b1f9f4..106c5a6 100644 +--- a/net/rxrpc/ar-key.c ++++ b/net/rxrpc/ar-key.c +@@ -26,8 +26,8 @@ + #include "ar-internal.h" + + static int rxrpc_vet_description_s(const char *); +-static int rxrpc_instantiate(struct key *, const void *, size_t); +-static int rxrpc_instantiate_s(struct key *, const void *, size_t); ++static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); ++static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); + static void rxrpc_destroy(struct key *); + static void rxrpc_destroy_s(struct key *); + static void rxrpc_describe(const struct key *, struct seq_file *); +@@ -678,7 +678,7 @@ error: + * + * if no data is provided, then a no-security key is made + */ +-static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) ++static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + const struct rxrpc_key_data_v1 *v1; + struct rxrpc_key_token *token, **pp; +@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + u32 kver; + int ret; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + + /* handle a no-security key */ +- if (!data && datalen == 0) ++ if (!prep->data && prep->datalen == 0) + return 0; + + /* determine if the XDR payload format is being used */ +- if (datalen > 7 * 4) { +- ret = rxrpc_instantiate_xdr(key, data, datalen); ++ if (prep->datalen > 7 * 4) { ++ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); + if (ret != -EPROTO) + return ret; + } + + /* get the key interface version number */ + ret = -EINVAL; +- if (datalen <= 4 || !data) ++ if (prep->datalen <= 4 || !prep->data) + goto error; +- memcpy(&kver, data, sizeof(kver)); +- data += sizeof(kver); +- datalen -= sizeof(kver); ++ memcpy(&kver, prep->data, sizeof(kver)); ++ prep->data += sizeof(kver); ++ prep->datalen -= sizeof(kver); + + _debug("KEY I/F VERSION: %u", kver); + +@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + + /* deal with a version 1 key */ + ret = -EINVAL; +- if (datalen < sizeof(*v1)) ++ if (prep->datalen < sizeof(*v1)) + goto error; + +- v1 = data; +- if (datalen != sizeof(*v1) + v1->ticket_length) ++ v1 = prep->data; ++ if (prep->datalen != sizeof(*v1) + v1->ticket_length) + goto error; + + _debug("SCIX: %u", v1->security_index); +@@ -784,17 +784,17 @@ error: + * instantiate a server secret key + * data should be a pointer to the 8-byte secret key + */ +-static int rxrpc_instantiate_s(struct key *key, const void *data, +- size_t datalen) ++static int rxrpc_instantiate_s(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct crypto_blkcipher *ci; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + +- if (datalen != 8) ++ if (prep->datalen != 8) + return -EINVAL; + +- memcpy(&key->type_data, data, 8); ++ memcpy(&key->type_data, prep->data, 8); + + ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(ci)) { +@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, + return PTR_ERR(ci); + } + +- if (crypto_blkcipher_setkey(ci, data, 8) < 0) ++ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) + BUG(); + + key->payload.data = ci; +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 2d1bb8a..9e1e005 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int encrypted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = NULL; + char *datablob = NULL; +@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, + char *master_desc = NULL; + char *decrypted_datalen = NULL; + char *hex_encoded_iv = NULL; ++ size_t datalen = prep->datalen; + int ret; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; + datablob[datalen] = 0; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + ret = datablob_parse(datablob, &format, &master_desc, + &decrypted_datalen, &hex_encoded_iv); + if (ret < 0) +@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_update(struct key *key, const void *data, size_t datalen) ++static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = key->payload.data; + struct encrypted_key_payload *new_epayload; + char *buf; + char *new_master_desc = NULL; + const char *format = NULL; ++ size_t datalen = prep->datalen; + int ret = 0; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + buf = kmalloc(datalen + 1, GFP_KERNEL); +@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) + return -ENOMEM; + + buf[datalen] = 0; +- memcpy(buf, data, datalen); ++ memcpy(buf, prep->data, datalen); + ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); + if (ret < 0) + goto out; +diff --git a/security/keys/key.c b/security/keys/key.c +index 50d96d4..1d039af 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); + * key_construction_mutex. + */ + static int __key_instantiate_and_link(struct key *key, +- const void *data, +- size_t datalen, ++ struct key_preparsed_payload *prep, + struct key *keyring, + struct key *authkey, + unsigned long *_prealloc) +@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, + /* can't instantiate twice */ + if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { + /* instantiate the key */ +- ret = key->type->instantiate(key, data, datalen); ++ ret = key->type->instantiate(key, prep); + + if (ret == 0) { + /* mark the key as being instantiated */ +@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, + struct key *keyring, + struct key *authkey) + { ++ struct key_preparsed_payload prep; + unsigned long prealloc; + int ret; + ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = data; ++ prep.datalen = datalen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; ++ } ++ + if (keyring) { + ret = __key_link_begin(keyring, key->type, key->description, + &prealloc); + if (ret < 0) +- return ret; ++ goto error_free_preparse; + } + +- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, ++ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, + &prealloc); + + if (keyring) + __key_link_end(keyring, key->type, prealloc); + ++error_free_preparse: ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + +@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) + * if we get an error. + */ + static inline key_ref_t __key_update(key_ref_t key_ref, +- const void *payload, size_t plen) ++ struct key_preparsed_payload *prep) + { + struct key *key = key_ref_to_ptr(key_ref); + int ret; +@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, + + down_write(&key->sem); + +- ret = key->type->update(key, payload, plen); ++ ret = key->type->update(key, prep); + if (ret == 0) + /* updating a negative key instantiates it */ + clear_bit(KEY_FLAG_NEGATIVE, &key->flags); +@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + unsigned long flags) + { + unsigned long prealloc; ++ struct key_preparsed_payload prep; + const struct cred *cred = current_cred(); + struct key_type *ktype; + struct key *keyring, *key = NULL; +@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + } + + key_ref = ERR_PTR(-EINVAL); +- if (!ktype->match || !ktype->instantiate) +- goto error_2; ++ if (!ktype->match || !ktype->instantiate || ++ (!description && !ktype->preparse)) ++ goto error_put_type; + + keyring = key_ref_to_ptr(keyring_ref); + +@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + + key_ref = ERR_PTR(-ENOTDIR); + if (keyring->type != &key_type_keyring) +- goto error_2; ++ goto error_put_type; ++ ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = ktype->def_datalen; ++ if (ktype->preparse) { ++ ret = ktype->preparse(&prep); ++ if (ret < 0) { ++ key_ref = ERR_PTR(ret); ++ goto error_put_type; ++ } ++ if (!description) ++ description = prep.description; ++ key_ref = ERR_PTR(-EINVAL); ++ if (!description) ++ goto error_free_prep; ++ } + + ret = __key_link_begin(keyring, ktype, description, &prealloc); +- if (ret < 0) +- goto error_2; ++ if (ret < 0) { ++ key_ref = ERR_PTR(ret); ++ goto error_free_prep; ++ } + + /* if we're going to allocate a new key, we're going to have + * to modify the keyring */ + ret = key_permission(keyring_ref, KEY_WRITE); + if (ret < 0) { + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + /* if it's possible to update this type of key, search for an existing +@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + perm, flags); + if (IS_ERR(key)) { + key_ref = ERR_CAST(key); +- goto error_3; ++ goto error_link_end; + } + + /* instantiate it and link it into the target keyring */ +- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, +- &prealloc); ++ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); + if (ret < 0) { + key_put(key); + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); + +- error_3: ++error_link_end: + __key_link_end(keyring, ktype, prealloc); +- error_2: ++error_free_prep: ++ if (ktype->preparse) ++ ktype->free_preparse(&prep); ++error_put_type: + key_type_put(ktype); +- error: ++error: + return key_ref; + + found_matching_key: +@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + * - we can drop the locks first as we have the key pinned + */ + __key_link_end(keyring, ktype, prealloc); +- key_type_put(ktype); + +- key_ref = __key_update(key_ref, payload, plen); +- goto error; ++ key_ref = __key_update(key_ref, &prep); ++ goto error_free_prep; + } + EXPORT_SYMBOL(key_create_or_update); + +@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); + */ + int key_update(key_ref_t key_ref, const void *payload, size_t plen) + { ++ struct key_preparsed_payload prep; + struct key *key = key_ref_to_ptr(key_ref); + int ret; + +@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) + + /* attempt to update it if supported */ + ret = -EOPNOTSUPP; +- if (key->type->update) { +- down_write(&key->sem); +- +- ret = key->type->update(key, payload, plen); +- if (ret == 0) +- /* updating a negative key instantiates it */ +- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ if (!key->type->update) ++ goto error; + +- up_write(&key->sem); ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; + } + +- error: ++ down_write(&key->sem); ++ ++ ret = key->type->update(key, &prep); ++ if (ret == 0) ++ /* updating a negative key instantiates it */ ++ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ ++ up_write(&key->sem); ++ ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + EXPORT_SYMBOL(key_update); +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 3364fbf..505d40b 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, + * Extract the description of a new key from userspace and either add it as a + * new key to the specified keyring or update a matching key in that keyring. + * ++ * If the description is NULL or an empty string, the key type is asked to ++ * generate one from the payload. ++ * + * The keyring must be writable so that we can attach the key to it. + * + * If successful, the new key's serial number is returned, otherwise an error +@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, + if (ret < 0) + goto error; + +- description = strndup_user(_description, PAGE_SIZE); +- if (IS_ERR(description)) { +- ret = PTR_ERR(description); +- goto error; ++ description = NULL; ++ if (_description) { ++ description = strndup_user(_description, PAGE_SIZE); ++ if (IS_ERR(description)) { ++ ret = PTR_ERR(description); ++ goto error; ++ } ++ if (!*description) { ++ kfree(description); ++ description = NULL; ++ } + } + + /* pull the payload in if one was supplied */ +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 81e7852..f04d8cf 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) + * operations. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen); ++ struct key_preparsed_payload *prep); + static int keyring_match(const struct key *keyring, const void *criterion); + static void keyring_revoke(struct key *keyring); + static void keyring_destroy(struct key *keyring); +@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) + * Returns 0 on success, -EINVAL if given any data. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen) ++ struct key_preparsed_payload *prep) + { + int ret; + + ret = -EINVAL; +- if (datalen == 0) { ++ if (prep->datalen == 0) { + /* make the keyring available by name if it has one */ + keyring_publish_name(keyring); + ret = 0; +diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c +index 60d4e3f..85730d5 100644 +--- a/security/keys/request_key_auth.c ++++ b/security/keys/request_key_auth.c +@@ -19,7 +19,8 @@ + #include + #include "internal.h" + +-static int request_key_auth_instantiate(struct key *, const void *, size_t); ++static int request_key_auth_instantiate(struct key *, ++ struct key_preparsed_payload *); + static void request_key_auth_describe(const struct key *, struct seq_file *); + static void request_key_auth_revoke(struct key *); + static void request_key_auth_destroy(struct key *); +@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { + * Instantiate a request-key authorisation key. + */ + static int request_key_auth_instantiate(struct key *key, +- const void *data, +- size_t datalen) ++ struct key_preparsed_payload *prep) + { +- key->payload.data = (struct request_key_auth *) data; ++ key->payload.data = (struct request_key_auth *)prep->data; + return 0; + } + +diff --git a/security/keys/trusted.c b/security/keys/trusted.c +index 2d5d041..42036c7 100644 +--- a/security/keys/trusted.c ++++ b/security/keys/trusted.c +@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) + * + * On success, return 0. Otherwise return errno. + */ +-static int trusted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int trusted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct trusted_key_payload *payload = NULL; + struct trusted_key_options *options = NULL; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + int key_cmd; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + + options = trusted_options_alloc(); +@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) + /* + * trusted_update - reseal an existing key with new PCR values + */ +-static int trusted_update(struct key *key, const void *data, size_t datalen) ++static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct trusted_key_payload *p = key->payload.data; + struct trusted_key_payload *new_p; + struct trusted_key_options *new_o; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + + if (!p->migratable) + return -EPERM; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); +@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) + goto out; + } + +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + ret = datablob_parse(datablob, new_p, new_o); + if (ret != Opt_update) { +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index c7660a2..55dc889 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); + /* + * instantiate a user defined key + */ +-int user_instantiate(struct key *key, const void *data, size_t datalen) ++int user_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + ret = key_payload_reserve(key, datalen); +@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) + + /* attach the data */ + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + rcu_assign_keypointer(key, upayload); + ret = 0; + +@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); + * update a user defined key + * - the key's semaphore is write-locked + */ +-int user_update(struct key *key, const void *data, size_t datalen) ++int user_update(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload, *zap; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + /* construct a replacement payload */ +@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) + goto error; + + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + + /* check the quota and attach the new data */ + zap = upayload; +-- +1.7.11.4 + + +From a3f7dff6cbc2eb6be871a58fef34cacf7f78abf8 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 13:09:33 +0100 +Subject: [PATCH 03/26] MPILIB: Provide count_leading/trailing_zeros() based + on arch functions + +Provide count_leading/trailing_zeros() macros based on extant arch bit scanning +functions rather than reimplementing from scratch in MPILIB. + +Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). + +Also move the definition to asm-generic as other people may be interested in +using it. + +Signed-off-by: David Howells +Cc: David S. Miller +Cc: Dmitry Kasatkin +Cc: Arnd Bergmann +--- + include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ + lib/mpi/longlong.h | 138 +------------------------------ + lib/mpi/mpi-bit.c | 2 +- + lib/mpi/mpi-pow.c | 4 +- + 4 files changed, 62 insertions(+), 139 deletions(-) + create mode 100644 include/asm-generic/bitops/count_zeros.h + +diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h +new file mode 100644 +index 0000000..97520d2 +--- /dev/null ++++ b/include/asm-generic/bitops/count_zeros.h +@@ -0,0 +1,57 @@ ++/* Count leading and trailing zeros functions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ ++#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ ++ ++#include ++ ++/** ++ * count_leading_zeros - Count the number of zeros from the MSB back ++ * @x: The value ++ * ++ * Count the number of leading zeros from the MSB going towards the LSB in @x. ++ * ++ * If the MSB of @x is set, the result is 0. ++ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. ++ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. ++ */ ++static inline int count_leading_zeros(unsigned long x) ++{ ++ if (sizeof(x) == 4) ++ return BITS_PER_LONG - fls(x); ++ else ++ return BITS_PER_LONG - fls64(x); ++} ++ ++#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG ++ ++/** ++ * count_trailing_zeros - Count the number of zeros from the LSB forwards ++ * @x: The value ++ * ++ * Count the number of trailing zeros from the LSB going towards the MSB in @x. ++ * ++ * If the LSB of @x is set, the result is 0. ++ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. ++ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. ++ */ ++static inline int count_trailing_zeros(unsigned long x) ++{ ++#define COUNT_TRAILING_ZEROS_0 (-1) ++ ++ if (sizeof(x) == 4) ++ return ffs(x); ++ else ++ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; ++} ++ ++#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ +diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h +index 29f9862..678ce4f 100644 +--- a/lib/mpi/longlong.h ++++ b/lib/mpi/longlong.h +@@ -19,6 +19,8 @@ + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ + ++#include ++ + /* You have to define the following before including this file: + * + * UWtype -- An unsigned type, default type for operations (typically a "word") +@@ -146,12 +148,6 @@ do { \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +- +-#define count_leading_zeros(count, x) \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))) +-#define COUNT_LEADING_ZEROS_0 32 + #endif /* __a29k__ */ + + #if defined(__alpha) && W_TYPE_SIZE == 64 +@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +- __asm__ ("bsch/1 %1,%0" \ +- : "=g" (count) \ +- : "g" ((USItype)(x)), \ +- "0" ((USItype)0)) + #endif + + /*************************************** +@@ -354,27 +345,6 @@ do { USItype __r; \ + } while (0) + extern USItype __udiv_qrnnd(); + #endif /* LONGLONG_STANDALONE */ +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __tmp; \ +- __asm__ ( \ +- "ldi 1,%0\n" \ +- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ +- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ +- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ +- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ +- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ +- "extru %1,30,1,%1 ; Extract bit 1.\n" \ +- "sub %0,%1,%0 ; Subtract it. " \ +- : "=r" (count), "=r" (__tmp) : "1" (x)); \ +-} while (0) + #endif /* hppa */ + + /*************************************** +@@ -457,15 +427,6 @@ do { \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("bsrl %1,%0" \ +- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define count_trailing_zeros(count, x) \ +- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) + #ifndef UMUL_TIME + #define UMUL_TIME 40 + #endif +@@ -536,15 +497,6 @@ do { \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("scanbit %1,%0" \ +- : "=r" (__cbtmp) \ +- : "r" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ + #if defined(__i960mx) /* what is the proper symbol to test??? */ + #define rshift_rhlc(r, h, l, c) \ + do { \ +@@ -603,11 +555,6 @@ do { \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +- __asm__ ("bfffo %1{%b2:%b2},%0" \ +- : "=d" ((USItype)(count)) \ +- : "od" ((USItype)(x)), "n" (0)) +-#define COUNT_LEADING_ZEROS_0 32 + #else /* not mc68020 */ + #define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ +@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("ff1 %0,%1" \ +- : "=r" (__cbtmp) \ +- : "r" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define COUNT_LEADING_ZEROS_0 63 /* sic */ + #if defined(__m88110__) + #define umul_ppmm(wh, wl, u, v) \ + do { \ +@@ -779,12 +717,6 @@ do { \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +-#define count_trailing_zeros(count, x) \ +-do { \ +- __asm__("ffsd %2,%0" \ +- : "=r"((USItype) (count)) \ +- : "0"((USItype) 0), "r"((USItype) (x))); \ +- } while (0) + #endif /* __ns32000__ */ + + /*************************************** +@@ -855,11 +787,6 @@ do { \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +-#define count_leading_zeros(count, x) \ +- __asm__ ("{cntlz|cntlzw} %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))) +-#define COUNT_LEADING_ZEROS_0 32 + #if defined(_ARCH_PPC) + #define umul_ppmm(ph, pl, m0, m1) \ + do { \ +@@ -1001,19 +928,6 @@ do { \ + } while (0) + #define UMUL_TIME 20 + #define UDIV_TIME 200 +-#define count_leading_zeros(count, x) \ +-do { \ +- if ((x) >= 0x10000) \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x) >> 16)); \ +- else { \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))); \ +- (count) += 16; \ +- } \ +-} while (0) + #endif /* RT/ROMP */ + + /*************************************** +@@ -1142,13 +1056,6 @@ do { \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) + #define UDIV_TIME 37 +-#define count_leading_zeros(count, x) \ +- __asm__ ("scan %1,0,%0" \ +- : "=r" ((USItype)(x)) \ +- : "r" ((USItype)(count))) +-/* Early sparclites return 63 for an argument of 0, but they warn that future +- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 +- undefined. */ + #endif /* __sparclite__ */ + #endif /* __sparc_v8__ */ + /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +@@ -1454,47 +1361,6 @@ do { \ + #define udiv_qrnnd __udiv_qrnnd_c + #endif + +-#undef count_leading_zeros +-#if !defined(count_leading_zeros) +- extern +-#ifdef __STDC__ +- const +-#endif +- unsigned char __clz_tab[]; +-#define count_leading_zeros(count, x) \ +-do { \ +- UWtype __xr = (x); \ +- UWtype __a; \ +- \ +- if (W_TYPE_SIZE <= 32) { \ +- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ +- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ +- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ +- } \ +- else { \ +- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ +- if (((__xr >> __a) & 0xff) != 0) \ +- break; \ +- } \ +- \ +- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ +-} while (0) +- /* This version gives a well-defined value for zero. */ +-#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +-#endif +- +-#if !defined(count_trailing_zeros) +-/* Define count_trailing_zeros using count_leading_zeros. The latter might be +- defined in asm, but if it is not, the C version above is good enough. */ +-#define count_trailing_zeros(count, x) \ +-do { \ +- UWtype __ctz_x = (x); \ +- UWtype __ctz_c; \ +- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ +- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ +-} while (0) +-#endif +- + #ifndef UDIV_NEEDS_NORMALIZATION + #define UDIV_NEEDS_NORMALIZATION 0 + #endif +diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c +index 5687248..503537e 100644 +--- a/lib/mpi/mpi-bit.c ++++ b/lib/mpi/mpi-bit.c +@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) + if (a->nlimbs) { + mpi_limb_t alimb = a->d[a->nlimbs - 1]; + if (alimb) +- count_leading_zeros(n, alimb); ++ n = count_leading_zeros(alimb); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; +diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c +index 67f3e79..5464c87 100644 +--- a/lib/mpi/mpi-pow.c ++++ b/lib/mpi/mpi-pow.c +@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + mp = mp_marker = mpi_alloc_limb_space(msize); + if (!mp) + goto enomem; +- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); ++ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); + if (mod_shift_cnt) + mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); + else +@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + + i = esize - 1; + e = ep[i]; +- count_leading_zeros(c, e); ++ c = count_leading_zeros(e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MPI_LIMB - 1 - c; + +-- +1.7.11.4 + + +From 79e4c942f35117b405402acf0f075ff79260e546 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:21 +0100 +Subject: [PATCH 04/26] KEYS: Document asymmetric key type + +In-source documentation for the asymmetric key type. This will be located in: + + Documentation/crypto/asymmetric-keys.txt + +Signed-off-by: David Howells +--- + Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++ + 1 file changed, 312 insertions(+) + create mode 100644 Documentation/crypto/asymmetric-keys.txt + +diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt +new file mode 100644 +index 0000000..b767590 +--- /dev/null ++++ b/Documentation/crypto/asymmetric-keys.txt +@@ -0,0 +1,312 @@ ++ ============================================= ++ ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE ++ ============================================= ++ ++Contents: ++ ++ - Overview. ++ - Key identification. ++ - Accessing asymmetric keys. ++ - Signature verification. ++ - Asymmetric key subtypes. ++ - Instantiation data parsers. ++ ++ ++======== ++OVERVIEW ++======== ++ ++The "asymmetric" key type is designed to be a container for the keys used in ++public-key cryptography, without imposing any particular restrictions on the ++form or mechanism of the cryptography or form of the key. ++ ++The asymmetric key is given a subtype that defines what sort of data is ++associated with the key and provides operations to describe and destroy it. ++However, no requirement is made that the key data actually be stored in the ++key. ++ ++A completely in-kernel key retention and operation subtype can be defined, but ++it would also be possible to provide access to cryptographic hardware (such as ++a TPM) that might be used to both retain the relevant key and perform ++operations using that key. In such a case, the asymmetric key would then ++merely be an interface to the TPM driver. ++ ++Also provided is the concept of a data parser. Data parsers are responsible ++for extracting information from the blobs of data passed to the instantiation ++function. The first data parser that recognises the blob gets to set the ++subtype of the key and define the operations that can be done on that key. ++ ++A data parser may interpret the data blob as containing the bits representing a ++key, or it may interpret it as a reference to a key held somewhere else in the ++system (for example, a TPM). ++ ++ ++================== ++KEY IDENTIFICATION ++================== ++ ++If a key is added with an empty name, the instantiation data parsers are given ++the opportunity to pre-parse a key and to determine the description the key ++should be given from the content of the key. ++ ++This can then be used to refer to the key, either by complete match or by ++partial match. The key type may also use other criteria to refer to a key. ++ ++The asymmetric key type's match function can then perform a wider range of ++comparisons than just the straightforward comparison of the description with ++the criterion string: ++ ++ (1) If the criterion string is of the form "id:" then the match ++ function will examine a key's fingerprint to see if the hex digits given ++ after the "id:" match the tail. For instance: ++ ++ keyctl search @s asymmetric id:5acc2142 ++ ++ will match a key with fingerprint: ++ ++ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 ++ ++ (2) If the criterion string is of the form ":" then the ++ match will match the ID as in (1), but with the added restriction that ++ only keys of the specified subtype (e.g. tpm) will be matched. For ++ instance: ++ ++ keyctl search @s asymmetric tpm:5acc2142 ++ ++Looking in /proc/keys, the last 8 hex digits of the key fingerprint are ++displayed, along with the subtype: ++ ++ 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] ++ ++ ++========================= ++ACCESSING ASYMMETRIC KEYS ++========================= ++ ++For general access to asymmetric keys from within the kernel, the following ++inclusion is required: ++ ++ #include ++ ++This gives access to functions for dealing with asymmetric / public keys. ++Three enums are defined there for representing public-key cryptography ++algorithms: ++ ++ enum pkey_algo ++ ++digest algorithms used by those: ++ ++ enum pkey_hash_algo ++ ++and key identifier representations: ++ ++ enum pkey_id_type ++ ++Note that the key type representation types are required because key ++identifiers from different standards aren't necessarily compatible. For ++instance, PGP generates key identifiers by hashing the key data plus some ++PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. ++ ++The operations defined upon a key are: ++ ++ (1) Signature verification. ++ ++Other operations are possible (such as encryption) with the same key data ++required for verification, but not currently supported, and others ++(eg. decryption and signature generation) require extra key data. ++ ++ ++SIGNATURE VERIFICATION ++---------------------- ++ ++An operation is provided to perform cryptographic signature verification, using ++an asymmetric key to provide or to provide access to the public key. ++ ++ int verify_signature(const struct key *key, ++ const struct public_key_signature *sig); ++ ++The caller must have already obtained the key from some source and can then use ++it to check the signature. The caller must have parsed the signature and ++transferred the relevant bits to the structure pointed to by sig. ++ ++ struct public_key_signature { ++ u8 *digest; ++ u8 digest_size; ++ enum pkey_hash_algo pkey_hash_algo : 8; ++ u8 nr_mpi; ++ union { ++ MPI mpi[2]; ++ ... ++ }; ++ }; ++ ++The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that ++make up the actual signature must be stored in sig->mpi[] and the count of MPIs ++placed in sig->nr_mpi. ++ ++In addition, the data must have been digested by the caller and the resulting ++hash must be pointed to by sig->digest and the size of the hash be placed in ++sig->digest_size. ++ ++The function will return 0 upon success or -EKEYREJECTED if the signature ++doesn't match. ++ ++The function may also return -ENOTSUPP if an unsupported public-key algorithm ++or public-key/hash algorithm combination is specified or the key doesn't ++support the operation; -EBADMSG or -ERANGE if some of the parameters have weird ++data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned ++if the key argument is the wrong type or is incompletely set up. ++ ++ ++======================= ++ASYMMETRIC KEY SUBTYPES ++======================= ++ ++Asymmetric keys have a subtype that defines the set of operations that can be ++performed on that key and that determines what data is attached as the key ++payload. The payload format is entirely at the whim of the subtype. ++ ++The subtype is selected by the key data parser and the parser must initialise ++the data required for it. The asymmetric key retains a reference on the ++subtype module. ++ ++The subtype definition structure can be found in: ++ ++ #include ++ ++and looks like the following: ++ ++ struct asymmetric_key_subtype { ++ struct module *owner; ++ const char *name; ++ ++ void (*describe)(const struct key *key, struct seq_file *m); ++ void (*destroy)(void *payload); ++ int (*verify_signature)(const struct key *key, ++ const struct public_key_signature *sig); ++ }; ++ ++Asymmetric keys point to this with their type_data[0] member. ++ ++The owner and name fields should be set to the owning module and the name of ++the subtype. Currently, the name is only used for print statements. ++ ++There are a number of operations defined by the subtype: ++ ++ (1) describe(). ++ ++ Mandatory. This allows the subtype to display something in /proc/keys ++ against the key. For instance the name of the public key algorithm type ++ could be displayed. The key type will display the tail of the key ++ identity string after this. ++ ++ (2) destroy(). ++ ++ Mandatory. This should free the memory associated with the key. The ++ asymmetric key will look after freeing the fingerprint and releasing the ++ reference on the subtype module. ++ ++ (3) verify_signature(). ++ ++ Optional. These are the entry points for the key usage operations. ++ Currently there is only the one defined. If not set, the caller will be ++ given -ENOTSUPP. The subtype may do anything it likes to implement an ++ operation, including offloading to hardware. ++ ++ ++========================== ++INSTANTIATION DATA PARSERS ++========================== ++ ++The asymmetric key type doesn't generally want to store or to deal with a raw ++blob of data that holds the key data. It would have to parse it and error ++check it each time it wanted to use it. Further, the contents of the blob may ++have various checks that can be performed on it (eg. self-signatures, validity ++dates) and may contain useful data about the key (identifiers, capabilities). ++ ++Also, the blob may represent a pointer to some hardware containing the key ++rather than the key itself. ++ ++Examples of blob formats for which parsers could be implemented include: ++ ++ - OpenPGP packet stream [RFC 4880]. ++ - X.509 ASN.1 stream. ++ - Pointer to TPM key. ++ - Pointer to UEFI key. ++ ++During key instantiation each parser in the list is tried until one doesn't ++return -EBADMSG. ++ ++The parser definition structure can be found in: ++ ++ #include ++ ++and looks like the following: ++ ++ struct asymmetric_key_parser { ++ struct module *owner; ++ const char *name; ++ ++ int (*parse)(struct key_preparsed_payload *prep); ++ }; ++ ++The owner and name fields should be set to the owning module and the name of ++the parser. ++ ++There is currently only a single operation defined by the parser, and it is ++mandatory: ++ ++ (1) parse(). ++ ++ This is called to preparse the key from the key creation and update paths. ++ In particular, it is called during the key creation _before_ a key is ++ allocated, and as such, is permitted to provide the key's description in ++ the case that the caller declines to do so. ++ ++ The caller passes a pointer to the following struct with all of the fields ++ cleared, except for data, datalen and quotalen [see ++ Documentation/security/keys.txt]. ++ ++ struct key_preparsed_payload { ++ char *description; ++ void *type_data[2]; ++ void *payload; ++ const void *data; ++ size_t datalen; ++ size_t quotalen; ++ }; ++ ++ The instantiation data is in a blob pointed to by data and is datalen in ++ size. The parse() function is not permitted to change these two values at ++ all, and shouldn't change any of the other values _unless_ they are ++ recognise the blob format and will not return -EBADMSG to indicate it is ++ not theirs. ++ ++ If the parser is happy with the blob, it should propose a description for ++ the key and attach it to ->description, ->type_data[0] should be set to ++ point to the subtype to be used, ->payload should be set to point to the ++ initialised data for that subtype, ->type_data[1] should point to a hex ++ fingerprint and quotalen should be updated to indicate how much quota this ++ key should account for. ++ ++ When clearing up, the data attached to ->type_data[1] and ->description ++ will be kfree()'d and the data attached to ->payload will be passed to the ++ subtype's ->destroy() method to be disposed of. A module reference for ++ the subtype pointed to by ->type_data[0] will be put. ++ ++ ++ If the data format is not recognised, -EBADMSG should be returned. If it ++ is recognised, but the key cannot for some reason be set up, some other ++ negative error code should be returned. On success, 0 should be returned. ++ ++ The key's fingerprint string may be partially matched upon. For a ++ public-key algorithm such as RSA and DSA this will likely be a printable ++ hex version of the key's fingerprint. ++ ++Functions are provided to register and unregister parsers: ++ ++ int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); ++ void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); ++ ++Parsers may not have the same name. The names are otherwise only used for ++displaying in debugging messages. +-- +1.7.11.4 + + +From 2fb78e0d337ac41f2cddad18fc5c34374e5298ab Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:21 +0100 +Subject: [PATCH 05/26] KEYS: Implement asymmetric key type + +Create a key type that can be used to represent an asymmetric key type for use +in appropriate cryptographic operations, such as encryption, decryption, +signature generation and signature verification. + +The key type is "asymmetric" and can provide access to a variety of +cryptographic algorithms. + +Possibly, this would be better as "public_key" - but that has the disadvantage +that "public key" is an overloaded term. + +Signed-off-by: David Howells +--- + crypto/Kconfig | 1 + + crypto/Makefile | 1 + + crypto/asymmetric_keys/Kconfig | 13 +++ + crypto/asymmetric_keys/Makefile | 7 ++ + crypto/asymmetric_keys/asymmetric_keys.h | 15 +++ + crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++ + include/keys/asymmetric-subtype.h | 55 +++++++++++ + include/keys/asymmetric-type.h | 25 +++++ + 8 files changed, 273 insertions(+) + create mode 100644 crypto/asymmetric_keys/Kconfig + create mode 100644 crypto/asymmetric_keys/Makefile + create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h + create mode 100644 crypto/asymmetric_keys/asymmetric_type.c + create mode 100644 include/keys/asymmetric-subtype.h + create mode 100644 include/keys/asymmetric-type.h + +diff --git a/crypto/Kconfig b/crypto/Kconfig +index a323805..1ca0b24 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER + key cipher algorithms. + + source "drivers/crypto/Kconfig" ++source crypto/asymmetric_keys/Kconfig + + endif # if CRYPTO +diff --git a/crypto/Makefile b/crypto/Makefile +index 30f33d6..ced472e 100644 +--- a/crypto/Makefile ++++ b/crypto/Makefile +@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o + # + obj-$(CONFIG_XOR_BLOCKS) += xor.o + obj-$(CONFIG_ASYNC_CORE) += async_tx/ ++obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +new file mode 100644 +index 0000000..cad29b3 +--- /dev/null ++++ b/crypto/asymmetric_keys/Kconfig +@@ -0,0 +1,13 @@ ++menuconfig ASYMMETRIC_KEY_TYPE ++ tristate "Asymmetric (public-key cryptographic) key type" ++ depends on KEYS ++ help ++ This option provides support for a key type that holds the data for ++ the asymmetric keys used for public key cryptographic operations such ++ as encryption, decryption, signature generation and signature ++ verification. ++ ++if ASYMMETRIC_KEY_TYPE ++ ++ ++endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +new file mode 100644 +index 0000000..b725bcc +--- /dev/null ++++ b/crypto/asymmetric_keys/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for asymmetric cryptographic keys ++# ++ ++obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o ++ ++asymmetric_keys-y := asymmetric_type.o +diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h +new file mode 100644 +index 0000000..515b634 +--- /dev/null ++++ b/crypto/asymmetric_keys/asymmetric_keys.h +@@ -0,0 +1,15 @@ ++/* Internal definitions for asymmetric key type ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++static inline const char *asymmetric_key_id(const struct key *key) ++{ ++ return key->type_data.p[1]; ++} +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +new file mode 100644 +index 0000000..bfb0424 +--- /dev/null ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -0,0 +1,156 @@ ++/* Asymmetric public-key cryptography key type ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++ ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Match asymmetric keys on (part of) their name ++ * We have some shorthand methods for matching keys. We allow: ++ * ++ * "" - request a key by description ++ * "id:" - request a key matching the ID ++ * ":" - request a key of a subtype ++ */ ++static int asymmetric_key_match(const struct key *key, const void *description) ++{ ++ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ const char *spec = description; ++ const char *id, *kid; ++ ptrdiff_t speclen; ++ size_t idlen, kidlen; ++ ++ if (!subtype || !spec || !*spec) ++ return 0; ++ ++ /* See if the full key description matches as is */ ++ if (key->description && strcmp(key->description, description) == 0) ++ return 1; ++ ++ /* All tests from here on break the criterion description into a ++ * specifier, a colon and then an identifier. ++ */ ++ id = strchr(spec, ':'); ++ if (!id) ++ return 0; ++ ++ speclen = id - spec; ++ id++; ++ ++ /* Anything after here requires a partial match on the ID string */ ++ kid = asymmetric_key_id(key); ++ if (!kid) ++ return 0; ++ ++ idlen = strlen(id); ++ kidlen = strlen(kid); ++ if (idlen > kidlen) ++ return 0; ++ ++ kid += kidlen - idlen; ++ if (strcasecmp(id, kid) != 0) ++ return 0; ++ ++ if (speclen == 2 && ++ memcmp(spec, "id", 2) == 0) ++ return 1; ++ ++ if (speclen == subtype->name_len && ++ memcmp(spec, subtype->name, speclen) == 0) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * Describe the asymmetric key ++ */ ++static void asymmetric_key_describe(const struct key *key, struct seq_file *m) ++{ ++ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ const char *kid = asymmetric_key_id(key); ++ size_t n; ++ ++ seq_puts(m, key->description); ++ ++ if (subtype) { ++ seq_puts(m, ": "); ++ subtype->describe(key, m); ++ ++ if (kid) { ++ seq_putc(m, ' '); ++ n = strlen(kid); ++ if (n <= 8) ++ seq_puts(m, kid); ++ else ++ seq_puts(m, kid + n - 8); ++ } ++ ++ seq_puts(m, " ["); ++ /* put something here to indicate the key's capabilities */ ++ seq_putc(m, ']'); ++ } ++} ++ ++/* ++ * Instantiate a asymmetric_key defined key. The key was preparsed, so we just ++ * have to transfer the data here. ++ */ ++static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) ++{ ++ return -EOPNOTSUPP; ++} ++ ++/* ++ * dispose of the data dangling from the corpse of a asymmetric key ++ */ ++static void asymmetric_key_destroy(struct key *key) ++{ ++ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ if (subtype) { ++ subtype->destroy(key->payload.data); ++ module_put(subtype->owner); ++ key->type_data.p[0] = NULL; ++ } ++ kfree(key->type_data.p[1]); ++ key->type_data.p[1] = NULL; ++} ++ ++struct key_type key_type_asymmetric = { ++ .name = "asymmetric", ++ .instantiate = asymmetric_key_instantiate, ++ .match = asymmetric_key_match, ++ .destroy = asymmetric_key_destroy, ++ .describe = asymmetric_key_describe, ++}; ++EXPORT_SYMBOL_GPL(key_type_asymmetric); ++ ++/* ++ * Module stuff ++ */ ++static int __init asymmetric_key_init(void) ++{ ++ return register_key_type(&key_type_asymmetric); ++} ++ ++static void __exit asymmetric_key_cleanup(void) ++{ ++ unregister_key_type(&key_type_asymmetric); ++} ++ ++module_init(asymmetric_key_init); ++module_exit(asymmetric_key_cleanup); +diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h +new file mode 100644 +index 0000000..4b840e8 +--- /dev/null ++++ b/include/keys/asymmetric-subtype.h +@@ -0,0 +1,55 @@ ++/* Asymmetric public-key cryptography key subtype ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H ++#define _KEYS_ASYMMETRIC_SUBTYPE_H ++ ++#include ++#include ++ ++struct public_key_signature; ++ ++/* ++ * Keys of this type declare a subtype that indicates the handlers and ++ * capabilities. ++ */ ++struct asymmetric_key_subtype { ++ struct module *owner; ++ const char *name; ++ unsigned short name_len; /* length of name */ ++ ++ /* Describe a key of this subtype for /proc/keys */ ++ void (*describe)(const struct key *key, struct seq_file *m); ++ ++ /* Destroy a key of this subtype */ ++ void (*destroy)(void *payload); ++ ++ /* Verify the signature on a key of this subtype (optional) */ ++ int (*verify_signature)(const struct key *key, ++ const struct public_key_signature *sig); ++}; ++ ++/** ++ * asymmetric_key_subtype - Get the subtype from an asymmetric key ++ * @key: The key of interest. ++ * ++ * Retrieves and returns the subtype pointer of the asymmetric key from the ++ * type-specific data attached to the key. ++ */ ++static inline ++struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) ++{ ++ return key->type_data.p[0]; ++} ++ ++#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ +diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h +new file mode 100644 +index 0000000..7dd4734 +--- /dev/null ++++ b/include/keys/asymmetric-type.h +@@ -0,0 +1,25 @@ ++/* Asymmetric Public-key cryptography key type interface ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_TYPE_H ++#define _KEYS_ASYMMETRIC_TYPE_H ++ ++#include ++ ++extern struct key_type key_type_asymmetric; ++ ++/* ++ * The payload is at the discretion of the subtype. ++ */ ++ ++#endif /* _KEYS_ASYMMETRIC_TYPE_H */ +-- +1.7.11.4 + + +From d28ffd9e0c8987e5af59ae38bb48779b0d221f00 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:32 +0100 +Subject: [PATCH 06/26] KEYS: Asymmetric key pluggable data parsers + +The instantiation data passed to the asymmetric key type are expected to be +formatted in some way, and there are several possible standard ways to format +the data. + +The two obvious standards are OpenPGP keys and X.509 certificates. The latter +is especially useful when dealing with UEFI, and the former might be useful +when dealing with, say, eCryptfs. + +Further, it might be desirable to provide formatted blobs that indicate +hardware is to be accessed to retrieve the keys or that the keys live +unretrievably in a hardware store, but that the keys can be used by means of +the hardware. + +From userspace, the keys can be loaded using the keyctl command, for example, +an X.509 binary certificate: + + keyctl padd asymmetric foo @s +--- + crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++- + include/keys/asymmetric-parser.h | 37 ++++++++++ + 2 files changed, 156 insertions(+), 1 deletion(-) + create mode 100644 include/keys/asymmetric-parser.h + +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +index bfb0424..cf80765 100644 +--- a/crypto/asymmetric_keys/asymmetric_type.c ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -11,6 +11,7 @@ + * 2 of the Licence, or (at your option) any later version. + */ + #include ++#include + #include + #include + #include +@@ -18,6 +19,9 @@ + + MODULE_LICENSE("GPL"); + ++static LIST_HEAD(asymmetric_key_parsers); ++static DECLARE_RWSEM(asymmetric_key_parsers_sem); ++ + /* + * Match asymmetric keys on (part of) their name + * We have some shorthand methods for matching keys. We allow: +@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) + } + + /* ++ * Preparse a asymmetric payload to get format the contents appropriately for the ++ * internal payload to cut down on the number of scans of the data performed. ++ * ++ * We also generate a proposed description from the contents of the key that ++ * can be used to name the key if the user doesn't want to provide one. ++ */ ++static int asymmetric_key_preparse(struct key_preparsed_payload *prep) ++{ ++ struct asymmetric_key_parser *parser; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (prep->datalen == 0) ++ return -EINVAL; ++ ++ down_read(&asymmetric_key_parsers_sem); ++ ++ ret = -EBADMSG; ++ list_for_each_entry(parser, &asymmetric_key_parsers, link) { ++ pr_debug("Trying parser '%s'\n", parser->name); ++ ++ ret = parser->parse(prep); ++ if (ret != -EBADMSG) { ++ pr_debug("Parser recognised the format (ret %d)\n", ++ ret); ++ break; ++ } ++ } ++ ++ up_read(&asymmetric_key_parsers_sem); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++ ++/* ++ * Clean up the preparse data ++ */ ++static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) ++{ ++ struct asymmetric_key_subtype *subtype = prep->type_data[0]; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (subtype) { ++ subtype->destroy(prep->payload); ++ module_put(subtype->owner); ++ } ++ kfree(prep->type_data[1]); ++ kfree(prep->description); ++} ++ ++/* + * Instantiate a asymmetric_key defined key. The key was preparsed, so we just + * have to transfer the data here. + */ + static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { +- return -EOPNOTSUPP; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ ret = key_payload_reserve(key, prep->quotalen); ++ if (ret == 0) { ++ key->type_data.p[0] = prep->type_data[0]; ++ key->type_data.p[1] = prep->type_data[1]; ++ key->payload.data = prep->payload; ++ prep->type_data[0] = NULL; ++ prep->type_data[1] = NULL; ++ prep->payload = NULL; ++ } ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; + } + + /* +@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) + + struct key_type key_type_asymmetric = { + .name = "asymmetric", ++ .preparse = asymmetric_key_preparse, ++ .free_preparse = asymmetric_key_free_preparse, + .instantiate = asymmetric_key_instantiate, + .match = asymmetric_key_match, + .destroy = asymmetric_key_destroy, +@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { + }; + EXPORT_SYMBOL_GPL(key_type_asymmetric); + ++/** ++ * register_asymmetric_key_parser - Register a asymmetric key blob parser ++ * @parser: The parser to register ++ */ ++int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) ++{ ++ struct asymmetric_key_parser *cursor; ++ int ret; ++ ++ down_write(&asymmetric_key_parsers_sem); ++ ++ list_for_each_entry(cursor, &asymmetric_key_parsers, link) { ++ if (strcmp(cursor->name, parser->name) == 0) { ++ pr_err("Asymmetric key parser '%s' already registered\n", ++ parser->name); ++ ret = -EEXIST; ++ goto out; ++ } ++ } ++ ++ list_add_tail(&parser->link, &asymmetric_key_parsers); ++ ++ pr_notice("Asymmetric key parser '%s' registered\n", parser->name); ++ ret = 0; ++ ++out: ++ up_write(&asymmetric_key_parsers_sem); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); ++ ++/** ++ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser ++ * @parser: The parser to unregister ++ */ ++void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) ++{ ++ down_write(&asymmetric_key_parsers_sem); ++ list_del(&parser->link); ++ up_write(&asymmetric_key_parsers_sem); ++ ++ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); ++} ++EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); ++ + /* + * Module stuff + */ +diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h +new file mode 100644 +index 0000000..09b3b48 +--- /dev/null ++++ b/include/keys/asymmetric-parser.h +@@ -0,0 +1,37 @@ ++/* Asymmetric public-key cryptography data parser ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_PARSER_H ++#define _KEYS_ASYMMETRIC_PARSER_H ++ ++/* ++ * Key data parser. Called during key instantiation. ++ */ ++struct asymmetric_key_parser { ++ struct list_head link; ++ struct module *owner; ++ const char *name; ++ ++ /* Attempt to parse a key from the data blob passed to add_key() or ++ * keyctl_instantiate(). Should also generate a proposed description ++ * that the caller can optionally use for the key. ++ * ++ * Return EBADMSG if not recognised. ++ */ ++ int (*parse)(struct key_preparsed_payload *prep); ++}; ++ ++extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); ++extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); ++ ++#endif /* _KEYS_ASYMMETRIC_PARSER_H */ +-- +1.7.11.4 + + +From 171881bb3693176db4d0f85f78066fcdb6266525 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:24:55 +0100 +Subject: [PATCH 07/26] KEYS: Asymmetric public-key algorithm crypto key + subtype + +Add a subtype for supporting asymmetric public-key encryption algorithms such +as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 8 +++ + crypto/asymmetric_keys/Makefile | 2 + + crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/public_key.h | 28 ++++++++++ + include/crypto/public_key.h | 104 ++++++++++++++++++++++++++++++++++ + 5 files changed, 250 insertions(+) + create mode 100644 crypto/asymmetric_keys/public_key.c + create mode 100644 crypto/asymmetric_keys/public_key.h + create mode 100644 include/crypto/public_key.h + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index cad29b3..bbfccaa 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE + + if ASYMMETRIC_KEY_TYPE + ++config ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ tristate "Asymmetric public-key crypto algorithm subtype" ++ select MPILIB ++ help ++ This option provides support for asymmetric public key type handling. ++ If signature generation and/or verification are to be used, ++ appropriate hash algorithms (such as SHA-1) must be available. ++ ENOPKG will be reported if the requisite algorithm is unavailable. + + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index b725bcc..5ed46ee 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -5,3 +5,5 @@ + obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + + asymmetric_keys-y := asymmetric_type.o ++ ++obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +new file mode 100644 +index 0000000..cb2e291 +--- /dev/null ++++ b/crypto/asymmetric_keys/public_key.c +@@ -0,0 +1,108 @@ ++/* In-software asymmetric public-key crypto subtype ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PKEY: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include "public_key.h" ++ ++MODULE_LICENSE("GPL"); ++ ++const char *const pkey_algo[PKEY_ALGO__LAST] = { ++ [PKEY_ALGO_DSA] = "DSA", ++ [PKEY_ALGO_RSA] = "RSA", ++}; ++EXPORT_SYMBOL_GPL(pkey_algo); ++ ++const char *const pkey_hash_algo[PKEY_HASH__LAST] = { ++ [PKEY_HASH_MD4] = "md4", ++ [PKEY_HASH_MD5] = "md5", ++ [PKEY_HASH_SHA1] = "sha1", ++ [PKEY_HASH_RIPE_MD_160] = "rmd160", ++ [PKEY_HASH_SHA256] = "sha256", ++ [PKEY_HASH_SHA384] = "sha384", ++ [PKEY_HASH_SHA512] = "sha512", ++ [PKEY_HASH_SHA224] = "sha224", ++}; ++EXPORT_SYMBOL_GPL(pkey_hash_algo); ++ ++const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { ++ [PKEY_ID_PGP] = "PGP", ++ [PKEY_ID_X509] = "X509", ++}; ++EXPORT_SYMBOL_GPL(pkey_id_type); ++ ++/* ++ * Provide a part of a description of the key for /proc/keys. ++ */ ++static void public_key_describe(const struct key *asymmetric_key, ++ struct seq_file *m) ++{ ++ struct public_key *key = asymmetric_key->payload.data; ++ ++ if (key) ++ seq_printf(m, "%s.%s", ++ pkey_id_type[key->id_type], key->algo->name); ++} ++ ++/* ++ * Destroy a public key algorithm key. ++ */ ++void public_key_destroy(void *payload) ++{ ++ struct public_key *key = payload; ++ int i; ++ ++ if (key) { ++ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) ++ mpi_free(key->mpi[i]); ++ kfree(key); ++ } ++} ++EXPORT_SYMBOL_GPL(public_key_destroy); ++ ++/* ++ * Verify a signature using a public key. ++ */ ++static int public_key_verify_signature(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct public_key *pk = key->payload.data; ++ ++ if (!pk->algo->verify_signature) ++ return -ENOTSUPP; ++ ++ if (sig->nr_mpi != pk->algo->n_sig_mpi) { ++ pr_debug("Signature has %u MPI not %u\n", ++ sig->nr_mpi, pk->algo->n_sig_mpi); ++ return -EINVAL; ++ } ++ ++ return pk->algo->verify_signature(pk, sig); ++} ++ ++/* ++ * Public key algorithm asymmetric key subtype ++ */ ++struct asymmetric_key_subtype public_key_subtype = { ++ .owner = THIS_MODULE, ++ .name = "public_key", ++ .describe = public_key_describe, ++ .destroy = public_key_destroy, ++ .verify_signature = public_key_verify_signature, ++}; ++EXPORT_SYMBOL_GPL(public_key_subtype); +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +new file mode 100644 +index 0000000..1f86aad +--- /dev/null ++++ b/crypto/asymmetric_keys/public_key.h +@@ -0,0 +1,28 @@ ++/* Public key algorithm internals ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++ ++extern struct asymmetric_key_subtype public_key_subtype; ++ ++/* ++ * Public key algorithm definition. ++ */ ++struct public_key_algorithm { ++ const char *name; ++ u8 n_pub_mpi; /* Number of MPIs in public key */ ++ u8 n_sec_mpi; /* Number of MPIs in secret key */ ++ u8 n_sig_mpi; /* Number of MPIs in a signature */ ++ int (*verify_signature)(const struct public_key *key, ++ const struct public_key_signature *sig); ++}; +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +new file mode 100644 +index 0000000..4b8b6c1 +--- /dev/null ++++ b/include/crypto/public_key.h +@@ -0,0 +1,104 @@ ++/* Asymmetric public-key algorithm definitions ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_PUBLIC_KEY_H ++#define _LINUX_PUBLIC_KEY_H ++ ++#include ++ ++enum pkey_algo { ++ PKEY_ALGO_DSA, ++ PKEY_ALGO_RSA, ++ PKEY_ALGO__LAST ++}; ++ ++extern const char *const pkey_algo[PKEY_ALGO__LAST]; ++ ++enum pkey_hash_algo { ++ PKEY_HASH_MD4, ++ PKEY_HASH_MD5, ++ PKEY_HASH_SHA1, ++ PKEY_HASH_RIPE_MD_160, ++ PKEY_HASH_SHA256, ++ PKEY_HASH_SHA384, ++ PKEY_HASH_SHA512, ++ PKEY_HASH_SHA224, ++ PKEY_HASH__LAST ++}; ++ ++extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; ++ ++enum pkey_id_type { ++ PKEY_ID_PGP, /* OpenPGP generated key ID */ ++ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ ++ PKEY_ID_TYPE__LAST ++}; ++ ++extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; ++ ++/* ++ * Cryptographic data for the public-key subtype of the asymmetric key type. ++ * ++ * Note that this may include private part of the key as well as the public ++ * part. ++ */ ++struct public_key { ++ const struct public_key_algorithm *algo; ++ u8 capabilities; ++#define PKEY_CAN_ENCRYPT 0x01 ++#define PKEY_CAN_DECRYPT 0x02 ++#define PKEY_CAN_SIGN 0x04 ++#define PKEY_CAN_VERIFY 0x08 ++ enum pkey_id_type id_type : 8; ++ union { ++ MPI mpi[5]; ++ struct { ++ MPI p; /* DSA prime */ ++ MPI q; /* DSA group order */ ++ MPI g; /* DSA group generator */ ++ MPI y; /* DSA public-key value = g^x mod p */ ++ MPI x; /* DSA secret exponent (if present) */ ++ } dsa; ++ struct { ++ MPI n; /* RSA public modulus */ ++ MPI e; /* RSA public encryption exponent */ ++ MPI d; /* RSA secret encryption exponent (if present) */ ++ MPI p; /* RSA secret prime (if present) */ ++ MPI q; /* RSA secret prime (if present) */ ++ } rsa; ++ }; ++}; ++ ++extern void public_key_destroy(void *payload); ++ ++/* ++ * Public key cryptography signature data ++ */ ++struct public_key_signature { ++ u8 *digest; ++ u8 digest_size; /* Number of bytes in digest */ ++ u8 nr_mpi; /* Occupancy of mpi[] */ ++ enum pkey_hash_algo pkey_hash_algo : 8; ++ union { ++ MPI mpi[2]; ++ struct { ++ MPI s; /* m^d mod n */ ++ } rsa; ++ struct { ++ MPI r; ++ MPI s; ++ } dsa; ++ }; ++}; ++ ++#endif /* _LINUX_PUBLIC_KEY_H */ +-- +1.7.11.4 + + +From 8e45e274bb3f8bb90306e0102a2c48ea1ef179fb Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:04 +0100 +Subject: [PATCH 08/26] KEYS: Provide signature verification with an + asymmetric key + +Provide signature verification using an asymmetric-type key to indicate the +public key to be used. + +The API is a single function that can be found in crypto/public_key.h: + + int verify_signature(const struct key *key, + const struct public_key_signature *sig) + +The first argument is the appropriate key to be used and the second argument +is the parsed signature data: + + struct public_key_signature { + u8 *digest; + u16 digest_size; + enum pkey_hash_algo pkey_hash_algo : 8; + union { + MPI mpi[2]; + struct { + MPI s; /* m^d mod n */ + } rsa; + struct { + MPI r; + MPI s; + } dsa; + }; + }; + +This should be filled in prior to calling the function. The hash algorithm +should already have been called and the hash finalised and the output should +be in a buffer pointed to by the 'digest' member. + +Any extra data to be added to the hash by the hash format (eg. PGP) should +have been added by the caller prior to finalising the hash. + +It is assumed that the signature is made up of a number of MPI values. If an +algorithm becomes available for which this is not the case, the above structure +will have to change. + +It is also assumed that it will have been checked that the signature algorithm +matches the key algorithm. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Makefile | 2 +- + crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++ + include/crypto/public_key.h | 4 ++++ + 3 files changed, 54 insertions(+), 1 deletion(-) + create mode 100644 crypto/asymmetric_keys/signature.c + +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 5ed46ee..8dcdf0c 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -4,6 +4,6 @@ + + obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + +-asymmetric_keys-y := asymmetric_type.o ++asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c +new file mode 100644 +index 0000000..50b3f88 +--- /dev/null ++++ b/crypto/asymmetric_keys/signature.c +@@ -0,0 +1,49 @@ ++/* Signature verification with an asymmetric key ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++ ++/** ++ * verify_signature - Initiate the use of an asymmetric key to verify a signature ++ * @key: The asymmetric key to verify against ++ * @sig: The signature to check ++ * ++ * Returns 0 if successful or else an error. ++ */ ++int verify_signature(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct asymmetric_key_subtype *subtype; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (key->type != &key_type_asymmetric) ++ return -EINVAL; ++ subtype = asymmetric_key_subtype(key); ++ if (!subtype || ++ !key->payload.data) ++ return -EINVAL; ++ if (!subtype->verify_signature) ++ return -ENOTSUPP; ++ ++ ret = subtype->verify_signature(key, sig); ++ ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(verify_signature); +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 4b8b6c1..f5b0224 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -101,4 +101,8 @@ struct public_key_signature { + }; + }; + ++struct key; ++extern int verify_signature(const struct key *key, ++ const struct public_key_signature *sig); ++ + #endif /* _LINUX_PUBLIC_KEY_H */ +-- +1.7.11.4 + + +From 941e72448fc68f41a56798112a6f20df6bcd0ad0 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:22 +0100 +Subject: [PATCH 09/26] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA + signature verification + +Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by +RSA signature verification as per RFC3447 section 5.2.2 step 1. + +Signed-off-by: David Howells +--- + lib/mpi/Makefile | 1 + + lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 71 insertions(+) + create mode 100644 lib/mpi/mpi-cmp.c + +diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile +index 45ca90a..019a68c 100644 +--- a/lib/mpi/Makefile ++++ b/lib/mpi/Makefile +@@ -14,6 +14,7 @@ mpi-y = \ + generic_mpih-add1.o \ + mpicoder.o \ + mpi-bit.o \ ++ mpi-cmp.o \ + mpih-cmp.o \ + mpih-div.o \ + mpih-mul.o \ +diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c +new file mode 100644 +index 0000000..1871e7b +--- /dev/null ++++ b/lib/mpi/mpi-cmp.c +@@ -0,0 +1,70 @@ ++/* mpi-cmp.c - MPI functions ++ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. ++ * ++ * This file is part of GnuPG. ++ * ++ * GnuPG is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * GnuPG 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ */ ++ ++#include "mpi-internal.h" ++ ++int mpi_cmp_ui(MPI u, unsigned long v) ++{ ++ mpi_limb_t limb = v; ++ ++ mpi_normalize(u); ++ if (!u->nlimbs && !limb) ++ return 0; ++ if (u->sign) ++ return -1; ++ if (u->nlimbs > 1) ++ return 1; ++ ++ if (u->d[0] == limb) ++ return 0; ++ else if (u->d[0] > limb) ++ return 1; ++ else ++ return -1; ++} ++EXPORT_SYMBOL_GPL(mpi_cmp_ui); ++ ++int mpi_cmp(MPI u, MPI v) ++{ ++ mpi_size_t usize, vsize; ++ int cmp; ++ ++ mpi_normalize(u); ++ mpi_normalize(v); ++ usize = u->nlimbs; ++ vsize = v->nlimbs; ++ if (!u->sign && v->sign) ++ return 1; ++ if (u->sign && !v->sign) ++ return -1; ++ if (usize != vsize && !u->sign && !v->sign) ++ return usize - vsize; ++ if (usize != vsize && u->sign && v->sign) ++ return vsize + usize; ++ if (!usize) ++ return 0; ++ cmp = mpihelp_cmp(u->d, v->d, usize); ++ if (!cmp) ++ return 0; ++ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) ++ return 1; ++ return -1; ++} ++EXPORT_SYMBOL_GPL(mpi_cmp); +-- +1.7.11.4 + + +From ca876ff8fde3c6febb8a8578ca0e1608576071bf Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:40 +0100 +Subject: [PATCH 10/26] RSA: Implement signature verification algorithm + [PKCS#1 / RFC3447] + +Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only +the signature verification algorithm is supported. This uses the asymmetric +public key subtype to hold its key data. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 7 + + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/public_key.h | 2 + + crypto/asymmetric_keys/rsa.c | 269 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 279 insertions(+) + create mode 100644 crypto/asymmetric_keys/rsa.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index bbfccaa..561759d 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE + appropriate hash algorithms (such as SHA-1) must be available. + ENOPKG will be reported if the requisite algorithm is unavailable. + ++config PUBLIC_KEY_ALGO_RSA ++ tristate "RSA public-key algorithm" ++ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select MPILIB_EXTRA ++ help ++ This option enables support for the RSA algorithm (PKCS#1, RFC3447). ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 8dcdf0c..7c92691 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o ++obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +index 1f86aad..5e5e356 100644 +--- a/crypto/asymmetric_keys/public_key.h ++++ b/crypto/asymmetric_keys/public_key.h +@@ -26,3 +26,5 @@ struct public_key_algorithm { + int (*verify_signature)(const struct public_key *key, + const struct public_key_signature *sig); + }; ++ ++extern const struct public_key_algorithm RSA_public_key_algorithm; +diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c +new file mode 100644 +index 0000000..9b31ee2 +--- /dev/null ++++ b/crypto/asymmetric_keys/rsa.c +@@ -0,0 +1,269 @@ ++/* RSA asymmetric public-key algorithm [RFC3447] ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "RSA: "fmt ++#include ++#include ++#include ++#include "public_key.h" ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("RSA Public Key Algorithm"); ++ ++#define kenter(FMT, ...) \ ++ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) ++#define kleave(FMT, ...) \ ++ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) ++ ++/* ++ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. ++ */ ++static const u8 RSA_digest_info_MD5[] = { ++ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, ++ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ ++ 0x05, 0x00, 0x04, 0x10 ++}; ++ ++static const u8 RSA_digest_info_SHA1[] = { ++ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, ++ 0x2B, 0x0E, 0x03, 0x02, 0x1A, ++ 0x05, 0x00, 0x04, 0x14 ++}; ++ ++static const u8 RSA_digest_info_RIPE_MD_160[] = { ++ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, ++ 0x2B, 0x24, 0x03, 0x02, 0x01, ++ 0x05, 0x00, 0x04, 0x14 ++}; ++ ++static const u8 RSA_digest_info_SHA224[] = { ++ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, ++ 0x05, 0x00, 0x04, 0x1C ++}; ++ ++static const u8 RSA_digest_info_SHA256[] = { ++ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, ++ 0x05, 0x00, 0x04, 0x20 ++}; ++ ++static const u8 RSA_digest_info_SHA384[] = { ++ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, ++ 0x05, 0x00, 0x04, 0x30 ++}; ++ ++static const u8 RSA_digest_info_SHA512[] = { ++ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, ++ 0x05, 0x00, 0x04, 0x40 ++}; ++ ++static const struct { ++ const u8 *data; ++ size_t size; ++} RSA_ASN1_templates[PKEY_HASH__LAST] = { ++#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } ++ [PKEY_HASH_MD5] = _(MD5), ++ [PKEY_HASH_SHA1] = _(SHA1), ++ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), ++ [PKEY_HASH_SHA256] = _(SHA256), ++ [PKEY_HASH_SHA384] = _(SHA384), ++ [PKEY_HASH_SHA512] = _(SHA512), ++ [PKEY_HASH_SHA224] = _(SHA224), ++#undef _ ++}; ++ ++/* ++ * RSAVP1() function [RFC3447 sec 5.2.2] ++ */ ++static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) ++{ ++ MPI m; ++ int ret; ++ ++ /* (1) Validate 0 <= s < n */ ++ if (mpi_cmp_ui(s, 0) < 0) { ++ kleave(" = -EBADMSG [s < 0]"); ++ return -EBADMSG; ++ } ++ if (mpi_cmp(s, key->rsa.n) >= 0) { ++ kleave(" = -EBADMSG [s >= n]"); ++ return -EBADMSG; ++ } ++ ++ m = mpi_alloc(0); ++ if (!m) ++ return -ENOMEM; ++ ++ /* (2) m = s^e mod n */ ++ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); ++ if (ret < 0) { ++ mpi_free(m); ++ return ret; ++ } ++ ++ *_m = m; ++ return 0; ++} ++ ++/* ++ * Integer to Octet String conversion [RFC3447 sec 4.1] ++ */ ++static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) ++{ ++ unsigned X_size, x_size; ++ int X_sign; ++ u8 *X; ++ ++ /* Make sure the string is the right length. The number should begin ++ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero ++ * bits not being reported by MPI. ++ */ ++ x_size = mpi_get_nbits(x); ++ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); ++ if (x_size != xLen * 8 - 15) ++ return -ERANGE; ++ ++ X = mpi_get_buffer(x, &X_size, &X_sign); ++ if (!X) ++ return -ENOMEM; ++ if (X_sign < 0) { ++ kfree(X); ++ return -EBADMSG; ++ } ++ if (X_size != xLen - 1) { ++ kfree(X); ++ return -EBADMSG; ++ } ++ ++ *_X = X; ++ return 0; ++} ++ ++/* ++ * Perform the RSA signature verification. ++ * @H: Value of hash of data and metadata ++ * @EM: The computed signature value ++ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) ++ * @hash_size: The size of H ++ * @asn1_template: The DigestInfo ASN.1 template ++ * @asn1_size: Size of asm1_template[] ++ */ ++static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, ++ const u8 *asn1_template, size_t asn1_size) ++{ ++ unsigned PS_end, T_offset, i; ++ ++ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); ++ ++ if (k < 2 + 1 + asn1_size + hash_size) ++ return -EBADMSG; ++ ++ /* Decode the EMSA-PKCS1-v1_5 */ ++ if (EM[1] != 0x01) { ++ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); ++ return -EBADMSG; ++ } ++ ++ T_offset = k - (asn1_size + hash_size); ++ PS_end = T_offset - 1; ++ if (EM[PS_end] != 0x00) { ++ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); ++ return -EBADMSG; ++ } ++ ++ for (i = 2; i < PS_end; i++) { ++ if (EM[i] != 0xff) { ++ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); ++ return -EBADMSG; ++ } ++ } ++ ++ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { ++ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); ++ return -EBADMSG; ++ } ++ ++ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { ++ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); ++ return -EKEYREJECTED; ++ } ++ ++ kleave(" = 0"); ++ return 0; ++} ++ ++/* ++ * Perform the verification step [RFC3447 sec 8.2.2]. ++ */ ++static int RSA_verify_signature(const struct public_key *key, ++ const struct public_key_signature *sig) ++{ ++ size_t tsize; ++ int ret; ++ ++ /* Variables as per RFC3447 sec 8.2.2 */ ++ const u8 *H = sig->digest; ++ u8 *EM = NULL; ++ MPI m = NULL; ++ size_t k; ++ ++ kenter(""); ++ ++ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) ++ return -ENOTSUPP; ++ ++ /* (1) Check the signature size against the public key modulus size */ ++ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; ++ ++ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; ++ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); ++ if (tsize != k) { ++ ret = -EBADMSG; ++ goto error; ++ } ++ ++ /* (2b) Apply the RSAVP1 verification primitive to the public key */ ++ ret = RSAVP1(key, sig->rsa.s, &m); ++ if (ret < 0) ++ goto error; ++ ++ /* (2c) Convert the message representative (m) to an encoded message ++ * (EM) of length k octets. ++ * ++ * NOTE! The leading zero byte is suppressed by MPI, so we pass a ++ * pointer to the _preceding_ byte to RSA_verify()! ++ */ ++ ret = RSA_I2OSP(m, k, &EM); ++ if (ret < 0) ++ goto error; ++ ++ ret = RSA_verify(H, EM - 1, k, sig->digest_size, ++ RSA_ASN1_templates[sig->pkey_hash_algo].data, ++ RSA_ASN1_templates[sig->pkey_hash_algo].size); ++ ++error: ++ kfree(EM); ++ mpi_free(m); ++ kleave(" = %d", ret); ++ return ret; ++} ++ ++const struct public_key_algorithm RSA_public_key_algorithm = { ++ .name = "RSA", ++ .n_pub_mpi = 2, ++ .n_sec_mpi = 3, ++ .n_sig_mpi = 1, ++ .verify_signature = RSA_verify_signature, ++}; ++EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); +-- +1.7.11.4 + + +From e179a9b04469ea018a8fdb53f11c57222ba540a0 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:28:05 +0100 +Subject: [PATCH 11/26] RSA: Fix signature verification for shorter signatures + +gpg can produce a signature file where length of signature is less than the +modulus size because the amount of space an MPI takes up is kept as low as +possible by discarding leading zeros. This regularly happens for several +modules during the build. + +Fix it by relaxing check in RSA verification code. + +Thanks to Tomas Mraz and Miloslav Trmac for help. + +Signed-off-by: Milan Broz +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/rsa.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c +index 9b31ee2..4a6a069 100644 +--- a/crypto/asymmetric_keys/rsa.c ++++ b/crypto/asymmetric_keys/rsa.c +@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key, + return -ENOTSUPP; + + /* (1) Check the signature size against the public key modulus size */ +- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; ++ k = mpi_get_nbits(key->rsa.n); ++ tsize = mpi_get_nbits(sig->rsa.s); + +- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; ++ /* According to RFC 4880 sec 3.2, length of MPI is computed starting ++ * from most significant bit. So the RFC 3447 sec 8.2.2 size check ++ * must be relaxed to conform with shorter signatures - so we fail here ++ * only if signature length is longer than modulus size. ++ */ + pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); +- if (tsize != k) { ++ if (k < tsize) { + ret = -EBADMSG; + goto error; + } + ++ /* Round up and convert to octets */ ++ k = (k + 7) / 8; ++ + /* (2b) Apply the RSAVP1 verification primitive to the public key */ + ret = RSAVP1(key, sig->rsa.s, &m); + if (ret < 0) +-- +1.7.11.4 + + +From d412c256ea6170b6aeceb9f1eb1737d991473634 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:30:46 +0100 +Subject: [PATCH 12/26] X.509: Implement simple static OID registry + +Implement a simple static OID registry that allows the mapping of an encoded +OID to an enum value for ease of use. + +The OID registry index enum appears in the: + + linux/oid_registry.h + +header file. A script generates the registry from lines in the header file +that look like: + + OID_foo,/*1.2.3.4*/ + +The actual OID is taken to be represented by the numbers with interpolated +dots in the comment. + +All other lines in the header are ignored. + +The registry is queries by calling: + + OID look_up_oid(const void *data, size_t datasize); + +This returns a number from the registry enum representing the OID if found or +OID__NR if not. + +Signed-off-by: David Howells +--- + include/linux/oid_registry.h | 90 +++++++++++++++++++ + lib/.gitignore | 2 +- + lib/Kconfig | 5 ++ + lib/Makefile | 16 ++++ + lib/build_OID_registry | 209 +++++++++++++++++++++++++++++++++++++++++++ + lib/oid_registry.c | 89 ++++++++++++++++++ + 6 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 include/linux/oid_registry.h + create mode 100755 lib/build_OID_registry + create mode 100644 lib/oid_registry.c + +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +new file mode 100644 +index 0000000..5928546 +--- /dev/null ++++ b/include/linux/oid_registry.h +@@ -0,0 +1,90 @@ ++/* ASN.1 Object identifier (OID) registry ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_OID_REGISTRY_H ++#define _LINUX_OID_REGISTRY_H ++ ++#include ++ ++/* ++ * OIDs are turned into these values if possible, or OID__NR if not held here. ++ * ++ * NOTE! Do not mess with the format of each line as this is read by ++ * build_OID_registry.pl to generate the data for look_up_OID(). ++ */ ++enum OID { ++ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ ++ OID_id_dsa, /* 1.2.840.10040.4.1 */ ++ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ ++ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ ++ ++ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ ++ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ ++ OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ ++ OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ ++ OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ ++ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ ++ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ ++ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ ++ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ ++ OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ ++ /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ ++ OID_data, /* 1.2.840.113549.1.7.1 */ ++ OID_signed_data, /* 1.2.840.113549.1.7.2 */ ++ /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ ++ OID_email_address, /* 1.2.840.113549.1.9.1 */ ++ OID_content_type, /* 1.2.840.113549.1.9.3 */ ++ OID_messageDigest, /* 1.2.840.113549.1.9.4 */ ++ OID_signingTime, /* 1.2.840.113549.1.9.5 */ ++ OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ ++ OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ ++ ++ /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ ++ OID_md2, /* 1.2.840.113549.2.2 */ ++ OID_md4, /* 1.2.840.113549.2.4 */ ++ OID_md5, /* 1.2.840.113549.2.5 */ ++ ++ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ ++ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ ++ OID_sha1, /* 1.3.14.3.2.26 */ ++ ++ /* Distinguished Name attribute IDs [RFC 2256] */ ++ OID_commonName, /* 2.5.4.3 */ ++ OID_surname, /* 2.5.4.4 */ ++ OID_countryName, /* 2.5.4.6 */ ++ OID_locality, /* 2.5.4.7 */ ++ OID_stateOrProvinceName, /* 2.5.4.8 */ ++ OID_organizationName, /* 2.5.4.10 */ ++ OID_organizationUnitName, /* 2.5.4.11 */ ++ OID_title, /* 2.5.4.12 */ ++ OID_description, /* 2.5.4.13 */ ++ OID_name, /* 2.5.4.41 */ ++ OID_givenName, /* 2.5.4.42 */ ++ OID_initials, /* 2.5.4.43 */ ++ OID_generationalQualifier, /* 2.5.4.44 */ ++ ++ /* Certificate extension IDs */ ++ OID_subjectKeyIdentifier, /* 2.5.29.14 */ ++ OID_keyUsage, /* 2.5.29.15 */ ++ OID_subjectAltName, /* 2.5.29.17 */ ++ OID_issuerAltName, /* 2.5.29.18 */ ++ OID_basicConstraints, /* 2.5.29.19 */ ++ OID_crlDistributionPoints, /* 2.5.29.31 */ ++ OID_certPolicies, /* 2.5.29.32 */ ++ OID_authorityKeyIdentifier, /* 2.5.29.35 */ ++ OID_extKeyUsage, /* 2.5.29.37 */ ++ ++ OID__NR ++}; ++ ++extern enum OID look_up_OID(const void *data, size_t datasize); ++ ++#endif /* _LINUX_OID_REGISTRY_H */ +diff --git a/lib/.gitignore b/lib/.gitignore +index 3bef1ea..09aae85 100644 +--- a/lib/.gitignore ++++ b/lib/.gitignore +@@ -3,4 +3,4 @@ + # + gen_crc32table + crc32table.h +- ++oid_registry_data.c +diff --git a/lib/Kconfig b/lib/Kconfig +index bb94c1b..4b31a46 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -396,4 +396,9 @@ config SIGNATURE + config LIBFDT + bool + ++config OID_REGISTRY ++ tristate ++ help ++ Enable fast lookup object identifier registry. ++ + endmenu +diff --git a/lib/Makefile b/lib/Makefile +index 42d283e..b042896 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN $@ + + $(obj)/crc32table.h: $(obj)/gen_crc32table + $(call cmd,crc32) ++ ++# ++# Build a fast OID lookip registry from include/linux/oid_registry.h ++# ++obj-$(CONFIG_OID_REGISTRY) += oid_registry.o ++ ++$(obj)/oid_registry.c: $(obj)/oid_registry_data.c ++ ++$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ ++ $(src)/build_OID_registry ++ $(call cmd,build_OID_registry) ++ ++quiet_cmd_build_OID_registry = GEN $@ ++ cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ ++ ++clean-files += oid_registry_data.c +diff --git a/lib/build_OID_registry b/lib/build_OID_registry +new file mode 100755 +index 0000000..dfbdaab +--- /dev/null ++++ b/lib/build_OID_registry +@@ -0,0 +1,209 @@ ++#!/usr/bin/perl -w ++# ++# Build a static ASN.1 Object Identified (OID) registry ++# ++# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++# Written by David Howells (dhowells@redhat.com) ++# ++# This program is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public Licence ++# as published by the Free Software Foundation; either version ++# 2 of the Licence, or (at your option) any later version. ++# ++ ++use strict; ++ ++my @names = (); ++my @oids = (); ++ ++if ($#ARGV != 1) { ++ print STDERR "Format: ", $0, " \n"; ++ exit(2); ++} ++ ++# ++# Open the file to read from ++# ++open IN_FILE, "<$ARGV[0]" || die; ++while () { ++ chomp; ++ if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { ++ push @names, $1; ++ push @oids, $2; ++ } ++} ++close IN_FILE || die; ++ ++# ++# Open the files to write into ++# ++open C_FILE, ">$ARGV[1]" or die; ++print C_FILE "/*\n"; ++print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; ++print C_FILE " */\n"; ++ ++# ++# Split the data up into separate lists and also determine the lengths of the ++# encoded data arrays. ++# ++my @indices = (); ++my @lengths = (); ++my $total_length = 0; ++ ++print "Compiling ", $#names + 1, " OIDs\n"; ++ ++for (my $i = 0; $i <= $#names; $i++) { ++ my $name = $names[$i]; ++ my $oid = $oids[$i]; ++ ++ my @components = split(/[.]/, $oid); ++ ++ # Determine the encoded length of this OID ++ my $size = $#components; ++ for (my $loop = 2; $loop <= $#components; $loop++) { ++ my $c = $components[$loop]; ++ ++ # We will base128 encode the number ++ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); ++ $tmp = int($tmp / 7); ++ $size += $tmp; ++ } ++ push @lengths, $size; ++ push @indices, $total_length; ++ $total_length += $size; ++} ++ ++# ++# Emit the look-up-by-OID index table ++# ++print C_FILE "\n"; ++if ($total_length <= 255) { ++ print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; ++} else { ++ print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; ++} ++for (my $i = 0; $i <= $#names; $i++) { ++ print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" ++} ++print C_FILE "\t[OID__NR] = ", $total_length, "\n"; ++print C_FILE "};\n"; ++ ++# ++# Encode the OIDs ++# ++my @encoded_oids = (); ++ ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = (); ++ ++ my @components = split(/[.]/, $oids[$i]); ++ ++ push @octets, $components[0] * 40 + $components[1]; ++ ++ for (my $loop = 2; $loop <= $#components; $loop++) { ++ my $c = $components[$loop]; ++ ++ # Base128 encode the number ++ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); ++ $tmp = int($tmp / 7); ++ ++ for (; $tmp > 0; $tmp--) { ++ push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; ++ } ++ push @octets, $c & 0x7f; ++ } ++ ++ push @encoded_oids, \@octets; ++} ++ ++# ++# Create a hash value for each OID ++# ++my @hash_values = (); ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$i]}; ++ ++ my $hash = $#octets; ++ foreach (@octets) { ++ $hash += $_ * 33; ++ } ++ ++ $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); ++ ++ push @hash_values, $hash & 0xff; ++} ++ ++# ++# Emit the OID data ++# ++print C_FILE "\n"; ++print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$i]}; ++ print C_FILE "\t"; ++ print C_FILE $_, ", " foreach (@octets); ++ print C_FILE "\t// ", $names[$i]; ++ print C_FILE "\n"; ++} ++print C_FILE "};\n"; ++ ++# ++# Build the search index table (ordered by length then hash then content) ++# ++my @index_table = ( 0 .. $#names ); ++ ++@index_table = sort { ++ my @octets_a = @{$encoded_oids[$a]}; ++ my @octets_b = @{$encoded_oids[$b]}; ++ ++ return $hash_values[$a] <=> $hash_values[$b] ++ if ($hash_values[$a] != $hash_values[$b]); ++ return $#octets_a <=> $#octets_b ++ if ($#octets_a != $#octets_b); ++ for (my $i = $#octets_a; $i >= 0; $i--) { ++ return $octets_a[$i] <=> $octets_b[$i] ++ if ($octets_a[$i] != $octets_b[$i]); ++ } ++ return 0; ++ ++} @index_table; ++ ++# ++# Emit the search index and hash value table ++# ++print C_FILE "\n"; ++print C_FILE "static const struct {\n"; ++print C_FILE "\tunsigned char hash;\n"; ++if ($#names <= 255) { ++ print C_FILE "\tenum OID oid : 8;\n"; ++} else { ++ print C_FILE "\tenum OID oid : 16;\n"; ++} ++print C_FILE "} oid_search_table[OID__NR] = {\n"; ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$index_table[$i]]}; ++ printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", ++ $i, ++ $hash_values[$index_table[$i]], ++ $names[$index_table[$i]]); ++ printf C_FILE "%02x", $_ foreach (@octets); ++ print C_FILE "\n"; ++} ++print C_FILE "};\n"; ++ ++# ++# Emit the OID debugging name table ++# ++#print C_FILE "\n"; ++#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; ++# ++#for (my $i = 0; $i <= $#names; $i++) { ++# print C_FILE "\t\"", $names[$i], "\",\n" ++#} ++#print C_FILE "\t\"Unknown-OID\"\n"; ++#print C_FILE "};\n"; ++ ++# ++# Polish off ++# ++close C_FILE or die; +diff --git a/lib/oid_registry.c b/lib/oid_registry.c +new file mode 100644 +index 0000000..33cfd17 +--- /dev/null ++++ b/lib/oid_registry.c +@@ -0,0 +1,89 @@ ++/* ASN.1 Object identifier (OID) registry ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include "oid_registry_data.c" ++ ++/** ++ * look_up_OID - Find an OID registration for the specified data ++ * @data: Binary representation of the OID ++ * @datasize: Size of the binary representation ++ */ ++enum OID look_up_OID(const void *data, size_t datasize) ++{ ++ const unsigned char *octets = data; ++ enum OID oid; ++ unsigned char xhash; ++ unsigned i, j, k, hash; ++ size_t len; ++ ++ /* Hash the OID data */ ++ hash = datasize - 1; ++ ++ for (i = 0; i < datasize; i++) ++ hash += octets[i] * 33; ++ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; ++ hash &= 0xff; ++ ++ /* Binary search the OID registry. OIDs are stored in ascending order ++ * of hash value then ascending order of size and then in ascending ++ * order of reverse value. ++ */ ++ i = 0; ++ k = OID__NR; ++ while (i < k) { ++ j = (i + k) / 2; ++ ++ xhash = oid_search_table[j].hash; ++ if (xhash > hash) { ++ k = j; ++ continue; ++ } ++ if (xhash < hash) { ++ i = j + 1; ++ continue; ++ } ++ ++ oid = oid_search_table[j].oid; ++ len = oid_index[oid + 1] - oid_index[oid]; ++ if (len > datasize) { ++ k = j; ++ continue; ++ } ++ if (len < datasize) { ++ i = j + 1; ++ continue; ++ } ++ ++ /* Variation is most likely to be at the tail end of the ++ * OID, so do the comparison in reverse. ++ */ ++ while (len > 0) { ++ unsigned char a = oid_data[oid_index[oid] + --len]; ++ unsigned char b = octets[len]; ++ if (a > b) { ++ k = j; ++ goto next; ++ } ++ if (a < b) { ++ i = j + 1; ++ goto next; ++ } ++ } ++ return oid; ++ next: ++ ; ++ } ++ ++ return OID__NR; ++} ++EXPORT_SYMBOL_GPL(look_up_OID); +-- +1.7.11.4 + + +From 098335ed1edc5ec7ae7a346416654e12bb9bcd65 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:30:51 +0100 +Subject: [PATCH 13/26] X.509: Add utility functions to render OIDs as strings + +Add a pair of utility functions to render OIDs as strings. The first takes an +encoded OID and turns it into a "a.b.c.d" form string: + + int sprint_oid(const void *data, size_t datasize, + char *buffer, size_t bufsize); + +The second takes an OID enum index and calls the first on the data held +therein: + + int sprint_OID(enum OID oid, char *buffer, size_t bufsize); + +Signed-off-by: David Howells +--- + include/linux/oid_registry.h | 2 ++ + lib/oid_registry.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 83 insertions(+) + +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +index 5928546..6926db7 100644 +--- a/include/linux/oid_registry.h ++++ b/include/linux/oid_registry.h +@@ -86,5 +86,7 @@ enum OID { + }; + + extern enum OID look_up_OID(const void *data, size_t datasize); ++extern int sprint_oid(const void *, size_t, char *, size_t); ++extern int sprint_OID(enum OID, char *, size_t); + + #endif /* _LINUX_OID_REGISTRY_H */ +diff --git a/lib/oid_registry.c b/lib/oid_registry.c +index 33cfd17..d8de11f 100644 +--- a/lib/oid_registry.c ++++ b/lib/oid_registry.c +@@ -11,6 +11,9 @@ + + #include + #include ++#include ++#include ++#include + #include "oid_registry_data.c" + + /** +@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize) + return OID__NR; + } + EXPORT_SYMBOL_GPL(look_up_OID); ++ ++/* ++ * sprint_OID - Print an Object Identifier into a buffer ++ * @data: The encoded OID to print ++ * @datasize: The size of the encoded OID ++ * @buffer: The buffer to render into ++ * @bufsize: The size of the buffer ++ * ++ * The OID is rendered into the buffer in "a.b.c.d" format and the number of ++ * bytes is returned. -EBADMSG is returned if the data could not be intepreted ++ * and -ENOBUFS if the buffer was too small. ++ */ ++int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) ++{ ++ const unsigned char *v = data, *end = v + datasize; ++ unsigned long num; ++ unsigned char n; ++ size_t ret; ++ int count; ++ ++ if (v >= end) ++ return -EBADMSG; ++ ++ n = *v++; ++ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); ++ buffer += count; ++ bufsize -= count; ++ if (bufsize == 0) ++ return -ENOBUFS; ++ ++ while (v < end) { ++ num = 0; ++ n = *v++; ++ if (!(n & 0x80)) { ++ num = n; ++ } else { ++ num = n & 0x7f; ++ do { ++ if (v >= end) ++ return -EBADMSG; ++ n = *v++; ++ num <<= 7; ++ num |= n & 0x7f; ++ } while (n & 0x80); ++ } ++ ret += count = snprintf(buffer, bufsize, ".%lu", num); ++ buffer += count; ++ bufsize -= count; ++ if (bufsize == 0) ++ return -ENOBUFS; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sprint_oid); ++ ++/** ++ * sprint_OID - Print an Object Identifier into a buffer ++ * @oid: The OID to print ++ * @buffer: The buffer to render into ++ * @bufsize: The size of the buffer ++ * ++ * The OID is rendered into the buffer in "a.b.c.d" format and the number of ++ * bytes is returned. ++ */ ++int sprint_OID(enum OID oid, char *buffer, size_t bufsize) ++{ ++ int ret; ++ ++ BUG_ON(oid >= OID__NR); ++ ++ ret = sprint_oid(oid_data + oid_index[oid], ++ oid_index[oid + 1] - oid_index[oid], ++ buffer, bufsize); ++ BUG_ON(ret == -EBADMSG); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sprint_OID); +-- +1.7.11.4 + + +From 3ddb8a2f1fe420777491641d39328741d9a28565 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:31:13 +0100 +Subject: [PATCH 14/26] X.509: Add simple ASN.1 grammar compiler + +Add a simple ASN.1 grammar compiler. This produces a bytecode output that can +be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it +is trying to parse. + +Action functions can be specified in the grammar by interpolating: + + ({ foo }) + +after a type, for example: + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING ({ do_key_data }) + } + +The decoder is expected to call these after matching this type and parsing the +contents if it is a constructed type. + +The grammar compiler does not currently support the SET type (though it does +support SET OF) as I can't see a good way of tracking which members have been +encountered yet without using up extra stack space. + +Currently, the grammar compiler will fail if more than 256 bytes of bytecode +would be produced or more than 256 actions have been specified as it uses +8-bit jump values and action indices to keep space usage down. + +Signed-off-by: David Howells +--- + include/linux/asn1.h | 67 ++ + include/linux/asn1_ber_bytecode.h | 87 +++ + init/Kconfig | 8 + + scripts/.gitignore | 1 + + scripts/Makefile | 2 + + scripts/Makefile.build | 11 + + scripts/asn1_compiler.c | 1545 +++++++++++++++++++++++++++++++++++++ + 7 files changed, 1721 insertions(+) + create mode 100644 include/linux/asn1.h + create mode 100644 include/linux/asn1_ber_bytecode.h + create mode 100644 scripts/asn1_compiler.c + +diff --git a/include/linux/asn1.h b/include/linux/asn1.h +new file mode 100644 +index 0000000..5c3f4e4 +--- /dev/null ++++ b/include/linux/asn1.h +@@ -0,0 +1,67 @@ ++/* ASN.1 BER/DER/CER encoding definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_H ++#define _LINUX_ASN1_H ++ ++/* Class */ ++enum asn1_class { ++ ASN1_UNIV = 0, /* Universal */ ++ ASN1_APPL = 1, /* Application */ ++ ASN1_CONT = 2, /* Context */ ++ ASN1_PRIV = 3 /* Private */ ++}; ++#define ASN1_CLASS_BITS 0xc0 ++ ++ ++enum asn1_method { ++ ASN1_PRIM = 0, /* Primitive */ ++ ASN1_CONS = 1 /* Constructed */ ++}; ++#define ASN1_CONS_BIT 0x20 ++ ++/* Tag */ ++enum asn1_tag { ++ ASN1_EOC = 0, /* End Of Contents or N/A */ ++ ASN1_BOOL = 1, /* Boolean */ ++ ASN1_INT = 2, /* Integer */ ++ ASN1_BTS = 3, /* Bit String */ ++ ASN1_OTS = 4, /* Octet String */ ++ ASN1_NULL = 5, /* Null */ ++ ASN1_OID = 6, /* Object Identifier */ ++ ASN1_ODE = 7, /* Object Description */ ++ ASN1_EXT = 8, /* External */ ++ ASN1_REAL = 9, /* Real float */ ++ ASN1_ENUM = 10, /* Enumerated */ ++ ASN1_EPDV = 11, /* Embedded PDV */ ++ ASN1_UTF8STR = 12, /* UTF8 String */ ++ ASN1_RELOID = 13, /* Relative OID */ ++ /* 14 - Reserved */ ++ /* 15 - Reserved */ ++ ASN1_SEQ = 16, /* Sequence and Sequence of */ ++ ASN1_SET = 17, /* Set and Set of */ ++ ASN1_NUMSTR = 18, /* Numerical String */ ++ ASN1_PRNSTR = 19, /* Printable String */ ++ ASN1_TEXSTR = 20, /* T61 String / Teletext String */ ++ ASN1_VIDSTR = 21, /* Videotex String */ ++ ASN1_IA5STR = 22, /* IA5 String */ ++ ASN1_UNITIM = 23, /* Universal Time */ ++ ASN1_GENTIM = 24, /* General Time */ ++ ASN1_GRASTR = 25, /* Graphic String */ ++ ASN1_VISSTR = 26, /* Visible String */ ++ ASN1_GENSTR = 27, /* General String */ ++ ASN1_UNISTR = 28, /* Universal String */ ++ ASN1_CHRSTR = 29, /* Character String */ ++ ASN1_BMPSTR = 30, /* BMP String */ ++ ASN1_LONG_TAG = 31 /* Long form tag */ ++}; ++ ++#endif /* _LINUX_ASN1_H */ +diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h +new file mode 100644 +index 0000000..945d44a +--- /dev/null ++++ b/include/linux/asn1_ber_bytecode.h +@@ -0,0 +1,87 @@ ++/* ASN.1 BER/DER/CER parsing state machine internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_BER_BYTECODE_H ++#define _LINUX_ASN1_BER_BYTECODE_H ++ ++#ifdef __KERNEL__ ++#include ++#endif ++#include ++ ++typedef int (*asn1_action_t)(void *context, ++ size_t hdrlen, /* In case of ANY type */ ++ unsigned char tag, /* In case of ANY type */ ++ const void *value, size_t vlen); ++ ++struct asn1_decoder { ++ const unsigned char *machine; ++ size_t machlen; ++ const asn1_action_t *actions; ++}; ++ ++enum asn1_opcode { ++ /* The tag-matching ops come first and the odd-numbered slots ++ * are for OR_SKIP ops. ++ */ ++#define ASN1_OP_MATCH__SKIP 0x01 ++#define ASN1_OP_MATCH__ACT 0x02 ++#define ASN1_OP_MATCH__JUMP 0x04 ++#define ASN1_OP_MATCH__ANY 0x08 ++#define ASN1_OP_MATCH__COND 0x10 ++ ++ ASN1_OP_MATCH = 0x00, ++ ASN1_OP_MATCH_OR_SKIP = 0x01, ++ ASN1_OP_MATCH_ACT = 0x02, ++ ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, ++ ASN1_OP_MATCH_JUMP = 0x04, ++ ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, ++ ASN1_OP_MATCH_ANY = 0x08, ++ ASN1_OP_MATCH_ANY_ACT = 0x0a, ++ /* Everything before here matches unconditionally */ ++ ++ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, ++ ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, ++ ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, ++ ASN1_OP_COND_MATCH_ANY = 0x18, ++ ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, ++ ++ /* Everything before here will want a tag from the data */ ++#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT ++ ++ /* These are here to help fill up space */ ++ ASN1_OP_COND_FAIL = 0x1b, ++ ASN1_OP_COMPLETE = 0x1c, ++ ASN1_OP_ACT = 0x1d, ++ ASN1_OP_RETURN = 0x1e, ++ ++ /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ ++ ASN1_OP_END_SEQ = 0x20, ++ ASN1_OP_END_SET = 0x21, ++ ASN1_OP_END_SEQ_OF = 0x22, ++ ASN1_OP_END_SET_OF = 0x23, ++ ASN1_OP_END_SEQ_ACT = 0x24, ++ ASN1_OP_END_SET_ACT = 0x25, ++ ASN1_OP_END_SEQ_OF_ACT = 0x26, ++ ASN1_OP_END_SET_OF_ACT = 0x27, ++#define ASN1_OP_END__SET 0x01 ++#define ASN1_OP_END__OF 0x02 ++#define ASN1_OP_END__ACT 0x04 ++ ++ ASN1_OP__NR ++}; ++ ++#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) ++#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) ++#define _jump_target(N) (N) ++#define _action(N) (N) ++ ++#endif /* _LINUX_ASN1_BER_BYTECODE_H */ +diff --git a/init/Kconfig b/init/Kconfig +index af6c7f8..66cc885 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1612,4 +1612,12 @@ config PADATA + depends on SMP + bool + ++config ASN1 ++ tristate ++ help ++ Build a simple ASN.1 grammar compiler that produces a bytecode output ++ that can be interpreted by the ASN.1 stream decoder and used to ++ inform it as to what tags are to be expected in a stream and what ++ functions to call on what tags. ++ + source "kernel/Kconfig.locks" +diff --git a/scripts/.gitignore b/scripts/.gitignore +index 65f362d..fb070fa 100644 +--- a/scripts/.gitignore ++++ b/scripts/.gitignore +@@ -10,3 +10,4 @@ ihex2fw + recordmcount + docproc + sortextable ++asn1_compiler +diff --git a/scripts/Makefile b/scripts/Makefile +index a55b006..01e7adb 100644 +--- a/scripts/Makefile ++++ b/scripts/Makefile +@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash + hostprogs-$(CONFIG_IKCONFIG) += bin2c + hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount + hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable ++hostprogs-$(CONFIG_ASN1) += asn1_compiler + + HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include ++HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include + + always := $(hostprogs-y) $(hostprogs-m) + +diff --git a/scripts/Makefile.build b/scripts/Makefile.build +index ff1720d..0e801c3 100644 +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ + $(obj)/%.lds: $(src)/%.lds.S FORCE + $(call if_changed_dep,cpp_lds_S) + ++# ASN.1 grammar ++# --------------------------------------------------------------------------- ++quiet_cmd_asn1_compiler = ASN.1 $@ ++ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ ++ $(subst .h,.c,$@) $(subst .c,.h,$@) ++ ++.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h ++ ++$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler ++ $(call cmd,asn1_compiler) ++ + # Build the compiled-in targets + # --------------------------------------------------------------------------- + +diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c +new file mode 100644 +index 0000000..db0e5cd +--- /dev/null ++++ b/scripts/asn1_compiler.c +@@ -0,0 +1,1545 @@ ++/* Simplified ASN.1 notation parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum token_type { ++ DIRECTIVE_ABSENT, ++ DIRECTIVE_ALL, ++ DIRECTIVE_ANY, ++ DIRECTIVE_APPLICATION, ++ DIRECTIVE_AUTOMATIC, ++ DIRECTIVE_BEGIN, ++ DIRECTIVE_BIT, ++ DIRECTIVE_BMPString, ++ DIRECTIVE_BOOLEAN, ++ DIRECTIVE_BY, ++ DIRECTIVE_CHARACTER, ++ DIRECTIVE_CHOICE, ++ DIRECTIVE_CLASS, ++ DIRECTIVE_COMPONENT, ++ DIRECTIVE_COMPONENTS, ++ DIRECTIVE_CONSTRAINED, ++ DIRECTIVE_CONTAINING, ++ DIRECTIVE_DEFAULT, ++ DIRECTIVE_DEFINED, ++ DIRECTIVE_DEFINITIONS, ++ DIRECTIVE_EMBEDDED, ++ DIRECTIVE_ENCODED, ++ DIRECTIVE_ENCODING_CONTROL, ++ DIRECTIVE_END, ++ DIRECTIVE_ENUMERATED, ++ DIRECTIVE_EXCEPT, ++ DIRECTIVE_EXPLICIT, ++ DIRECTIVE_EXPORTS, ++ DIRECTIVE_EXTENSIBILITY, ++ DIRECTIVE_EXTERNAL, ++ DIRECTIVE_FALSE, ++ DIRECTIVE_FROM, ++ DIRECTIVE_GeneralString, ++ DIRECTIVE_GeneralizedTime, ++ DIRECTIVE_GraphicString, ++ DIRECTIVE_IA5String, ++ DIRECTIVE_IDENTIFIER, ++ DIRECTIVE_IMPLICIT, ++ DIRECTIVE_IMPLIED, ++ DIRECTIVE_IMPORTS, ++ DIRECTIVE_INCLUDES, ++ DIRECTIVE_INSTANCE, ++ DIRECTIVE_INSTRUCTIONS, ++ DIRECTIVE_INTEGER, ++ DIRECTIVE_INTERSECTION, ++ DIRECTIVE_ISO646String, ++ DIRECTIVE_MAX, ++ DIRECTIVE_MIN, ++ DIRECTIVE_MINUS_INFINITY, ++ DIRECTIVE_NULL, ++ DIRECTIVE_NumericString, ++ DIRECTIVE_OBJECT, ++ DIRECTIVE_OCTET, ++ DIRECTIVE_OF, ++ DIRECTIVE_OPTIONAL, ++ DIRECTIVE_ObjectDescriptor, ++ DIRECTIVE_PATTERN, ++ DIRECTIVE_PDV, ++ DIRECTIVE_PLUS_INFINITY, ++ DIRECTIVE_PRESENT, ++ DIRECTIVE_PRIVATE, ++ DIRECTIVE_PrintableString, ++ DIRECTIVE_REAL, ++ DIRECTIVE_RELATIVE_OID, ++ DIRECTIVE_SEQUENCE, ++ DIRECTIVE_SET, ++ DIRECTIVE_SIZE, ++ DIRECTIVE_STRING, ++ DIRECTIVE_SYNTAX, ++ DIRECTIVE_T61String, ++ DIRECTIVE_TAGS, ++ DIRECTIVE_TRUE, ++ DIRECTIVE_TeletexString, ++ DIRECTIVE_UNION, ++ DIRECTIVE_UNIQUE, ++ DIRECTIVE_UNIVERSAL, ++ DIRECTIVE_UTCTime, ++ DIRECTIVE_UTF8String, ++ DIRECTIVE_UniversalString, ++ DIRECTIVE_VideotexString, ++ DIRECTIVE_VisibleString, ++ DIRECTIVE_WITH, ++ NR__DIRECTIVES, ++ TOKEN_ASSIGNMENT = NR__DIRECTIVES, ++ TOKEN_OPEN_CURLY, ++ TOKEN_CLOSE_CURLY, ++ TOKEN_OPEN_SQUARE, ++ TOKEN_CLOSE_SQUARE, ++ TOKEN_OPEN_ACTION, ++ TOKEN_CLOSE_ACTION, ++ TOKEN_COMMA, ++ TOKEN_NUMBER, ++ TOKEN_TYPE_NAME, ++ TOKEN_ELEMENT_NAME, ++ NR__TOKENS ++}; ++ ++static const unsigned char token_to_tag[NR__TOKENS] = { ++ /* EOC goes first */ ++ [DIRECTIVE_BOOLEAN] = ASN1_BOOL, ++ [DIRECTIVE_INTEGER] = ASN1_INT, ++ [DIRECTIVE_BIT] = ASN1_BTS, ++ [DIRECTIVE_OCTET] = ASN1_OTS, ++ [DIRECTIVE_NULL] = ASN1_NULL, ++ [DIRECTIVE_OBJECT] = ASN1_OID, ++ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, ++ [DIRECTIVE_EXTERNAL] = ASN1_EXT, ++ [DIRECTIVE_REAL] = ASN1_REAL, ++ [DIRECTIVE_ENUMERATED] = ASN1_ENUM, ++ [DIRECTIVE_EMBEDDED] = 0, ++ [DIRECTIVE_UTF8String] = ASN1_UTF8STR, ++ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, ++ /* 14 */ ++ /* 15 */ ++ [DIRECTIVE_SEQUENCE] = ASN1_SEQ, ++ [DIRECTIVE_SET] = ASN1_SET, ++ [DIRECTIVE_NumericString] = ASN1_NUMSTR, ++ [DIRECTIVE_PrintableString] = ASN1_PRNSTR, ++ [DIRECTIVE_T61String] = ASN1_TEXSTR, ++ [DIRECTIVE_TeletexString] = ASN1_TEXSTR, ++ [DIRECTIVE_VideotexString] = ASN1_VIDSTR, ++ [DIRECTIVE_IA5String] = ASN1_IA5STR, ++ [DIRECTIVE_UTCTime] = ASN1_UNITIM, ++ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, ++ [DIRECTIVE_GraphicString] = ASN1_GRASTR, ++ [DIRECTIVE_VisibleString] = ASN1_VISSTR, ++ [DIRECTIVE_GeneralString] = ASN1_GENSTR, ++ [DIRECTIVE_UniversalString] = ASN1_UNITIM, ++ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, ++ [DIRECTIVE_BMPString] = ASN1_BMPSTR, ++}; ++ ++static const char asn1_classes[4][5] = { ++ [ASN1_UNIV] = "UNIV", ++ [ASN1_APPL] = "APPL", ++ [ASN1_CONT] = "CONT", ++ [ASN1_PRIV] = "PRIV" ++}; ++ ++static const char asn1_methods[2][5] = { ++ [ASN1_UNIV] = "PRIM", ++ [ASN1_APPL] = "CONS" ++}; ++ ++static const char *const asn1_universal_tags[32] = { ++ "EOC", ++ "BOOL", ++ "INT", ++ "BTS", ++ "OTS", ++ "NULL", ++ "OID", ++ "ODE", ++ "EXT", ++ "REAL", ++ "ENUM", ++ "EPDV", ++ "UTF8STR", ++ "RELOID", ++ NULL, /* 14 */ ++ NULL, /* 15 */ ++ "SEQ", ++ "SET", ++ "NUMSTR", ++ "PRNSTR", ++ "TEXSTR", ++ "VIDSTR", ++ "IA5STR", ++ "UNITIM", ++ "GENTIM", ++ "GRASTR", ++ "VISSTR", ++ "GENSTR", ++ "UNISTR", ++ "CHRSTR", ++ "BMPSTR", ++ NULL /* 31 */ ++}; ++ ++static const char *filename; ++static const char *grammar_name; ++static const char *outputname; ++static const char *headername; ++ ++static const char *const directives[NR__DIRECTIVES] = { ++#define _(X) [DIRECTIVE_##X] = #X ++ _(ABSENT), ++ _(ALL), ++ _(ANY), ++ _(APPLICATION), ++ _(AUTOMATIC), ++ _(BEGIN), ++ _(BIT), ++ _(BMPString), ++ _(BOOLEAN), ++ _(BY), ++ _(CHARACTER), ++ _(CHOICE), ++ _(CLASS), ++ _(COMPONENT), ++ _(COMPONENTS), ++ _(CONSTRAINED), ++ _(CONTAINING), ++ _(DEFAULT), ++ _(DEFINED), ++ _(DEFINITIONS), ++ _(EMBEDDED), ++ _(ENCODED), ++ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", ++ _(END), ++ _(ENUMERATED), ++ _(EXCEPT), ++ _(EXPLICIT), ++ _(EXPORTS), ++ _(EXTENSIBILITY), ++ _(EXTERNAL), ++ _(FALSE), ++ _(FROM), ++ _(GeneralString), ++ _(GeneralizedTime), ++ _(GraphicString), ++ _(IA5String), ++ _(IDENTIFIER), ++ _(IMPLICIT), ++ _(IMPLIED), ++ _(IMPORTS), ++ _(INCLUDES), ++ _(INSTANCE), ++ _(INSTRUCTIONS), ++ _(INTEGER), ++ _(INTERSECTION), ++ _(ISO646String), ++ _(MAX), ++ _(MIN), ++ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", ++ [DIRECTIVE_NULL] = "NULL", ++ _(NumericString), ++ _(OBJECT), ++ _(OCTET), ++ _(OF), ++ _(OPTIONAL), ++ _(ObjectDescriptor), ++ _(PATTERN), ++ _(PDV), ++ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", ++ _(PRESENT), ++ _(PRIVATE), ++ _(PrintableString), ++ _(REAL), ++ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", ++ _(SEQUENCE), ++ _(SET), ++ _(SIZE), ++ _(STRING), ++ _(SYNTAX), ++ _(T61String), ++ _(TAGS), ++ _(TRUE), ++ _(TeletexString), ++ _(UNION), ++ _(UNIQUE), ++ _(UNIVERSAL), ++ _(UTCTime), ++ _(UTF8String), ++ _(UniversalString), ++ _(VideotexString), ++ _(VisibleString), ++ _(WITH) ++}; ++ ++struct action { ++ struct action *next; ++ unsigned char index; ++ char name[]; ++}; ++ ++static struct action *action_list; ++static unsigned nr_actions; ++ ++struct token { ++ unsigned short line; ++ enum token_type token_type : 8; ++ unsigned char size; ++ struct action *action; ++ const char *value; ++ struct type *type; ++}; ++ ++static struct token *token_list; ++static unsigned nr_tokens; ++ ++static int directive_compare(const void *_key, const void *_pdir) ++{ ++ const struct token *token = _key; ++ const char *const *pdir = _pdir, *dir = *pdir; ++ size_t dlen, clen; ++ int val; ++ ++ dlen = strlen(dir); ++ clen = (dlen < token->size) ? dlen : token->size; ++ ++ //printf("cmp(%*.*s,%s) = ", ++ // (int)token->size, (int)token->size, token->value, ++ // dir); ++ ++ val = memcmp(token->value, dir, clen); ++ if (val != 0) { ++ //printf("%d [cmp]\n", val); ++ return val; ++ } ++ ++ if (dlen == token->size) { ++ //printf("0\n"); ++ return 0; ++ } ++ //printf("%d\n", (int)dlen - (int)token->size); ++ return dlen - token->size; /* shorter -> negative */ ++} ++ ++/* ++ * Tokenise an ASN.1 grammar ++ */ ++static void tokenise(char *buffer, char *end) ++{ ++ struct token *tokens; ++ char *line, *nl, *p, *q; ++ unsigned tix, lineno; ++ ++ /* Assume we're going to have half as many tokens as we have ++ * characters ++ */ ++ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); ++ if (!tokens) { ++ perror(NULL); ++ exit(1); ++ } ++ tix = 0; ++ ++ lineno = 0; ++ while (buffer < end) { ++ /* First of all, break out a line */ ++ lineno++; ++ line = buffer; ++ nl = memchr(line, '\n', end - buffer); ++ if (!nl) { ++ buffer = nl = end; ++ } else { ++ buffer = nl + 1; ++ *nl = '\0'; ++ } ++ ++ /* Remove "--" comments */ ++ p = line; ++ next_comment: ++ while ((p = memchr(p, '-', nl - p))) { ++ if (p[1] == '-') { ++ /* Found a comment; see if there's a terminator */ ++ q = p + 2; ++ while ((q = memchr(q, '-', nl - q))) { ++ if (q[1] == '-') { ++ /* There is - excise the comment */ ++ q += 2; ++ memmove(p, q, nl - q); ++ goto next_comment; ++ } ++ q++; ++ } ++ *p = '\0'; ++ nl = p; ++ break; ++ } else { ++ p++; ++ } ++ } ++ ++ p = line; ++ while (p < nl) { ++ /* Skip white space */ ++ while (p < nl && isspace(*p)) ++ *(p++) = 0; ++ if (p >= nl) ++ break; ++ ++ tokens[tix].line = lineno; ++ tokens[tix].value = p; ++ ++ /* Handle string tokens */ ++ if (isalpha(*p)) { ++ const char **dir; ++ ++ /* Can be a directive, type name or element ++ * name. Find the end of the name. ++ */ ++ q = p + 1; ++ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) ++ q++; ++ tokens[tix].size = q - p; ++ p = q; ++ ++ /* If it begins with a lowercase letter then ++ * it's an element name ++ */ ++ if (islower(tokens[tix].value[0])) { ++ tokens[tix++].token_type = TOKEN_ELEMENT_NAME; ++ continue; ++ } ++ ++ /* Otherwise we need to search the directive ++ * table ++ */ ++ dir = bsearch(&tokens[tix], directives, ++ sizeof(directives) / sizeof(directives[1]), ++ sizeof(directives[1]), ++ directive_compare); ++ if (dir) { ++ tokens[tix++].token_type = dir - directives; ++ continue; ++ } ++ ++ tokens[tix++].token_type = TOKEN_TYPE_NAME; ++ continue; ++ } ++ ++ /* Handle numbers */ ++ if (isdigit(*p)) { ++ /* Find the end of the number */ ++ q = p + 1; ++ while (q < nl && (isdigit(*q))) ++ q++; ++ tokens[tix].size = q - p; ++ p = q; ++ tokens[tix++].token_type = TOKEN_NUMBER; ++ continue; ++ } ++ ++ if (nl - p >= 3) { ++ if (memcmp(p, "::=", 3) == 0) { ++ p += 3; ++ tokens[tix].size = 3; ++ tokens[tix++].token_type = TOKEN_ASSIGNMENT; ++ continue; ++ } ++ } ++ ++ if (nl - p >= 2) { ++ if (memcmp(p, "({", 2) == 0) { ++ p += 2; ++ tokens[tix].size = 2; ++ tokens[tix++].token_type = TOKEN_OPEN_ACTION; ++ continue; ++ } ++ if (memcmp(p, "})", 2) == 0) { ++ p += 2; ++ tokens[tix].size = 2; ++ tokens[tix++].token_type = TOKEN_CLOSE_ACTION; ++ continue; ++ } ++ } ++ ++ if (nl - p >= 1) { ++ tokens[tix].size = 1; ++ switch (*p) { ++ case '{': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_OPEN_CURLY; ++ continue; ++ case '}': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_CLOSE_CURLY; ++ continue; ++ case '[': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_OPEN_SQUARE; ++ continue; ++ case ']': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; ++ continue; ++ case ',': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_COMMA; ++ continue; ++ default: ++ break; ++ } ++ } ++ ++ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", ++ filename, lineno, *p); ++ exit(1); ++ } ++ } ++ ++ nr_tokens = tix; ++ printf("Extracted %u tokens\n", nr_tokens); ++ ++#if 0 ++ { ++ int n; ++ for (n = 0; n < nr_tokens; n++) ++ printf("Token %3u: '%*.*s'\n", ++ n, ++ (int)token_list[n].size, (int)token_list[n].size, ++ token_list[n].value); ++ } ++#endif ++} ++ ++static void build_type_list(void); ++static void parse(void); ++static void render(FILE *out, FILE *hdr); ++ ++/* ++ * ++ */ ++int main(int argc, char **argv) ++{ ++ struct stat st; ++ ssize_t readlen; ++ FILE *out, *hdr; ++ char *buffer, *p; ++ int fd; ++ ++ if (argc != 4) { ++ fprintf(stderr, "Format: %s \n", ++ argv[0]); ++ exit(2); ++ } ++ ++ filename = argv[1]; ++ outputname = argv[2]; ++ headername = argv[3]; ++ ++ fd = open(filename, O_RDONLY); ++ if (fd < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (fstat(fd, &st) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (!(buffer = malloc(st.st_size + 1))) { ++ perror(NULL); ++ exit(1); ++ } ++ ++ if ((readlen = read(fd, buffer, st.st_size)) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (close(fd) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (readlen != st.st_size) { ++ fprintf(stderr, "%s: Short read\n", filename); ++ exit(1); ++ } ++ ++ p = strrchr(argv[1], '/'); ++ p = p ? p + 1 : argv[1]; ++ grammar_name = strdup(p); ++ if (!p) { ++ perror(NULL); ++ exit(1); ++ } ++ p = strchr(grammar_name, '.'); ++ if (p) ++ *p = '\0'; ++ ++ buffer[readlen] = 0; ++ tokenise(buffer, buffer + readlen); ++ build_type_list(); ++ parse(); ++ ++ out = fopen(outputname, "w"); ++ if (!out) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ hdr = fopen(headername, "w"); ++ if (!out) { ++ perror(headername); ++ exit(1); ++ } ++ ++ render(out, hdr); ++ ++ if (fclose(out) < 0) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ if (fclose(hdr) < 0) { ++ perror(headername); ++ exit(1); ++ } ++ ++ return 0; ++} ++ ++enum compound { ++ NOT_COMPOUND, ++ SET, ++ SET_OF, ++ SEQUENCE, ++ SEQUENCE_OF, ++ CHOICE, ++ ANY, ++ TYPE_REF, ++ TAG_OVERRIDE ++}; ++ ++struct element { ++ struct type *type_def; ++ struct token *name; ++ struct token *type; ++ struct action *action; ++ struct element *children; ++ struct element *next; ++ struct element *render_next; ++ struct element *list_next; ++ uint8_t n_elements; ++ enum compound compound : 8; ++ enum asn1_class class : 8; ++ enum asn1_method method : 8; ++ uint8_t tag; ++ unsigned entry_index; ++ unsigned flags; ++#define ELEMENT_IMPLICIT 0x0001 ++#define ELEMENT_EXPLICIT 0x0002 ++#define ELEMENT_MARKED 0x0004 ++#define ELEMENT_RENDERED 0x0008 ++#define ELEMENT_SKIPPABLE 0x0010 ++#define ELEMENT_CONDITIONAL 0x0020 ++}; ++ ++struct type { ++ struct token *name; ++ struct token *def; ++ struct element *element; ++ unsigned ref_count; ++ unsigned flags; ++#define TYPE_STOP_MARKER 0x0001 ++#define TYPE_BEGIN 0x0002 ++}; ++ ++static struct type *type_list; ++static struct type **type_index; ++static unsigned nr_types; ++ ++static int type_index_compare(const void *_a, const void *_b) ++{ ++ const struct type *const *a = _a, *const *b = _b; ++ ++ if ((*a)->name->size != (*b)->name->size) ++ return (*a)->name->size - (*b)->name->size; ++ else ++ return memcmp((*a)->name->value, (*b)->name->value, ++ (*a)->name->size); ++} ++ ++static int type_finder(const void *_key, const void *_ti) ++{ ++ const struct token *token = _key; ++ const struct type *const *ti = _ti; ++ const struct type *type = *ti; ++ ++ if (token->size != type->name->size) ++ return token->size - type->name->size; ++ else ++ return memcmp(token->value, type->name->value, ++ token->size); ++} ++ ++/* ++ * Build up a list of types and a sorted index to that list. ++ */ ++static void build_type_list(void) ++{ ++ struct type *types; ++ unsigned nr, t, n; ++ ++ nr = 0; ++ for (n = 0; n < nr_tokens - 1; n++) ++ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && ++ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) ++ nr++; ++ ++ if (nr == 0) { ++ fprintf(stderr, "%s: No defined types\n", filename); ++ exit(1); ++ } ++ ++ nr_types = nr; ++ types = type_list = calloc(nr + 1, sizeof(type_list[0])); ++ if (!type_list) { ++ perror(NULL); ++ exit(1); ++ } ++ type_index = calloc(nr, sizeof(type_index[0])); ++ if (!type_index) { ++ perror(NULL); ++ exit(1); ++ } ++ ++ t = 0; ++ types[t].flags |= TYPE_BEGIN; ++ for (n = 0; n < nr_tokens - 1; n++) { ++ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && ++ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { ++ types[t].name = &token_list[n]; ++ type_index[t] = &types[t]; ++ t++; ++ } ++ } ++ types[t].name = &token_list[n + 1]; ++ types[t].flags |= TYPE_STOP_MARKER; ++ ++ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); ++ ++ printf("Extracted %u types\n", nr_types); ++#if 0 ++ for (n = 0; n < nr_types; n++) { ++ struct type *type = type_index[n]; ++ printf("- %*.*s\n", ++ (int)type->name->size, ++ (int)type->name->size, ++ type->name->value); ++ } ++#endif ++} ++ ++static struct element *parse_type(struct token **_cursor, struct token *stop, ++ struct token *name); ++ ++/* ++ * Parse the token stream ++ */ ++static void parse(void) ++{ ++ struct token *cursor; ++ struct type *type; ++ ++ /* Parse one type definition statement at a time */ ++ type = type_list; ++ do { ++ cursor = type->name; ++ ++ if (cursor[0].token_type != TOKEN_TYPE_NAME || ++ cursor[1].token_type != TOKEN_ASSIGNMENT) ++ abort(); ++ cursor += 2; ++ ++ type->element = parse_type(&cursor, type[1].name, NULL); ++ type->element->type_def = type; ++ ++ if (cursor != type[1].name) { ++ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ } while (type++, !(type->flags & TYPE_STOP_MARKER)); ++ ++ printf("Extracted %u actions\n", nr_actions); ++} ++ ++static struct element *element_list; ++ ++static struct element *alloc_elem(struct token *type) ++{ ++ struct element *e = calloc(1, sizeof(*e)); ++ if (!e) { ++ perror(NULL); ++ exit(1); ++ } ++ e->list_next = element_list; ++ element_list = e; ++ return e; ++} ++ ++static struct element *parse_compound(struct token **_cursor, struct token *end, ++ int alternates); ++ ++/* ++ * Parse one type definition statement ++ */ ++static struct element *parse_type(struct token **_cursor, struct token *end, ++ struct token *name) ++{ ++ struct element *top, *element; ++ struct action *action, **ppaction; ++ struct token *cursor = *_cursor; ++ struct type **ref; ++ char *p; ++ int labelled = 0, implicit = 0; ++ ++ top = element = alloc_elem(cursor); ++ element->class = ASN1_UNIV; ++ element->method = ASN1_PRIM; ++ element->tag = token_to_tag[cursor->token_type]; ++ element->name = name; ++ ++ /* Extract the tag value if one given */ ++ if (cursor->token_type == TOKEN_OPEN_SQUARE) { ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ switch (cursor->token_type) { ++ case DIRECTIVE_UNIVERSAL: ++ element->class = ASN1_UNIV; ++ cursor++; ++ break; ++ case DIRECTIVE_APPLICATION: ++ element->class = ASN1_APPL; ++ cursor++; ++ break; ++ case TOKEN_NUMBER: ++ element->class = ASN1_CONT; ++ break; ++ case DIRECTIVE_PRIVATE: ++ element->class = ASN1_PRIV; ++ cursor++; ++ break; ++ default: ++ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_NUMBER) { ++ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ element->tag &= ~0x1f; ++ element->tag |= strtoul(cursor->value, &p, 10); ++ if (p - cursor->value != cursor->size) ++ abort(); ++ cursor++; ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_CLOSE_SQUARE) { ++ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ labelled = 1; ++ } ++ ++ /* Handle implicit and explicit markers */ ++ if (cursor->token_type == DIRECTIVE_IMPLICIT) { ++ element->flags |= ELEMENT_IMPLICIT; ++ implicit = 1; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { ++ element->flags |= ELEMENT_EXPLICIT; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ if (labelled) { ++ if (!implicit) ++ element->method |= ASN1_CONS; ++ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; ++ element->children = alloc_elem(cursor); ++ element = element->children; ++ element->class = ASN1_UNIV; ++ element->method = ASN1_PRIM; ++ element->tag = token_to_tag[cursor->token_type]; ++ element->name = name; ++ } ++ ++ /* Extract the type we're expecting here */ ++ element->type = cursor; ++ switch (cursor->token_type) { ++ case DIRECTIVE_ANY: ++ element->compound = ANY; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_NULL: ++ case DIRECTIVE_BOOLEAN: ++ case DIRECTIVE_ENUMERATED: ++ case DIRECTIVE_INTEGER: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_EXTERNAL: ++ element->method = ASN1_CONS; ++ ++ case DIRECTIVE_BMPString: ++ case DIRECTIVE_GeneralString: ++ case DIRECTIVE_GraphicString: ++ case DIRECTIVE_IA5String: ++ case DIRECTIVE_ISO646String: ++ case DIRECTIVE_NumericString: ++ case DIRECTIVE_PrintableString: ++ case DIRECTIVE_T61String: ++ case DIRECTIVE_TeletexString: ++ case DIRECTIVE_UniversalString: ++ case DIRECTIVE_UTF8String: ++ case DIRECTIVE_VideotexString: ++ case DIRECTIVE_VisibleString: ++ case DIRECTIVE_ObjectDescriptor: ++ case DIRECTIVE_GeneralizedTime: ++ case DIRECTIVE_UTCTime: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_BIT: ++ case DIRECTIVE_OCTET: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != DIRECTIVE_STRING) ++ goto parse_error; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_OBJECT: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != DIRECTIVE_IDENTIFIER) ++ goto parse_error; ++ cursor++; ++ break; ++ ++ case TOKEN_TYPE_NAME: ++ element->compound = TYPE_REF; ++ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), ++ type_finder); ++ if (!ref) { ++ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor->type = *ref; ++ (*ref)->ref_count++; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_CHOICE: ++ element->compound = CHOICE; ++ cursor++; ++ element->children = parse_compound(&cursor, end, 1); ++ break; ++ ++ case DIRECTIVE_SEQUENCE: ++ element->compound = SEQUENCE; ++ element->method = ASN1_CONS; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type == DIRECTIVE_OF) { ++ element->compound = SEQUENCE_OF; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ element->children = parse_type(&cursor, end, NULL); ++ } else { ++ element->children = parse_compound(&cursor, end, 0); ++ } ++ break; ++ ++ case DIRECTIVE_SET: ++ element->compound = SET; ++ element->method = ASN1_CONS; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type == DIRECTIVE_OF) { ++ element->compound = SET_OF; ++ cursor++; ++ if (cursor >= end) ++ goto parse_error; ++ element->children = parse_type(&cursor, end, NULL); ++ } else { ++ element->children = parse_compound(&cursor, end, 1); ++ } ++ break; ++ ++ default: ++ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ /* Handle elements that are optional */ ++ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || ++ cursor->token_type == DIRECTIVE_DEFAULT) ++ ) { ++ cursor++; ++ top->flags |= ELEMENT_SKIPPABLE; ++ } ++ ++ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_ELEMENT_NAME) { ++ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ action = malloc(sizeof(struct action) + cursor->size + 1); ++ if (!action) { ++ perror(NULL); ++ exit(1); ++ } ++ action->index = 0; ++ memcpy(action->name, cursor->value, cursor->size); ++ action->name[cursor->size] = 0; ++ ++ for (ppaction = &action_list; ++ *ppaction; ++ ppaction = &(*ppaction)->next ++ ) { ++ int cmp = strcmp(action->name, (*ppaction)->name); ++ if (cmp == 0) { ++ free(action); ++ action = *ppaction; ++ goto found; ++ } ++ if (cmp < 0) { ++ action->next = *ppaction; ++ *ppaction = action; ++ nr_actions++; ++ goto found; ++ } ++ } ++ action->next = NULL; ++ *ppaction = action; ++ nr_actions++; ++ found: ++ ++ element->action = action; ++ cursor->action = action; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_CLOSE_ACTION) { ++ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ } ++ ++ *_cursor = cursor; ++ return top; ++ ++parse_error: ++ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ ++overrun_error: ++ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); ++ exit(1); ++} ++ ++/* ++ * Parse a compound type list ++ */ ++static struct element *parse_compound(struct token **_cursor, struct token *end, ++ int alternates) ++{ ++ struct element *children, **child_p = &children, *element; ++ struct token *cursor = *_cursor, *name; ++ ++ if (cursor->token_type != TOKEN_OPEN_CURLY) { ++ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ ++ if (cursor->token_type == TOKEN_OPEN_CURLY) { ++ fprintf(stderr, "%s:%d: Empty compound\n", ++ filename, cursor->line); ++ exit(1); ++ } ++ ++ for (;;) { ++ name = NULL; ++ if (cursor->token_type == TOKEN_ELEMENT_NAME) { ++ name = cursor; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ element = parse_type(&cursor, end, name); ++ if (alternates) ++ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; ++ ++ *child_p = element; ++ child_p = &element->next; ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_COMMA) ++ break; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ children->flags &= ~ELEMENT_CONDITIONAL; ++ ++ if (cursor->token_type != TOKEN_CLOSE_CURLY) { ++ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ ++ *_cursor = cursor; ++ return children; ++ ++overrun_error: ++ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); ++ exit(1); ++} ++ ++static void render_element(FILE *out, struct element *e, struct element *tag); ++static void render_out_of_line_list(FILE *out); ++ ++static int nr_entries; ++static int render_depth = 1; ++static struct element *render_list, **render_list_p = &render_list; ++ ++__attribute__((format(printf, 2, 3))) ++static void render_opcode(FILE *out, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (out) { ++ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); ++ va_start(va, fmt); ++ vfprintf(out, fmt, va); ++ va_end(va); ++ } ++ nr_entries++; ++} ++ ++__attribute__((format(printf, 2, 3))) ++static void render_more(FILE *out, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (out) { ++ va_start(va, fmt); ++ vfprintf(out, fmt, va); ++ va_end(va); ++ } ++} ++ ++/* ++ * Render the grammar into a state machine definition. ++ */ ++static void render(FILE *out, FILE *hdr) ++{ ++ struct element *e; ++ struct action *action; ++ struct type *root; ++ int index; ++ ++ fprintf(hdr, "/*\n"); ++ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); ++ fprintf(hdr, " *\n"); ++ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); ++ fprintf(hdr, " */\n"); ++ fprintf(hdr, "#include \n"); ++ fprintf(hdr, "\n"); ++ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); ++ if (ferror(hdr)) { ++ perror(headername); ++ exit(1); ++ } ++ ++ fprintf(out, "/*\n"); ++ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); ++ fprintf(out, " *\n"); ++ fprintf(out, " * ASN.1 parser for %s\n", grammar_name); ++ fprintf(out, " */\n"); ++ fprintf(out, "#include \n"); ++ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); ++ fprintf(out, "\n"); ++ if (ferror(out)) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ /* Tabulate the action functions we might have to call */ ++ fprintf(hdr, "\n"); ++ index = 0; ++ for (action = action_list; action; action = action->next) { ++ action->index = index++; ++ fprintf(hdr, ++ "extern int %s(void *, size_t, unsigned char," ++ " const void *, size_t);\n", ++ action->name); ++ } ++ fprintf(hdr, "\n"); ++ ++ fprintf(out, "enum %s_actions {\n", grammar_name); ++ for (action = action_list; action; action = action->next) ++ fprintf(out, "\tACT_%s = %u,\n", ++ action->name, action->index); ++ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); ++ fprintf(out, "};\n"); ++ ++ fprintf(out, "\n"); ++ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", ++ grammar_name, grammar_name); ++ for (action = action_list; action; action = action->next) ++ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); ++ fprintf(out, "};\n"); ++ ++ if (ferror(out)) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ /* We do two passes - the first one calculates all the offsets */ ++ printf("Pass 1\n"); ++ nr_entries = 0; ++ root = &type_list[0]; ++ render_element(NULL, root->element, NULL); ++ render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); ++ render_out_of_line_list(NULL); ++ ++ for (e = element_list; e; e = e->list_next) ++ e->flags &= ~ELEMENT_RENDERED; ++ ++ /* And then we actually render */ ++ printf("Pass 2\n"); ++ fprintf(out, "\n"); ++ fprintf(out, "static const unsigned char %s_machine[] = {\n", ++ grammar_name); ++ ++ nr_entries = 0; ++ root = &type_list[0]; ++ render_element(out, root->element, NULL); ++ render_opcode(out, "ASN1_OP_COMPLETE,\n"); ++ render_out_of_line_list(out); ++ ++ fprintf(out, "};\n"); ++ ++ fprintf(out, "\n"); ++ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); ++ fprintf(out, "\t.machine = %s_machine,\n", grammar_name); ++ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); ++ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); ++ fprintf(out, "};\n"); ++} ++ ++/* ++ * Render the out-of-line elements ++ */ ++static void render_out_of_line_list(FILE *out) ++{ ++ struct element *e, *ce; ++ const char *act; ++ int entry; ++ ++ while ((e = render_list)) { ++ render_list = e->render_next; ++ if (!render_list) ++ render_list_p = &render_list; ++ ++ render_more(out, "\n"); ++ e->entry_index = entry = nr_entries; ++ render_depth++; ++ for (ce = e->children; ce; ce = ce->next) ++ render_element(out, ce, NULL); ++ render_depth--; ++ ++ act = e->action ? "_ACT" : ""; ++ switch (e->compound) { ++ case SEQUENCE: ++ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); ++ break; ++ case SEQUENCE_OF: ++ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ break; ++ case SET: ++ render_opcode(out, "ASN1_OP_END_SET%s,\n", act); ++ break; ++ case SET_OF: ++ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ break; ++ } ++ if (e->action) ++ render_opcode(out, "_action(ACT_%s),\n", ++ e->action->name); ++ render_opcode(out, "ASN1_OP_RETURN,\n"); ++ } ++} ++ ++/* ++ * Render an element. ++ */ ++static void render_element(FILE *out, struct element *e, struct element *tag) ++{ ++ struct element *ec; ++ const char *cond, *act; ++ int entry, skippable = 0, outofline = 0; ++ ++ if (e->flags & ELEMENT_SKIPPABLE || ++ (tag && tag->flags & ELEMENT_SKIPPABLE)) ++ skippable = 1; ++ ++ if ((e->type_def && e->type_def->ref_count > 1) || ++ skippable) ++ outofline = 1; ++ ++ if (e->type_def && out) { ++ render_more(out, "\t// %*.*s\n", ++ (int)e->type_def->name->size, (int)e->type_def->name->size, ++ e->type_def->name->value); ++ } ++ ++ /* Render the operation */ ++ cond = (e->flags & ELEMENT_CONDITIONAL || ++ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; ++ act = e->action ? "_ACT" : ""; ++ switch (e->compound) { ++ case ANY: ++ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); ++ if (e->name) ++ render_more(out, "\t\t// %*.*s", ++ (int)e->name->size, (int)e->name->size, ++ e->name->value); ++ render_more(out, "\n"); ++ goto dont_render_tag; ++ ++ case TAG_OVERRIDE: ++ render_element(out, e->children, e); ++ return; ++ ++ case SEQUENCE: ++ case SEQUENCE_OF: ++ case SET: ++ case SET_OF: ++ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", ++ cond, ++ outofline ? "_JUMP" : "", ++ skippable ? "_OR_SKIP" : ""); ++ break; ++ ++ case CHOICE: ++ goto dont_render_tag; ++ ++ case TYPE_REF: ++ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) ++ goto dont_render_tag; ++ default: ++ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", ++ cond, act, ++ skippable ? "_OR_SKIP" : ""); ++ break; ++ } ++ ++ if (e->name) ++ render_more(out, "\t\t// %*.*s", ++ (int)e->name->size, (int)e->name->size, ++ e->name->value); ++ render_more(out, "\n"); ++ ++ /* Render the tag */ ++ if (!tag) ++ tag = e; ++ if (tag->class == ASN1_UNIV && ++ tag->tag != 14 && ++ tag->tag != 15 && ++ tag->tag != 31) ++ render_opcode(out, "_tag(%s, %s, %s),\n", ++ asn1_classes[tag->class], ++ asn1_methods[tag->method | e->method], ++ asn1_universal_tags[tag->tag]); ++ else ++ render_opcode(out, "_tagn(%s, %s, %2u),\n", ++ asn1_classes[tag->class], ++ asn1_methods[tag->method | e->method], ++ tag->tag); ++ tag = NULL; ++dont_render_tag: ++ ++ /* Deal with compound types */ ++ switch (e->compound) { ++ case TYPE_REF: ++ render_element(out, e->type->type->element, tag); ++ if (e->action) ++ render_opcode(out, "ASN1_OP_ACT,\n"); ++ break; ++ ++ case SEQUENCE: ++ if (outofline) { ++ /* Render out-of-line for multiple use or ++ * skipability */ ++ render_opcode(out, "_jump_target(%u),", e->entry_index); ++ if (e->type_def && e->type_def->name) ++ render_more(out, "\t\t// --> %*.*s", ++ (int)e->type_def->name->size, ++ (int)e->type_def->name->size, ++ e->type_def->name->value); ++ render_more(out, "\n"); ++ if (!(e->flags & ELEMENT_RENDERED)) { ++ e->flags |= ELEMENT_RENDERED; ++ *render_list_p = e; ++ render_list_p = &e->render_next; ++ } ++ return; ++ } else { ++ /* Render inline for single use */ ++ render_depth++; ++ for (ec = e->children; ec; ec = ec->next) ++ render_element(out, ec, NULL); ++ render_depth--; ++ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); ++ } ++ break; ++ ++ case SEQUENCE_OF: ++ case SET_OF: ++ if (outofline) { ++ /* Render out-of-line for multiple use or ++ * skipability */ ++ render_opcode(out, "_jump_target(%u),", e->entry_index); ++ if (e->type_def && e->type_def->name) ++ render_more(out, "\t\t// --> %*.*s", ++ (int)e->type_def->name->size, ++ (int)e->type_def->name->size, ++ e->type_def->name->value); ++ render_more(out, "\n"); ++ if (!(e->flags & ELEMENT_RENDERED)) { ++ e->flags |= ELEMENT_RENDERED; ++ *render_list_p = e; ++ render_list_p = &e->render_next; ++ } ++ return; ++ } else { ++ /* Render inline for single use */ ++ entry = nr_entries; ++ render_depth++; ++ render_element(out, e->children, NULL); ++ render_depth--; ++ if (e->compound == SEQUENCE_OF) ++ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); ++ else ++ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ } ++ break; ++ ++ case SET: ++ /* I can't think of a nice way to do SET support without having ++ * a stack of bitmasks to make sure no element is repeated. ++ * The bitmask has also to be checked that no non-optional ++ * elements are left out whilst not preventing optional ++ * elements from being left out. ++ */ ++ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); ++ exit(1); ++ ++ case CHOICE: ++ for (ec = e->children; ec; ec = ec->next) ++ render_element(out, ec, NULL); ++ if (!skippable) ++ render_opcode(out, "ASN1_OP_COND_FAIL,\n"); ++ if (e->action) ++ render_opcode(out, "ASN1_OP_ACT,\n"); ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (e->action) ++ render_opcode(out, "_action(ACT_%s),\n", e->action->name); ++} +-- +1.7.11.4 + + +From 8ea3f94cc16a23e3edbebf12f4223e654eb8219d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:16 +0100 +Subject: [PATCH 15/26] X.509: Add an ASN.1 decoder + +Add an ASN.1 BER/DER/CER decoder. This uses the bytecode from the ASN.1 +compiler in the previous patch to inform it as to what to expect to find in the +encoded byte stream. The output from the compiler also tells it what functions +to call on what tags, thus allowing the caller to retrieve information. + +The decoder is called as follows: + + int asn1_decoder(const struct asn1_decoder *decoder, + void *context, + const unsigned char *data, + size_t datalen); + +The decoder argument points to the bytecode from the ASN.1 compiler. context +is the caller's context and is passed to the action functions. data and +datalen define the byte stream to be decoded. + + +Note that the decoder is currently limited to datalen being less than 64K. +This reduces the amount of stack space used by the decoder because ASN.1 is a +nested construct. Similarly, the decoder is limited to a maximum of 10 levels +of constructed data outside of a leaf node also in an effort to keep stack +usage down. + +These restrictions can be raised if necessary. + +Signed-off-by: David Howells +--- + include/linux/asn1_decoder.h | 24 +++ + lib/Makefile | 2 + + lib/asn1_decoder.c | 477 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 503 insertions(+) + create mode 100644 include/linux/asn1_decoder.h + create mode 100644 lib/asn1_decoder.c + +diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h +new file mode 100644 +index 0000000..fa2ff5b +--- /dev/null ++++ b/include/linux/asn1_decoder.h +@@ -0,0 +1,24 @@ ++/* ASN.1 decoder ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_DECODER_H ++#define _LINUX_ASN1_DECODER_H ++ ++#include ++ ++struct asn1_decoder; ++ ++extern int asn1_ber_decoder(const struct asn1_decoder *decoder, ++ void *context, ++ const unsigned char *data, ++ size_t datalen); ++ ++#endif /* _LINUX_ASN1_DECODER_H */ +diff --git a/lib/Makefile b/lib/Makefile +index b042896..ca856b6 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \ + $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) + lib-$(CONFIG_LIBFDT) += $(libfdt_files) + ++obj-$(CONFIG_ASN1) += asn1_decoder.o ++ + hostprogs-y := gen_crc32table + clean-files := crc32table.h + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +new file mode 100644 +index 0000000..2e4196d +--- /dev/null ++++ b/lib/asn1_decoder.c +@@ -0,0 +1,477 @@ ++/* Decoder for ASN.1 BER/DER/CER encoded bytestream ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { ++ /* OPC TAG JMP ACT */ ++ [ASN1_OP_MATCH] = 1 + 1, ++ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, ++ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_ANY] = 1, ++ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, ++ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, ++ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_COND_MATCH_ANY] = 1, ++ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, ++ [ASN1_OP_COND_FAIL] = 1, ++ [ASN1_OP_COMPLETE] = 1, ++ [ASN1_OP_ACT] = 1 + 1, ++ [ASN1_OP_RETURN] = 1, ++ [ASN1_OP_END_SEQ] = 1, ++ [ASN1_OP_END_SEQ_OF] = 1 + 1, ++ [ASN1_OP_END_SET] = 1, ++ [ASN1_OP_END_SET_OF] = 1 + 1, ++ [ASN1_OP_END_SEQ_ACT] = 1 + 1, ++ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, ++ [ASN1_OP_END_SET_ACT] = 1 + 1, ++ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, ++}; ++ ++/* ++ * Find the length of an indefinite length object ++ */ ++static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, ++ const char **_errmsg, size_t *_err_dp) ++{ ++ unsigned char tag, tmp; ++ size_t dp = 0, len, n; ++ int indef_level = 1; ++ ++next_tag: ++ if (unlikely(datalen - dp < 2)) { ++ if (datalen == dp) ++ goto missing_eoc; ++ goto data_overrun_error; ++ } ++ ++ /* Extract a tag from the data */ ++ tag = data[dp++]; ++ if (tag == 0) { ++ /* It appears to be an EOC. */ ++ if (data[dp++] != 0) ++ goto invalid_eoc; ++ if (--indef_level <= 0) ++ return dp; ++ goto next_tag; ++ } ++ ++ if (unlikely((tag & 0x1f) == 0x1f)) { ++ do { ++ if (unlikely(datalen - dp < 2)) ++ goto data_overrun_error; ++ tmp = data[dp++]; ++ } while (tmp & 0x80); ++ } ++ ++ /* Extract the length */ ++ len = data[dp++]; ++ if (len < 0x7f) { ++ dp += len; ++ goto next_tag; ++ } ++ ++ if (unlikely(len == 0x80)) { ++ /* Indefinite length */ ++ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) ++ goto indefinite_len_primitive; ++ indef_level++; ++ goto next_tag; ++ } ++ ++ n = len - 0x80; ++ if (unlikely(n > sizeof(size_t) - 1)) ++ goto length_too_long; ++ if (unlikely(n > datalen - dp)) ++ goto data_overrun_error; ++ for (len = 0; n > 0; n--) { ++ len <<= 8; ++ len |= data[dp++]; ++ } ++ dp += len; ++ goto next_tag; ++ ++length_too_long: ++ *_errmsg = "Unsupported length"; ++ goto error; ++indefinite_len_primitive: ++ *_errmsg = "Indefinite len primitive not permitted"; ++ goto error; ++invalid_eoc: ++ *_errmsg = "Invalid length EOC"; ++ goto error; ++data_overrun_error: ++ *_errmsg = "Data overrun error"; ++ goto error; ++missing_eoc: ++ *_errmsg = "Missing EOC in indefinite len cons"; ++error: ++ *_err_dp = dp; ++ return -1; ++} ++ ++/** ++ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern ++ * @decoder: The decoder definition (produced by asn1_compiler) ++ * @context: The caller's context (to be passed to the action functions) ++ * @data: The encoded data ++ * @datasize: The size of the encoded data ++ * ++ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern ++ * produced by asn1_compiler. Action functions are called on marked tags to ++ * allow the caller to retrieve significant data. ++ * ++ * LIMITATIONS: ++ * ++ * To keep down the amount of stack used by this function, the following limits ++ * have been imposed: ++ * ++ * (1) This won't handle datalen > 65535 without increasing the size of the ++ * cons stack elements and length_too_long checking. ++ * ++ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf ++ * constructed types exceeds this, the decode will fail. ++ * ++ * (3) The SET type (not the SET OF type) isn't really supported as tracking ++ * what members of the set have been seen is a pain. ++ */ ++int asn1_ber_decoder(const struct asn1_decoder *decoder, ++ void *context, ++ const unsigned char *data, ++ size_t datalen) ++{ ++ const unsigned char *machine = decoder->machine; ++ const asn1_action_t *actions = decoder->actions; ++ size_t machlen = decoder->machlen; ++ enum asn1_opcode op; ++ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; ++ const char *errmsg; ++ size_t pc = 0, dp = 0, tdp = 0, len = 0; ++ int ret; ++ ++ unsigned char flags = 0; ++#define FLAG_INDEFINITE_LENGTH 0x01 ++#define FLAG_MATCHED 0x02 ++#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag ++ * - ie. whether or not we are going to parse ++ * a compound type. ++ */ ++ ++#define NR_CONS_STACK 10 ++ unsigned short cons_dp_stack[NR_CONS_STACK]; ++ unsigned short cons_datalen_stack[NR_CONS_STACK]; ++ unsigned char cons_hdrlen_stack[NR_CONS_STACK]; ++#define NR_JUMP_STACK 10 ++ unsigned char jump_stack[NR_JUMP_STACK]; ++ ++ if (datalen > 65535) ++ return -EMSGSIZE; ++ ++next_op: ++ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", ++ pc, machlen, dp, datalen, csp, jsp); ++ if (unlikely(pc >= machlen)) ++ goto machine_overrun_error; ++ op = machine[pc]; ++ if (unlikely(pc + asn1_op_lengths[op] > machlen)) ++ goto machine_overrun_error; ++ ++ /* If this command is meant to match a tag, then do that before ++ * evaluating the command. ++ */ ++ if (op <= ASN1_OP__MATCHES_TAG) { ++ unsigned char tmp; ++ ++ /* Skip conditional matches if possible */ ++ if ((op & ASN1_OP_MATCH__COND && ++ flags & FLAG_MATCHED) || ++ dp == datalen) { ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ } ++ ++ flags = 0; ++ hdr = 2; ++ ++ /* Extract a tag from the data */ ++ if (unlikely(dp >= datalen - 1)) ++ goto data_overrun_error; ++ tag = data[dp++]; ++ if (unlikely((tag & 0x1f) == 0x1f)) ++ goto long_tag_not_supported; ++ ++ if (op & ASN1_OP_MATCH__ANY) { ++ pr_debug("- any %02x\n", tag); ++ } else { ++ /* Extract the tag from the machine ++ * - Either CONS or PRIM are permitted in the data if ++ * CONS is not set in the op stream, otherwise CONS ++ * is mandatory. ++ */ ++ optag = machine[pc + 1]; ++ flags |= optag & FLAG_CONS; ++ ++ /* Determine whether the tag matched */ ++ tmp = optag ^ tag; ++ tmp &= ~(optag & ASN1_CONS_BIT); ++ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); ++ if (tmp != 0) { ++ /* All odd-numbered tags are MATCH_OR_SKIP. */ ++ if (op & ASN1_OP_MATCH__SKIP) { ++ pc += asn1_op_lengths[op]; ++ dp--; ++ goto next_op; ++ } ++ goto tag_mismatch; ++ } ++ } ++ flags |= FLAG_MATCHED; ++ ++ len = data[dp++]; ++ if (len > 0x7f) { ++ if (unlikely(len == 0x80)) { ++ /* Indefinite length */ ++ if (unlikely(!(tag & ASN1_CONS_BIT))) ++ goto indefinite_len_primitive; ++ flags |= FLAG_INDEFINITE_LENGTH; ++ if (unlikely(2 > datalen - dp)) ++ goto data_overrun_error; ++ } else { ++ int n = len - 0x80; ++ if (unlikely(n > 2)) ++ goto length_too_long; ++ if (unlikely(dp >= datalen - n)) ++ goto data_overrun_error; ++ hdr += n; ++ for (len = 0; n > 0; n--) { ++ len <<= 8; ++ len |= data[dp++]; ++ } ++ if (unlikely(len > datalen - dp)) ++ goto data_overrun_error; ++ } ++ } ++ ++ if (flags & FLAG_CONS) { ++ /* For expected compound forms, we stack the positions ++ * of the start and end of the data. ++ */ ++ if (unlikely(csp >= NR_CONS_STACK)) ++ goto cons_stack_overflow; ++ cons_dp_stack[csp] = dp; ++ cons_hdrlen_stack[csp] = hdr; ++ if (!(flags & FLAG_INDEFINITE_LENGTH)) { ++ cons_datalen_stack[csp] = datalen; ++ datalen = dp + len; ++ } else { ++ cons_datalen_stack[csp] = 0; ++ } ++ csp++; ++ } ++ ++ pr_debug("- TAG: %02x %zu%s\n", ++ tag, len, flags & FLAG_CONS ? " CONS" : ""); ++ tdp = dp; ++ } ++ ++ /* Decide how to handle the operation */ ++ switch (op) { ++ case ASN1_OP_MATCH_ANY_ACT: ++ case ASN1_OP_COND_MATCH_ANY_ACT: ++ ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); ++ if (ret < 0) ++ return ret; ++ goto skip_data; ++ ++ case ASN1_OP_MATCH_ACT: ++ case ASN1_OP_MATCH_ACT_OR_SKIP: ++ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: ++ ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); ++ if (ret < 0) ++ return ret; ++ goto skip_data; ++ ++ case ASN1_OP_MATCH: ++ case ASN1_OP_MATCH_OR_SKIP: ++ case ASN1_OP_MATCH_ANY: ++ case ASN1_OP_COND_MATCH_OR_SKIP: ++ case ASN1_OP_COND_MATCH_ANY: ++ skip_data: ++ if (!(flags & FLAG_CONS)) { ++ if (flags & FLAG_INDEFINITE_LENGTH) { ++ len = asn1_find_indefinite_length( ++ data + dp, datalen - dp, &errmsg, &dp); ++ if (len < 0) ++ goto error; ++ } ++ pr_debug("- LEAF: %zu\n", len); ++ dp += len; ++ } ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_MATCH_JUMP: ++ case ASN1_OP_MATCH_JUMP_OR_SKIP: ++ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: ++ pr_debug("- MATCH_JUMP\n"); ++ if (unlikely(jsp == NR_JUMP_STACK)) ++ goto jump_stack_overflow; ++ jump_stack[jsp++] = pc + asn1_op_lengths[op]; ++ pc = machine[pc + 2]; ++ goto next_op; ++ ++ case ASN1_OP_COND_FAIL: ++ if (unlikely(!(flags & FLAG_MATCHED))) ++ goto tag_mismatch; ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_COMPLETE: ++ if (unlikely(jsp != 0 || csp != 0)) { ++ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", ++ jsp, csp); ++ return -EBADMSG; ++ } ++ return 0; ++ ++ case ASN1_OP_END_SET: ++ case ASN1_OP_END_SET_ACT: ++ if (unlikely(!(flags & FLAG_MATCHED))) ++ goto tag_mismatch; ++ case ASN1_OP_END_SEQ: ++ case ASN1_OP_END_SET_OF: ++ case ASN1_OP_END_SEQ_OF: ++ case ASN1_OP_END_SEQ_ACT: ++ case ASN1_OP_END_SET_OF_ACT: ++ case ASN1_OP_END_SEQ_OF_ACT: ++ if (unlikely(csp <= 0)) ++ goto cons_stack_underflow; ++ csp--; ++ tdp = cons_dp_stack[csp]; ++ hdr = cons_hdrlen_stack[csp]; ++ len = datalen; ++ datalen = cons_datalen_stack[csp]; ++ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", ++ tdp, dp, len, datalen); ++ if (datalen == 0) { ++ /* Indefinite length - check for the EOC. */ ++ datalen = len; ++ if (unlikely(datalen - dp < 2)) ++ goto data_overrun_error; ++ if (data[dp++] != 0) { ++ if (op & ASN1_OP_END__OF) { ++ dp--; ++ csp++; ++ pc = machine[pc + 1]; ++ pr_debug("- continue\n"); ++ goto next_op; ++ } ++ goto missing_eoc; ++ } ++ if (data[dp++] != 0) ++ goto invalid_eoc; ++ len = dp - tdp - 2; ++ } else { ++ if (dp < len && (op & ASN1_OP_END__OF)) { ++ datalen = len; ++ csp++; ++ pc = machine[pc + 1]; ++ pr_debug("- continue\n"); ++ goto next_op; ++ } ++ if (dp != len) ++ goto cons_length_error; ++ len -= tdp; ++ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); ++ } ++ ++ if (op & ASN1_OP_END__ACT) { ++ unsigned char act; ++ if (op & ASN1_OP_END__OF) ++ act = machine[pc + 2]; ++ else ++ act = machine[pc + 1]; ++ ret = actions[act](context, hdr, 0, data + tdp, len); ++ } ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_ACT: ++ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_RETURN: ++ if (unlikely(jsp <= 0)) ++ goto jump_stack_underflow; ++ pc = jump_stack[--jsp]; ++ goto next_op; ++ ++ default: ++ break; ++ } ++ ++ /* Shouldn't reach here */ ++ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); ++ return -EBADMSG; ++ ++data_overrun_error: ++ errmsg = "Data overrun error"; ++ goto error; ++machine_overrun_error: ++ errmsg = "Machine overrun error"; ++ goto error; ++jump_stack_underflow: ++ errmsg = "Jump stack underflow"; ++ goto error; ++jump_stack_overflow: ++ errmsg = "Jump stack overflow"; ++ goto error; ++cons_stack_underflow: ++ errmsg = "Cons stack underflow"; ++ goto error; ++cons_stack_overflow: ++ errmsg = "Cons stack overflow"; ++ goto error; ++cons_length_error: ++ errmsg = "Cons length error"; ++ goto error; ++missing_eoc: ++ errmsg = "Missing EOC in indefinite len cons"; ++ goto error; ++invalid_eoc: ++ errmsg = "Invalid length EOC"; ++ goto error; ++length_too_long: ++ errmsg = "Unsupported length"; ++ goto error; ++indefinite_len_primitive: ++ errmsg = "Indefinite len primitive not permitted"; ++ goto error; ++tag_mismatch: ++ errmsg = "Unexpected tag"; ++ goto error; ++long_tag_not_supported: ++ errmsg = "Long tag not supported"; ++error: ++ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", ++ errmsg, pc, dp, optag, tag, len); ++ return -EBADMSG; ++} ++EXPORT_SYMBOL_GPL(asn1_ber_decoder); +-- +1.7.11.4 + + +From f055a9091c35be0171d39ca8e76bb4677d89eef1 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:27 +0100 +Subject: [PATCH 16/26] MPILIB: Provide a function to read raw data into an + MPI + +Provide a function to read raw data of a predetermined size into an MPI rather +than expecting the size to be encoded within the data. The data is assumed to +represent an unsigned integer, and the resulting MPI will be positive. + +The function looks like this: + + MPI mpi_read_raw_data(const void *, size_t); + +This is useful for reading ASN.1 integer primitives where the length is encoded +in the ASN.1 metadata. + +Signed-off-by: David Howells +--- + include/linux/mpi.h | 1 + + lib/mpi/mpicoder.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+) + +diff --git a/include/linux/mpi.h b/include/linux/mpi.h +index d02cca6..5af1b81 100644 +--- a/include/linux/mpi.h ++++ b/include/linux/mpi.h +@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); + + /*-- mpicoder.c --*/ + MPI do_encode_md(const void *sha_buffer, unsigned nbits); ++MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); + MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); + int mpi_fromstr(MPI val, const char *str); + u32 mpi_get_keyid(MPI a, u32 *keyid); +diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c +index f0fa659..3962b7f 100644 +--- a/lib/mpi/mpicoder.c ++++ b/lib/mpi/mpicoder.c +@@ -18,10 +18,65 @@ + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + ++#include ++#include + #include "mpi-internal.h" + + #define MAX_EXTERN_MPI_BITS 16384 + ++/** ++ * mpi_read_raw_data - Read a raw byte stream as a positive integer ++ * @xbuffer: The data to read ++ * @nbytes: The amount of data to read ++ */ ++MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) ++{ ++ const uint8_t *buffer = xbuffer; ++ int i, j; ++ unsigned nbits, nlimbs; ++ mpi_limb_t a; ++ MPI val = NULL; ++ ++ while (nbytes >= 0 && buffer[0] == 0) { ++ buffer++; ++ nbytes--; ++ } ++ ++ nbits = nbytes * 8; ++ if (nbits > MAX_EXTERN_MPI_BITS) { ++ pr_info("MPI: mpi too large (%u bits)\n", nbits); ++ return NULL; ++ } ++ if (nbytes > 0) ++ nbits -= count_leading_zeros(buffer[0]); ++ else ++ nbits = 0; ++ ++ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; ++ val = mpi_alloc(nlimbs); ++ if (!val) ++ return NULL; ++ val->nbits = nbits; ++ val->sign = 0; ++ val->nlimbs = nlimbs; ++ ++ if (nbytes > 0) { ++ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; ++ i %= BYTES_PER_MPI_LIMB; ++ for (j = nlimbs; j > 0; j--) { ++ a = 0; ++ for (; i < BYTES_PER_MPI_LIMB; i++) { ++ a <<= 8; ++ a |= *buffer++; ++ } ++ i = 0; ++ val->d[j - 1] = a; ++ } ++ } ++ return val; ++} ++EXPORT_SYMBOL_GPL(mpi_read_raw_data); ++ + MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) + { + const uint8_t *buffer = xbuffer; +-- +1.7.11.4 + + +From 3d816cdad8cdd5412ecc8f539bb09daef52ba361 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:48 +0100 +Subject: [PATCH 17/26] X.509: Add a crypto key parser for binary (DER) X.509 + certificates + +Add a crypto key parser for binary (DER) encoded X.509 certificates. The +certificate is parsed and, if possible, the signature is verified. + +An X.509 key can be added like this: + + # keyctl padd crypto bar @s +--- + crypto/asymmetric_keys/.gitignore | 1 + + crypto/asymmetric_keys/Kconfig | 10 + + crypto/asymmetric_keys/Makefile | 17 + + crypto/asymmetric_keys/x509.asn1 | 60 ++++ + crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/x509_parser.h | 36 +++ + crypto/asymmetric_keys/x509_public_key.c | 207 +++++++++++++ + crypto/asymmetric_keys/x509_rsakey.asn1 | 4 + + 8 files changed, 832 insertions(+) + create mode 100644 crypto/asymmetric_keys/.gitignore + create mode 100644 crypto/asymmetric_keys/x509.asn1 + create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c + create mode 100644 crypto/asymmetric_keys/x509_parser.h + create mode 100644 crypto/asymmetric_keys/x509_public_key.c + create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 + +diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore +new file mode 100644 +index 0000000..ee32837 +--- /dev/null ++++ b/crypto/asymmetric_keys/.gitignore +@@ -0,0 +1 @@ ++*-asn1.[ch] +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 561759d..6d2c2ea 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA + help + This option enables support for the RSA algorithm (PKCS#1, RFC3447). + ++config X509_CERTIFICATE_PARSER ++ tristate "X.509 certificate parser" ++ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select ASN1 ++ select OID_REGISTRY ++ help ++ This option procides support for parsing X.509 format blobs for key ++ data and provides the ability to instantiate a crypto key from a ++ public key packet found inside the certificate. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 7c92691..0727204 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++ ++# ++# X.509 Certificate handling ++# ++obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o ++x509_key_parser-y := \ ++ x509-asn1.o \ ++ x509_rsakey-asn1.o \ ++ x509_cert_parser.o \ ++ x509_public_key.o ++ ++$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h ++$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h ++$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h ++ ++clean-files += x509-asn1.c x509-asn1.h ++clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h +diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 +new file mode 100644 +index 0000000..bf32b3d +--- /dev/null ++++ b/crypto/asymmetric_keys/x509.asn1 +@@ -0,0 +1,60 @@ ++Certificate ::= SEQUENCE { ++ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), ++ signatureAlgorithm AlgorithmIdentifier, ++ signature BIT STRING ({ x509_note_signature }) ++ } ++ ++TBSCertificate ::= SEQUENCE { ++ version [ 0 ] Version DEFAULT, ++ serialNumber CertificateSerialNumber, ++ signature AlgorithmIdentifier ({ x509_note_pkey_algo }), ++ issuer Name ({ x509_note_issuer }), ++ validity Validity, ++ subject Name ({ x509_note_subject }), ++ subjectPublicKeyInfo SubjectPublicKeyInfo, ++ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, ++ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, ++ extensions [ 3 ] Extensions OPTIONAL ++ } ++ ++Version ::= INTEGER ++CertificateSerialNumber ::= INTEGER ++ ++AlgorithmIdentifier ::= SEQUENCE { ++ algorithm OBJECT IDENTIFIER ({ x509_note_OID }), ++ parameters ANY OPTIONAL ++} ++ ++Name ::= SEQUENCE OF RelativeDistinguishedName ++ ++RelativeDistinguishedName ::= SET OF AttributeValueAssertion ++ ++AttributeValueAssertion ::= SEQUENCE { ++ attributeType OBJECT IDENTIFIER ({ x509_note_OID }), ++ attributeValue ANY ({ x509_extract_name_segment }) ++ } ++ ++Validity ::= SEQUENCE { ++ notBefore Time ({ x509_note_not_before }), ++ notAfter Time ({ x509_note_not_after }) ++ } ++ ++Time ::= CHOICE { ++ utcTime UTCTime, ++ generalTime GeneralizedTime ++ } ++ ++SubjectPublicKeyInfo ::= SEQUENCE { ++ algorithm AlgorithmIdentifier, ++ subjectPublicKey BIT STRING ({ x509_extract_key_data }) ++ } ++ ++UniqueIdentifier ::= BIT STRING ++ ++Extensions ::= SEQUENCE OF Extension ++ ++Extension ::= SEQUENCE { ++ extnid OBJECT IDENTIFIER ({ x509_note_OID }), ++ critical BOOLEAN DEFAULT, ++ extnValue OCTET STRING ({ x509_process_extension }) ++ } +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +new file mode 100644 +index 0000000..8fcac94 +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -0,0 +1,497 @@ ++/* X.509 certificate parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "X.509: "fmt ++#include ++#include ++#include ++#include ++#include "public_key.h" ++#include "x509_parser.h" ++#include "x509-asn1.h" ++#include "x509_rsakey-asn1.h" ++ ++struct x509_parse_context { ++ struct x509_certificate *cert; /* Certificate being constructed */ ++ unsigned long data; /* Start of data */ ++ const void *cert_start; /* Start of cert content */ ++ const void *key; /* Key data */ ++ size_t key_size; /* Size of key data */ ++ enum OID last_oid; /* Last OID encountered */ ++ enum OID algo_oid; /* Algorithm OID */ ++ unsigned char nr_mpi; /* Number of MPIs stored */ ++ u8 o_size; /* Size of organizationName (O) */ ++ u8 cn_size; /* Size of commonName (CN) */ ++ u8 email_size; /* Size of emailAddress */ ++ u16 o_offset; /* Offset of organizationName (O) */ ++ u16 cn_offset; /* Offset of commonName (CN) */ ++ u16 email_offset; /* Offset of emailAddress */ ++}; ++ ++/* ++ * Free an X.509 certificate ++ */ ++void x509_free_certificate(struct x509_certificate *cert) ++{ ++ if (cert) { ++ public_key_destroy(cert->pub); ++ kfree(cert->issuer); ++ kfree(cert->subject); ++ kfree(cert->fingerprint); ++ kfree(cert->authority); ++ kfree(cert); ++ } ++} ++ ++/* ++ * Parse an X.509 certificate ++ */ ++struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) ++{ ++ struct x509_certificate *cert; ++ struct x509_parse_context *ctx; ++ long ret; ++ ++ ret = -ENOMEM; ++ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); ++ if (!cert) ++ goto error_no_cert; ++ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); ++ if (!cert->pub) ++ goto error_no_ctx; ++ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); ++ if (!ctx) ++ goto error_no_ctx; ++ ++ ctx->cert = cert; ++ ctx->data = (unsigned long)data; ++ ++ /* Attempt to decode the certificate */ ++ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); ++ if (ret < 0) ++ goto error_decode; ++ ++ /* Decode the public key */ ++ ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, ++ ctx->key, ctx->key_size); ++ if (ret < 0) ++ goto error_decode; ++ ++ kfree(ctx); ++ return cert; ++ ++error_decode: ++ kfree(ctx); ++error_no_ctx: ++ x509_free_certificate(cert); ++error_no_cert: ++ return ERR_PTR(ret); ++} ++ ++/* ++ * Note an OID when we find one for later processing when we know how ++ * to interpret it. ++ */ ++int x509_note_OID(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ ctx->last_oid = look_up_OID(value, vlen); ++ if (ctx->last_oid == OID__NR) { ++ char buffer[50]; ++ sprint_oid(value, vlen, buffer, sizeof(buffer)); ++ pr_debug("Unknown OID: [%zu] %s\n", ++ (unsigned long)value - ctx->data, buffer); ++ } ++ return 0; ++} ++ ++/* ++ * Save the position of the TBS data so that we can check the signature over it ++ * later. ++ */ ++int x509_note_tbs_certificate(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", ++ hdrlen, tag, (unsigned long)value - ctx->data, vlen); ++ ++ ctx->cert->tbs = value - hdrlen; ++ ctx->cert->tbs_size = vlen + hdrlen; ++ return 0; ++} ++ ++/* ++ * Record the public key algorithm ++ */ ++int x509_note_pkey_algo(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("PubKey Algo: %u\n", ctx->last_oid); ++ ++ switch (ctx->last_oid) { ++ case OID_md2WithRSAEncryption: ++ case OID_md3WithRSAEncryption: ++ default: ++ return -ENOPKG; /* Unsupported combination */ ++ ++ case OID_md4WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_MD5; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha1WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha256WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha384WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha512WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha224WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ } ++ ++ ctx->algo_oid = ctx->last_oid; ++ return 0; ++} ++ ++/* ++ * Note the whereabouts and type of the signature. ++ */ ++int x509_note_signature(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); ++ ++ if (ctx->last_oid != ctx->algo_oid) { ++ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", ++ ctx->algo_oid, ctx->last_oid); ++ return -EINVAL; ++ } ++ ++ ctx->cert->sig = value; ++ ctx->cert->sig_size = vlen; ++ return 0; ++} ++ ++/* ++ * Note some of the name segments from which we'll fabricate a name. ++ */ ++int x509_extract_name_segment(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ switch (ctx->last_oid) { ++ case OID_commonName: ++ ctx->cn_size = vlen; ++ ctx->cn_offset = (unsigned long)value - ctx->data; ++ break; ++ case OID_organizationName: ++ ctx->o_size = vlen; ++ ctx->o_offset = (unsigned long)value - ctx->data; ++ break; ++ case OID_email_address: ++ ctx->email_size = vlen; ++ ctx->email_offset = (unsigned long)value - ctx->data; ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Fabricate and save the issuer and subject names ++ */ ++static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, ++ unsigned char tag, ++ char **_name, size_t vlen) ++{ ++ const void *name, *data = (const void *)ctx->data; ++ size_t namesize; ++ char *buffer; ++ ++ if (*_name) ++ return -EINVAL; ++ ++ /* Empty name string if no material */ ++ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { ++ buffer = kmalloc(1, GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ buffer[0] = 0; ++ goto done; ++ } ++ ++ if (ctx->cn_size && ctx->o_size) { ++ /* Consider combining O and CN, but use only the CN if it is ++ * prefixed by the O, or a significant portion thereof. ++ */ ++ namesize = ctx->cn_size; ++ name = data + ctx->cn_offset; ++ if (ctx->cn_size >= ctx->o_size && ++ memcmp(data + ctx->cn_offset, data + ctx->o_offset, ++ ctx->o_size) == 0) ++ goto single_component; ++ if (ctx->cn_size >= 7 && ++ ctx->o_size >= 7 && ++ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) ++ goto single_component; ++ ++ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, ++ GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ ++ memcpy(buffer, ++ data + ctx->o_offset, ctx->o_size); ++ buffer[ctx->o_size + 0] = ':'; ++ buffer[ctx->o_size + 1] = ' '; ++ memcpy(buffer + ctx->o_size + 2, ++ data + ctx->cn_offset, ctx->cn_size); ++ buffer[ctx->o_size + 2 + ctx->cn_size] = 0; ++ goto done; ++ ++ } else if (ctx->cn_size) { ++ namesize = ctx->cn_size; ++ name = data + ctx->cn_offset; ++ } else if (ctx->o_size) { ++ namesize = ctx->o_size; ++ name = data + ctx->o_offset; ++ } else { ++ namesize = ctx->email_size; ++ name = data + ctx->email_offset; ++ } ++ ++single_component: ++ buffer = kmalloc(namesize + 1, GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ memcpy(buffer, name, namesize); ++ buffer[namesize] = 0; ++ ++done: ++ *_name = buffer; ++ ctx->cn_size = 0; ++ ctx->o_size = 0; ++ ctx->email_size = 0; ++ return 0; ++} ++ ++int x509_note_issuer(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); ++} ++ ++int x509_note_subject(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); ++} ++ ++/* ++ * Extract the data for the public key algorithm ++ */ ++int x509_extract_key_data(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ if (ctx->last_oid != OID_rsaEncryption) ++ return -ENOPKG; ++ ++ /* There seems to be an extraneous 0 byte on the front of the data */ ++ ctx->cert->pkey_algo = PKEY_ALGO_RSA; ++ ctx->key = value + 1; ++ ctx->key_size = vlen - 1; ++ return 0; ++} ++ ++/* ++ * Extract a RSA public key value ++ */ ++int rsa_extract_mpi(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ MPI mpi; ++ ++ if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { ++ pr_err("Too many public key MPIs in certificate\n"); ++ return -EBADMSG; ++ } ++ ++ mpi = mpi_read_raw_data(value, vlen); ++ if (!mpi) ++ return -ENOMEM; ++ ++ ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; ++ return 0; ++} ++ ++/* ++ * Process certificate extensions that are used to qualify the certificate. ++ */ ++int x509_process_extension(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ const unsigned char *v = value; ++ char *f; ++ int i; ++ ++ pr_debug("Extension: %u\n", ctx->last_oid); ++ ++ if (ctx->last_oid == OID_subjectKeyIdentifier) { ++ /* Get hold of the key fingerprint */ ++ if (vlen < 3) ++ return -EBADMSG; ++ if (v[0] != ASN1_OTS || v[1] != vlen - 2) ++ return -EBADMSG; ++ v += 2; ++ vlen -= 2; ++ ++ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); ++ if (!f) ++ return -ENOMEM; ++ for (i = 0; i < vlen; i++) ++ sprintf(f + i * 2, "%02x", v[i]); ++ pr_debug("fingerprint %s\n", f); ++ ctx->cert->fingerprint = f; ++ return 0; ++ } ++ ++ if (ctx->last_oid == OID_authorityKeyIdentifier) { ++ /* Get hold of the CA key fingerprint */ ++ if (vlen < 5) ++ return -EBADMSG; ++ if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || ++ v[1] != vlen - 2 || ++ v[2] != (ASN1_CONT << 6) || ++ v[3] != vlen - 4) ++ return -EBADMSG; ++ v += 4; ++ vlen -= 4; ++ ++ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); ++ if (!f) ++ return -ENOMEM; ++ for (i = 0; i < vlen; i++) ++ sprintf(f + i * 2, "%02x", v[i]); ++ pr_debug("authority %s\n", f); ++ ctx->cert->authority = f; ++ return 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Record a certificate time. ++ */ ++static int x509_note_time(time_t *_time, size_t hdrlen, ++ unsigned char tag, ++ const unsigned char *value, size_t vlen) ++{ ++ unsigned YY, MM, DD, hh, mm, ss; ++ const unsigned char *p = value; ++ ++#define dec2bin(X) ((X) - '0') ++#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) ++ ++ if (tag == ASN1_UNITIM) { ++ /* UTCTime: YYMMDDHHMMSSZ */ ++ if (vlen != 13) ++ goto unsupported_time; ++ YY = DD2bin(p); ++ if (YY > 50) ++ YY += 1900; ++ else ++ YY += 2000; ++ } else if (tag == ASN1_GENTIM) { ++ /* GenTime: YYYYMMDDHHMMSSZ */ ++ if (vlen != 15) ++ goto unsupported_time; ++ YY = DD2bin(p) * 100 + DD2bin(p); ++ } else { ++ goto unsupported_time; ++ } ++ ++ MM = DD2bin(p); ++ DD = DD2bin(p); ++ hh = DD2bin(p); ++ mm = DD2bin(p); ++ ss = DD2bin(p); ++ ++ if (*p != 'Z') ++ goto unsupported_time; ++ ++ *_time = mktime(YY, MM, DD, hh, mm, ss); ++ return 0; ++ ++unsupported_time: ++ pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", ++ tag, (int)vlen, (int)vlen, value); ++ return -EBADMSG; ++} ++ ++int x509_note_not_before(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); ++} ++ ++int x509_note_not_after(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); ++} +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +new file mode 100644 +index 0000000..635053f +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -0,0 +1,36 @@ ++/* X.509 certificate parser internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++ ++struct x509_certificate { ++ struct x509_certificate *next; ++ struct public_key *pub; /* Public key details */ ++ char *issuer; /* Name of certificate issuer */ ++ char *subject; /* Name of certificate subject */ ++ char *fingerprint; /* Key fingerprint as hex */ ++ char *authority; /* Authority key fingerprint as hex */ ++ time_t valid_from; ++ time_t valid_to; ++ enum pkey_algo pkey_algo : 8; /* Public key algorithm */ ++ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ ++ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ ++ const void *tbs; /* Signed data */ ++ size_t tbs_size; /* Size of signed data */ ++ const void *sig; /* Signature data */ ++ size_t sig_size; /* Size of sigature */ ++}; ++ ++/* ++ * x509_cert_parser.c ++ */ ++extern void x509_free_certificate(struct x509_certificate *cert); ++extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +new file mode 100644 +index 0000000..716917c +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -0,0 +1,207 @@ ++/* Instantiate a public key crypto key from an X.509 Certificate ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "X.509: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++#include "public_key.h" ++#include "x509_parser.h" ++ ++static const ++struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { ++ [PKEY_ALGO_DSA] = NULL, ++#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ ++ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) ++ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, ++#endif ++}; ++ ++/* ++ * Check the signature on a certificate using the provided public key ++ */ ++static int x509_check_signature(const struct public_key *pub, ++ const struct x509_certificate *cert) ++{ ++ struct public_key_signature *sig; ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ ++ /* We allocate the hash operational data storage on the end of our ++ * context data. ++ */ ++ ret = -ENOMEM; ++ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); ++ if (!sig) ++ goto error_no_sig; ++ ++ sig->pkey_hash_algo = cert->sig_hash_algo; ++ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; ++ sig->digest_size = digest_size; ++ ++ desc = (void *)sig + sizeof(*sig); ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ++ ret = -ENOMEM; ++ sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); ++ if (!sig->rsa.s) ++ goto error; ++ ++ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); ++ if (ret < 0) ++ goto error_mpi; ++ ++ ret = pub->algo->verify_signature(pub, sig); ++ ++ pr_debug("Cert Verification: %d\n", ret); ++ ++error_mpi: ++ mpi_free(sig->rsa.s); ++error: ++ kfree(sig); ++error_no_sig: ++ crypto_free_shash(tfm); ++ ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++ ++/* ++ * Attempt to parse a data blob for a key as an X509 certificate. ++ */ ++static int x509_key_preparse(struct key_preparsed_payload *prep) ++{ ++ struct x509_certificate *cert; ++ time_t now; ++ size_t srlen, sulen; ++ char *desc = NULL; ++ int ret; ++ ++ cert = x509_cert_parse(prep->data, prep->datalen); ++ if (IS_ERR(cert)) ++ return PTR_ERR(cert); ++ ++ pr_devel("Cert Issuer: %s\n", cert->issuer); ++ pr_devel("Cert Subject: %s\n", cert->subject); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); ++ pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); ++ pr_devel("Cert Signature: %s + %s\n", ++ pkey_algo[cert->sig_pkey_algo], ++ pkey_hash_algo[cert->sig_hash_algo]); ++ ++ if (!cert->fingerprint || !cert->authority) { ++ pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", ++ cert->subject); ++ ret = -EKEYREJECTED; ++ goto error_free_cert; ++ } ++ ++ now = CURRENT_TIME.tv_sec; ++ if (now < cert->valid_from) { ++ pr_warn("Cert %s is not yet valid\n", cert->fingerprint); ++ ret = -EKEYREJECTED; ++ goto error_free_cert; ++ } ++ if (now >= cert->valid_to) { ++ pr_warn("Cert %s has expired\n", cert->fingerprint); ++ ret = -EKEYEXPIRED; ++ goto error_free_cert; ++ } ++ ++ cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; ++ cert->pub->id_type = PKEY_ID_X509; ++ ++ /* Check the signature on the key */ ++ if (strcmp(cert->fingerprint, cert->authority) == 0) { ++ ret = x509_check_signature(cert->pub, cert); ++ if (ret < 0) ++ goto error_free_cert; ++ } ++ ++ /* Propose a description */ ++ sulen = strlen(cert->subject); ++ srlen = strlen(cert->fingerprint); ++ ret = -ENOMEM; ++ desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); ++ if (!desc) ++ goto error_free_cert; ++ memcpy(desc, cert->subject, sulen); ++ desc[sulen] = ':'; ++ desc[sulen + 1] = ' '; ++ memcpy(desc + sulen + 2, cert->fingerprint, srlen); ++ desc[sulen + 2 + srlen] = 0; ++ ++ /* We're pinning the module by being linked against it */ ++ __module_get(public_key_subtype.owner); ++ prep->type_data[0] = &public_key_subtype; ++ prep->type_data[1] = cert->fingerprint; ++ prep->payload = cert->pub; ++ prep->description = desc; ++ prep->quotalen = 100; ++ ++ /* We've finished with the certificate */ ++ cert->pub = NULL; ++ cert->fingerprint = NULL; ++ desc = NULL; ++ ret = 0; ++ ++error_free_cert: ++ x509_free_certificate(cert); ++ return ret; ++} ++ ++static struct asymmetric_key_parser x509_key_parser = { ++ .owner = THIS_MODULE, ++ .name = "x509", ++ .parse = x509_key_preparse, ++}; ++ ++/* ++ * Module stuff ++ */ ++static int __init x509_key_init(void) ++{ ++ return register_asymmetric_key_parser(&x509_key_parser); ++} ++ ++static void __exit x509_key_exit(void) ++{ ++ unregister_asymmetric_key_parser(&x509_key_parser); ++} ++ ++module_init(x509_key_init); ++module_exit(x509_key_exit); +diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 +new file mode 100644 +index 0000000..4ec7cc6 +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_rsakey.asn1 +@@ -0,0 +1,4 @@ ++RSAPublicKey ::= SEQUENCE { ++ modulus INTEGER ({ rsa_extract_mpi }), -- n ++ publicExponent INTEGER ({ rsa_extract_mpi }) -- e ++ } +-- +1.7.11.4 + + +From 955fc6ec995f6bec6c487eb46027e108e240ebe3 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:25 +0100 +Subject: [PATCH 18/26] MOD: Fix Rusty's module_sig_check() + +Make the following fixes to Rusty's module_sig_check() function: + + (1) mod_verify_sig() is not defined, resulting in a compilation error and + thereby breaking git bisect, so provide a dummy that returns an error. + + (2) Using strlen() on a static string is a waste of resources. Further, you + may end up with two copies of the string emitted. + + (3) Doing a memchr() of the bytes beyond the last position that the marker + can be in is a waste of resources. + +While we're at it, push responsibility for the return value entirely off to +mod_verify_sig() if we find a signature. + +Signed-off-by: David Howells +--- + kernel/Makefile | 1 + + kernel/module-internal.h | 14 ++++++++++++++ + kernel/module.c | 41 +++++++++++++++++++++++------------------ + kernel/module_signing.c | 23 +++++++++++++++++++++++ + 4 files changed, 61 insertions(+), 18 deletions(-) + create mode 100644 kernel/module-internal.h + create mode 100644 kernel/module_signing.c + +diff --git a/kernel/Makefile b/kernel/Makefile +index c0cc67a..08ba8a6 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +new file mode 100644 +index 0000000..14da0ea +--- /dev/null ++++ b/kernel/module-internal.h +@@ -0,0 +1,14 @@ ++/* Module internals ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++extern int mod_verify_sig(const void *mod, unsigned long modlen, ++ const void *sig, unsigned long siglen, ++ bool *_sig_ok); +diff --git a/kernel/module.c b/kernel/module.c +index 5c6f65c..ab69599 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include "module-internal.h" + + #define CREATE_TRACE_POINTS + #include +@@ -2438,34 +2439,38 @@ static inline void kmemleak_load_module(const struct module *mod, + #endif + + #ifdef CONFIG_MODULE_SIG ++ + static int module_sig_check(struct load_info *info, + const void *mod, unsigned long *len) + { ++ static const char module_sig_string[] = MODULE_SIG_STRING; + int err = 0; +- const unsigned long markerlen = strlen(MODULE_SIG_STRING); +- const void *p = mod, *end = mod + *len; +- +- /* Poor man's memmem. */ +- while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { +- if (p + markerlen > end) +- break; +- +- if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { +- const void *sig = p + markerlen; +- /* Truncate module up to signature. */ +- *len = p - mod; +- err = mod_verify_sig(mod, *len, +- sig, end - sig, +- &info->sig_ok); +- break; +- } +- p++; ++ const unsigned long markerlen = sizeof(module_sig_string) - 1; ++ const void *p = mod, *end = mod + *len, *sig; ++ const void *limit = end - markerlen - 1; ++ ++ if (markerlen < *len) { ++ /* Poor man's memmem. */ ++ do { ++ p = memchr(p, MODULE_SIG_STRING[0], limit - p); ++ if (!p) ++ break; ++ if (memcmp(p, module_sig_string, markerlen) != 0) ++ continue; ++ goto found_marker; ++ } while (++p < limit); + } + + /* Not having a signature is only an error if we're strict. */ + if (!err && !info->sig_ok && sig_enforce) + err = -EKEYREJECTED; + return err; ++ ++found_marker: ++ sig = p + markerlen; ++ /* Truncate module up to signature. */ ++ *len = p - mod; ++ return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); + } + #else /* !CONFIG_MODULE_SIG */ + static int module_sig_check(struct load_info *info, +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +new file mode 100644 +index 0000000..0af10a5 +--- /dev/null ++++ b/kernel/module_signing.c +@@ -0,0 +1,23 @@ ++/* Module signature checker ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include "module-internal.h" ++ ++/* ++ * Verify the signature on a module. ++ */ ++int mod_verify_sig(const void *mod, unsigned long modlen, ++ const void *sig, unsigned long siglen, ++ bool *_sig_ok) ++{ ++ return -EKEYREJECTED; ++} +-- +1.7.11.4 + + +From 4c31831859550149cdba65a37d72416c87dbbef6 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:25 +0100 +Subject: [PATCH 19/26] MODSIGN: Provide gitignore and make clean rules for + extra files + +Provide gitignore and make clean rules for extra files to hide and clean up the +extra files produced by module signing stuff once it is added. Also add a +clean up rule for the module content extractor program used to extract the data +to be signed. + +Signed-off-by: David Howells +--- + .gitignore | 13 +++++++++++++ + Makefile | 1 + + 2 files changed, 14 insertions(+) + +diff --git a/.gitignore b/.gitignore +index 57af07c..9736304 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -14,6 +14,10 @@ + *.o.* + *.a + *.s ++*.ko.unsigned ++*.ko.stripped ++*.ko.stripped.dig ++*.ko.stripped.sig + *.ko + *.so + *.so.dbg +@@ -84,3 +88,12 @@ GTAGS + *.orig + *~ + \#*# ++ ++# ++# Leavings from module signing ++# ++extra_certificates ++signing_key.priv ++signing_key.x509 ++signing_key.x509.keyid ++signing_key.x509.signer +diff --git a/Makefile b/Makefile +index 371ce88..644048d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ ++ -o -name '*.ko.*' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ +-- +1.7.11.4 + + +From 6977e69eef4379f34a2ad264856d74ac292284df Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:25 +0100 +Subject: [PATCH 20/26] MODSIGN: Provide Kconfig options + +Provide kernel configuration options for module signing. + +The following configuration options are added: + + CONFIG_MODULE_SIG_SHA1 + CONFIG_MODULE_SIG_SHA224 + CONFIG_MODULE_SIG_SHA256 + CONFIG_MODULE_SIG_SHA384 + CONFIG_MODULE_SIG_SHA512 + +These select the cryptographic hash used to digest the data prior to signing. +Additionally, the crypto module selected will be built into the kernel as it +won't be possible to load it as a module without incurring a circular +dependency when the kernel tries to check its signature. + +Signed-off-by: David Howells +--- + init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/init/Kconfig b/init/Kconfig +index fa8ccad..00d4579 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1593,12 +1593,50 @@ config MODULE_SIG + is simply appended to the module. For more information see + Documentation/module-signing.txt. + ++ !!!WARNING!!! If you enable this option, you MUST make sure that the ++ module DOES NOT get stripped after being signed. This includes the ++ debuginfo strip done by some packagers (such as rpmbuild) and ++ inclusion into an initramfs that wants the module size reduced. ++ + config MODULE_SIG_FORCE + bool "Require modules to be validly signed" + depends on MODULE_SIG + help + Reject unsigned modules or signed modules for which we don't have a + key. Without this, such modules will simply taint the kernel. ++ ++choice ++ prompt "Which hash algorithm should modules be signed with?" ++ depends on MODULE_SIG ++ help ++ This determines which sort of hashing algorithm will be used during ++ signature generation. This algorithm _must_ be built into the kernel ++ directly so that signature verification can take place. It is not ++ possible to load a signed module containing the algorithm to check ++ the signature on that module. ++ ++config MODULE_SIG_SHA1 ++ bool "Sign modules with SHA-1" ++ select CRYPTO_SHA1 ++ ++config MODULE_SIG_SHA224 ++ bool "Sign modules with SHA-224" ++ select CRYPTO_SHA256 ++ ++config MODULE_SIG_SHA256 ++ bool "Sign modules with SHA-256" ++ select CRYPTO_SHA256 ++ ++config MODULE_SIG_SHA384 ++ bool "Sign modules with SHA-384" ++ select CRYPTO_SHA512 ++ ++config MODULE_SIG_SHA512 ++ bool "Sign modules with SHA-512" ++ select CRYPTO_SHA512 ++ ++endchoice ++ + endif # MODULES + + config INIT_ALL_POSSIBLE +-- +1.7.11.4 + + +From 60378703cf88ed221ee602727c37ae241565d44a Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:25 +0100 +Subject: [PATCH 21/26] MODSIGN: Automatically generate module signing keys if + missing + +Automatically generate keys for module signing if they're absent so that +allyesconfig doesn't break. The builder should consider generating their own +key and certificate, however, so that the keys are appropriately named. + +The private key for the module signer should be placed in signing_key.priv +(unencrypted!) and the public key in an X.509 certificate as signing_key.x509. + +If a transient key is desired for signing the modules, a config file for +'openssl req' can be placed in x509.genkey, looking something like the +following: + + [ req ] + default_bits = 4096 + distinguished_name = req_distinguished_name + prompt = no + x509_extensions = myexts + + [ req_distinguished_name ] + O = Magarathea + CN = Glacier signing key + emailAddress = slartibartfast@magrathea.h2g2 + + [ myexts ] + basicConstraints=critical,CA:FALSE + keyUsage=digitalSignature + subjectKeyIdentifier=hash + authorityKeyIdentifier=hash + +The build process will use this to configure: + + openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ + -x509 -config x509.genkey \ + -outform DER -out signing_key.x509 \ + -keyout signing_key.priv + +to generate the key. + +Note that it is required that the X.509 certificate have a subjectKeyIdentifier +and an authorityKeyIdentifier. Without those, the certificate will be +rejected. These can be used to check the validity of a certificate. + +Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey, +whether or not they were generated automatically. + +Signed-off-by: David Howells +--- + kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 08ba8a6..83f1565 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ + targets += timeconst.h + $(obj)/timeconst.h: $(src)/timeconst.pl FORCE + $(call if_changed,timeconst) ++ ++ifeq ($(CONFIG_MODULE_SIG),y) ++ ++############################################################################### ++# ++# If module signing is requested, say by allyesconfig, but a key has not been ++# supplied, then one will need to be generated to make sure the build does not ++# fail and that the kernel may be used afterwards. ++# ++############################################################################### ++signing_key.priv signing_key.x509: x509.genkey ++ @echo "###" ++ @echo "### Now generating an X.509 key pair to be used for signing modules." ++ @echo "###" ++ @echo "### If this takes a long time, you might wish to run rngd in the" ++ @echo "### background to keep the supply of entropy topped up. It" ++ @echo "### needs to be run as root, and should use a hardware random" ++ @echo "### number generator if one is available, eg:" ++ @echo "###" ++ @echo "### rngd -r /dev/hwrandom" ++ @echo "###" ++ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ ++ -x509 -config x509.genkey \ ++ -outform DER -out signing_key.x509 \ ++ -keyout signing_key.priv ++ @echo "###" ++ @echo "### Key pair generated." ++ @echo "###" ++ ++x509.genkey: ++ @echo Generating X.509 key generation config ++ @echo >x509.genkey "[ req ]" ++ @echo >>x509.genkey "default_bits = 4096" ++ @echo >>x509.genkey "distinguished_name = req_distinguished_name" ++ @echo >>x509.genkey "prompt = no" ++ @echo >>x509.genkey "x509_extensions = myexts" ++ @echo >>x509.genkey ++ @echo >>x509.genkey "[ req_distinguished_name ]" ++ @echo >>x509.genkey "O = Magarathea" ++ @echo >>x509.genkey "CN = Glacier signing key" ++ @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" ++ @echo >>x509.genkey ++ @echo >>x509.genkey "[ myexts ]" ++ @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" ++ @echo >>x509.genkey "keyUsage=digitalSignature" ++ @echo >>x509.genkey "subjectKeyIdentifier=hash" ++ @echo >>x509.genkey "authorityKeyIdentifier=keyid" ++endif ++CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey +-- +1.7.11.4 + + +From 798049d9df83c8fd87fd5ddb97a77054558f4361 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:25 +0100 +Subject: [PATCH 22/26] MODSIGN: Provide module signing public keys to the + kernel + +Include a PGP keyring containing the public keys required to perform module +verification in the kernel image during build and create a special keyring +during boot which is then populated with keys of crypto type holding the public +keys found in the PGP keyring. + +These can be seen by root: + +[root@andromeda ~]# cat /proc/keys +07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] +15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 +... + +It is probably worth permitting root to invalidate these keys, resulting in +their removal and preventing further modules from being loaded with that key. + +Signed-off-by: David Howells +--- + kernel/Makefile | 11 ++++- + kernel/modsign_pubkey.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++ + kernel/module-internal.h | 2 + + 3 files changed, 123 insertions(+), 2 deletions(-) + create mode 100644 kernel/modsign_pubkey.c + +diff --git a/kernel/Makefile b/kernel/Makefile +index 83f1565..63f8386 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,7 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o +-obj-$(CONFIG_MODULE_SIG) += module_signing.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE + $(call if_changed,timeconst) + + ifeq ($(CONFIG_MODULE_SIG),y) ++# ++# Pull the signing certificate and any extra certificates into the kernel ++# ++extra_certificates: ++ touch $@ ++ ++kernel/modsign_pubkey.o: signing_key.x509 extra_certificates + + ############################################################################### + # +@@ -180,4 +187,4 @@ x509.genkey: + @echo >>x509.genkey "subjectKeyIdentifier=hash" + @echo >>x509.genkey "authorityKeyIdentifier=keyid" + endif +-CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey ++CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +new file mode 100644 +index 0000000..f504d9f +--- /dev/null ++++ b/kernel/modsign_pubkey.c +@@ -0,0 +1,112 @@ ++/* Public keys for module signature verification ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++struct key *modsign_keyring; ++ ++extern __initdata const u8 modsign_certificate_list[]; ++extern __initdata const u8 modsign_certificate_list_end[]; ++asm(".section .init.data,\"aw\"\n" ++ "modsign_certificate_list:\n" ++ ".incbin \"signing_key.x509\"\n" ++ ".incbin \"extra_certificates\"\n" ++ "modsign_certificate_list_end:" ++ ); ++ ++/* ++ * We need to make sure ccache doesn't cache the .o file as it doesn't notice ++ * if modsign.pub changes. ++ */ ++static __initdata const char annoy_ccache[] = __TIME__ "foo"; ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int module_verify_init(void) ++{ ++ pr_notice("Initialise module verification\n"); ++ ++ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", ++ 0, 0, current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_keyring)) ++ panic("Can't allocate module signing keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module signing keyring\n"); ++ ++ return 0; ++} ++ ++/* ++ * Must be initialised before we try and load the keys into the keyring. ++ */ ++device_initcall(module_verify_init); ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int load_module_signing_keys(void) ++{ ++ key_ref_t key; ++ const u8 *p, *end; ++ size_t plen; ++ ++ pr_notice("Loading module verification certificates\n"); ++ ++ end = modsign_certificate_list_end; ++ p = modsign_certificate_list; ++ while (p < end) { ++ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more ++ * than 256 bytes in size. ++ */ ++ if (end - p < 4) ++ goto dodgy_cert; ++ if (p[0] != 0x30 && ++ p[1] != 0x82) ++ goto dodgy_cert; ++ plen = (p[2] << 8) | p[3]; ++ plen += 4; ++ if (plen > end - p) ++ goto dodgy_cert; ++ ++ key = key_create_or_update(make_key_ref(modsign_keyring, 1), ++ "asymmetric", ++ NULL, ++ p, ++ plen, ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(key)) ++ pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("MODSIGN: Loaded cert '%s'\n", ++ key_ref_to_ptr(key)->description); ++ p += plen; ++ } ++ ++ return 0; ++ ++dodgy_cert: ++ pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); ++ return 0; ++} ++late_initcall(load_module_signing_keys); +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 14da0ea..648f481 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -9,6 +9,8 @@ + * 2 of the Licence, or (at your option) any later version. + */ + ++extern struct key *modsign_keyring; ++ + extern int mod_verify_sig(const void *mod, unsigned long modlen, + const void *sig, unsigned long siglen, + bool *_sig_ok); +-- +1.7.11.4 + + +From dcac300c703bc9a237deab7c7f0301f3803a3a9a Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:26 +0100 +Subject: [PATCH 23/26] MODSIGN: Implement module signature checking + +Check the signature on the module against the keys compiled into the kernel or +available in a hardware key store. + +Currently, only RSA keys are supported - though that's easy enough to change, +and the signature is expected to contain raw components (so not a PGP or +PKCS#7 formatted blob). + +The signature blob is expected to consist of the following pieces in order: + + (1) The binary identifier for the key. This is expected to match the + SubjectKeyIdentifier from an X.509 certificate. Only X.509 type + identifiers are currently supported. + + (2) The signature data, consisting of a series of MPIs in which each is in + the format of a 2-byte BE word sizes followed by the content data. + + (3) A 12 byte information block of the form: + + struct module_signature { + enum pkey_algo algo : 8; + enum pkey_hash_algo hash : 8; + enum pkey_id_type id_type : 8; + u8 __pad; + __be32 id_length; + __be32 sig_length; + }; + + The three enums are defined in crypto/public_key.h. + + 'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA). + + 'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1, + etc.). + + 'id_type' contains the public-key identifier type (0->PGP, 1->X.509). + + '__pad' should be 0. + + 'id_length' should contain in the binary identifier length in BE form. + + 'sig_length' should contain in the signature data length in BE form. + + The lengths are in BE order rather than CPU order to make dealing with + cross-compilation easier. + +Signed-off-by: David Howells +--- + init/Kconfig | 8 ++ + kernel/module_signing.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 230 insertions(+), 1 deletion(-) + +diff --git a/init/Kconfig b/init/Kconfig +index 00d4579..63fcbeb 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL + config MODULE_SIG + bool "Module signature verification" + depends on MODULES ++ select CONFIG_KEYS ++ select CONFIG_CRYPTO ++ select ASYMMETRIC_KEY_TYPE ++ select ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select PUBLIC_KEY_ALGO_RSA ++ select ASN1 ++ select OID_REGISTRY ++ select X509_CERTIFICATE_PARSER + help + Check modules for valid signatures upon load: the signature + is simply appended to the module. For more information see +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 0af10a5..83eb505 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -10,14 +10,235 @@ + */ + + #include ++#include ++#include ++#include ++#include + #include "module-internal.h" + + /* ++ * Module signature information block. ++ * ++ * The constituents of the signature section are, in order: ++ * ++ * - Signer's name ++ * - Key identifier ++ * - Signature data ++ * - Information block ++ */ ++struct module_signature { ++ enum pkey_algo algo : 8; /* Public-key crypto algorithm */ ++ enum pkey_hash_algo hash : 8; /* Digest algorithm */ ++ enum pkey_id_type id_type : 8; /* Key identifier type */ ++ u8 signer_len; /* Length of signer's name */ ++ u8 key_id_len; /* Length of key identifier */ ++ u8 __pad[3]; ++ __be32 sig_len; /* Length of signature data */ ++}; ++ ++/* ++ * Digest the module contents. ++ */ ++static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, ++ const void *mod, ++ unsigned long modlen) ++{ ++ struct public_key_signature *pks; ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ ++ /* We allocate the hash operational data storage on the end of our ++ * context data and the digest output buffer on the end of that. ++ */ ++ ret = -ENOMEM; ++ pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); ++ if (!pks) ++ goto error_no_pks; ++ ++ pks->pkey_hash_algo = hash; ++ pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; ++ pks->digest_size = digest_size; ++ ++ desc = (void *)pks + sizeof(*pks); ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ++ ret = crypto_shash_finup(desc, mod, modlen, pks->digest); ++ if (ret < 0) ++ goto error; ++ ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = ok\n", __func__); ++ return pks; ++ ++error: ++ kfree(pks); ++error_no_pks: ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ERR_PTR(ret); ++} ++ ++/* ++ * Extract an MPI array from the signature data. This represents the actual ++ * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the ++ * size of the MPI in bytes. ++ * ++ * RSA signatures only have one MPI, so currently we only read one. ++ */ ++static int mod_extract_mpi_array(struct public_key_signature *pks, ++ const void *data, size_t len) ++{ ++ size_t nbytes; ++ MPI mpi; ++ ++ if (len < 3) ++ return -EBADMSG; ++ nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; ++ data += 2; ++ len -= 2; ++ if (len != nbytes) ++ return -EBADMSG; ++ ++ mpi = mpi_read_raw_data(data, nbytes); ++ if (!mpi) ++ return -ENOMEM; ++ pks->mpi[0] = mpi; ++ pks->nr_mpi = 1; ++ return 0; ++} ++ ++/* ++ * Request an asymmetric key. ++ */ ++static struct key *request_asymmetric_key(const char *signer, size_t signer_len, ++ const u8 *key_id, size_t key_id_len) ++{ ++ key_ref_t key; ++ size_t i; ++ char *id, *q; ++ ++ pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); ++ ++ /* Construct an identifier. */ ++ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); ++ if (!id) ++ return ERR_PTR(-ENOKEY); ++ ++ memcpy(id, signer, signer_len); ++ ++ q = id + signer_len; ++ *q++ = ':'; ++ *q++ = ' '; ++ for (i = 0; i < key_id_len; i++) { ++ *q++ = hex_asc[*key_id >> 4]; ++ *q++ = hex_asc[*key_id++ & 0x0f]; ++ } ++ ++ *q = 0; ++ ++ pr_debug("Look up: \"%s\"\n", id); ++ ++ key = keyring_search(make_key_ref(modsign_keyring, 1), ++ &key_type_asymmetric, id); ++ kfree(id); ++ ++ if (IS_ERR(key)) { ++ switch (PTR_ERR(key)) { ++ /* Hide some search errors */ ++ case -EACCES: ++ case -ENOTDIR: ++ case -EAGAIN: ++ return ERR_PTR(-ENOKEY); ++ default: ++ return ERR_CAST(key); ++ } ++ } ++ ++ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); ++ return key_ref_to_ptr(key); ++} ++ ++/* + * Verify the signature on a module. + */ + int mod_verify_sig(const void *mod, unsigned long modlen, + const void *sig, unsigned long siglen, + bool *_sig_ok) + { +- return -EKEYREJECTED; ++ struct public_key_signature *pks; ++ struct module_signature ms; ++ struct key *key; ++ size_t sig_len; ++ int ret; ++ ++ pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); ++ ++ if (siglen <= sizeof(ms)) ++ return -EBADMSG; ++ ++ memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); ++ siglen -= sizeof(ms); ++ ++ sig_len = be32_to_cpu(ms.sig_len); ++ if (sig_len >= siglen || ++ siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) ++ return -EBADMSG; ++ ++ /* For the moment, only support RSA and X.509 identifiers */ ++ if (ms.algo != PKEY_ALGO_RSA || ++ ms.id_type != PKEY_ID_X509) ++ return -ENOPKG; ++ ++ if (ms.hash >= PKEY_HASH__LAST || ++ !pkey_hash_algo[ms.hash]) ++ return -ENOPKG; ++ ++ key = request_asymmetric_key(sig, ms.signer_len, ++ sig + ms.signer_len, ms.key_id_len); ++ if (IS_ERR(key)) ++ return PTR_ERR(key); ++ ++ pks = mod_make_digest(ms.hash, mod, modlen); ++ if (IS_ERR(pks)) { ++ ret = PTR_ERR(pks); ++ goto error_put_key; ++ } ++ ++ ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, ++ sig_len); ++ if (ret < 0) ++ goto error_free_pks; ++ ++ ret = verify_signature(key, pks); ++ pr_devel("verify_signature() = %d\n", ret); ++ ++ if (ret == 0) ++ *_sig_ok = true; ++ ++error_free_pks: ++ mpi_free(pks->rsa.s); ++ kfree(pks); ++error_put_key: ++ key_put(key); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; + } +-- +1.7.11.4 + + +From 89fbf1de73ed1ef29a3943d9f3bcf69a433191da Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:13:26 +0100 +Subject: [PATCH 24/26] MODSIGN: Provide a script for generating a key ID from + an X.509 cert + +Provide a script to parse an X.509 certificate and certain pieces of +information from it in order to generate a key identifier to be included within +a module signature. + +The script takes the Subject Name and extracts (if present) the +organizationName (O), the commonName (CN) and the emailAddress and fabricates +the signer's name from them: + + (1) If both O and CN exist, then the name will be "O: CN", unless: + + (a) CN is prefixed by O, in which case only CN is used. + + (b) CN and O share at least the first 7 characters, in which case only CN + is used. + + (2) Otherwise, CN is used if present. + + (3) Otherwise, O is used if present. + + (4) Otherwise the emailAddress is used, if present. + + (5) Otherwise a blank name is used. + +The script emits a binary encoded identifier in the following form: + + - 2 BE bytes indicating the length of the signer's name. + + - 2 BE bytes indicating the length of the subject key identifier. + + - The characters of the signer's name. + + - The bytes of the subject key identifier. + +Signed-off-by: David Howells +--- + scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 268 insertions(+) + create mode 100755 scripts/x509keyid + +diff --git a/scripts/x509keyid b/scripts/x509keyid +new file mode 100755 +index 0000000..c8e91a4 +--- /dev/null ++++ b/scripts/x509keyid +@@ -0,0 +1,268 @@ ++#!/usr/bin/perl -w ++# ++# Generate an identifier from an X.509 certificate that can be placed in a ++# module signature to indentify the key to use. ++# ++# Format: ++# ++# ./scripts/x509keyid ++# ++# We read the DER-encoded X509 certificate and parse it to extract the Subject ++# name and Subject Key Identifier. The provide the data we need to build the ++# certificate identifier. ++# ++# The signer's name part of the identifier is fabricated from the commonName, ++# the organizationName or the emailAddress components of the X.509 subject ++# name and written to the second named file. ++# ++# The subject key ID to select which of that signer's certificates we're ++# intending to use to sign the module is written to the third named file. ++# ++use strict; ++ ++my $raw_data; ++ ++die "Need three filenames\n" if ($#ARGV != 2); ++ ++my $src = $ARGV[0]; ++ ++open(FD, "<$src") || die $src; ++binmode FD; ++my @st = stat(FD); ++die $src if (!@st); ++read(FD, $raw_data, $st[7]) || die $src; ++close(FD); ++ ++my $UNIV = 0 << 6; ++my $APPL = 1 << 6; ++my $CONT = 2 << 6; ++my $PRIV = 3 << 6; ++ ++my $CONS = 0x20; ++ ++my $BOOLEAN = 0x01; ++my $INTEGER = 0x02; ++my $BIT_STRING = 0x03; ++my $OCTET_STRING = 0x04; ++my $NULL = 0x05; ++my $OBJ_ID = 0x06; ++my $UTF8String = 0x0c; ++my $SEQUENCE = 0x10; ++my $SET = 0x11; ++my $UTCTime = 0x17; ++my $GeneralizedTime = 0x18; ++ ++my %OIDs = ( ++ pack("CCC", 85, 4, 3) => "commonName", ++ pack("CCC", 85, 4, 6) => "countryName", ++ pack("CCC", 85, 4, 10) => "organizationName", ++ pack("CCC", 85, 4, 11) => "organizationUnitName", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", ++ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", ++ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", ++ pack("CCC", 85, 29, 19) => "basicConstraints" ++); ++ ++############################################################################### ++# ++# Extract an ASN.1 element from a string and return information about it. ++# ++############################################################################### ++sub asn1_extract($$@) ++{ ++ my ($cursor, $expected_tag, $optional) = @_; ++ ++ return [ -1 ] ++ if ($cursor->[1] == 0 && $optional); ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" ++ if ($cursor->[1] < 2); ++ ++ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ ++ if ($expected_tag != -1 && $tag != $expected_tag) { ++ return [ -1 ] ++ if ($optional); ++ die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, ++ " not ", $expected_tag, ")\n"; ++ } ++ ++ $cursor->[0] += 2; ++ $cursor->[1] -= 2; ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" ++ if (($tag & 0x1f) == 0x1f); ++ die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" ++ if ($len == 0x80); ++ ++ if ($len > 0x80) { ++ my $l = $len - 0x80; ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" ++ if ($cursor->[1] < $l); ++ ++ if ($l == 0x1) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); ++ } elsif ($l = 0x2) { ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ } elsif ($l = 0x3) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); ++ } elsif ($l = 0x4) { ++ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); ++ } else { ++ die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; ++ } ++ ++ $cursor->[0] += $l; ++ $cursor->[1] -= $l; ++ } ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" ++ if ($cursor->[1] < $len); ++ ++ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; ++ $cursor->[0] += $len; ++ $cursor->[1] -= $len; ++ ++ return $ret; ++} ++ ++############################################################################### ++# ++# Retrieve the data referred to by a cursor ++# ++############################################################################### ++sub asn1_retrieve($) ++{ ++ my ($cursor) = @_; ++ my ($offset, $len, $data) = @$cursor; ++ return substr($$data, $offset, $len); ++} ++ ++############################################################################### ++# ++# Roughly parse the X.509 certificate ++# ++############################################################################### ++my $cursor = [ 0, length($raw_data), \$raw_data ]; ++ ++my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); ++my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); ++my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); ++my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); ++my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); ++my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); ++my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); ++ ++my $subject_key_id = (); ++my $authority_key_id = (); ++ ++# ++# Parse the extension list ++# ++if ($extension_list->[0] != -1) { ++ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); ++ ++ while ($extensions->[1]->[1] > 0) { ++ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); ++ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); ++ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); ++ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); ++ ++ my $raw_oid = asn1_retrieve($x_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $x_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($x_val->[1]); ++ ++ if ($x_type eq "subjectKeyIdentifier") { ++ my $vcursor = [ 0, length($raw_value), \$raw_value ]; ++ ++ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); ++ } ++ } ++} ++ ++############################################################################### ++# ++# Determine what we're going to use as the signer's name. In order of ++# preference, take one of: commonName, organizationName or emailAddress. ++# ++############################################################################### ++my $org = ""; ++my $cn = ""; ++my $email = ""; ++ ++while ($subject->[1]->[1] > 0) { ++ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); ++ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); ++ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); ++ my $n_val = asn1_extract($attr->[1], -1); ++ ++ my $raw_oid = asn1_retrieve($n_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $n_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($n_val->[1]); ++ ++ if ($n_type eq "organizationName") { ++ $org = $raw_value; ++ } elsif ($n_type eq "commonName") { ++ $cn = $raw_value; ++ } elsif ($n_type eq "emailAddress") { ++ $email = $raw_value; ++ } ++} ++ ++my $id_name = $email; ++ ++if ($org && $cn) { ++ # Don't use the organizationName if the commonName repeats it ++ if (length($org) <= length($cn) && ++ substr($cn, 0, length($org)) eq $org) { ++ $id_name = $cn; ++ goto got_id_name; ++ } ++ ++ # Or a signifcant chunk of it ++ if (length($org) >= 7 && ++ length($cn) >= 7 && ++ substr($cn, 0, 7) eq substr($org, 0, 7)) { ++ $id_name = $cn; ++ goto got_id_name; ++ } ++ ++ $id_name = $org . ": " . $cn; ++} elsif ($org) { ++ $id_name = $org; ++} elsif ($cn) { ++ $id_name = $cn; ++} ++ ++got_id_name: ++ ++############################################################################### ++# ++# Output the signer's name and the key identifier that we're going to include ++# in module signatures. ++# ++############################################################################### ++die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" ++ if (!$subject_key_id); ++ ++my $id_key_id = asn1_retrieve($subject_key_id->[1]); ++ ++open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; ++print OUTFD $id_name; ++close OUTFD || die $ARGV[1]; ++ ++open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; ++print OUTFD $id_key_id; ++close OUTFD || die $ARGV[2]; +-- +1.7.11.4 + + +From 007c8fc3412f0a55cd3a32c5e42236703a17d1c1 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 24 Sep 2012 10:46:36 -0400 +Subject: [PATCH 25/26] MODSIGN: Add modules_sign make target + +If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this +patch will cause the modules to get a signature installed. The make target +is intended to be run after 'make modules_install', and will modify the +modules in-place in the installed location. + +The signature will be appended to the module, along with some information +about the signature size and a magic string that indicates the presence of +the signature. This requires private and public keys to be available. By +default these are expected to be found in files: + + signing_key.priv + signing_key.x509 + +in the base directory of the build. The first is the private key in PEM +form and the second is the X.509 certificate in DER form as can be generated +from openssl: + + openssl req \ + -new -x509 -outform PEM -out signing_key.x509 \ + -keyout signing_key.priv -nodes \ + -subj "/CN=H2G2/O=Magrathea/CN=Slartibartfast" + +If the secret key is not found then signing will be skipped and the unsigned +module from (1) will just be copied to foo.ko. + +If signing occurs, lines like the following will be seen: + + SIGN [M] /fs/foo/foo.ko + +will appear in the build log. If the signature step will be skipped and the +following will be seen: + + NO SIGN [M] /fs/foo/foo.ko + +NOTE! After the signature step, the signed module must not be passed through +strip. If you wish to strip or otherwise modify the kernel modules, use the +built-in stripping capabilities with 'make modules_install' or perform said +modifications before calling this make target. This restriction may affect +packaging tools (such as rpmbuild) and initramfs composition tools. + +Based heavily on work by: David Howells +Signed-off-by: Josh Boyer +--- + Makefile | 6 +++ + scripts/Makefile.modsign | 72 +++++++++++++++++++++++++++++ + scripts/sign-file | 115 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 193 insertions(+) + create mode 100644 scripts/Makefile.modsign + create mode 100644 scripts/sign-file + +diff --git a/Makefile b/Makefile +index 644048d..4479147 100644 +--- a/Makefile ++++ b/Makefile +@@ -965,6 +965,12 @@ _modinst_post: _modinst_ + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst + $(call cmd,depmod) + ++ifeq ($(CONFIG_MODULE_SIG), y) ++PHONY += modules_sign ++modules_sign: ++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign ++endif ++ + else # CONFIG_MODULES + + # Modules not configured +diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign +new file mode 100644 +index 0000000..17326bc +--- /dev/null ++++ b/scripts/Makefile.modsign +@@ -0,0 +1,72 @@ ++# ========================================================================== ++# Signing modules ++# ========================================================================== ++ ++PHONY := __modsign ++__modsign: ++ ++include scripts/Kbuild.include ++ ++__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) ++modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) ++ ++PHONY += $(modules) ++__modsign: $(modules) ++ @: ++ ++MODSECKEY = ./signing_key.priv ++MODPUBKEY = ./signing_key.x509 ++ ++ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) ++ifeq ($(KBUILD_SRC),) ++ # no O= is being used ++ SCRIPTS_DIR := scripts ++else ++ SCRIPTS_DIR := $(KBUILD_SRC)/scripts ++endif ++SIGN_MODULES := 1 ++else ++SIGN_MODULES := 0 ++endif ++ ++# only sign if it's an in-tree module ++ifneq ($(KBUILD_EXTMOD),) ++SIGN_MODULES := 0 ++endif ++ ++ifeq ($(SIGN_MODULES),1) ++ ++quiet_cmd_genkeyid = GENKEYID $@ ++ cmd_genkeyid = \ ++ perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid ++ ++%.signer %.keyid: % ++ $(call if_changed,genkeyid) ++ ++KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid ++quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) ++ cmd_sign_ko = \ ++ sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) \ ++ $(2)/$(notdir $@) $(2)/$(notdir $@).signed && \ ++ mv $(2)/$(notdir $@).signed $(2)/$(notdir $@) && \ ++ rm -rf $(2)/$(notdir $@).{dig,sig} ++else ++KEYRING_DEP := ++quiet_cmd_sign_ko = NO SIGN [M] $@ ++ cmd_sign_ko = \ ++ true ++endif ++ ++# Modules built outside the kernel source tree go into extra by default ++INSTALL_MOD_DIR ?= extra ++ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) ++ ++modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) ++ ++$(modules): $(KEYRING_DEP) ++ $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) ++ ++# Declare the contents of the .PHONY variable as phony. We keep that ++# # information in a variable se we can use it in if_changed and friends. ++ ++.PHONY: $(PHONY) +diff --git a/scripts/sign-file b/scripts/sign-file +new file mode 100644 +index 0000000..1a472bb +--- /dev/null ++++ b/scripts/sign-file +@@ -0,0 +1,115 @@ ++#!/bin/sh ++# ++# Sign a module file using the given key. ++# ++# Format: sign-file ++# ++ ++scripts=`dirname $0` ++ ++CONFIG_MODULE_SIG_SHA512=y ++if [ -r .config ] ++then ++ source ./.config ++fi ++ ++key="$1" ++x509="$2" ++src="$3" ++dst="$4" ++ ++if [ ! -r "$key" ] ++then ++ echo "Can't read private key" >&2 ++ exit 2 ++fi ++ ++if [ ! -r "$x509" ] ++then ++ echo "Can't read X.509 certificate" >&2 ++ exit 2 ++fi ++if [ ! -r "$x509.signer" ] ++then ++ echo "Can't read Signer name" >&2 ++ exit 2; ++fi ++if [ ! -r "$x509.keyid" ] ++then ++ echo "Can't read Key identifier" >&2 ++ exit 2; ++fi ++ ++# ++# Signature parameters ++# ++algo=1 # Public-key crypto algorithm: RSA ++hash= # Digest algorithm ++id_type=1 # Identifier type: X.509 ++ ++# ++# Digest the data ++# ++dgst= ++if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] ++then ++ prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" ++ dgst=-sha1 ++ hash=2 ++elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] ++then ++ prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" ++ dgst=-sha224 ++ hash=7 ++elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] ++then ++ prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" ++ dgst=-sha256 ++ hash=4 ++elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] ++then ++ prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" ++ dgst=-sha384 ++ hash=5 ++elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] ++then ++ prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" ++ dgst=-sha512 ++ hash=6 ++else ++ echo "$0: Can't determine hash algorithm" >&2 ++ exit 2 ++fi ++ ++( ++perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? ++openssl dgst $dgst -binary $src || exit $? ++) >$src.dig || exit $? ++ ++# ++# Generate the binary signature, which will be just the integer that comprises ++# the signature with no metadata attached. ++# ++openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? ++signerlen=`stat -c %s $x509.signer` ++keyidlen=`stat -c %s $x509.keyid` ++siglen=`stat -c %s $src.sig` ++ ++# ++# Build the signed binary ++# ++( ++ cat $src || exit $? ++ echo '~Module signature appended~' || exit $? ++ cat $x509.signer $x509.keyid || exit $? ++ ++ # Preface each signature integer with a 2-byte BE length ++ perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? ++ cat $src.sig || exit $? ++ ++ # Generate the information block ++ perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? ++) >$dst~ || exit $? ++ ++# Permit in-place signing ++mv $dst~ $dst || exit $? +-- +1.7.11.4 + + +From 33c6737b352ec10a7e0d7b053fbb084c0b7a9d36 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 20:51:59 +0100 +Subject: [PATCH 26/26] MODSIGN: Extend the policy on signature check failure + +Extend the policy on handling various sorts of signature check failure such as +not having the requisite key available or being in FIPS mode. + +If the key specified is not known (ENOKEY) permit the module to be loaded in +non-enforcing mode, otherwise reject it. + +If in FIPS mode, any loading failure shall cause a panic. + +Also print a warning if we try and fail to find a module signing key: + + Request for unknown module key 'Magrathea: Glacier signing key: 5dd0839552bd6af498253f8af1e65da3472941c6' err -11 + +This contains the identity field and the key ID from the signature as well as +the error code. The error codes are the raw return from keyring_search() and +may be translated to -ENOKEY. + +Signed-off-by: David Howells +--- + kernel/Makefile | 2 +- + kernel/module.c | 9 ++++++++- + kernel/module_signing.c | 3 +++ + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 63f8386..111a845 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -177,7 +177,7 @@ x509.genkey: + @echo >>x509.genkey "x509_extensions = myexts" + @echo >>x509.genkey + @echo >>x509.genkey "[ req_distinguished_name ]" +- @echo >>x509.genkey "O = Magarathea" ++ @echo >>x509.genkey "O = Magrathea" + @echo >>x509.genkey "CN = Glacier signing key" + @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" + @echo >>x509.genkey +diff --git a/kernel/module.c b/kernel/module.c +index ab69599..de16959 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include "module-internal.h" + + #define CREATE_TRACE_POINTS +@@ -2470,7 +2471,13 @@ found_marker: + sig = p + markerlen; + /* Truncate module up to signature. */ + *len = p - mod; +- return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); ++ err = mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); ++ if (err < 0 && fips_enabled) ++ panic("Module verification failed with error %d in FIPS mode\n", ++ err); ++ if (err == -ENOKEY && !sig_enforce) ++ err = 0; ++ return err; + } + #else /* !CONFIG_MODULE_SIG */ + static int module_sig_check(struct load_info *info, +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 83eb505..2beea56 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -159,6 +159,9 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + key = keyring_search(make_key_ref(modsign_keyring, 1), + &key_type_asymmetric, id); ++ if (IS_ERR(key)) ++ pr_warn("Request for unknown module key '%s' err %ld\n", ++ id, PTR_ERR(key)); + kfree(id); + + if (IS_ERR(key)) { +-- +1.7.11.4 + diff --git a/secure-boot-20120809.patch b/secure-boot-20120924.patch similarity index 70% rename from secure-boot-20120809.patch rename to secure-boot-20120924.patch index 0d6a837cf..37beb41b2 100644 --- a/secure-boot-20120809.patch +++ b/secure-boot-20120924.patch @@ -1,7 +1,7 @@ -From 617309bdd75bbce794ae2d41d44e7b76fb8c6d8b Mon Sep 17 00:00:00 2001 +From 57c0dbcbafaa724313c672830ff0087f56a84c47 Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Thu, 8 Mar 2012 09:56:33 -0500 -Subject: [PATCH 01/13] Secure boot: Add new capability +Date: Thu, 20 Sep 2012 10:40:56 -0400 +Subject: [PATCH 01/14] Secure boot: Add new capability Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. @@ -15,7 +15,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/capability.h b/include/linux/capability.h -index d10b7ed..6a39163 100644 +index d10b7ed..4345bc8 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -364,7 +364,11 @@ struct cpu_vfs_cap_data { @@ -23,22 +23,22 @@ index d10b7ed..6a39163 100644 #define CAP_BLOCK_SUSPEND 36 -#define CAP_LAST_CAP CAP_BLOCK_SUSPEND -+/* Allow things that are dangerous under secure boot */ ++/* Allow things that trivially permit root to modify the running kernel */ + -+#define CAP_SECURE_FIRMWARE 37 ++#define CAP_COMPROMISE_KERNEL 37 + -+#define CAP_LAST_CAP CAP_SECURE_FIRMWARE ++#define CAP_LAST_CAP CAP_COMPROMISE_KERNEL #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) -- -1.7.11.2 +1.7.11.4 -From ac892cb2320872717005736c8ef88208c12e61ee Mon Sep 17 00:00:00 2001 +From 95fd8148be46036e20fc64c480104d2a2b454e27 Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Thu, 8 Mar 2012 10:10:38 -0500 -Subject: [PATCH 02/13] PCI: Lock down BAR access in secure boot environments +Date: Thu, 20 Sep 2012 10:40:57 -0400 +Subject: [PATCH 02/14] PCI: Lock down BAR access in secure boot environments Any hardware that can potentially generate DMA has to be locked down from userspace in order to avoid it being possible for an attacker to cause @@ -53,14 +53,14 @@ Signed-off-by: Matthew Garrett 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index 6869009..a1ad0f7 100644 +index 6869009..c03fb85 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -542,6 +542,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, loff_t init_off = off; u8 *data = (u8*) buf; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (off > dev->cfg_size) @@ -70,7 +70,7 @@ index 6869009..a1ad0f7 100644 resource_size_t start, end; int i; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + for (i = 0; i < PCI_ROM_RESOURCE; i++) @@ -80,21 +80,21 @@ index 6869009..a1ad0f7 100644 struct bin_attribute *attr, char *buf, loff_t off, size_t count) { -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + return pci_resource_io(filp, kobj, attr, buf, off, count, true); } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index 27911b5..01d4753 100644 +index 27911b5..ac8c9a5 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -135,6 +135,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof int size = dp->size; int cnt; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (pos >= size) @@ -104,7 +104,7 @@ index 27911b5..01d4753 100644 #endif /* HAVE_PCI_MMAP */ int ret = 0; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + switch (cmd) { @@ -115,12 +115,12 @@ index 27911b5..01d4753 100644 int i, ret; - if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) return -EPERM; /* Make sure the caller is mapping a real resource for this device */ diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c -index e1c1ec5..a778ba9 100644 +index e1c1ec5..97e785f 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, @@ -128,18 +128,18 @@ index e1c1ec5..a778ba9 100644 int err = 0; - if (!capable(CAP_SYS_ADMIN)) -+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL)) return -EPERM; dev = pci_get_bus_and_slot(bus, dfn); -- -1.7.11.2 +1.7.11.4 -From 4c02feefb934d587f03c74cc48e8d58904416c68 Mon Sep 17 00:00:00 2001 +From 2d23d2726583d79062e58abcc32c7dd027d312aa Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Thu, 8 Mar 2012 10:35:59 -0500 -Subject: [PATCH 03/13] x86: Lock down IO port access in secure boot +Date: Thu, 20 Sep 2012 10:40:58 -0400 +Subject: [PATCH 03/14] x86: Lock down IO port access in secure boot environments IO port access would permit users to gain access to PCI configuration @@ -154,7 +154,7 @@ Signed-off-by: Matthew Garrett 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c -index 8c96897..c3a1bb2 100644 +index 8c96897..a2578c4 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -28,7 +28,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) @@ -162,7 +162,7 @@ index 8c96897..c3a1bb2 100644 if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) return -EINVAL; - if (turn_on && !capable(CAP_SYS_RAWIO)) -+ if (turn_on && (!capable(CAP_SYS_RAWIO) || !capable(CAP_SECURE_FIRMWARE))) ++ if (turn_on && (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL))) return -EPERM; /* @@ -171,32 +171,32 @@ index 8c96897..c3a1bb2 100644 /* Trying to gain more privileges? */ if (level > old) { - if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) return -EPERM; } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index e5eedfa..8f5f872 100644 +index e5eedfa..1e0a660 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, unsigned long i = *ppos; const char __user * tmp = buf; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; while (count-- > 0 && i < 65536) { -- -1.7.11.2 +1.7.11.4 -From d379d102316075d51011b81748433530d294a70c Mon Sep 17 00:00:00 2001 +From e063cb2f3a667d2540682d4bdbef91fdb23b1a84 Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Fri, 9 Mar 2012 08:39:37 -0500 -Subject: [PATCH 04/13] ACPI: Limit access to custom_method +Date: Thu, 20 Sep 2012 10:40:59 -0400 +Subject: [PATCH 04/14] ACPI: Limit access to custom_method It must be impossible for even root to get code executed in kernel context under a secure boot environment. custom_method effectively allows arbitrary @@ -208,27 +208,27 @@ Signed-off-by: Matthew Garrett 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index 5d42c24..3e78014 100644 +index 5d42c24..247d58b 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, struct acpi_table_header table; acpi_status status; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (!(*ppos)) { /* parse the table header to get the table length */ if (count <= sizeof(struct acpi_table_header)) -- -1.7.11.2 +1.7.11.4 -From afc7c002eb264fc745a38fb6ec322be4928338dd Mon Sep 17 00:00:00 2001 +From a1cccbd084c7355dcb2be7ae2934f168ce9ba9d5 Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Fri, 9 Mar 2012 08:46:50 -0500 -Subject: [PATCH 05/13] asus-wmi: Restrict debugfs interface +Date: Thu, 20 Sep 2012 10:41:00 -0400 +Subject: [PATCH 05/14] asus-wmi: Restrict debugfs interface We have no way of validating what all of the Asus WMI methods do on a given machine, and there's a risk that some will allow hardware state to @@ -241,47 +241,47 @@ Signed-off-by: Matthew Garrett 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c7a36f6..0fb58bc 100644 +index 2eb9fe8..61e055d 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -1509,6 +1509,9 @@ static int show_dsts(struct seq_file *m, void *data) +@@ -1523,6 +1523,9 @@ static int show_dsts(struct seq_file *m, void *data) int err; u32 retval = -1; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); if (err < 0) -@@ -1525,6 +1528,9 @@ static int show_devs(struct seq_file *m, void *data) +@@ -1539,6 +1542,9 @@ static int show_devs(struct seq_file *m, void *data) int err; u32 retval = -1; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, &retval); -@@ -1549,6 +1555,9 @@ static int show_call(struct seq_file *m, void *data) +@@ -1563,6 +1569,9 @@ static int show_call(struct seq_file *m, void *data) union acpi_object *obj; acpi_status status; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, asus->debug.method_id, &input, &output); -- -1.7.11.2 +1.7.11.4 -From 21bd1f0da09b40a0ba50636267f7eac8f839a336 Mon Sep 17 00:00:00 2001 +From 1c9e53b626268f82509062751eda14e8572717cf Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Fri, 9 Mar 2012 09:28:15 -0500 -Subject: [PATCH 06/13] Restrict /dev/mem and /dev/kmem in secure boot setups +Date: Thu, 20 Sep 2012 10:41:01 -0400 +Subject: [PATCH 06/14] Restrict /dev/mem and /dev/kmem in secure boot setups Allowing users to write to address space makes it possible for the kernel to be subverted. Restrict this when we need to protect the kernel. @@ -292,14 +292,14 @@ Signed-off-by: Matthew Garrett 1 file changed, 6 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 8f5f872..c1de8e1 100644 +index 1e0a660..33eb947 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, unsigned long copied; void *ptr; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (!valid_phys_addr_range(p, count)) @@ -309,96 +309,86 @@ index 8f5f872..c1de8e1 100644 char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ int err = 0; -+ if (!capable(CAP_SECURE_FIRMWARE)) ++ if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + if (p < (unsigned long) high_memory) { unsigned long to_write = min_t(unsigned long, count, (unsigned long)high_memory - p); -- -1.7.11.2 +1.7.11.4 -From 1940a18cd651113f5b46f5a41290065963d6fbad Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Fri, 9 Mar 2012 11:47:56 -0500 -Subject: [PATCH 07/13] kexec: Disable in a secure boot environment - -kexec could be used as a vector for a malicious user to use a signed kernel -to circumvent the secure boot trust model. In the long run we'll want to -support signed kexec payloads, but for the moment we should just disable -loading entirely in that situation. - -Signed-off-by: Matthew Garrett ---- - kernel/kexec.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kernel/kexec.c b/kernel/kexec.c -index 0668d58..48852ec 100644 ---- a/kernel/kexec.c -+++ b/kernel/kexec.c -@@ -944,7 +944,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, - int result; - - /* We only trust the superuser with rebooting the system. */ -- if (!capable(CAP_SYS_BOOT)) -+ if (!capable(CAP_SYS_BOOT) || !capable(CAP_SECURE_FIRMWARE)) - return -EPERM; - - /* --- -1.7.11.2 - - -From c83bad5d60b8f02ebbedf9b4c4b69cdee49a7976 Mon Sep 17 00:00:00 2001 +From fbf919bf372b9a7a08bdacac8129d47ced1b1f19 Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Mon, 25 Jun 2012 19:45:15 -0400 -Subject: [PATCH 08/13] Secure boot: Add a dummy kernel parameter that will +Date: Thu, 20 Sep 2012 10:41:02 -0400 +Subject: [PATCH 07/14] Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode -This forcibly drops CAP_SECURE_FIRMWARE from both cap_permitted and cap_bset +This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset in the init_cred struct, which everything else inherits from. This works on any machine and can be used to develop even if the box doesn't have UEFI. Signed-off-by: Josh Boyer --- - kernel/cred.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) + Documentation/kernel-parameters.txt | 7 +++++++ + kernel/cred.c | 17 +++++++++++++++++ + 2 files changed, 24 insertions(+) +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 9b2b8d3..93978d5 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -2562,6 +2562,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + Note: increases power consumption, thus should only be + enabled if running jitter sensitive (HPC/RT) workloads. + ++ secureboot_enable= ++ [KNL] Enables an emulated UEFI Secure Boot mode. This ++ locks down various aspects of the kernel guarded by the ++ CAP_COMPROMISE_KERNEL capability. This includes things ++ like /dev/mem, IO port access, and other areas. It can ++ be used on non-UEFI machines for testing purposes. ++ + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be diff --git a/kernel/cred.c b/kernel/cred.c -index de728ac..0d71d02 100644 +index de728ac..7e6e83f 100644 --- a/kernel/cred.c +++ b/kernel/cred.c -@@ -623,6 +623,20 @@ void __init cred_init(void) +@@ -623,6 +623,23 @@ void __init cred_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); } -+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -+static int __init secureboot_enable(char *str) ++void __init secureboot_enable() +{ ++ pr_info("Secure boot enabled\n"); ++ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); ++ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++} + ++/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ ++static int __init secureboot_enable_opt(char *str) ++{ + int sb_enable = !!simple_strtol(str, NULL, 0); -+ pr_info("Secure Boot mode %s\n", (sb_enable ? "enabled" : "disabled")); -+ if (sb_enable) { -+ cap_lower((&init_cred)->cap_bset, CAP_SECURE_FIRMWARE); -+ cap_lower((&init_cred)->cap_permitted, CAP_SECURE_FIRMWARE); -+ } ++ if (sb_enable) ++ secureboot_enable(); + return 1; +} -+__setup("secureboot_enable=", secureboot_enable); ++__setup("secureboot_enable=", secureboot_enable_opt); + /** * prepare_kernel_cred - Prepare a set of credentials for a kernel service * @daemon: A userspace daemon to be used as a reference -- -1.7.11.2 +1.7.11.4 -From b70595f1523ecadc4ce9d43e9a0c465436ed1007 Mon Sep 17 00:00:00 2001 +From 43ed7865d867ae692e30227d66fa58cdecbd9269 Mon Sep 17 00:00:00 2001 From: Matthew Garrett -Date: Wed, 18 Jul 2012 11:28:00 -0400 -Subject: [PATCH 09/13] efi: Enable secure boot lockdown automatically when +Date: Thu, 20 Sep 2012 10:41:03 -0400 +Subject: [PATCH 08/14] efi: Enable secure boot lockdown automatically when enabled in firmware The firmware has a set of flags that indicate whether secure boot is enabled @@ -407,13 +397,26 @@ down. Signed-off-by: Matthew Garrett --- + Documentation/x86/zero-page.txt | 2 ++ arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ arch/x86/include/asm/bootparam.h | 3 ++- arch/x86/kernel/setup.c | 3 +++ include/linux/cred.h | 2 ++ - kernel/cred.c | 18 +++++++++++------- - 5 files changed, 50 insertions(+), 8 deletions(-) + 5 files changed, 41 insertions(+), 1 deletion(-) +diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt +index cf5437d..7f9ed48 100644 +--- a/Documentation/x86/zero-page.txt ++++ b/Documentation/x86/zero-page.txt +@@ -27,6 +27,8 @@ Offset Proto Name Meaning + 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) + 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer + (below) ++1EB/001 ALL kbd_status Numlock is enabled ++1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns + 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures + 2D0/A00 ALL e820_map E820 memory map table + (array of struct e820entry) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b3e0227..3789356 100644 --- a/arch/x86/boot/compressed/eboot.c @@ -505,54 +508,19 @@ index ebbed2c..a24faf1 100644 /* * check for validity of credentials */ -diff --git a/kernel/cred.c b/kernel/cred.c -index 0d71d02..c43e2b0 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -623,19 +623,23 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+void __init secureboot_enable() -+{ -+ pr_info("Secure boot enabled\n"); -+ cap_lower((&init_cred)->cap_bset, CAP_SECURE_FIRMWARE); -+ cap_lower((&init_cred)->cap_permitted, CAP_SECURE_FIRMWARE); -+} -+ - /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ --static int __init secureboot_enable(char *str) -+static int __init secureboot_enable_opt(char *str) - { - - int sb_enable = !!simple_strtol(str, NULL, 0); -- pr_info("Secure Boot mode %s\n", (sb_enable ? "enabled" : "disabled")); -- if (sb_enable) { -- cap_lower((&init_cred)->cap_bset, CAP_SECURE_FIRMWARE); -- cap_lower((&init_cred)->cap_permitted, CAP_SECURE_FIRMWARE); -- } -+ if (sb_enable) -+ secureboot_enable(); - return 1; - } --__setup("secureboot_enable=", secureboot_enable); -+__setup("secureboot_enable=", secureboot_enable_opt); - - /** - * prepare_kernel_cred - Prepare a set of credentials for a kernel service -- -1.7.11.2 +1.7.11.4 -From 411c18c35ccacb1a9e3f3dc67383a6431e110e17 Mon Sep 17 00:00:00 2001 +From 3acf1ceb5f6f3be9103c9da16ddc24afc6d8b02a Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Mon, 25 Jun 2012 19:57:30 -0400 -Subject: [PATCH 10/13] acpi: Ignore acpi_rsdp kernel parameter in a secure +Date: Thu, 20 Sep 2012 10:41:04 -0400 +Subject: [PATCH 09/14] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment This option allows userspace to pass the RSDP address to the kernel. This could potentially be used to circumvent the secure boot trust model. -We ignore the setting if we don't have the CAP_SECURE_FIRMWARE capability. +We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. Signed-off-by: Josh Boyer --- @@ -560,7 +528,7 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 9eaf708..50c94e4 100644 +index 9eaf708..f94341b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); @@ -568,18 +536,83 @@ index 9eaf708..50c94e4 100644 { #ifdef CONFIG_KEXEC - if (acpi_rsdp) -+ if (acpi_rsdp && capable(CAP_SECURE_FIRMWARE)) ++ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) return acpi_rsdp; #endif -- -1.7.11.2 +1.7.11.4 -From 7bf87e8da8c7b57ba7f9448855c8ec84c684fb65 Mon Sep 17 00:00:00 2001 +From 03fb06d272ddc1062e610521c5cfdbe42f251209 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:05 -0400 +Subject: [PATCH 10/14] SELinux: define mapping for new Secure Boot capability + +Add the name of the new Secure Boot capability. This allows SELinux +policies to properly map CAP_COMPROMISE_KERNEL to the appropriate +capability class. + +Signed-off-by: Josh Boyer +--- + security/selinux/include/classmap.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h +index df2de54..70e2834 100644 +--- a/security/selinux/include/classmap.h ++++ b/security/selinux/include/classmap.h +@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { + { "memprotect", { "mmap_zero", NULL } }, + { "peer", { "recv", NULL } }, + { "capability2", +- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", +- NULL } }, ++ { "mac_override", "mac_admin", "syslog", "wake_alarm", ++ "block_suspend", "compromise_kernel", NULL } }, + { "kernel_service", { "use_as_override", "create_files_as", NULL } }, + { "tun_socket", + { COMMON_SOCK_PERMS, NULL } }, +-- +1.7.11.4 + + +From 0cfaa5ecf01f8eaaa2a84d88b7258a94ac9a1bfe Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 4 Sep 2012 11:55:13 -0400 +Subject: [PATCH 11/14] kexec: Disable in a secure boot environment + +kexec could be used as a vector for a malicious user to use a signed kernel +to circumvent the secure boot trust model. In the long run we'll want to +support signed kexec payloads, but for the moment we should just disable +loading entirely in that situation. + +Signed-off-by: Matthew Garrett +--- + kernel/kexec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/kexec.c b/kernel/kexec.c +index 0668d58..8b976a5 100644 +--- a/kernel/kexec.c ++++ b/kernel/kexec.c +@@ -944,7 +944,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, + int result; + + /* We only trust the superuser with rebooting the system. */ +- if (!capable(CAP_SYS_BOOT)) ++ if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + /* +-- +1.7.11.4 + + +From 895c46276788b3711aee05a1a1d685eff69d48b9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Jun 2012 21:29:46 -0400 -Subject: [PATCH 11/13] Documentation: kernel-parameters.txt remove +Subject: [PATCH 12/14] Documentation: kernel-parameters.txt remove capability.disable Remove the documentation for capability.disable. The code supporting this @@ -597,7 +630,7 @@ Signed-off-by: Josh Boyer 1 file changed, 6 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index ad7e2e5..33c4029 100644 +index 93978d5..e3e5f8c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. @@ -614,98 +647,13 @@ index ad7e2e5..33c4029 100644 See Documentation/s390/CommonIO for details. -- -1.7.11.2 +1.7.11.4 -From ec0ca55ba3d1c2a59b0c0b6e38f7ae9966d676aa Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 26 Jun 2012 14:15:51 -0400 -Subject: [PATCH 12/13] SELinux: define mapping for new Secure Boot capability - -Add the name of the new Secure Boot capability. This allows SELinux -policies to properly map CAP_SECURE_FIRMWARE to the appropriate -capability class. - -Signed-off-by: Josh Boyer ---- - security/selinux/include/classmap.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index df2de54..0a1e348 100644 ---- a/security/selinux/include/classmap.h -+++ b/security/selinux/include/classmap.h -@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { - { "memprotect", { "mmap_zero", NULL } }, - { "peer", { "recv", NULL } }, - { "capability2", -- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", -- NULL } }, -+ { "mac_override", "mac_admin", "syslog", "wake_alarm", -+ "block_suspend", "secure_firmware", NULL } }, - { "kernel_service", { "use_as_override", "create_files_as", NULL } }, - { "tun_socket", - { COMMON_SOCK_PERMS, NULL } }, --- -1.7.11.2 - - -From 0a90e99e45f5c8eddd3b8cfcd63a4c6355c5688d Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 26 Jun 2012 16:27:26 -0400 -Subject: [PATCH 13/13] modsign: Reject unsigned modules in a Secure Boot - environment - -If a machine is booted into a Secure Boot environment, we need to -protect the trust model. This requires that all modules be signed -with a key that is in the kernel's _modsign keyring. We add a -capability check and reject modules that are not signed. - -Signed-off-by: Josh Boyer ---- - kernel/module-verify.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 22036d4..f6821b3 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - #include - #include "module-verify.h" - #include "module-verify-defs.h" -@@ -699,7 +700,7 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) - /* The ELF checker found the sig for us if it exists */ - if (mvdata.sig_index <= 0) { - /* Deal with an unsigned module */ -- if (modsign_signedonly) { -+ if (modsign_signedonly || !capable(CAP_SECURE_FIRMWARE)) { - pr_err("An attempt to load unsigned module was rejected\n"); - return -EKEYREJECTED; - } else { -@@ -736,7 +737,7 @@ out: - break; - case -ENOKEY: /* Signed, but we don't have the public key */ - pr_err("Module signed with unknown public key\n"); -- if (!modsign_signedonly) { -+ if (!modsign_signedonly && capable(CAP_SECURE_FIRMWARE)) { - /* Allow a module to be signed with an unknown public - * key unless we're enforcing. - */ --- -1.7.11.2 - -From: Matthew Garrett -To: matt.fleming@intel.com -Cc: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, - x86@kernel.org, Matthew Garrett -Date: Thu, 26 Jul 2012 18:00:00 -0400 -Message-Id: <1343340000-7587-1-git-send-email-mjg@redhat.com> -Subject: [PATCH] efi: Build EFI stub with EFI-appropriate options +From 294d339c63b0f67a362efaa62713f26d9f496da8 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 26 Jul 2012 18:00:00 -0400 +Subject: [PATCH 13/14] efi: Build EFI stub with EFI-appropriate options We can't assume the presence of the red zone while we're still in a boot services environment, so we should build with -fno-red-zone to avoid @@ -714,7 +662,7 @@ simpler. Signed-off-by: Matthew Garrett --- - arch/x86/boot/compressed/Makefile | 3 +++ + arch/x86/boot/compressed/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile @@ -731,4 +679,48 @@ index e398bb5..8a84501 100644 ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif +-- +1.7.11.4 + + +From d1a225668878a3339adcd7ce0be256e857360ada Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 26 Jun 2012 16:27:26 -0400 +Subject: [PATCH 14/14] modsign: Reject unsigned modules in a Secure Boot + environment + +If a machine is booted into a Secure Boot environment, we need to +protect the trust model. This requires that all modules be signed +with a key that is in the kernel's _modsign keyring. We add a +capability check and reject modules that are not signed. + +Signed-off-by: Josh Boyer +--- + kernel/module.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/module.c b/kernel/module.c +index de16959..5af69cc 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2463,7 +2463,7 @@ static int module_sig_check(struct load_info *info, + } + + /* Not having a signature is only an error if we're strict. */ +- if (!err && !info->sig_ok && sig_enforce) ++ if (!err && !info->sig_ok && (sig_enforce || !capable(CAP_COMPROMISE_KERNEL))) + err = -EKEYREJECTED; + return err; + +@@ -2475,7 +2475,7 @@ found_marker: + if (err < 0 && fips_enabled) + panic("Module verification failed with error %d in FIPS mode\n", + err); +- if (err == -ENOKEY && !sig_enforce) ++ if (err == -ENOKEY && (!sig_enforce && capable(CAP_COMPROMISE_KERNEL))) + err = 0; + return err; + } +-- +1.7.11.4 diff --git a/x509.genkey b/x509.genkey new file mode 100644 index 000000000..2f90e1bce --- /dev/null +++ b/x509.genkey @@ -0,0 +1,16 @@ +[ req ] +default_bits = 4096 +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = myexts + +[ req_distinguished_name ] +O = Fedora +CN = Fedora kernel signing key +emailAddress = kernel-team@fedoraproject.org + +[ myexts ] +basicConstraints=critical,CA:FALSE +keyUsage=digitalSignature +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid From c7019bcac4a422a924590a1e75a0d2024a2fafc9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Sep 2012 15:41:08 -0400 Subject: [PATCH 044/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 3a0206fc7..73a9349bb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2307,7 +2307,7 @@ fi # ||----w | # || || %changelog -* Tue Sep 25 2012 Josh Boyer +* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.4 - Move the modules-extra processing to a script - Prep mod-extra.sh for signed modules - Switch to using modsign-post-KS upstream with x509 certs From bea0ea29e21cd49b4589b9e222a47f793ddfbb18 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Sep 2012 08:27:10 -0400 Subject: [PATCH 045/492] Linux v3.6-rc7-71-g6399413 --- kernel.spec | 11 +- sources | 2 +- team-net-next-update-20120924.patch | 499 ---------------------------- team-net-next-update-20120927.patch | 335 +++++++++++++++++++ 4 files changed, 343 insertions(+), 504 deletions(-) delete mode 100644 team-net-next-update-20120924.patch create mode 100644 team-net-next-update-20120927.patch diff --git a/kernel.spec b/kernel.spec index 73a9349bb..0526cc15a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 7 # The git snapshot level -%define gitrev 1 +%define gitrev 2 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -658,7 +658,7 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch Patch150: team-net-next-20120808.patch -Patch151: team-net-next-update-20120924.patch +Patch151: team-net-next-update-20120927.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch @@ -1313,7 +1313,7 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch ApplyPatch team-net-next-20120808.patch -ApplyPatch team-net-next-update-20120924.patch +ApplyPatch team-net-next-update-20120927.patch # Architecture patches # x86(-64) @@ -2307,6 +2307,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.1 +- Linux v3.6-rc7-71-g6399413 + * Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.4 - Move the modules-extra processing to a script - Prep mod-extra.sh for signed modules diff --git a/sources b/sources index a55fa4ef4..194a869ac 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 7704196874c5a7ae69a3ba5363b3665d patch-3.6-rc7.xz -47b618da3a92738d00dc7ee990b46fe5 patch-3.6-rc7-git1.xz +296e17cd963df93f9c9be8721a81080a patch-3.6-rc7-git2.xz diff --git a/team-net-next-update-20120924.patch b/team-net-next-update-20120924.patch deleted file mode 100644 index c0899c5aa..000000000 --- a/team-net-next-update-20120924.patch +++ /dev/null @@ -1,499 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.59.1.102 with SMTP id bf6csp906180ved; - Sun, 23 Sep 2012 23:03:07 -0700 (PDT) -Received: by 10.68.239.5 with SMTP id vo5mr33801766pbc.102.1348466586432; - Sun, 23 Sep 2012 23:03:06 -0700 (PDT) -Return-Path: -Received: from bastion.fedoraproject.org (bastion01.fedoraproject.org. [209.132.181.2]) - by mx.google.com with ESMTP id s5si6031726pay.21.2012.09.23.23.03.04; - Sun, 23 Sep 2012 23:03:06 -0700 (PDT) -Received-SPF: pass (google.com: domain of kernel-bounces@lists.fedoraproject.org designates 209.132.181.2 as permitted sender) client-ip=209.132.181.2; -Authentication-Results: mx.google.com; spf=pass (google.com: domain of kernel-bounces@lists.fedoraproject.org designates 209.132.181.2 as permitted sender) smtp.mail=kernel-bounces@lists.fedoraproject.org -Received: from lists.fedoraproject.org (collab03.vpn.fedoraproject.org [192.168.1.70]) - by bastion01.phx2.fedoraproject.org (Postfix) with ESMTP id 4185D224F5; - Mon, 24 Sep 2012 06:03:03 +0000 (UTC) -Received: from collab03.fedoraproject.org (localhost [127.0.0.1]) - by lists.fedoraproject.org (Postfix) with ESMTP id E30B53FCF8; - Mon, 24 Sep 2012 06:03:02 +0000 (UTC) -X-Original-To: kernel@lists.fedoraproject.org -Delivered-To: kernel@lists.fedoraproject.org -Received: from smtp-mm02.fedoraproject.org (smtp-mm02.fedoraproject.org - [66.35.62.164]) - by lists.fedoraproject.org (Postfix) with ESMTP id 7F9D03FCF8 - for ; - Mon, 24 Sep 2012 06:03:00 +0000 (UTC) -Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) - by smtp-mm02.fedoraproject.org (Postfix) with ESMTP id 3A0AA3FC66 - for ; - Mon, 24 Sep 2012 06:03:00 +0000 (UTC) -Received: from int-mx11.intmail.prod.int.phx2.redhat.com - (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8O62uU3010033 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 24 Sep 2012 02:02:59 -0400 -Received: from localhost (ovpn-116-32.ams2.redhat.com [10.36.116.32]) - by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP - id q8O62sNM029515; Mon, 24 Sep 2012 02:02:55 -0400 -From: Jiri Pirko -To: kernel@lists.fedoraproject.org -Subject: [patch F18/rawhide] team: update to latest net-next -Date: Mon, 24 Sep 2012 08:02:54 +0200 -Message-Id: <1348466574-1982-1-git-send-email-jpirko@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 -Cc: brouer@redhat.com, jforbes@redhat.com, jwboyer@redhat.com -X-BeenThere: kernel@lists.fedoraproject.org -X-Mailman-Version: 2.1.12 -Precedence: list -List-Id: "Fedora kernel development." -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -MIME-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: base64 -Sender: kernel-bounces@lists.fedoraproject.org -Errors-To: kernel-bounces@lists.fedoraproject.org - -Update team driver to latest net-next. - -Split patches available here: -http://people.redhat.com/jpirko/f18_team_update_3/ - -Jiri Pirko (5): - team: add support for non-ethernet devices - team: don't print warn message on -ESRCH during event send - vlan: add helper which can be called to see if device is used by vlan - team: do not allow to add VLAN challenged port when vlan is used - team: send port changed when added - - drivers/net/team/Kconfig | 4 +- - drivers/net/team/team.c | 137 ++++++++++++++++++++++++-------- - drivers/net/team/team_mode_broadcast.c | 8 +- - drivers/net/team/team_mode_roundrobin.c | 8 +- - include/linux/if_team.h | 4 +- - include/linux/if_vlan.h | 9 ++- - net/8021q/vlan_core.c | 6 ++ - 7 files changed, 128 insertions(+), 48 deletions(-) - -Signed-off-by: Jiri Pirko - -diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig -index 6a7260b..6b08bd4 100644 ---- a/drivers/net/team/Kconfig -+++ b/drivers/net/team/Kconfig -@@ -21,7 +21,7 @@ config NET_TEAM_MODE_BROADCAST - ---help--- - Basic mode where packets are transmitted always by all suitable ports. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_broadcast. -@@ -33,7 +33,7 @@ config NET_TEAM_MODE_ROUNDROBIN - Basic mode where port used for transmitting packets is selected in - round-robin fashion using packet counter. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_roundrobin. -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 341b65d..17d4be3 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -54,29 +54,29 @@ static struct team_port *team_port_get_rtnl(const struct net_device *dev) - } - - /* -- * Since the ability to change mac address for open port device is tested in -+ * Since the ability to change device address for open port device is tested in - * team_port_add, this function can be called without control of return value - */ --static int __set_port_mac(struct net_device *port_dev, -- const unsigned char *dev_addr) -+static int __set_port_dev_addr(struct net_device *port_dev, -+ const unsigned char *dev_addr) - { - struct sockaddr addr; - -- memcpy(addr.sa_data, dev_addr, ETH_ALEN); -- addr.sa_family = ARPHRD_ETHER; -+ memcpy(addr.sa_data, dev_addr, port_dev->addr_len); -+ addr.sa_family = port_dev->type; - return dev_set_mac_address(port_dev, &addr); - } - --static int team_port_set_orig_mac(struct team_port *port) -+static int team_port_set_orig_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->orig.dev_addr); -+ return __set_port_dev_addr(port->dev, port->orig.dev_addr); - } - --int team_port_set_team_mac(struct team_port *port) -+int team_port_set_team_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->team->dev->dev_addr); -+ return __set_port_dev_addr(port->dev, port->team->dev->dev_addr); - } --EXPORT_SYMBOL(team_port_set_team_mac); -+EXPORT_SYMBOL(team_port_set_team_dev_addr); - - static void team_refresh_port_linkup(struct team_port *port) - { -@@ -848,7 +848,10 @@ static struct netpoll_info *team_netpoll_info(struct team *team) - } - #endif - --static void __team_port_change_check(struct team_port *port, bool linkup); -+static void __team_port_change_port_added(struct team_port *port, bool linkup); -+ -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev); - - static int team_port_add(struct team *team, struct net_device *port_dev) - { -@@ -857,9 +860,8 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - char *portname = port_dev->name; - int err; - -- if (port_dev->flags & IFF_LOOPBACK || -- port_dev->type != ARPHRD_ETHER) { -- netdev_err(dev, "Device %s is of an unsupported type\n", -+ if (port_dev->flags & IFF_LOOPBACK) { -+ netdev_err(dev, "Device %s is loopback device. Loopback devices can't be added as a team port\n", - portname); - return -EINVAL; - } -@@ -870,6 +872,17 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - return -EBUSY; - } - -+ if (port_dev->features & NETIF_F_VLAN_CHALLENGED && -+ vlan_uses_dev(dev)) { -+ netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n", -+ portname); -+ return -EPERM; -+ } -+ -+ err = team_dev_type_check_change(dev, port_dev); -+ if (err) -+ return err; -+ - if (port_dev->flags & IFF_UP) { - netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", - portname); -@@ -891,7 +904,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - goto err_set_mtu; - } - -- memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); -+ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); - - err = team_port_enter(team, port); - if (err) { -@@ -948,7 +961,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - team_port_enable(team, port); - list_add_tail_rcu(&port->list, &team->port_list); - __team_compute_features(team); -- __team_port_change_check(port, !!netif_carrier_ok(port_dev)); -+ __team_port_change_port_added(port, !!netif_carrier_ok(port_dev)); - __team_options_change_check(team); - - netdev_info(dev, "Port device %s added\n", portname); -@@ -972,7 +985,7 @@ err_vids_add: - - err_dev_open: - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - - err_port_enter: - dev_set_mtu(port_dev, port->orig.mtu); -@@ -983,6 +996,8 @@ err_set_mtu: - return err; - } - -+static void __team_port_change_port_removed(struct team_port *port); -+ - static int team_port_del(struct team *team, struct net_device *port_dev) - { - struct net_device *dev = team->dev; -@@ -999,8 +1014,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - __team_option_inst_mark_removed_port(team, port); - __team_options_change_check(team); - __team_option_inst_del_port(team, port); -- port->removed = true; -- __team_port_change_check(port, false); -+ __team_port_change_port_removed(port); - team_port_disable(team, port); - list_del_rcu(&port->list); - netdev_rx_handler_unregister(port_dev); -@@ -1009,7 +1023,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - vlan_vids_del_by_dev(port_dev, dev); - dev_close(port_dev); - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - dev_set_mtu(port_dev, port->orig.mtu); - synchronize_rcu(); - kfree(port); -@@ -1295,17 +1309,18 @@ static void team_set_rx_mode(struct net_device *dev) - - static int team_set_mac_address(struct net_device *dev, void *p) - { -+ struct sockaddr *addr = p; - struct team *team = netdev_priv(dev); - struct team_port *port; -- int err; - -- err = eth_mac_addr(dev, p); -- if (err) -- return err; -+ if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; - rcu_read_lock(); - list_for_each_entry_rcu(port, &team->port_list, list) -- if (team->ops.port_change_mac) -- team->ops.port_change_mac(team, port); -+ if (team->ops.port_change_dev_addr) -+ team->ops.port_change_dev_addr(team, port); - rcu_read_unlock(); - return 0; - } -@@ -1536,6 +1551,45 @@ static const struct net_device_ops team_netdev_ops = { - * rt netlink interface - ***********************/ - -+static void team_setup_by_port(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ dev->header_ops = port_dev->header_ops; -+ dev->type = port_dev->type; -+ dev->hard_header_len = port_dev->hard_header_len; -+ dev->addr_len = port_dev->addr_len; -+ dev->mtu = port_dev->mtu; -+ memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); -+ memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; -+} -+ -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ struct team *team = netdev_priv(dev); -+ char *portname = port_dev->name; -+ int err; -+ -+ if (dev->type == port_dev->type) -+ return 0; -+ if (!list_empty(&team->port_list)) { -+ netdev_err(dev, "Device %s is of different type\n", portname); -+ return -EBUSY; -+ } -+ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); -+ err = notifier_to_errno(err); -+ if (err) { -+ netdev_err(dev, "Refused to change device type\n"); -+ return err; -+ } -+ dev_uc_flush(dev); -+ dev_mc_flush(dev); -+ team_setup_by_port(dev, port_dev); -+ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); -+ return 0; -+} -+ - static void team_setup(struct net_device *dev) - { - ether_setup(dev); -@@ -2245,19 +2299,17 @@ static void __team_options_change_check(struct team *team) - list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); - } - err = team_nl_send_event_options_get(team, &sel_opt_inst_list); -- if (err) -+ if (err && err != -ESRCH) - netdev_warn(team->dev, "Failed to send options change via netlink (err %d)\n", - err); - } - - /* rtnl lock is held */ --static void __team_port_change_check(struct team_port *port, bool linkup) -+ -+static void __team_port_change_send(struct team_port *port, bool linkup) - { - int err; - -- if (!port->removed && port->state.linkup == linkup) -- return; -- - port->changed = true; - port->state.linkup = linkup; - team_refresh_port_linkup(port); -@@ -2276,12 +2328,29 @@ static void __team_port_change_check(struct team_port *port, bool linkup) - - send_event: - err = team_nl_send_event_port_list_get(port->team); -- if (err) -- netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", -- port->dev->name); -+ if (err && err != -ESRCH) -+ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", -+ port->dev->name, err); - - } - -+static void __team_port_change_check(struct team_port *port, bool linkup) -+{ -+ if (port->state.linkup != linkup) -+ __team_port_change_send(port, linkup); -+} -+ -+static void __team_port_change_port_added(struct team_port *port, bool linkup) -+{ -+ __team_port_change_send(port, linkup); -+} -+ -+static void __team_port_change_port_removed(struct team_port *port) -+{ -+ port->removed = true; -+ __team_port_change_send(port, false); -+} -+ - static void team_port_change_check(struct team_port *port, bool linkup) - { - struct team *team = port->team; -diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c -index c96e4d2..9db0171 100644 ---- a/drivers/net/team/team_mode_broadcast.c -+++ b/drivers/net/team/team_mode_broadcast.c -@@ -48,18 +48,18 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) - - static int bc_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void bc_port_change_mac(struct team *team, struct team_port *port) -+static void bc_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops bc_mode_ops = { - .transmit = bc_transmit, - .port_enter = bc_port_enter, -- .port_change_mac = bc_port_change_mac, -+ .port_change_dev_addr = bc_port_change_dev_addr, - }; - - static const struct team_mode bc_mode = { -diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c -index ad7ed0e..105135a 100644 ---- a/drivers/net/team/team_mode_roundrobin.c -+++ b/drivers/net/team/team_mode_roundrobin.c -@@ -66,18 +66,18 @@ drop: - - static int rr_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void rr_port_change_mac(struct team *team, struct team_port *port) -+static void rr_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops rr_mode_ops = { - .transmit = rr_transmit, - .port_enter = rr_port_enter, -- .port_change_mac = rr_port_change_mac, -+ .port_change_dev_addr = rr_port_change_dev_addr, - }; - - static const struct team_mode rr_mode = { -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index aa2e167..667f2a5 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -105,7 +105,7 @@ struct team_mode_ops { - bool (*transmit)(struct team *team, struct sk_buff *skb); - int (*port_enter)(struct team *team, struct team_port *port); - void (*port_leave)(struct team *team, struct team_port *port); -- void (*port_change_mac)(struct team *team, struct team_port *port); -+ void (*port_change_dev_addr)(struct team *team, struct team_port *port); - void (*port_enabled)(struct team *team, struct team_port *port); - void (*port_disabled)(struct team *team, struct team_port *port); - }; -@@ -231,7 +231,7 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team, - return NULL; - } - --extern int team_port_set_team_mac(struct team_port *port); -+extern int team_port_set_team_dev_addr(struct team_port *port); - extern int team_options_register(struct team *team, - const struct team_option *option, - size_t option_count); -diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h -index a810987..e6ff12d 100644 ---- a/include/linux/if_vlan.h -+++ b/include/linux/if_vlan.h -@@ -74,8 +74,6 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) - /* found in socket.c */ - extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); - --struct vlan_info; -- - static inline int is_vlan_dev(struct net_device *dev) - { - return dev->priv_flags & IFF_802_1Q_VLAN; -@@ -101,6 +99,8 @@ extern int vlan_vids_add_by_dev(struct net_device *dev, - const struct net_device *by_dev); - extern void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev); -+ -+extern bool vlan_uses_dev(const struct net_device *dev); - #else - static inline struct net_device * - __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) -@@ -151,6 +151,11 @@ static inline void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev) - { - } -+ -+static inline bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return false; -+} - #endif - - /** -diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c -index 8ca533c..b258da8 100644 ---- a/net/8021q/vlan_core.c -+++ b/net/8021q/vlan_core.c -@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_device *dev, - vlan_vid_del(dev, vid_info->vid); - } - EXPORT_SYMBOL(vlan_vids_del_by_dev); -+ -+bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return rtnl_dereference(dev->vlan_info) ? true : false; -+} -+EXPORT_SYMBOL(vlan_uses_dev); - diff --git a/team-net-next-update-20120927.patch b/team-net-next-update-20120927.patch new file mode 100644 index 000000000..a61311619 --- /dev/null +++ b/team-net-next-update-20120927.patch @@ -0,0 +1,335 @@ +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/Kconfig ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/Kconfig +@@ -21,7 +21,7 @@ config NET_TEAM_MODE_BROADCAST + ---help--- + Basic mode where packets are transmitted always by all suitable ports. + +- All added ports are setup to have team's mac address. ++ All added ports are setup to have team's device address. + + To compile this team mode as a module, choose M here: the module + will be called team_mode_broadcast. +@@ -33,7 +33,7 @@ config NET_TEAM_MODE_ROUNDROBIN + Basic mode where port used for transmitting packets is selected in + round-robin fashion using packet counter. + +- All added ports are setup to have team's mac address. ++ All added ports are setup to have team's device address. + + To compile this team mode as a module, choose M here: the module + will be called team_mode_roundrobin. +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team.c ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team.c +@@ -54,29 +54,29 @@ static struct team_port *team_port_get_r + } + + /* +- * Since the ability to change mac address for open port device is tested in ++ * Since the ability to change device address for open port device is tested in + * team_port_add, this function can be called without control of return value + */ +-static int __set_port_mac(struct net_device *port_dev, +- const unsigned char *dev_addr) ++static int __set_port_dev_addr(struct net_device *port_dev, ++ const unsigned char *dev_addr) + { + struct sockaddr addr; + +- memcpy(addr.sa_data, dev_addr, ETH_ALEN); +- addr.sa_family = ARPHRD_ETHER; ++ memcpy(addr.sa_data, dev_addr, port_dev->addr_len); ++ addr.sa_family = port_dev->type; + return dev_set_mac_address(port_dev, &addr); + } + +-static int team_port_set_orig_mac(struct team_port *port) ++static int team_port_set_orig_dev_addr(struct team_port *port) + { +- return __set_port_mac(port->dev, port->orig.dev_addr); ++ return __set_port_dev_addr(port->dev, port->orig.dev_addr); + } + +-int team_port_set_team_mac(struct team_port *port) ++int team_port_set_team_dev_addr(struct team_port *port) + { +- return __set_port_mac(port->dev, port->team->dev->dev_addr); ++ return __set_port_dev_addr(port->dev, port->team->dev->dev_addr); + } +-EXPORT_SYMBOL(team_port_set_team_mac); ++EXPORT_SYMBOL(team_port_set_team_dev_addr); + + static void team_refresh_port_linkup(struct team_port *port) + { +@@ -967,6 +967,8 @@ static struct netpoll_info *team_netpoll + #endif + + static void __team_port_change_port_added(struct team_port *port, bool linkup); ++static int team_dev_type_check_change(struct net_device *dev, ++ struct net_device *port_dev); + + static int team_port_add(struct team *team, struct net_device *port_dev) + { +@@ -975,9 +977,8 @@ static int team_port_add(struct team *te + char *portname = port_dev->name; + int err; + +- if (port_dev->flags & IFF_LOOPBACK || +- port_dev->type != ARPHRD_ETHER) { +- netdev_err(dev, "Device %s is of an unsupported type\n", ++ if (port_dev->flags & IFF_LOOPBACK) { ++ netdev_err(dev, "Device %s is loopback device. Loopback devices can't be added as a team port\n", + portname); + return -EINVAL; + } +@@ -988,6 +989,17 @@ static int team_port_add(struct team *te + return -EBUSY; + } + ++ if (port_dev->features & NETIF_F_VLAN_CHALLENGED && ++ vlan_uses_dev(dev)) { ++ netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n", ++ portname); ++ return -EPERM; ++ } ++ ++ err = team_dev_type_check_change(dev, port_dev); ++ if (err) ++ return err; ++ + if (port_dev->flags & IFF_UP) { + netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", + portname); +@@ -1010,7 +1022,7 @@ static int team_port_add(struct team *te + goto err_set_mtu; + } + +- memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); ++ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); + + err = team_port_enter(team, port); + if (err) { +@@ -1091,7 +1103,7 @@ err_vids_add: + + err_dev_open: + team_port_leave(team, port); +- team_port_set_orig_mac(port); ++ team_port_set_orig_dev_addr(port); + + err_port_enter: + dev_set_mtu(port_dev, port->orig.mtu); +@@ -1129,7 +1141,7 @@ static int team_port_del(struct team *te + vlan_vids_del_by_dev(port_dev, dev); + dev_close(port_dev); + team_port_leave(team, port); +- team_port_set_orig_mac(port); ++ team_port_set_orig_dev_addr(port); + dev_set_mtu(port_dev, port->orig.mtu); + synchronize_rcu(); + kfree(port); +@@ -1480,17 +1492,18 @@ static void team_set_rx_mode(struct net_ + + static int team_set_mac_address(struct net_device *dev, void *p) + { ++ struct sockaddr *addr = p; + struct team *team = netdev_priv(dev); + struct team_port *port; +- int err; + +- err = eth_mac_addr(dev, p); +- if (err) +- return err; ++ if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) ++ return -EADDRNOTAVAIL; ++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; + rcu_read_lock(); + list_for_each_entry_rcu(port, &team->port_list, list) +- if (team->ops.port_change_mac) +- team->ops.port_change_mac(team, port); ++ if (team->ops.port_change_dev_addr) ++ team->ops.port_change_dev_addr(team, port); + rcu_read_unlock(); + return 0; + } +@@ -1721,6 +1734,45 @@ static const struct net_device_ops team_ + * rt netlink interface + ***********************/ + ++static void team_setup_by_port(struct net_device *dev, ++ struct net_device *port_dev) ++{ ++ dev->header_ops = port_dev->header_ops; ++ dev->type = port_dev->type; ++ dev->hard_header_len = port_dev->hard_header_len; ++ dev->addr_len = port_dev->addr_len; ++ dev->mtu = port_dev->mtu; ++ memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); ++ memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; ++} ++ ++static int team_dev_type_check_change(struct net_device *dev, ++ struct net_device *port_dev) ++{ ++ struct team *team = netdev_priv(dev); ++ char *portname = port_dev->name; ++ int err; ++ ++ if (dev->type == port_dev->type) ++ return 0; ++ if (!list_empty(&team->port_list)) { ++ netdev_err(dev, "Device %s is of different type\n", portname); ++ return -EBUSY; ++ } ++ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); ++ err = notifier_to_errno(err); ++ if (err) { ++ netdev_err(dev, "Refused to change device type\n"); ++ return err; ++ } ++ dev_uc_flush(dev); ++ dev_mc_flush(dev); ++ team_setup_by_port(dev, port_dev); ++ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); ++ return 0; ++} ++ + static void team_setup(struct net_device *dev) + { + ether_setup(dev); +@@ -2442,7 +2494,7 @@ static void __team_options_change_check( + list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); + } + err = team_nl_send_event_options_get(team, &sel_opt_inst_list); +- if (err) ++ if (err && err != -ESRCH) + netdev_warn(team->dev, "Failed to send options change via netlink (err %d)\n", + err); + } +@@ -2471,9 +2523,9 @@ static void __team_port_change_send(stru + + send_event: + err = team_nl_send_event_port_list_get(port->team); +- if (err) +- netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", +- port->dev->name); ++ if (err && err != -ESRCH) ++ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", ++ port->dev->name, err); + + } + +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_broadcast.c ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_broadcast.c +@@ -48,18 +48,18 @@ static bool bc_transmit(struct team *tea + + static int bc_port_enter(struct team *team, struct team_port *port) + { +- return team_port_set_team_mac(port); ++ return team_port_set_team_dev_addr(port); + } + +-static void bc_port_change_mac(struct team *team, struct team_port *port) ++static void bc_port_change_dev_addr(struct team *team, struct team_port *port) + { +- team_port_set_team_mac(port); ++ team_port_set_team_dev_addr(port); + } + + static const struct team_mode_ops bc_mode_ops = { + .transmit = bc_transmit, + .port_enter = bc_port_enter, +- .port_change_mac = bc_port_change_mac, ++ .port_change_dev_addr = bc_port_change_dev_addr, + }; + + static const struct team_mode bc_mode = { +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_roundrobin.c ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_roundrobin.c +@@ -66,18 +66,18 @@ drop: + + static int rr_port_enter(struct team *team, struct team_port *port) + { +- return team_port_set_team_mac(port); ++ return team_port_set_team_dev_addr(port); + } + +-static void rr_port_change_mac(struct team *team, struct team_port *port) ++static void rr_port_change_dev_addr(struct team *team, struct team_port *port) + { +- team_port_set_team_mac(port); ++ team_port_set_team_dev_addr(port); + } + + static const struct team_mode_ops rr_mode_ops = { + .transmit = rr_transmit, + .port_enter = rr_port_enter, +- .port_change_mac = rr_port_change_mac, ++ .port_change_dev_addr = rr_port_change_dev_addr, + }; + + static const struct team_mode rr_mode = { +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_team.h ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_team.h +@@ -108,7 +108,7 @@ struct team_mode_ops { + bool (*transmit)(struct team *team, struct sk_buff *skb); + int (*port_enter)(struct team *team, struct team_port *port); + void (*port_leave)(struct team *team, struct team_port *port); +- void (*port_change_mac)(struct team *team, struct team_port *port); ++ void (*port_change_dev_addr)(struct team *team, struct team_port *port); + void (*port_enabled)(struct team *team, struct team_port *port); + void (*port_disabled)(struct team *team, struct team_port *port); + }; +@@ -238,7 +238,7 @@ static inline struct team_port *team_get + return NULL; + } + +-extern int team_port_set_team_mac(struct team_port *port); ++extern int team_port_set_team_dev_addr(struct team_port *port); + extern int team_options_register(struct team *team, + const struct team_option *option, + size_t option_count); +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_vlan.h ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_vlan.h +@@ -74,8 +74,6 @@ static inline struct vlan_ethhdr *vlan_e + /* found in socket.c */ + extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); + +-struct vlan_info; +- + static inline int is_vlan_dev(struct net_device *dev) + { + return dev->priv_flags & IFF_802_1Q_VLAN; +@@ -101,6 +99,8 @@ extern int vlan_vids_add_by_dev(struct n + const struct net_device *by_dev); + extern void vlan_vids_del_by_dev(struct net_device *dev, + const struct net_device *by_dev); ++ ++extern bool vlan_uses_dev(const struct net_device *dev); + #else + static inline struct net_device * + __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) +@@ -151,6 +151,11 @@ static inline void vlan_vids_del_by_dev( + const struct net_device *by_dev) + { + } ++ ++static inline bool vlan_uses_dev(const struct net_device *dev) ++{ ++ return false; ++} + #endif + + /** +--- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/net/8021q/vlan_core.c ++++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/net/8021q/vlan_core.c +@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_dev + vlan_vid_del(dev, vid_info->vid); + } + EXPORT_SYMBOL(vlan_vids_del_by_dev); ++ ++bool vlan_uses_dev(const struct net_device *dev) ++{ ++ return rtnl_dereference(dev->vlan_info) ? true : false; ++} ++EXPORT_SYMBOL(vlan_uses_dev); From 3b80dddb2f54d9cb30ee26765557f2c1b5349ad9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Sep 2012 08:31:01 -0400 Subject: [PATCH 046/492] Split out kernel-tools-libs (rhbz 859943) --- kernel.spec | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index 0526cc15a..dc1cf0209 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -869,18 +869,28 @@ Provides: cpufrequtils = 1:009-0.6.p1 Obsoletes: cpufreq-utils < 1:009-0.6.p1 Obsoletes: cpufrequtils < 1:009-0.6.p1 Obsoletes: cpuspeed < 1:1.5-16 +Requires: kernel-tools-libs = %{version}-%{release} %description -n kernel-tools This package contains the tools/ directory from the kernel source and the supporting documentation. -%package -n kernel-tools-devel +%package -n kernel-tools-libs +Summary: Libraries for the kernels-tools +Group: Development/System +License: GPLv2 +%description -n kernel-tools-libs +This package contains the libraries built from the tools/ directory +from the kernel source. + +%package -n kernel-tools-libs-devel Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 Requires: kernel-tools = %{version}-%{release} Provides: cpupowerutils-devel = 1:009-0.6.p1 Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 -%description -n kernel-tools-devel +Requires: kernel-tools-libs = %{version}-%{release} +%description -n kernel-tools-libs-devel This package contains the development files for the tools/ directory from the kernel source. @@ -2214,8 +2224,6 @@ fi %{_bindir}/centrino-decode %{_bindir}/powernow-k8-decode %endif -%{_libdir}/libcpupower.so.0 -%{_libdir}/libcpupower.so.0.0.0 %{_unitdir}/cpupower.service %{_mandir}/man[1-8]/cpupower* %config(noreplace) %{_sysconfdir}/sysconfig/cpupower @@ -2233,7 +2241,11 @@ fi %endif %ifarch %{cpupowerarchs} -%files -n kernel-tools-devel +%files -n kernel-tools-libs +%{_libdir}/libcpupower.so.0 +%{_libdir}/libcpupower.so.0.0.0 + +%files -n kernel-tools-libs-devel %{_libdir}/libcpupower.so %{_includedir}/cpufreq.h %endif @@ -2307,6 +2319,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.2 +- Split out kernel-tools-libs (rhbz 859943) + * Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.1 - Linux v3.6-rc7-71-g6399413 From 4b466bb5a0525b7c0287b39aad545355c550a2b0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Sep 2012 15:29:28 -0400 Subject: [PATCH 047/492] Linux v3.6-rc7-103-g6672d90 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index dc1cf0209..6f7dea3e8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 7 # The git snapshot level -%define gitrev 2 +%define gitrev 3 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2319,6 +2319,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git3.1 +- Linux v3.6-rc7-103-g6672d90 + * Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.2 - Split out kernel-tools-libs (rhbz 859943) diff --git a/sources b/sources index 194a869ac..1066188c7 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz 7704196874c5a7ae69a3ba5363b3665d patch-3.6-rc7.xz -296e17cd963df93f9c9be8721a81080a patch-3.6-rc7-git2.xz +50cdb8abbb0a4abe3ac4ac0421f1c189 patch-3.6-rc7-git3.xz From 85cffef59ed199cf982ede5f0af56bcb84bd6fb3 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 1 Oct 2012 07:44:16 -0500 Subject: [PATCH 048/492] Linux 3.6.0 --- config-generic | 8 ++-- config-nodebug | 110 ++++++++++++++++++++++----------------------- config-x86-generic | 2 +- kernel.spec | 16 ++++--- sources | 4 +- 5 files changed, 71 insertions(+), 69 deletions(-) diff --git a/config-generic b/config-generic index 9b63e75f9..8f795f5d5 100644 --- a/config-generic +++ b/config-generic @@ -1456,13 +1456,13 @@ CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y # CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3028,7 +3028,7 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# CONFIG_USB_UAS is not set # @@ -3981,7 +3981,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set diff --git a/config-nodebug b/config-nodebug index d99deeb2f..5b4187680 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,111 +2,111 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y -CONFIG_FAIL_MMC_REQUEST=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_NFSD_FAULT_INJECTION=y +# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set -CONFIG_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/config-x86-generic b/config-x86-generic index ad22edd8d..de9582a01 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -320,7 +320,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -CONFIG_MAXSMP=y +# CONFIG_MAXSMP is not set CONFIG_HP_ILO=m diff --git a/kernel.spec b/kernel.spec index 6f7dea3e8..b24c376bb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 0 +%global released_kernel 1 # Sign modules on x86. Make sure the config files match this setting if more # architectures are added. @@ -68,7 +68,7 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 5 +%define base_sublevel 6 ## If this is a released kernel ## %if 0%{?released_kernel} @@ -93,9 +93,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 7 +%define rcrev 0 # The git snapshot level -%define gitrev 3 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -176,7 +176,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -2319,6 +2319,10 @@ fi # ||----w | # || || %changelog +* Mon Oct 01 2012 Justin M. Forbes - 3.6.0-1 +- Linux 3.6.0 +- Disable debugging options. + * Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git3.1 - Linux v3.6-rc7-103-g6672d90 diff --git a/sources b/sources index 1066188c7..8ca40febd 100644 --- a/sources +++ b/sources @@ -1,3 +1 @@ -24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -7704196874c5a7ae69a3ba5363b3665d patch-3.6-rc7.xz -50cdb8abbb0a4abe3ac4ac0421f1c189 patch-3.6-rc7-git3.xz +1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz From 63d527976ab38e62c43876fa14a7e8d86636e29a Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 2 Oct 2012 08:20:54 +0100 Subject: [PATCH 049/492] - Update ARM configs for 3.6 final - Add highbank SATA driver for stability - Build in OMAP MMC and DMA drivers to fix borkage for now --- arm-highbank-sata-fix.patch | 599 ++++++++++++++++++++++++++++++++++++ config-arm-generic | 9 + config-arm-highbank | 2 + config-arm-omap | 16 +- config-arm-tegra | 6 +- config-arm-versatile | 1 + kernel.spec | 6 + 7 files changed, 631 insertions(+), 8 deletions(-) create mode 100644 arm-highbank-sata-fix.patch diff --git a/arm-highbank-sata-fix.patch b/arm-highbank-sata-fix.patch new file mode 100644 index 000000000..fda7b219e --- /dev/null +++ b/arm-highbank-sata-fix.patch @@ -0,0 +1,599 @@ +From: Mark Langsdorf +Date: Thu, 6 Sep 2012 21:03:30 +0000 (-0500) +Subject: ata: add platform driver for Calxeda AHCI controller +X-Git-Tag: next-20121002~68^2~5 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=8996b89d6bc98ae2f6d6e6e624a42a3f89d06949;hp=100f586bd0959fe0e52b8a0b8cb49a3df1c6b044 + +ata: add platform driver for Calxeda AHCI controller + +Calxeda highbank SATA phy has intermittent problems bringing up a link +with Gen3 drives. Retrying the phy hard reset can work-around this issue, +but each reset also disables spread spectrum support. The reset function +also needs to reprogram the phy to enable spread spectrum support. + +Create a new driver based on ahci_platform to support the Calxeda Highbank +SATA controller. + +Signed-off-by: Mark Langsdorf +Signed-off-by: Rob Herring +Signed-off-by: Jeff Garzik +--- + +diff --git a/Documentation/devicetree/bindings/arm/calxeda/combophy.txt b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt +new file mode 100644 +index 0000000..6622bdb +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt +@@ -0,0 +1,17 @@ ++Calxeda Highbank Combination Phys for SATA ++ ++Properties: ++- compatible : Should be "calxeda,hb-combophy" ++- #phy-cells: Should be 1. ++- reg : Address and size for Combination Phy registers. ++- phydev: device ID for programming the combophy. ++ ++Example: ++ ++ combophy5: combo-phy@fff5d000 { ++ compatible = "calxeda,hb-combophy"; ++ #phy-cells = <1>; ++ reg = <0xfff5d000 0x1000>; ++ phydev = <31>; ++ }; ++ +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 8bb8a76..147c1f6 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -8,9 +8,17 @@ Required properties: + - interrupts : + - reg : + ++Optional properties: ++- calxeda,port-phys: phandle-combophy and lane assignment, which maps each ++ SATA port to a combophy and a lane within that ++ combophy ++ + Example: + sata@ffe08000 { + compatible = "calxeda,hb-ahci"; + reg = <0xffe08000 0x1000>; + interrupts = <115>; ++ calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1 ++ &combophy0 2 &combophy0 3>; ++ + }; +diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts +index 9fecf1a..5204cf7 100644 +--- a/arch/arm/boot/dts/highbank.dts ++++ b/arch/arm/boot/dts/highbank.dts +@@ -121,6 +121,9 @@ + compatible = "calxeda,hb-ahci"; + reg = <0xffe08000 0x10000>; + interrupts = <0 83 4>; ++ calxeda,port-phys = <&combophy5 0 &combophy0 0 ++ &combophy0 1 &combophy0 2 ++ &combophy0 3>; + }; + + sdhci@ffe0e000 { +@@ -306,5 +309,19 @@ + reg = <0xfff51000 0x1000>; + interrupts = <0 80 4 0 81 4 0 82 4>; + }; ++ ++ combophy0: combo-phy@fff58000 { ++ compatible = "calxeda,hb-combophy"; ++ #phy-cells = <1>; ++ reg = <0xfff58000 0x1000>; ++ phydev = <5>; ++ }; ++ ++ combophy5: combo-phy@fff5d000 { ++ compatible = "calxeda,hb-combophy"; ++ #phy-cells = <1>; ++ reg = <0xfff5d000 0x1000>; ++ phydev = <31>; ++ }; + }; + }; +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index 27cecd3..e08d322 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG + help + This option enables the taskfile dumping and NCQ debugging. + ++config SATA_HIGHBANK ++ tristate "Calxeda Highbank SATA support" ++ help ++ This option enables support for the Calxeda Highbank SoC's ++ onboard SATA. ++ ++ If unsure, say N. ++ + config SATA_MV + tristate "Marvell SATA support" + help +diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile +index a454a13..8b384f1 100644 +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL) += sata_fsl.o + obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o + obj-$(CONFIG_SATA_SIL24) += sata_sil24.o + obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o ++obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o + + # SFF w/ custom DMA + obj-$(CONFIG_PDC_ADMA) += pdc_adma.o +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 09728e0..dc187c7 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -277,7 +277,6 @@ static int ahci_resume(struct device *dev) + SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); + + static const struct of_device_id ahci_of_match[] = { +- { .compatible = "calxeda,hb-ahci", }, + { .compatible = "snps,spear-ahci", }, + {}, + }; +diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c +new file mode 100644 +index 0000000..0d7c4c2 +--- /dev/null ++++ b/drivers/ata/sata_highbank.c +@@ -0,0 +1,450 @@ ++/* ++ * Calxeda Highbank AHCI SATA platform driver ++ * Copyright 2012 Calxeda, Inc. ++ * ++ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ahci.h" ++ ++#define CPHY_MAP(dev, addr) ((((dev) & 0x1f) << 7) | (((addr) >> 9) & 0x7f)) ++#define CPHY_ADDR(addr) (((addr) & 0x1ff) << 2) ++#define SERDES_CR_CTL 0x80a0 ++#define SERDES_CR_ADDR 0x80a1 ++#define SERDES_CR_DATA 0x80a2 ++#define CR_BUSY 0x0001 ++#define CR_START 0x0001 ++#define CR_WR_RDN 0x0002 ++#define CPHY_RX_INPUT_STS 0x2002 ++#define CPHY_SATA_OVERRIDE 0x4000 ++#define CPHY_OVERRIDE 0x2005 ++#define SPHY_LANE 0x100 ++#define SPHY_HALF_RATE 0x0001 ++#define CPHY_SATA_DPLL_MODE 0x0700 ++#define CPHY_SATA_DPLL_SHIFT 8 ++#define CPHY_SATA_DPLL_RESET (1 << 11) ++#define CPHY_PHY_COUNT 6 ++#define CPHY_LANE_COUNT 4 ++#define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) ++ ++static DEFINE_SPINLOCK(cphy_lock); ++/* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based ++ * sata ports to their phys and then to their lanes within the phys ++ */ ++struct phy_lane_info { ++ void __iomem *phy_base; ++ u8 lane_mapping; ++ u8 phy_devs; ++}; ++static struct phy_lane_info port_data[CPHY_PORT_COUNT]; ++ ++static u32 __combo_phy_reg_read(u8 sata_port, u32 addr) ++{ ++ u32 data; ++ u8 dev = port_data[sata_port].phy_devs; ++ spin_lock(&cphy_lock); ++ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); ++ data = readl(port_data[sata_port].phy_base + CPHY_ADDR(addr)); ++ spin_unlock(&cphy_lock); ++ return data; ++} ++ ++static void __combo_phy_reg_write(u8 sata_port, u32 addr, u32 data) ++{ ++ u8 dev = port_data[sata_port].phy_devs; ++ spin_lock(&cphy_lock); ++ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); ++ writel(data, port_data[sata_port].phy_base + CPHY_ADDR(addr)); ++ spin_unlock(&cphy_lock); ++} ++ ++static void combo_phy_wait_for_ready(u8 sata_port) ++{ ++ while (__combo_phy_reg_read(sata_port, SERDES_CR_CTL) & CR_BUSY) ++ udelay(5); ++} ++ ++static u32 combo_phy_read(u8 sata_port, u32 addr) ++{ ++ combo_phy_wait_for_ready(sata_port); ++ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); ++ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_START); ++ combo_phy_wait_for_ready(sata_port); ++ return __combo_phy_reg_read(sata_port, SERDES_CR_DATA); ++} ++ ++static void combo_phy_write(u8 sata_port, u32 addr, u32 data) ++{ ++ combo_phy_wait_for_ready(sata_port); ++ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); ++ __combo_phy_reg_write(sata_port, SERDES_CR_DATA, data); ++ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_WR_RDN | CR_START); ++} ++ ++static void highbank_cphy_disable_overrides(u8 sata_port) ++{ ++ u8 lane = port_data[sata_port].lane_mapping; ++ u32 tmp; ++ if (unlikely(port_data[sata_port].phy_base == NULL)) ++ return; ++ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); ++ tmp &= ~CPHY_SATA_OVERRIDE; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++} ++ ++static void cphy_override_rx_mode(u8 sata_port, u32 val) ++{ ++ u8 lane = port_data[sata_port].lane_mapping; ++ u32 tmp; ++ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); ++ tmp &= ~CPHY_SATA_OVERRIDE; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++ ++ tmp |= CPHY_SATA_OVERRIDE; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++ ++ tmp &= ~CPHY_SATA_DPLL_MODE; ++ tmp |= val << CPHY_SATA_DPLL_SHIFT; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++ ++ tmp |= CPHY_SATA_DPLL_RESET; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++ ++ tmp &= ~CPHY_SATA_DPLL_RESET; ++ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); ++ ++ msleep(15); ++} ++ ++static void highbank_cphy_override_lane(u8 sata_port) ++{ ++ u8 lane = port_data[sata_port].lane_mapping; ++ u32 tmp, k = 0; ++ ++ if (unlikely(port_data[sata_port].phy_base == NULL)) ++ return; ++ do { ++ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + ++ lane * SPHY_LANE); ++ } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); ++ cphy_override_rx_mode(sata_port, 3); ++} ++ ++static int highbank_initialize_phys(struct device *dev, void __iomem *addr) ++{ ++ struct device_node *sata_node = dev->of_node; ++ int phy_count = 0, phy, port = 0; ++ void __iomem *cphy_base[CPHY_PHY_COUNT]; ++ struct device_node *phy_nodes[CPHY_PHY_COUNT]; ++ memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); ++ memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); ++ ++ do { ++ u32 tmp; ++ struct of_phandle_args phy_data; ++ if (of_parse_phandle_with_args(sata_node, ++ "calxeda,port-phys", "#phy-cells", ++ port, &phy_data)) ++ break; ++ for (phy = 0; phy < phy_count; phy++) { ++ if (phy_nodes[phy] == phy_data.np) ++ break; ++ } ++ if (phy_nodes[phy] == NULL) { ++ phy_nodes[phy] = phy_data.np; ++ cphy_base[phy] = of_iomap(phy_nodes[phy], 0); ++ if (cphy_base[phy] == NULL) { ++ return 0; ++ } ++ phy_count += 1; ++ } ++ port_data[port].lane_mapping = phy_data.args[0]; ++ of_property_read_u32(phy_nodes[phy], "phydev", &tmp); ++ port_data[port].phy_devs = tmp; ++ port_data[port].phy_base = cphy_base[phy]; ++ of_node_put(phy_data.np); ++ port += 1; ++ } while (port < CPHY_PORT_COUNT); ++ return 0; ++} ++ ++static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); ++ struct ata_port *ap = link->ap; ++ struct ahci_port_priv *pp = ap->private_data; ++ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; ++ struct ata_taskfile tf; ++ bool online; ++ u32 sstatus; ++ int rc; ++ int retry = 10; ++ ++ ahci_stop_engine(ap); ++ ++ /* clear D2H reception area to properly wait for D2H FIS */ ++ ata_tf_init(link->device, &tf); ++ tf.command = 0x80; ++ ata_tf_to_fis(&tf, 0, 0, d2h_fis); ++ ++ do { ++ highbank_cphy_disable_overrides(link->ap->port_no); ++ rc = sata_link_hardreset(link, timing, deadline, &online, NULL); ++ highbank_cphy_override_lane(link->ap->port_no); ++ ++ /* If the status is 1, we are connected, but the link did not ++ * come up. So retry resetting the link again. ++ */ ++ if (sata_scr_read(link, SCR_STATUS, &sstatus)) ++ break; ++ if (!(sstatus & 0x3)) ++ break; ++ } while (!online && retry--); ++ ++ ahci_start_engine(ap); ++ ++ if (online) ++ *class = ahci_dev_classify(ap); ++ ++ return rc; ++} ++ ++static struct ata_port_operations ahci_highbank_ops = { ++ .inherits = &ahci_ops, ++ .hardreset = ahci_highbank_hardreset, ++}; ++ ++static const struct ata_port_info ahci_highbank_port_info = { ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_highbank_ops, ++}; ++ ++static struct scsi_host_template ahci_highbank_platform_sht = { ++ AHCI_SHT("highbank-ahci"), ++}; ++ ++static const struct of_device_id ahci_of_match[] = { ++ { .compatible = "calxeda,hb-ahci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ahci_of_match); ++ ++static int __init ahci_highbank_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_host_priv *hpriv; ++ struct ata_host *host; ++ struct resource *mem; ++ int irq; ++ int n_ports; ++ int i; ++ int rc; ++ struct ata_port_info pi = ahci_highbank_port_info; ++ const struct ata_port_info *ppi[] = { &pi, NULL }; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) { ++ dev_err(dev, "no mmio space\n"); ++ return -EINVAL; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev, "no irq\n"); ++ return -EINVAL; ++ } ++ ++ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); ++ if (!hpriv) { ++ dev_err(dev, "can't alloc ahci_host_priv\n"); ++ return -ENOMEM; ++ } ++ ++ hpriv->flags |= (unsigned long)pi.private_data; ++ ++ hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); ++ if (!hpriv->mmio) { ++ dev_err(dev, "can't map %pR\n", mem); ++ return -ENOMEM; ++ } ++ ++ rc = highbank_initialize_phys(dev, hpriv->mmio); ++ if (rc) ++ return rc; ++ ++ ++ ahci_save_initial_config(dev, hpriv, 0, 0); ++ ++ /* prepare host */ ++ if (hpriv->cap & HOST_CAP_NCQ) ++ pi.flags |= ATA_FLAG_NCQ; ++ ++ if (hpriv->cap & HOST_CAP_PMP) ++ pi.flags |= ATA_FLAG_PMP; ++ ++ ahci_set_em_messages(hpriv, &pi); ++ ++ /* CAP.NP sometimes indicate the index of the last enabled ++ * port, at other times, that of the last possible port, so ++ * determining the maximum port number requires looking at ++ * both CAP.NP and port_map. ++ */ ++ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); ++ ++ host = ata_host_alloc_pinfo(dev, ppi, n_ports); ++ if (!host) { ++ rc = -ENOMEM; ++ goto err0; ++ } ++ ++ host->private_data = hpriv; ++ ++ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) ++ host->flags |= ATA_HOST_PARALLEL_SCAN; ++ ++ if (pi.flags & ATA_FLAG_EM) ++ ahci_reset_em(host); ++ ++ for (i = 0; i < host->n_ports; i++) { ++ struct ata_port *ap = host->ports[i]; ++ ++ ata_port_desc(ap, "mmio %pR", mem); ++ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); ++ ++ /* set enclosure management message type */ ++ if (ap->flags & ATA_FLAG_EM) ++ ap->em_message_type = hpriv->em_msg_type; ++ ++ /* disabled/not-implemented port */ ++ if (!(hpriv->port_map & (1 << i))) ++ ap->ops = &ata_dummy_port_ops; ++ } ++ ++ rc = ahci_reset_controller(host); ++ if (rc) ++ goto err0; ++ ++ ahci_init_controller(host); ++ ahci_print_info(host, "platform"); ++ ++ rc = ata_host_activate(host, irq, ahci_interrupt, 0, ++ &ahci_highbank_platform_sht); ++ if (rc) ++ goto err0; ++ ++ return 0; ++err0: ++ return rc; ++} ++ ++static int __devexit ahci_highbank_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ata_host *host = dev_get_drvdata(dev); ++ ++ ata_host_detach(host); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int ahci_highbank_suspend(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ void __iomem *mmio = hpriv->mmio; ++ u32 ctl; ++ int rc; ++ ++ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { ++ dev_err(dev, "firmware update required for suspend/resume\n"); ++ return -EIO; ++ } ++ ++ /* ++ * AHCI spec rev1.1 section 8.3.3: ++ * Software must disable interrupts prior to requesting a ++ * transition of the HBA to D3 state. ++ */ ++ ctl = readl(mmio + HOST_CTL); ++ ctl &= ~HOST_IRQ_EN; ++ writel(ctl, mmio + HOST_CTL); ++ readl(mmio + HOST_CTL); /* flush */ ++ ++ rc = ata_host_suspend(host, PMSG_SUSPEND); ++ if (rc) ++ return rc; ++ ++ return 0; ++} ++ ++static int ahci_highbank_resume(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ int rc; ++ ++ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { ++ rc = ahci_reset_controller(host); ++ if (rc) ++ return rc; ++ ++ ahci_init_controller(host); ++ } ++ ++ ata_host_resume(host); ++ ++ return 0; ++} ++#endif ++ ++SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, ++ ahci_highbank_suspend, ahci_highbank_resume); ++ ++static struct platform_driver ahci_highbank_driver = { ++ .remove = __devexit_p(ahci_highbank_remove), ++ .driver = { ++ .name = "highbank-ahci", ++ .owner = THIS_MODULE, ++ .of_match_table = ahci_of_match, ++ .pm = &ahci_highbank_pm_ops, ++ }, ++ .probe = ahci_highbank_probe, ++}; ++ ++module_platform_driver(ahci_highbank_driver); ++ ++MODULE_DESCRIPTION("Calxeda Highbank AHCI SATA platform driver"); ++MODULE_AUTHOR("Mark Langsdorf "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("sata:highbank"); diff --git a/config-arm-generic b/config-arm-generic index fca13551a..5f4fbf42b 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -107,6 +107,8 @@ CONFIG_SMC911X=m CONFIG_SMSC911X=m CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SPI=m # Generic GPIO options CONFIG_GENERIC_GPIO=y @@ -196,6 +198,13 @@ CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_DEBUG is not set +# Device tree +CONFIG_OF=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_OF_GPIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y + # HW Disabled because it causes issues on ARM platforms # disable TPM on arm at least on the trimslices it causes havoc diff --git a/config-arm-highbank b/config-arm-highbank index 6fe9262bd..6b023e02e 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -36,6 +36,8 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y +CONFIG_SATA_HIGHBANK=m + # CONFIG_DVB_TDA1004X is not set # CONFIG_DVB_PLL is not set diff --git a/config-arm-omap b/config-arm-omap index b44a44590..b698e4849 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -27,6 +27,10 @@ CONFIG_OMAP_PM_NOOP=y CONFIG_OMAP_IOMMU=y CONFIG_OMAP3_EMU=y CONFIG_HWSPINLOCK_OMAP=m +CONFIG_DMA_OMAP=y +# CONFIG_DMADEVICES_VDEBUG is not set + +CONFIG_ARM_OMAP2PLUS_CPUFREQ=y # # TI OMAP2/3/4 Specific Features @@ -36,16 +40,14 @@ CONFIG_ARCH_OMAP2PLUS_TYPICAL=y CONFIG_ARCH_OMAP3=y CONFIG_ARCH_OMAP4=y CONFIG_SOC_OMAP3430=y -# CONFIG_SOC_OMAPTI81XX is not set -# CONFIG_SOC_OMAPAM33XX is not set -# CONFIG_SOC_OMAPTI816X is not set +CONFIG_SOC_TI81XX=y +CONFIG_SOC_AM33XX=y +CONFIG_SOC_OMAPTI816X=y CONFIG_OMAP_PACKAGE_CBB=y CONFIG_OMAP_PACKAGE_CBL=y CONFIG_OMAP_PACKAGE_CBS=y # CONFIG_OMAP4_ERRATA_I688 is not set -CONFIG_ARM_OMAP2PLUS_CPUFREQ=y - # # OMAP Board Type # @@ -146,6 +148,7 @@ CONFIG_PM_OPP=y # OMAP Hardware # CONFIG_WL_TI=y +CONFIG_WLCORE_SDIO=m CONFIG_TI_ST=m CONFIG_GPIOLIB=y CONFIG_MTD_NAND_OMAP2=y @@ -158,6 +161,7 @@ CONFIG_INPUT_TWL4030_PWRBUTTON=m CONFIG_INPUT_TWL4030_VIBRA=m CONFIG_INPUT_TWL6040_VIBRA=m CONFIG_KEYBOARD_OMAP4=m +CONFIG_KEYBOARD_TWL4030=m CONFIG_TOUCHSCREEN_TI_TSCADC=m CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y @@ -243,7 +247,7 @@ CONFIG_USB_MUSB_HDRC=y # CONFIG_USB_GADGET_OMAP is not set # CONFIG_ISP1301_OMAP is not set -CONFIG_MMC_OMAP=m +CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_TWL4030_USB=y CONFIG_TWL6030_USB=y diff --git a/config-arm-tegra b/config-arm-tegra index a754dd6ba..5ec5a6762 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -32,6 +32,8 @@ CONFIG_MMC_SDHCI_TEGRA=y # CONFIG_RCU_BOOST is not set CONFIG_TEGRA_SYSTEM_DMA=y CONFIG_TEGRA_EMC_SCALING_ENABLE=y +CONFIG_TEGRA_AHB=y +CONFIG_TEGRA20_APB_DMA=y CONFIG_ARM_THUMBEE=y CONFIG_SWP_EMULATE=y # CONFIG_CPU_BPREDICT_DISABLE is not set @@ -63,6 +65,7 @@ CONFIG_RTC_DRV_TEGRA=y CONFIG_SND_SOC_TEGRA=m CONFIG_SND_SOC_TEGRA_ALC5632=m +CONFIG_SND_SOC_TEGRA_WM8753=m CONFIG_SND_SOC_TEGRA_WM8903=m CONFIG_SND_SOC_TEGRA_TRIMSLICE=m # CONFIG_SND_SOC_TEGRA30_AHUB is not set @@ -78,7 +81,7 @@ CONFIG_NVEC_LEDS=y CONFIG_CPU_PM=y CONFIG_ARM_CPU_SUSPEND=y -#CONFIG_CRYPTO_DEV_TEGRA_AES=m +CONFIG_CRYPTO_DEV_TEGRA_AES=m CONFIG_PL310_ERRATA_753970=y CONFIG_LEDS_RENESAS_TPU=y @@ -88,4 +91,3 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_OF_GPIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y - diff --git a/config-arm-versatile b/config-arm-versatile index 54499f9b9..f65720782 100644 --- a/config-arm-versatile +++ b/config-arm-versatile @@ -1,5 +1,6 @@ CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_VEXPRESS_CA9X4=y +CONFIG_ARCH_VEXPRESS_DT=y CONFIG_PLAT_VERSATILE_CLCD=y CONFIG_PLAT_VERSATILE_SCHED_CLOCK=y CONFIG_PLAT_VERSATILE=y diff --git a/kernel.spec b/kernel.spec index b24c376bb..2048f270c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -739,6 +739,7 @@ Patch21005: arm-tegra-usb-no-reset-linux33.patch Patch21006: arm-tegra-sdhci-module-fix.patch # ARM highbank patches +Patch21010: arm-highbank-sata-fix.patch Patch21094: power-x86-destdir.patch @@ -2319,6 +2320,11 @@ fi # ||----w | # || || %changelog +* Tue Oct 2 2012 Peter Robinson +- Update ARM configs for 3.6 final +- Add highbank SATA driver for stability +- Build in OMAP MMC and DMA drivers to fix borkage for now + * Mon Oct 01 2012 Justin M. Forbes - 3.6.0-1 - Linux 3.6.0 - Disable debugging options. From 8c28af15557a250657c73cacfd0374c40cc28eae Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Oct 2012 09:56:09 -0400 Subject: [PATCH 050/492] Patch from David Howells to fix overflow on 32-bit X.509 certs (rhbz 861322) --- kernel.spec | 5 +- modsign-post-KS-jwb.patch | 174 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 2048f270c..db1dabfca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2320,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 02 2012 Josh Boyer +- Patch from David Howells to fix overflow on 32-bit X.509 certs (rhbz 861322) + * Tue Oct 2 2012 Peter Robinson - Update ARM configs for 3.6 final - Add highbank SATA driver for stability diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch index 6dd81ffa0..ec61f3472 100644 --- a/modsign-post-KS-jwb.patch +++ b/modsign-post-KS-jwb.patch @@ -9151,3 +9151,177 @@ index 83eb505..2beea56 100644 -- 1.7.11.4 +The current choice of lifetime for the autogenerated X.509 of 100 years, +putting the validTo date in 2112, causes problems on 32-bit systems where a +32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. + +This can result in something like: + + Loading module verification certificates + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired + MODSIGN: Problem loading in-kernel X.509 certificate (-127) + +Or: + + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid + MODSIGN: Problem loading in-kernel X.509 certificate (-129) + +Instead of turning the dates into time_t values and comparing, turn the system +clock and the ASN.1 dates into tm structs and compare those piecemeal instead. + +Reported-by: Rusty Russell +Signed-off-by: David Howells +--- + + crypto/asymmetric_keys/x509_cert_parser.c | 25 ++++++++--------- + crypto/asymmetric_keys/x509_parser.h | 4 +-- + crypto/asymmetric_keys/x509_public_key.c | 42 ++++++++++++++++++++++++++--- + 3 files changed, 51 insertions(+), 20 deletions(-) + + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 8fcac94..db07e8c 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, + /* + * Record a certificate time. + */ +-static int x509_note_time(time_t *_time, size_t hdrlen, ++static int x509_note_time(struct tm *tm, size_t hdrlen, + unsigned char tag, + const unsigned char *value, size_t vlen) + { +- unsigned YY, MM, DD, hh, mm, ss; + const unsigned char *p = value; + + #define dec2bin(X) ((X) - '0') +@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, + /* UTCTime: YYMMDDHHMMSSZ */ + if (vlen != 13) + goto unsupported_time; +- YY = DD2bin(p); +- if (YY > 50) +- YY += 1900; ++ tm->tm_year = DD2bin(p); ++ if (tm->tm_year >= 50) ++ tm->tm_year += 1900; + else +- YY += 2000; ++ tm->tm_year += 2000; + } else if (tag == ASN1_GENTIM) { + /* GenTime: YYYYMMDDHHMMSSZ */ + if (vlen != 15) + goto unsupported_time; +- YY = DD2bin(p) * 100 + DD2bin(p); ++ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); + } else { + goto unsupported_time; + } + +- MM = DD2bin(p); +- DD = DD2bin(p); +- hh = DD2bin(p); +- mm = DD2bin(p); +- ss = DD2bin(p); ++ tm->tm_year -= 1900; ++ tm->tm_mon = DD2bin(p) - 1; ++ tm->tm_mday = DD2bin(p); ++ tm->tm_hour = DD2bin(p); ++ tm->tm_min = DD2bin(p); ++ tm->tm_sec = DD2bin(p); + + if (*p != 'Z') + goto unsupported_time; + +- *_time = mktime(YY, MM, DD, hh, mm, ss); + return 0; + + unsupported_time: +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 635053f..f86dc5f 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -18,8 +18,8 @@ struct x509_certificate { + char *subject; /* Name of certificate subject */ + char *fingerprint; /* Key fingerprint as hex */ + char *authority; /* Authority key fingerprint as hex */ +- time_t valid_from; +- time_t valid_to; ++ struct tm valid_from; ++ struct tm valid_to; + enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 716917c..5ab736d 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -106,7 +106,7 @@ error_no_sig: + static int x509_key_preparse(struct key_preparsed_payload *prep) + { + struct x509_certificate *cert; +- time_t now; ++ struct tm now; + size_t srlen, sulen; + char *desc = NULL; + int ret; +@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); + pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); +- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); ++ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, ++ cert->valid_from.tm_mday, cert->valid_from.tm_hour, ++ cert->valid_from.tm_min, cert->valid_from.tm_sec); ++ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, ++ cert->valid_to.tm_mday, cert->valid_to.tm_hour, ++ cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", + pkey_algo[cert->sig_pkey_algo], + pkey_hash_algo[cert->sig_hash_algo]); +@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- now = CURRENT_TIME.tv_sec; +- if (now < cert->valid_from) { ++ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); ++ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, ++ now.tm_hour, now.tm_min, now.tm_sec); ++ if (now.tm_year < cert->valid_from.tm_year || ++ (now.tm_year == cert->valid_from.tm_year && ++ (now.tm_mon < cert->valid_from.tm_mon || ++ (now.tm_mon == cert->valid_from.tm_mon && ++ (now.tm_mday < cert->valid_from.tm_mday || ++ (now.tm_mday == cert->valid_from.tm_mday && ++ (now.tm_hour < cert->valid_from.tm_hour || ++ (now.tm_hour == cert->valid_from.tm_hour && ++ (now.tm_min < cert->valid_from.tm_min || ++ (now.tm_min == cert->valid_from.tm_min && ++ (now.tm_sec < cert->valid_from.tm_sec ++ ))))))))))) { + pr_warn("Cert %s is not yet valid\n", cert->fingerprint); + ret = -EKEYREJECTED; + goto error_free_cert; + } +- if (now >= cert->valid_to) { ++ if (now.tm_year > cert->valid_to.tm_year || ++ (now.tm_year == cert->valid_to.tm_year && ++ (now.tm_mon > cert->valid_to.tm_mon || ++ (now.tm_mon == cert->valid_to.tm_mon && ++ (now.tm_mday > cert->valid_to.tm_mday || ++ (now.tm_mday == cert->valid_to.tm_mday && ++ (now.tm_hour > cert->valid_to.tm_hour || ++ (now.tm_hour == cert->valid_to.tm_hour && ++ (now.tm_min > cert->valid_to.tm_min || ++ (now.tm_min == cert->valid_to.tm_min && ++ (now.tm_sec > cert->valid_to.tm_sec ++ ))))))))))) { + pr_warn("Cert %s has expired\n", cert->fingerprint); + ret = -EKEYEXPIRED; + goto error_free_cert; + From b48142ecf2278a715b23f8b9e8c8d855dd0b8215 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 2 Oct 2012 15:36:46 -0500 Subject: [PATCH 051/492] Power: Fix VMX fix for memcpy case (rhbz 862420) --- kernel.spec | 9 +++ powerpc-fix-VMX-fix-for-memcpy-case.patch | 97 +++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 powerpc-fix-VMX-fix-for-memcpy-case.patch diff --git a/kernel.spec b/kernel.spec index db1dabfca..54311175c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -759,6 +759,9 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 862420 +Patch22068: powerpc-fix-VMX-fix-for-memcpy-case.patch + # END OF PATCH DEFINITIONS %endif @@ -1468,6 +1471,9 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 862420 +ApplyPatch powerpc-fix-VMX-fix-for-memcpy-case.patch + # END OF PATCH APPLICATIONS %endif @@ -2320,6 +2326,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 02 2012 Justin M. Forbes - 3.6.0-2 +- Power: Fix VMX fix for memcpy case (rhbz 862420) + * Tue Oct 02 2012 Josh Boyer - Patch from David Howells to fix overflow on 32-bit X.509 certs (rhbz 861322) diff --git a/powerpc-fix-VMX-fix-for-memcpy-case.patch b/powerpc-fix-VMX-fix-for-memcpy-case.patch new file mode 100644 index 000000000..78a0a70e6 --- /dev/null +++ b/powerpc-fix-VMX-fix-for-memcpy-case.patch @@ -0,0 +1,97 @@ +From patchwork Tue Oct 2 00:59:13 2012 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: powerpc: fix VMX fix for memcpy case +Date: Mon, 01 Oct 2012 14:59:13 -0000 +From: Nishanth Aravamudan +X-Patchwork-Id: 188371 +Message-Id: <20121002005912.GA27768@linux.vnet.ibm.com> +To: Anton Blanchard +Cc: paulus@samba.org, linuxppc-dev@lists.ozlabs.org + +[urgh, sorry Anton, Ben & Paul, inadvertently hit send before adding +linuxppc-dev to the cc!] + +Hi Anton, + +In 2fae7cdb60240e2e2d9b378afbf6d9fcce8a3890 ("powerpc: Fix VMX in +interrupt check in POWER7 copy loops"), I think you inadvertently +introduced a regression for memcpy on POWER7 machines. copyuer and +memcpy diverge slightly in their use of cr1 (copyuser doesn't use it, +but memcpy does) and you end up clobbering that register with your fix. +That results in (taken from an FC18 kernel): + +[ 18.824604] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052f40 +[ 18.824618] Oops: Unrecoverable VMX/Altivec Unavailable Exception, sig: 6 [#1] +[ 18.824623] SMP NR_CPUS=1024 NUMA pSeries +[ 18.824633] Modules linked in: tg3(+) be2net(+) cxgb4(+) ipr(+) sunrpc xts lrw gf128mul dm_crypt dm_round_robin dm_multipath linear raid10 raid456 async_raid6_recov async_memcpy async_pq raid6_pq async_xor xor async_tx raid1 raid0 scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua squashfs cramfs +[ 18.824705] NIP: c000000000052f40 LR: c00000000020b874 CTR: 0000000000000512 +[ 18.824709] REGS: c000001f1fef7790 TRAP: 0f20 Not tainted (3.6.0-0.rc6.git0.2.fc18.ppc64) +[ 18.824713] MSR: 8000000000009032 CR: 4802802e XER: 20000010 +[ 18.824726] SOFTE: 0 +[ 18.824728] CFAR: 0000000000000f20 +[ 18.824731] TASK = c000000fa7128400[0] 'swapper/24' THREAD: c000000fa7480000 CPU: 24 +GPR00: 00000000ffffffc0 c000001f1fef7a10 c00000000164edc0 c000000f9b9a8120 +GPR04: c000000f9b9a8124 0000000000001438 0000000000000060 03ffffff064657ee +GPR08: 0000000080000000 0000000000000010 0000000000000020 0000000000000030 +GPR12: 0000000028028022 c00000000ff25400 0000000000000001 0000000000000000 +GPR16: 0000000000000000 7fffffffffffffff c0000000016b2180 c00000000156a500 +GPR20: c000000f968c7a90 c0000000131c31d8 c000001f1fef4000 c000000001561d00 +GPR24: 000000000000000a 0000000000000000 0000000000000001 0000000000000012 +GPR28: c000000fa5c04f80 00000000000008bc c0000000015c0a28 000000000000022e +[ 18.824792] NIP [c000000000052f40] .memcpy_power7+0x5a0/0x7c4 +[ 18.824797] LR [c00000000020b874] .pcpu_free_area+0x174/0x2d0 +[ 18.824800] Call Trace: +[ 18.824803] [c000001f1fef7a10] [c000000000052c14] .memcpy_power7+0x274/0x7c4 (unreliable) +[ 18.824809] [c000001f1fef7b10] [c00000000020b874] .pcpu_free_area+0x174/0x2d0 +[ 18.824813] [c000001f1fef7bb0] [c00000000020ba88] .free_percpu+0xb8/0x1b0 +[ 18.824819] [c000001f1fef7c50] [c00000000043d144] .throtl_pd_exit+0x94/0xd0 +[ 18.824824] [c000001f1fef7cf0] [c00000000043acf8] .blkg_free+0x88/0xe0 +[ 18.824829] [c000001f1fef7d90] [c00000000018c048] .rcu_process_callbacks+0x2e8/0x8a0 +[ 18.824835] [c000001f1fef7e90] [c0000000000a8ce8] .__do_softirq+0x158/0x4d0 +[ 18.824840] [c000001f1fef7f90] [c000000000025ecc] .call_do_softirq+0x14/0x24 +[ 18.824845] [c000000fa7483650] [c000000000010e80] .do_softirq+0x160/0x1a0 +[ 18.824850] [c000000fa74836f0] [c0000000000a94a4] .irq_exit+0xf4/0x120 +[ 18.824854] [c000000fa7483780] [c000000000020c44] .timer_interrupt+0x154/0x4d0 +[ 18.824859] [c000000fa7483830] [c000000000003be0] decrementer_common+0x160/0x180 +[ 18.824866] --- Exception: 901 at .plpar_hcall_norets+0x84/0xd4 +[ 18.824866] LR = .check_and_cede_processor+0x48/0x80 +[ 18.824871] [c000000fa7483b20] [c00000000007f018] .check_and_cede_processor+0x18/0x80 (unreliable) +[ 18.824877] [c000000fa7483b90] [c00000000007f104] .dedicated_cede_loop+0x84/0x150 +[ 18.824883] [c000000fa7483c50] [c0000000006bc030] .cpuidle_enter+0x30/0x50 +[ 18.824887] [c000000fa7483cc0] [c0000000006bc9f4] .cpuidle_idle_call+0x104/0x720 +[ 18.824892] [c000000fa7483d80] [c000000000070af8] .pSeries_idle+0x18/0x40 +[ 18.824897] [c000000fa7483df0] [c000000000019084] .cpu_idle+0x1a4/0x380 +[ 18.824902] [c000000fa7483ec0] [c0000000008a4c18] .start_secondary+0x520/0x528 +[ 18.824907] [c000000fa7483f90] [c0000000000093f0] .start_secondary_prolog+0x10/0x14 +[ 18.824911] Instruction dump: +[ 18.824914] 38840008 90030000 90e30004 38630008 7ca62850 7cc300d0 78c7e102 7cf01120 +[ 18.824923] 78c60660 39200010 39400020 39600030 <7e00200c> 7c0020ce 38840010 409f001c +[ 18.824935] ---[ end trace 0bb95124affaaa45 ]--- +[ 18.825046] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052d08 + +I believe the right fix is to make memcpy match usercopy and not use +cr1. + +Signed-off-by: Nishanth Aravamudan + +--- +I've not tested this fix yet, but I think it's logically correct. +Probably needs to go to 3.6-stable as well. + +diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S +index 7ba6c96..0663630 100644 +--- a/arch/powerpc/lib/memcpy_power7.S ++++ b/arch/powerpc/lib/memcpy_power7.S +@@ -239,8 +239,8 @@ _GLOBAL(memcpy_power7) + ori r9,r9,1 /* stream=1 */ + + srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */ +- cmpldi cr1,r7,0x3FF +- ble cr1,1f ++ cmpldi r7,0x3FF ++ ble 1f + li r7,0x3FF + 1: lis r0,0x0E00 /* depth=7 */ + sldi r7,r7,7 From b12047e72c7526815109775fe0fd239b932fd349 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Oct 2012 08:23:43 -0400 Subject: [PATCH 052/492] Make sure kernel-tools-libs-devel provides kernel-tools-devel --- kernel.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 54311175c..6660a2f0e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -894,6 +894,7 @@ Requires: kernel-tools = %{version}-%{release} Provides: cpupowerutils-devel = 1:009-0.6.p1 Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 Requires: kernel-tools-libs = %{version}-%{release} +Provides: kernel-tools-devel %description -n kernel-tools-libs-devel This package contains the development files for the tools/ directory from the kernel source. @@ -2326,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 03 2012 Josh Boyer +- Make sure kernel-tools-libs-devel provides kernel-tools-devel + * Tue Oct 02 2012 Justin M. Forbes - 3.6.0-2 - Power: Fix VMX fix for memcpy case (rhbz 862420) From dd2f784babd1af7960b01d6cebf45cabf8f1aad0 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 3 Oct 2012 12:02:43 -0400 Subject: [PATCH 053/492] Drop vgem patches, not doing anything yet. --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 6660a2f0e..dbb2a4d80 100644 --- a/kernel.spec +++ b/kernel.spec @@ -693,7 +693,7 @@ Patch1100: handle-efi-roms.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch -Patch1800: drm-vgem.patch +#Patch1800: drm-vgem.patch # nouveau + drm fixes # intel drm is all merged upstream @@ -1421,7 +1421,7 @@ ApplyPatch handle-efi-roms.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch -ApplyPatch drm-vgem.patch +#ApplyPatch drm-vgem.patch # Nouveau DRM @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 03 2012 Adam Jackson +- Drop vgem patches, not doing anything yet. + * Wed Oct 03 2012 Josh Boyer - Make sure kernel-tools-libs-devel provides kernel-tools-devel From 5873a55fe115bf3b794a4da1ab300bcc2e1bb5b7 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Fri, 5 Oct 2012 08:12:12 +0100 Subject: [PATCH 054/492] Build MMC in on OMAP and Tegra until we work out why modules don't work --- config-arm-generic | 7 +++++++ config-arm-kirkwood | 4 ++++ config-arm-omap | 9 +++++++++ config-arm-tegra | 8 ++++++++ kernel.spec | 3 +++ 5 files changed, 31 insertions(+) diff --git a/config-arm-generic b/config-arm-generic index 5f4fbf42b..e2e6a7714 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -19,6 +19,8 @@ CONFIG_SMP_ON_UP=y CONFIG_ARM_ARCH_TIMER=y +CONFIG_CMDLINE="" + # CONFIG_FPE_NWFPE is not set CONFIG_FPE_FASTFPE=y @@ -32,12 +34,15 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_ATAGS_PROC=y +#CONFIG_XIP_KERNEL is not set + # DeviceTree CONFIG_USE_OF=y # CONFIG_OF_SELFTEST is not set CONFIG_PROC_DEVICETREE=y CONFIG_ARM_APPENDED_DTB=y CONFIG_I2C_MUX_PINCTRL=m +CONFIG_ARM_ATAG_DTB_COMPAT=y # Generic options we want for ARM that aren't defualt CONFIG_HIGHMEM=y @@ -116,6 +121,8 @@ CONFIG_GENERIC_GPIO=y CONFIG_MTD=m CONFIG_MTD_TESTS=m CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_AFS_PARTS is not set CONFIG_MTD_CHAR=m CONFIG_MTD_BLKDEVS=m diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 4d6dbf8c9..7b5d758e4 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -2,15 +2,19 @@ CONFIG_ARCH_KIRKWOOD=y CONFIG_ARCH_KIRKWOOD_DT=y # CONFIG_SMP is not set # CONFIG_VFP is not set + CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y CONFIG_MACH_MV88F6281GTW_GE=y CONFIG_MACH_SHEEVAPLUG=y CONFIG_MACH_ESATA_SHEEVAPLUG=y +CONFIG_MACH_DLINK_KIRKWOOD_DT=y CONFIG_MACH_GURUPLUG=y CONFIG_MACH_DREAMPLUG_DT=y CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_ICONNECT_DT=y +CONFIG_MACH_IB62X0_DT=y CONFIG_MACH_TS219=y CONFIG_MACH_TS41X=y CONFIG_MACH_OPENRD_BASE=y diff --git a/config-arm-omap b/config-arm-omap index b698e4849..ae328f190 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -247,6 +247,15 @@ CONFIG_USB_MUSB_HDRC=y # CONFIG_USB_GADGET_OMAP is not set # CONFIG_ISP1301_OMAP is not set + +# This block is temporary until we work out why the MMC modules don't work as modules +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF=y +CONFIG_MMC_SPI=y + CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_TWL4030_USB=y diff --git a/config-arm-tegra b/config-arm-tegra index 5ec5a6762..015af431d 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -27,6 +27,14 @@ CONFIG_TEGRA_IOMMU_SMMU=y CONFIG_I2C_TEGRA=y +# This block is temporary until we work out why the MMC modules don't work as modules +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF=y +CONFIG_MMC_SPI=y + CONFIG_MMC_SDHCI_TEGRA=y # CONFIG_RCU_BOOST is not set diff --git a/kernel.spec b/kernel.spec index dbb2a4d80..8aac3ca10 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 5 2012 Peter Robinson +- Build MMC in on OMAP and Tegra until we work out why modules don't work + * Wed Oct 03 2012 Adam Jackson - Drop vgem patches, not doing anything yet. From 0f1408ff0af4379a39310451a7a708df027e9c70 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 14:11:00 -0400 Subject: [PATCH 055/492] Adjust secure boot modsign patch --- kernel.spec | 5 ++- secure-boot-20120924.patch | 67 +++++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8aac3ca10..443b6e9ac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 05 2012 Josh Boyer +- Adjust secure boot modsign patch + * Fri Oct 5 2012 Peter Robinson - Build MMC in on OMAP and Tegra until we work out why modules don't work diff --git a/secure-boot-20120924.patch b/secure-boot-20120924.patch index 37beb41b2..8fb4d1327 100644 --- a/secure-boot-20120924.patch +++ b/secure-boot-20120924.patch @@ -683,44 +683,65 @@ index e398bb5..8a84501 100644 1.7.11.4 -From d1a225668878a3339adcd7ce0be256e857360ada Mon Sep 17 00:00:00 2001 + +From 1cc529e97756554953187fe48b9b8cf0e24b9bc7 Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Tue, 26 Jun 2012 16:27:26 -0400 -Subject: [PATCH 14/14] modsign: Reject unsigned modules in a Secure Boot +Date: Fri, 5 Oct 2012 10:12:48 -0400 +Subject: [PATCH] modsign: Always enforce module signing in a Secure Boot environment If a machine is booted into a Secure Boot environment, we need to protect the trust model. This requires that all modules be signed -with a key that is in the kernel's _modsign keyring. We add a -capability check and reject modules that are not signed. +with a key that is in the kernel's _modsign keyring. The checks for +this are already done via the 'sig_enforce' module parameter. Make +this visible within the kernel and force it to be true. Signed-off-by: Josh Boyer --- + kernel/cred.c | 8 ++++++++ kernel/module.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + 2 files changed, 10 insertions(+), 2 deletions(-) +diff --git a/kernel/cred.c b/kernel/cred.c +index 7e6e83f..2b0b980 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -623,11 +623,19 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++#ifdef CONFIG_MODULES ++extern bool sig_enforce; ++#endif ++ + void __init secureboot_enable() + { + pr_info("Secure boot enabled\n"); + cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); + cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++#ifdef CONFIG_MODULES ++ /* Enable module signature enforcing */ ++ sig_enforce = true; ++#endif + } + + /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index de16959..5af69cc 100644 +index de16959..7d4c50a 100644 --- a/kernel/module.c +++ b/kernel/module.c -@@ -2463,7 +2463,7 @@ static int module_sig_check(struct load_info *info, - } +@@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - /* Not having a signature is only an error if we're strict. */ -- if (!err && !info->sig_ok && sig_enforce) -+ if (!err && !info->sig_ok && (sig_enforce || !capable(CAP_COMPROMISE_KERNEL))) - err = -EKEYREJECTED; - return err; + #ifdef CONFIG_MODULE_SIG + #ifdef CONFIG_MODULE_SIG_FORCE +-static bool sig_enforce = true; ++bool sig_enforce = true; + #else +-static bool sig_enforce = false; ++bool sig_enforce = false; -@@ -2475,7 +2475,7 @@ found_marker: - if (err < 0 && fips_enabled) - panic("Module verification failed with error %d in FIPS mode\n", - err); -- if (err == -ENOKEY && !sig_enforce) -+ if (err == -ENOKEY && (!sig_enforce && capable(CAP_COMPROMISE_KERNEL))) - err = 0; - return err; - } + static int param_set_bool_enable_only(const char *val, + const struct kernel_param *kp) -- 1.7.11.4 From cc41f66d974d94adfd0150abfa9321a74089831d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 6 Oct 2012 08:53:08 -0400 Subject: [PATCH 056/492] secure boot modsign depends on CONFIG_MODULE_SIG not CONFIG_MODULES --- kernel.spec | 5 ++++- secure-boot-20120924.patch | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 443b6e9ac..d9949f7fa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Sat Oct 06 2012 Josh Boyer +- secure boot modsign depends on CONFIG_MODULE_SIG not CONFIG_MODULES + * Fri Oct 05 2012 Josh Boyer - Adjust secure boot modsign patch diff --git a/secure-boot-20120924.patch b/secure-boot-20120924.patch index 8fb4d1327..a9c63de14 100644 --- a/secure-boot-20120924.patch +++ b/secure-boot-20120924.patch @@ -710,7 +710,7 @@ index 7e6e83f..2b0b980 100644 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); } -+#ifdef CONFIG_MODULES ++#ifdef CONFIG_MODULE_SIG +extern bool sig_enforce; +#endif + @@ -719,7 +719,7 @@ index 7e6e83f..2b0b980 100644 pr_info("Secure boot enabled\n"); cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+#ifdef CONFIG_MODULES ++#ifdef CONFIG_MODULE_SIG + /* Enable module signature enforcing */ + sig_enforce = true; +#endif From 61db236d135282d11e0c01c0c6ea55d7d785a9ea Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 6 Oct 2012 20:07:42 +0100 Subject: [PATCH 057/492] Fix handle-efi-roms.patch to actually use the copy it got from EFI --- handle-efi-roms.patch | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/handle-efi-roms.patch b/handle-efi-roms.patch index 7f02a1c3d..3002b1f89 100644 --- a/handle-efi-roms.patch +++ b/handle-efi-roms.patch @@ -332,19 +332,25 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c --- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-07-21 16:58:29.000000000 -0400 +++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-08-22 15:25:40.531244893 -0400 -@@ -126,6 +126,12 @@ +@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) + void __iomem *rom; + + /* ++ * Some devices may provide ROMs via a source other than the BAR ++ */ ++ if (pdev->rom && pdev->romlen) { ++ *size = pdev->romlen; ++ return phys_to_virt(pdev->rom); ++ /* + * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy + * memory map if the VGA enable bit of the Bridge Control register is + * set for embedded VGA. + */ +- if (res->flags & IORESOURCE_ROM_SHADOW) { ++ } else if (res->flags & IORESOURCE_ROM_SHADOW) { /* primary video rom always starts here */ start = (loff_t)0xC0000; *size = 0x20000; /* cover C000:0 through E000:0 */ -+ /* -+ * Some devices may provide ROMs via a source other than the BAR -+ */ -+ } else if (pdev->rom && pdev->romlen) { -+ *size = pdev->romlen; -+ return phys_to_virt(pdev->rom); - } else { - if (res->flags & - (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { @@ -219,7 +225,8 @@ if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) return; From 5768fdefaf8225b52c1913fa6944a007b0de92d8 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 8 Oct 2012 10:53:09 -0500 Subject: [PATCH 058/492] Linux 3.6.1 --- kernel.spec | 7 +++++-- sources | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d9949f7fa..e0b754f02 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2327,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 08 2012 Justin M. Forbes 3.6.1-1 +- Linux 3.6.1 + * Sat Oct 06 2012 Josh Boyer - secure boot modsign depends on CONFIG_MODULE_SIG not CONFIG_MODULES diff --git a/sources b/sources index 8ca40febd..152630c87 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz +775f1389a934512341726f9b4aeaf661 patch-3.6.1.xz From 9d69565a5faac2eaef445d164b834d708e7a3aa9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Oct 2012 08:27:17 -0400 Subject: [PATCH 059/492] Drop unhandled irq polling patch --- kernel.spec | 9 +- unhandled-irqs-switch-to-polling.patch | 245 ------------------------- 2 files changed, 4 insertions(+), 250 deletions(-) delete mode 100644 unhandled-irqs-switch-to-polling.patch diff --git a/kernel.spec b/kernel.spec index e0b754f02..37dacd532 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -746,8 +746,6 @@ Patch21094: power-x86-destdir.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -Patch21400: unhandled-irqs-switch-to-polling.patch - Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions @@ -1459,8 +1457,6 @@ ApplyPatch power-x86-destdir.patch #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -ApplyPatch unhandled-irqs-switch-to-polling.patch - ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions @@ -2327,6 +2323,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 09 2012 Josh Boyer +- Drop unhandled irq polling patch + * Mon Oct 08 2012 Justin M. Forbes 3.6.1-1 - Linux 3.6.1 diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch deleted file mode 100644 index 0fc4d080e..000000000 --- a/unhandled-irqs-switch-to-polling.patch +++ /dev/null @@ -1,245 +0,0 @@ -From f9b32cd97783f2be14386f1347439e86109050b9 Mon Sep 17 00:00:00 2001 -From: Jeroen Van den Keybus -Date: Mon, 30 Jan 2012 22:37:28 +0100 -Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to - low-performance polling IRQ mode - -It seems that some motherboard designs using the ASM1083 PCI/PCIe -bridge (PCI device ID 1b21:1080, Rev. 01) suffer from stuck IRQ lines -on the PCI bus (causing the kernel to emit 'IRQxx: nobody cared' and -disable the IRQ). The following patch is an attempt to mitigate the -serious impact of permanently disabling an IRQ in that case and -actually make PCI devices better usable on this platform. - -It seems that the bridge fails to issue a IRQ deassertion message on -the PCIe bus, when the relevant driver causes the interrupting PCI -device to deassert its IRQ line. To solve this issue, it was tried to -re-issue an IRQ on a PCI device being able to do so (e1000 in this -case), but we suspect that the attempt to re-assert/deassert may have -occurred too soon after the initial IRQ for the ASM1083. Anyway, it -didn't work but if, after some delay, a new IRQ occurred, the related -IRQ deassertion message eventually did clear the IOAPIC IRQ. It would -be useful to re-enable the IRQ here. - -Therefore the patch below to poll_spurious_irqs() in spurious.c is -proposed, It does the following: - -1. lets the kernel decide that an IRQ is unhandled after only 10 -positives (instead of 100,000); -2. briefly (a few seconds or so, currently 1 s) switches to polling -IRQ at a higher rate than usual (100..1,000Hz instead of 10Hz, -currently 100Hz), but not too high to avoid excessive CPU load. Any -device drivers 'see' their interrupts handled with a higher latency -than usual, but they will still operate properly; -3. afterwards, simply reenable the IRQ. - -If proper operation of the PCIe legacy IRQ line emulation is restored -after 3, the system operates again at normal performance. If the IRQ -is still stuck after this procedure, the sequence repeats. - -If a genuinely stuck IRQ is used with this solution, the system would -simply sustain short bursts of 10 unhandled IRQs per second, and use -polling mode indefinitely at a moderate 100Hz rate. It seemed a good -alternative to the default irqpoll behaviour to me, which is why I -left it in poll_spurious_irqs() (instead of creating a new kernel -option). Additionally, if any device happens to share an IRQ with a -faulty one, that device is no longer banned forever. - -Debugging output is still present and may be removed. Bad IRQ -reporting is also commented out now. - -I have now tried it for about 2 months and I can conclude the following: - -1. The patch works and, judging from my Firewire card interrupt on -IRQ16, which repeats every 64 secs, I can confirm that the IRQ usually -gets reset when a new IRQ arrives (polling mode runs for 64 seconds -every time). -2. When testing a SiL-3114 SATA PCI card behind the ASM1083, I could -keep this running at fairly high speeds (50..70MB/s) for an hour or -so, but eventually the SiL driver crashed. In such conditions the PCI -system had to deal with a few hundred IRQs per second / polling mode -kicking in every 5..10 seconds). - -I would like to thank Clemens Ladisch for his invaluable help in -finding a solution (and providing a patch to avoid my SATA going down -every time during debugging). - -Signed-off-by: Jeroen Van den Keybus - -Make it less chatty. Only kick it in if we detect an ASM1083 PCI bridge. -Fix logic error due to lack of braces - -Josh Boyer -====== ---- - drivers/pci/quirks.c | 16 +++++++++++ - kernel/irq/spurious.c | 73 +++++++++++++++++++++++++++++++++++++++--------- - 2 files changed, 75 insertions(+), 14 deletions(-) - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 78fda9c..6ba5dbf 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); - -+/* ASM108x transparent PCI bridges apparently have broken IRQ deassert -+ * handling. This causes interrupts to get "stuck" and eventually disabled. -+ * However, the interrupts are often shared and disabling them is fairly bad. -+ * It's been somewhat successful to switch to polling mode and retry after -+ * a bit, so let's do that. -+ */ -+extern int irq_poll_and_retry; -+static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) -+{ -+ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", -+ dev->vendor, dev->device); -+ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); -+ irq_poll_and_retry = 1; -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); -+ - #ifdef CONFIG_X86_IO_APIC - /* - * Boot interrupts on some chipsets cannot be turned off. For these chipsets, -diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c -index 611cd60..f722eb6 100644 ---- a/kernel/irq/spurious.c -+++ b/kernel/irq/spurious.c -@@ -18,6 +18,8 @@ - - static int irqfixup __read_mostly; - -+int irq_poll_and_retry = 0; -+ - #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) - static void poll_spurious_irqs(unsigned long dummy); - static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); -@@ -141,12 +143,13 @@ out: - static void poll_spurious_irqs(unsigned long dummy) - { - struct irq_desc *desc; -- int i; -+ int i, poll_again; - - if (atomic_inc_return(&irq_poll_active) != 1) - goto out; - irq_poll_cpu = smp_processor_id(); - -+ poll_again = 0; /* Will stay false as long as no polling candidate is found */ - for_each_irq_desc(i, desc) { - unsigned int state; - -@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned long dummy) - if (!(state & IRQS_SPURIOUS_DISABLED)) - continue; - -- local_irq_disable(); -- try_one_irq(i, desc, true); -- local_irq_enable(); -+ /* We end up here with a disabled spurious interrupt. -+ desc->irqs_unhandled now tracks the number of times -+ the interrupt has been polled */ -+ if (irq_poll_and_retry) { -+ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ -+ local_irq_disable(); -+ try_one_irq(i, desc, true); -+ local_irq_enable(); -+ desc->irqs_unhandled++; -+ poll_again = 1; -+ } else { -+ irq_enable(desc); /* Reenable the interrupt line */ -+ desc->depth--; -+ desc->istate &= (~IRQS_SPURIOUS_DISABLED); -+ desc->irqs_unhandled = 0; -+ } -+ } else { -+ local_irq_disable(); -+ try_one_irq(i, desc, true); -+ local_irq_enable(); -+ } - } -+ if (poll_again) -+ mod_timer(&poll_spurious_irq_timer, -+ jiffies + POLL_SPURIOUS_IRQ_INTERVAL); - out: - atomic_dec(&irq_poll_active); -- mod_timer(&poll_spurious_irq_timer, -- jiffies + POLL_SPURIOUS_IRQ_INTERVAL); - } - - static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqreturn_t action_ret) - } - - /* -- * If 99,900 of the previous 100,000 interrupts have not been handled -+ * If 9 of the previous 10 interrupts have not been handled - * then assume that the IRQ is stuck in some manner. Drop a diagnostic - * and try to turn the IRQ off. - * -- * (The other 100-of-100,000 interrupts may have been a correctly -+ * Although this may cause early deactivation of a sporadically -+ * malfunctioning IRQ line, the poll system will: -+ * a) Poll it for 100 cycles at a 100 Hz rate -+ * b) Reenable it afterwards -+ * -+ * In worst case, with current settings, this will cause short bursts -+ * of 10 interrupts every second. -+ * -+ * (The other single interrupt may have been a correctly - * functioning device sharing an IRQ with the failing one) - */ - static void -@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc, - void note_interrupt(unsigned int irq, struct irq_desc *desc, - irqreturn_t action_ret) - { -+ int unhandled_thresh = 999000; -+ - if (desc->istate & IRQS_POLL_INPROGRESS) - return; - -@@ -302,19 +334,32 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, - } - - desc->irq_count++; -- if (likely(desc->irq_count < 100000)) -- return; -+ if (!irq_poll_and_retry) { -+ if (likely(desc->irq_count < 100000)) -+ return; -+ } else { -+ if (likely(desc->irq_count < 10)) -+ return; -+ } - - desc->irq_count = 0; -- if (unlikely(desc->irqs_unhandled > 99900)) { -+ if (irq_poll_and_retry) -+ unhandled_thresh = 9; -+ -+ if (unlikely(desc->irqs_unhandled >= unhandled_thresh)) { - /* -- * The interrupt is stuck -+ * The interrupt might be stuck - */ -- __report_bad_irq(irq, desc, action_ret); -+ if (!irq_poll_and_retry) { -+ __report_bad_irq(irq, desc, action_ret); -+ printk(KERN_EMERG "Disabling IRQ %d\n", irq); -+ } else { -+ printk(KERN_INFO "IRQ %d might be stuck. Polling\n", -+ irq); -+ } - /* - * Now kill the IRQ - */ -- printk(KERN_EMERG "Disabling IRQ #%d\n", irq); - desc->istate |= IRQS_SPURIOUS_DISABLED; - desc->depth++; - irq_disable(desc); --- -1.7.7.6 - From 9abf1b6acad78c6b36f09c49788d33bcbef6c0d8 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 11 Oct 2012 15:03:26 +0100 Subject: [PATCH 060/492] Update ARM config for missing newoption items --- config-arm-generic | 124 +++++++++++++++++++++++++++++++++++++++---- config-arm-highbank | 7 ++- config-arm-imx | 73 ++++++++++++++++--------- config-arm-kirkwood | 37 +++++++------ config-arm-omap | 94 +++++++++++++++++++++++--------- config-arm-tegra | 3 -- config-arm-versatile | 23 +++++++- kernel.spec | 3 ++ 8 files changed, 283 insertions(+), 81 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index e2e6a7714..0a253eb0c 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -21,28 +21,34 @@ CONFIG_ARM_ARCH_TIMER=y CONFIG_CMDLINE="" +# CONFIG_ARM_LPAE is not set # CONFIG_FPE_NWFPE is not set CONFIG_FPE_FASTFPE=y +CONFIG_HIGHPTE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_UACCESS_WITH_MEMCPY=y # Generic ARM Errata CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_751472=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_ARM_ERRATA_742231=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y + # Generic ARM config options CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_LOCAL_TIMERS=y CONFIG_ATAGS_PROC=y -#CONFIG_XIP_KERNEL is not set - -# DeviceTree -CONFIG_USE_OF=y -# CONFIG_OF_SELFTEST is not set -CONFIG_PROC_DEVICETREE=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_I2C_MUX_PINCTRL=m -CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_PL330_DMA=y +CONFIG_AMBA_PL08X=y +CONFIG_PL330_DMA=y +# CONFIG_XIP_KERNEL is not set +# CONFIG_PID_IN_CONTEXTIDR is not set # Generic options we want for ARM that aren't defualt CONFIG_HIGHMEM=y @@ -68,6 +74,8 @@ CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_THERMAL=y +CONFIG_ETHERNET=y + CONFIG_PERF_EVENTS=y CONFIG_PERF_COUNTERS=y @@ -93,12 +101,15 @@ CONFIG_LBDAF=y CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_PINCTRL_SINGLE=m CONFIG_USB_ULPI=y CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m CONFIG_SND_SOC=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_SIMPLE_CARD=m # CONFIG_SND_SOC_CACHE_LZO is not set CONFIG_SND_SOC_ALL_CODECS=m @@ -111,9 +122,22 @@ CONFIG_DM9000_DEBUGLEVEL=4 CONFIG_SMC911X=m CONFIG_SMSC911X=m +CONFIG_SERIO_AMBAKMI=m +CONFIG_I2C_NOMADIK=m +CONFIG_ARM_SP805_WATCHDOG=m +CONFIG_FB_ARMCLCD=m +CONFIG_MPCORE_WATCHDOG=m + +CONFIG_MMC_ARMMMCI=m CONFIG_MMC_SDHCI_PLTFM=m CONFIG_MMC_SDHCI_OF=m CONFIG_MMC_SPI=m +CONFIG_MMC_DW=m +CONFIG_MMC_DW_PLTFM=m +CONFIG_MMC_DW_PCI=m +# CONFIG_MMC_DW_IDMAC is not set +CONFIG_MMC_SDHCI_PXAV3=m +CONFIG_MMC_SDHCI_PXAV2=m # Generic GPIO options CONFIG_GENERIC_GPIO=y @@ -148,6 +172,7 @@ CONFIG_MTD_ALAUDA=m # CONFIG_MTD_ONENAND is not set CONFIG_MTD_JEDECPROBE=m CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_IMPA7=m CONFIG_MTD_MAP_BANK_WIDTH_1=y CONFIG_MTD_MAP_BANK_WIDTH_2=y # CONFIG_MTD_MAP_BANK_WIDTH_4 is not set @@ -183,6 +208,8 @@ CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_RESERVE=1 # CONFIG_MTD_UBI_GLUEBI is not set # CONFIG_MTD_UBI_DEBUG is not set +CONFIG_MG_DISK=m +CONFIG_MG_DISK_RES=0 # CONFIG_SM_FTL is not set @@ -205,17 +232,96 @@ CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_DEBUG is not set +# HW crypto and rng +CONFIG_HW_RANDOM_ATMEL=m +CONFIG_HW_RANDOM_EXYNOS=m + # Device tree CONFIG_OF=y +CONFIG_USE_OF=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set + CONFIG_SERIAL_OF_PLATFORM=y CONFIG_OF_GPIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_OF_MDIO=m +CONFIG_MDIO_BUS_MUX_GPIO=m + +CONFIG_BPF_JIT=y + +CONFIG_RCU_FANOUT_LEAF=16 +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set + +CONFIG_RTC_DRV_88PM80X=m +CONFIG_RTC_DRV_PL030=m +CONFIG_RTC_DRV_PL031=m +CONFIG_RFKILL_REGULATOR=m +CONFIG_INPUT_88PM80X_ONKEY=y +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_SERIAL_AMBA_PL010=m +CONFIG_SERIAL_AMBA_PL011=m +CONFIG_GPIO_PL061=y +CONFIG_GPIO_MCP23S08=m +CONFIG_PL310_ERRATA_753970=y + +CONFIG_MFD_88PM800=m +CONFIG_MFD_88PM805=m +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +CONFIG_REGULATOR_GPIO=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_TPS62360=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_CHARGER_MANAGER=y +CONFIG_EXTCON_GPIO=m + +# CONFIG_XIP_KERNEL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_GPIO_EM is not set +# CONFIG_HVC_DCC is not set +# CONFIG_LEDS_RENESAS_TPU is not set + +# Possibly part of Snowball +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set + +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_COMMON_CLK_DEBUG is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set + +# CONFIG_DEBUG_PINCTRL is not set # HW Disabled because it causes issues on ARM platforms # disable TPM on arm at least on the trimslices it causes havoc # CONFIG_TCG_TPM is not set + # CONFIG_IMA is not set # ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! diff --git a/config-arm-highbank b/config-arm-highbank index 6b023e02e..952a21ac4 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -26,6 +26,9 @@ CONFIG_ATA_SFF=y CONFIG_NET_CALXEDA_XGMAC=y +CONFIG_EDAC_HIGHBANK_MC=m +CONFIG_EDAC_HIGHBANK_L2=m + CONFIG_GPIO_PL061=y CONFIG_SERIAL_AMBA_PL010=y @@ -38,9 +41,9 @@ CONFIG_RTC_DRV_PL031=y CONFIG_SATA_HIGHBANK=m -# CONFIG_DVB_TDA1004X is not set -# CONFIG_DVB_PLL is not set +CONFIG_OC_ETM=y +# CONFIG_NET_VENDOR_BROADCOM is not set # these were all requested to be disabled on highbank kernels by calxeda # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set diff --git a/config-arm-imx b/config-arm-imx index 88dd42b5f..bddff88ab 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -1,45 +1,62 @@ CONFIG_ARCH_MXC=y CONFIG_ARCH_MX51=y -CONFIG_MACH_MX51_BABBAGE=y -CONFIG_MACH_MX51_3DS=y -CONFIG_MACH_EUKREA_CPUIMX51=y + CONFIG_VFP=y CONFIG_NEON=y - -CONFIG_MACH_EUKREA_CPUIMX51SD=y -CONFIG_MACH_MX51_EFIKAMX=y -CONFIG_MACH_MX51_EFIKASB=y # CONFIG_SWP_EMULATE is not set # CONFIG_THUMB2_KERNEL is not set CONFIG_CPU_FREQ_IMX=y -CONFIG_W1_MASTER_MXC=m -CONFIG_IMX_DMA=y -CONFIG_IMX_SDMA=y + +CONFIG_SOC_IMX6Q=y + +CONFIG_MACH_ARMADILLO5X0=y +CONFIG_MACH_BUG=y +CONFIG_MACH_EUKREA_CPUIMX35=y +CONFIG_MACH_EUKREA_CPUIMX35SD=y +CONFIG_MACH_EUKREA_CPUIMX51=y +CONFIG_MACH_EUKREA_CPUIMX51SD=y +CONFIG_MACH_IMX31_DT=y +CONFIG_MACH_IMX51_DT=y +CONFIG_MACH_IMX53_DT=y +CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_MX31_3DS=y CONFIG_MACH_MX31ADS=y CONFIG_MACH_MX31LILLY=y CONFIG_MACH_MX31LITE=y -CONFIG_MACH_PCM037=y -CONFIG_MACH_MX31_3DS=y CONFIG_MACH_MX31MOBOARD=y -CONFIG_MACH_QONG=y -CONFIG_MACH_ARMADILLO5X0=y -CONFIG_MACH_KZM_ARM11_01=y -CONFIG_MACH_BUG=y -CONFIG_MACH_PCM043=y CONFIG_MACH_MX35_3DS=y -CONFIG_MACH_EUKREA_CPUIMX35=y +CONFIG_MACH_MX51_3DS=y +CONFIG_MACH_MX51_BABBAGE=y +CONFIG_MACH_MX51_EFIKAMX=y +CONFIG_MACH_MX51_EFIKASB=y +CONFIG_MACH_MX53_EVK=y +CONFIG_MACH_MX53_SMD=y +CONFIG_MACH_MX53_LOCO=y +CONFIG_MACH_MX53_ARD=y +CONFIG_MACH_PCM037=y +CONFIG_MACH_PCM037_EET=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_QONG=y CONFIG_MACH_VPR200=y -CONFIG_SOC_IMX6Q=y + +CONFIG_W1_MASTER_MXC=m +CONFIG_DMA_CACHE_RWFO=y +CONFIG_IMX_DMA=y +CONFIG_IMX_SDMA=y +CONFIG_MXS_DMA=y CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=m CONFIG_MXC_DEBUG_BOARD=y + # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_CACHE_L2X0=y CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_ERRATA_326103=y CONFIG_ARM_ERRATA_411920=y CONFIG_PL310_ERRATA_588369=y CONFIG_PL310_ERRATA_727915=y CONFIG_ARM_ERRATA_364296=y + CONFIG_PATA_IMX=m CONFIG_NET_VENDOR_FREESCALE=y CONFIG_FEC=y @@ -50,19 +67,19 @@ CONFIG_I2C_IMX=m CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_MCP23S08=m # CONFIG_GPIO_MC9S08DZ60 is not set -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_PLL=m -CONFIG_SND_IMX_SOC=m +CONFIG_PINCTRL_IMX51=y +CONFIG_PINCTRL_IMX53=y CONFIG_USB_EHCI_MXC=y +CONFIG_USB_MXS_PHY=m # CONFIG_USB_IMX21_HCD is not set CONFIG_MMC_SDHCI_ESDHC_IMX=m CONFIG_MMC_MXC=m CONFIG_RTC_MXC=y +CONFIG_RTC_DRV_MXC=m CONFIG_BACKLIGHT_PWM=m CONFIG_LEDS_PWM=m -CONFIG_MACH_PCM037_EET=y # CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set CONFIG_MXC_USE_EPIT=y CONFIG_HAVE_EPIT=y @@ -74,15 +91,19 @@ CONFIG_ARM_ERRATA_743622=y CONFIG_ARM_ERRATA_754322=y CONFIG_CAN_FLEXCAN=m CONFIG_MTD_NAND_MXC=m +CONFIG_MTD_NAND_GPMI_NAND=y CONFIG_INPUT_PWM_BEEPER=m CONFIG_SERIAL_IMX_CONSOLE=y CONFIG_IMX2_WDT=m + +CONFIG_SND_IMX_SOC=m CONFIG_SND_SOC_PHYCORE_AC97=m CONFIG_SND_SOC_EUKREA_TLV320=m +CONFIG_SND_SOC_IMX_SGTL5000=m CONFIG_PL310_ERRATA_769419=y CONFIG_LEDS_RENESAS_TPU=y -# CONFIG_ARM_LPAE is not set -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set +CONFIG_FB_IMX=m + +# CONFIG_NET_VENDOR_BROADCOM is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 7b5d758e4..c8d0ec181 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -3,32 +3,33 @@ CONFIG_ARCH_KIRKWOOD_DT=y # CONFIG_SMP is not set # CONFIG_VFP is not set +CONFIG_MACH_D2NET_V2=y CONFIG_MACH_DB88F6281_BP=y -CONFIG_MACH_RD88F6192_NAS=y -CONFIG_MACH_RD88F6281=y -CONFIG_MACH_MV88F6281GTW_GE=y -CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_DREAMPLUG_DT=y CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_DLINK_KIRKWOOD_DT=y +CONFIG_MACH_GOFLEXNET_DT=y CONFIG_MACH_GURUPLUG=y -CONFIG_MACH_DREAMPLUG_DT=y -CONFIG_MACH_DOCKSTAR=y CONFIG_MACH_ICONNECT_DT=y CONFIG_MACH_IB62X0_DT=y -CONFIG_MACH_TS219=y -CONFIG_MACH_TS41X=y +CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_LSXL_DT=y +CONFIG_MACH_MV88F6281GTW_GE=y +CONFIG_MACH_NETSPACE_V2=y +CONFIG_MACH_NETSPACE_MAX_V2=y +CONFIG_MACH_NET2BIG_V2=y +CONFIG_MACH_NET5BIG_V2=y CONFIG_MACH_OPENRD_BASE=y CONFIG_MACH_OPENRD_CLIENT=y CONFIG_MACH_OPENRD_ULTIMATE=y -CONFIG_MACH_NETSPACE_V2=y -CONFIG_MACH_INETSPACE_V2=y -CONFIG_MACH_NETSPACE_MAX_V2=y -CONFIG_MACH_D2NET_V2=y -CONFIG_MACH_NET2BIG_V2=y -CONFIG_MACH_NET5BIG_V2=y +CONFIG_MACH_RD88F6192_NAS=y +CONFIG_MACH_RD88F6281=y +CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_TS219=y +CONFIG_MACH_TS219_DT=y +CONFIG_MACH_TS41X=y CONFIG_MACH_T5325=y -# CONFIG_CPU_FEROCEON_OLD_ID is not set - CONFIG_CACHE_FEROCEON_L2=y CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y @@ -48,7 +49,11 @@ CONFIG_RTC_DRV_MV=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m +# CONFIG_CPU_FEROCEON_OLD_ID is not set # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_HIGHPTE is not set +# CONFIG_EDAC is not set + CONFIG_FB_XGI=m diff --git a/config-arm-omap b/config-arm-omap index ae328f190..6b94f4aa2 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -1,7 +1,4 @@ CONFIG_ARCH_OMAP=y -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set -# TI OMAP Common Features CONFIG_ARCH_OMAP_OTG=y # CONFIG_ARCH_OMAP1 is not set CONFIG_ARCH_OMAP2PLUS=y @@ -25,6 +22,7 @@ CONFIG_OMAP_DM_TIMER=y # CONFIG_OMAP_PM_NONE is not set CONFIG_OMAP_PM_NOOP=y CONFIG_OMAP_IOMMU=y +# CONFIG_OMAP_IOMMU_DEBUG is not set CONFIG_OMAP3_EMU=y CONFIG_HWSPINLOCK_OMAP=m CONFIG_DMA_OMAP=y @@ -43,6 +41,7 @@ CONFIG_SOC_OMAP3430=y CONFIG_SOC_TI81XX=y CONFIG_SOC_AM33XX=y CONFIG_SOC_OMAPTI816X=y +CONFIG_SOC_OMAP5=y CONFIG_OMAP_PACKAGE_CBB=y CONFIG_OMAP_PACKAGE_CBL=y CONFIG_OMAP_PACKAGE_CBS=y @@ -51,34 +50,35 @@ CONFIG_OMAP_PACKAGE_CBS=y # # OMAP Board Type # -CONFIG_MACH_OMAP_GENERIC=y -CONFIG_MACH_OMAP3_BEAGLE=y -CONFIG_MACH_DEVKIT8000=y -CONFIG_MACH_OMAP_LDP=y -CONFIG_MACH_OMAP3530_LV_SOM=y -CONFIG_MACH_OMAP3_TORPEDO=y -CONFIG_MACH_OVERO=y -CONFIG_MACH_OMAP3EVM=y -CONFIG_MACH_OMAP3517EVM=y -CONFIG_MACH_CRANEBOARD=y -CONFIG_MACH_OMAP3_PANDORA=y -CONFIG_MACH_OMAP3_TOUCHBOOK=y -CONFIG_MACH_OMAP_3430SDP=y -CONFIG_MACH_OMAP_ZOOM2=y -CONFIG_MACH_OMAP_ZOOM3=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y +CONFIG_MACH_CRANEBOARD=y +CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_IGEP0020=y CONFIG_MACH_IGEP0030=y -CONFIG_MACH_SBC3530=y +CONFIG_MACH_OMAP_GENERIC=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_OMAP_3630SDP=y CONFIG_MACH_OMAP_4430SDP=y +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP3_TOUCHBOOK=y +CONFIG_MACH_OMAP3_TORPEDO=y +CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3517EVM=y +CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP4_PANDA=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_TI8148EVM=y CONFIG_MACH_TI8168EVM=y +CONFIG_MACH_TOUCHBOOK=y # CONFIG_MACH_NOKIA_RM680 is not set # CONFIG_MACH_NOKIA_RX51 is not set -# CONFIG_MACH_TI8148EVM is not set -CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y # CONFIG_OMAP3_SDRC_AC_TIMING is not set @@ -122,7 +122,6 @@ CONFIG_ARM_GIC=y CONFIG_HAVE_ARM_SCU=y CONFIG_HAVE_ARM_TWD=y CONFIG_HOTPLUG_CPU=y -CONFIG_LOCAL_TIMERS=y CONFIG_HZ=128 # CONFIG_THUMB2_KERNEL is not set CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y @@ -144,12 +143,16 @@ CONFIG_PM_SLEEP_SMP=y CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y +CONFIG_OMAP4_THERMAL=y +CONFIG_OMAP5_THERMAL=y + # # OMAP Hardware # CONFIG_WL_TI=y CONFIG_WLCORE_SDIO=m CONFIG_TI_ST=m +# CONFIG_TI_CPSW is not set CONFIG_GPIOLIB=y CONFIG_MTD_NAND_OMAP2=y CONFIG_MTD_NAND_OMAP_PREFETCH=y @@ -157,6 +160,8 @@ CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y CONFIG_WL1251_SPI=m CONFIG_WL12XX_SPI=m CONFIG_WL12XX_SDIO_TEST=m +CONFIG_WL18XX=m +CONFIG_NFC_WILINK=m CONFIG_INPUT_TWL4030_PWRBUTTON=m CONFIG_INPUT_TWL4030_VIBRA=m CONFIG_INPUT_TWL6040_VIBRA=m @@ -170,14 +175,22 @@ CONFIG_TWL4030_CORE=y CONFIG_TWL4030_MADC=m CONFIG_TWL4030_POWER=y CONFIG_TWL4030_CODEC=y +CONFIG_TWL4030_WATCHDOG=m CONFIG_GPIO_TWL4030=m CONFIG_CHARGER_TWL4030=m CONFIG_TWL6030_PWM=m +CONFIG_TWL6040_CORE=y +CONFIG_SENSORS_TWL4030_MADC=m +CONFIG_TI_DAVINCI_EMAC=m +CONFIG_TI_DAVINCI_MDIO=m +CONFIG_TI_DAVINCI_CPDMA=m +CONFIG_LEDS_PWM=m CONFIG_MTD_ONENAND_OMAP2=y +CONFIG_HDQ_MASTER_OMAP=m CONFIG_I2C_OMAP=y CONFIG_SPI_OMAP24XX=y -CONFIG_MFD_OMAP_USB_HOST=m +CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m CONFIG_REGULATOR_TWL4030=y CONFIG_VIDEO_OMAP2_VOUT=m @@ -185,6 +198,7 @@ CONFIG_VIDEO_OMAP2_VOUT=m CONFIG_DRM=m CONFIG_DRM_OMAP=m +CONFIG_DRM_OMAP_NUM_CRTCS=2 # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set # CONFIG_FB_OMAP_LCD_VGA is not set CONFIG_OMAP2_VRAM=y @@ -195,7 +209,7 @@ CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y # CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set CONFIG_OMAP2_DSS_DPI=y # CONFIG_OMAP2_DSS_RFBI is not set -ONFIG_OMAP2_DSS_VENC=y +CONFIG_OMAP2_DSS_VENC=y CONFIG_OMAP4_DSS_HDMI=y # CONFIG_OMAP2_DSS_SDI is not set # CONFIG_OMAP2_DSS_DSI is not set @@ -205,6 +219,10 @@ CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y # CONFIG_FB_OMAP2 is not set +CONFIG_PANEL_TFP410=m +CONFIG_PANEL_PICODLP=m +CONFIG_BACKLIGHT_PANDORA=m + # # OMAP2/3 Display Device Drivers # @@ -225,6 +243,7 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y CONFIG_SND_OMAP_SOC_ZOOM2=y CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_OMAP_SOC_OMAP_HDMI=y # Because alsa is modular http://www.spinics.net/lists/linux-omap/msg67307.html # CONFIG_SND_OMAP_SOC_OMAP4_HDMI is not set CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m @@ -241,6 +260,9 @@ CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD_OMAP=y CONFIG_USB_MUSB_OMAP2PLUS=y CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_OHCI_HCD_OMAP3=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_MUSB_PIO_ONLY is not set # CONFIG_USB_MUSB_DEBUG is not set # @@ -272,5 +294,29 @@ CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 # CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set # CONFIG_TIDSPBRIDGE_BACKTRACE is not set +CONFIG_OMAP_REMOTEPROC=m +CONFIG_OMAP_BANDGAP=m +CONFIG_OMAP_IOVMM=m + CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m + +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_MTD_NAND_OMAP_BCH is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set + diff --git a/config-arm-tegra b/config-arm-tegra index 015af431d..748edc51c 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -15,7 +15,6 @@ CONFIG_MACH_SEABOARD=y CONFIG_MACH_TEGRA_DT=y CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y -CONFIG_MACH_TEGRA_DT=y CONFIG_MACH_VENTANA=y CONFIG_TEGRA_DEBUG_UARTD=y @@ -61,13 +60,11 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set # CONFIG_ARM_ERRATA_764369 is not set -CONFIG_LOCAL_TIMERS=y # CONFIG_THUMB2_KERNEL is not set # CONFIG_NEON is not set CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_MCP23S08 is not set # CONFIG_KEYBOARD_TEGRA is not set -# CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y CONFIG_RTC_DRV_TEGRA=y diff --git a/config-arm-versatile b/config-arm-versatile index f65720782..9c379361b 100644 --- a/config-arm-versatile +++ b/config-arm-versatile @@ -71,4 +71,25 @@ CONFIG_PL330_DMA=y CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y -CONFIG_I2C_VERSATILE=y +CONFIG_I2C_VERSATILE=m + +CONFIG_OC_ETM=y + +CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y +CONFIG_ARM_THUMBEE=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CACHE_L2X0=y +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_458693=y +CONFIG_ARM_ERRATA_460075=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_PL310_ERRATA_769419=y +CONFIG_NEON=y +CONFIG_PATA_PLATFORM=m +CONFIG_PATA_OF_PLATFORM=m +# CONFIG_NET_VENDOR_BROADCOM is not set + diff --git a/kernel.spec b/kernel.spec index 37dacd532..35c039d5a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2323,6 +2323,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 11 2012 Peter Robinson +- Update ARM config for missing newoption items + * Tue Oct 09 2012 Josh Boyer - Drop unhandled irq polling patch From 162ad0ffb6a79f6c17d1a472bcb7d11844661fb4 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sat, 13 Oct 2012 14:08:53 +0100 Subject: [PATCH 061/492] bump release --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 35c039d5a..fe6bef977 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2323,7 +2323,7 @@ fi # ||----w | # || || %changelog -* Thu Oct 11 2012 Peter Robinson +* Thu Oct 11 2012 Peter Robinson 3.6.1-2 - Update ARM config for missing newoption items * Tue Oct 09 2012 Josh Boyer From d4d4cfe7bf3aef4b4db88b6eb8160fa93c4400a9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Oct 2012 20:46:28 -0300 Subject: [PATCH 062/492] arm-exynos4: add regulator fix patches for SMDK310 and Origen boards Without those patches, both drivers oopses, due to a bug at the dummy regulator on Kernel 3.6. Also, some board components don't work without it. Those patches could not be 100% correct, but all components that are known to work with the upstream Kernel are available with it. Signed-off-by: Mauro Carvalho Chehab --- arm-origen-regulator-fix.patch | 12 +++++++++++ arm-smdk310-regulator-fix.patch | 36 +++++++++++++++++++++++++++++++++ kernel.spec | 7 +++++++ 3 files changed, 55 insertions(+) create mode 100644 arm-origen-regulator-fix.patch create mode 100644 arm-smdk310-regulator-fix.patch diff --git a/arm-origen-regulator-fix.patch b/arm-origen-regulator-fix.patch new file mode 100644 index 000000000..c91bfb84c --- /dev/null +++ b/arm-origen-regulator-fix.patch @@ -0,0 +1,12 @@ +diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c +index 4e574c2..5028fee 100644 +--- a/arch/arm/mach-exynos/mach-origen.c ++++ b/arch/arm/mach-exynos/mach-origen.c +@@ -121,6 +121,7 @@ static struct regulator_consumer_supply __initdata ldo14_consumer[] = { + }; + static struct regulator_consumer_supply __initdata ldo17_consumer[] = { + REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */ ++ REGULATOR_SUPPLY("vmmc", NULL), + }; + static struct regulator_consumer_supply __initdata buck1_consumer[] = { + REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */ diff --git a/arm-smdk310-regulator-fix.patch b/arm-smdk310-regulator-fix.patch new file mode 100644 index 000000000..0e0be1e4d --- /dev/null +++ b/arm-smdk310-regulator-fix.patch @@ -0,0 +1,36 @@ +--- linus.orig/arch/arm/mach-exynos/mach-smdkv310.c ++++ linus/arch/arm/mach-exynos/mach-smdkv310.c +@@ -14,6 +14,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -380,6 +382,14 @@ static void __init smdkv310_reserve(void + s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20); + } + ++static struct regulator_consumer_supply vddmmc_consumers[] __devinitdata = { ++ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"), ++ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"), ++ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), ++ REGULATOR_SUPPLY("vdd33a", "smsc911x"), ++ REGULATOR_SUPPLY("vddvario", "smsc911x"), ++}; ++ + static void __init smdkv310_machine_init(void) + { + s3c_i2c1_set_platdata(NULL); +@@ -387,6 +397,9 @@ static void __init smdkv310_machine_init + + smdkv310_smsc911x_init(); + ++ regulator_register_always_on(0, "fixed-3.3V", vddmmc_consumers, ++ ARRAY_SIZE(vddmmc_consumers), 3300000); ++ + s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); diff --git a/kernel.spec b/kernel.spec index fe6bef977..7e526d6e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -741,6 +741,10 @@ Patch21006: arm-tegra-sdhci-module-fix.patch # ARM highbank patches Patch21010: arm-highbank-sata-fix.patch +# ARM exynos4 +Patch21020: arm-smdk310-regulator-fix.patch +Patch21021: arm-origen-regulator-fix.patch + Patch21094: power-x86-destdir.patch #rhbz 754518 @@ -1341,6 +1345,9 @@ ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch +ApplyPatch arm-smdk310-regulator-fix.patch +ApplyPatch arm-origen-regulator-fix.patch + # # bugfixes to drivers and filesystems # From 0291edf1a161313392ab61a90b2ac774f5126f1e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Oct 2012 20:46:28 -0300 Subject: [PATCH 063/492] arm-exynos4: add regulator fix patches for SMDK310 and Origen boards Without those patches, both drivers oopses, due to a bug at the dummy regulator on Kernel 3.6. Also, some board components don't work without it. Those patches could not be 100% correct, but all components that are known to work with the upstream Kernel are available with it. Signed-off-by: Mauro Carvalho Chehab --- kernel.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel.spec b/kernel.spec index 7e526d6e7..b391426c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -745,6 +745,10 @@ Patch21010: arm-highbank-sata-fix.patch Patch21020: arm-smdk310-regulator-fix.patch Patch21021: arm-origen-regulator-fix.patch +# ARM exynos4 +Patch21020: arm-smdk310-regulator-fix.patch +Patch21021: arm-origen-regulator-fix.patch + Patch21094: power-x86-destdir.patch #rhbz 754518 @@ -1348,6 +1352,9 @@ ApplyPatch arm-tegra-sdhci-module-fix.patch ApplyPatch arm-smdk310-regulator-fix.patch ApplyPatch arm-origen-regulator-fix.patch +ApplyPatch arm-smdk310-regulator-fix.patch +ApplyPatch arm-origen-regulator-fix.patch + # # bugfixes to drivers and filesystems # From fb857079a60ef4ab06eaccfd92141ba994dc22ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 Oct 2012 08:41:30 -0300 Subject: [PATCH 064/492] omap: enable v4l2 drivers for omap2+ Signed-off-by: Mauro Carvalho Chehab --- config-arm-omap | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config-arm-omap b/config-arm-omap index 6b94f4aa2..8cda8dc2f 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -193,8 +193,16 @@ CONFIG_SPI_OMAP24XX=y CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m CONFIG_REGULATOR_TWL4030=y +# Enable V4L2 drivers for OMAP2+ +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_VPFE_CAPTURE=m CONFIG_VIDEO_OMAP2_VOUT=m # CONFIG_VIDEO_OMAP3 is not set +# Also enable vivi driver - useful for testing a full kernelspace V4L2 driver +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIVI=m CONFIG_DRM=m CONFIG_DRM_OMAP=m From bf61942c621833c0ad24485bb91340939c177185 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 15 Oct 2012 08:25:35 -0500 Subject: [PATCH 065/492] Linux 3.6.2 --- kernel.spec | 13 ++- powerpc-fix-VMX-fix-for-memcpy-case.patch | 97 ----------------------- secure-boot-20120924.patch | 34 -------- sources | 2 +- 4 files changed, 6 insertions(+), 140 deletions(-) delete mode 100644 powerpc-fix-VMX-fix-for-memcpy-case.patch diff --git a/kernel.spec b/kernel.spec index fe6bef977..c6444b63f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -757,9 +757,6 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 862420 -Patch22068: powerpc-fix-VMX-fix-for-memcpy-case.patch - # END OF PATCH DEFINITIONS %endif @@ -1468,9 +1465,6 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 862420 -ApplyPatch powerpc-fix-VMX-fix-for-memcpy-case.patch - # END OF PATCH APPLICATIONS %endif @@ -2323,6 +2317,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 15 2012 Justin M. Forbes 3.6.2-1 +- Linux 3.6.2 + * Thu Oct 11 2012 Peter Robinson 3.6.1-2 - Update ARM config for missing newoption items diff --git a/powerpc-fix-VMX-fix-for-memcpy-case.patch b/powerpc-fix-VMX-fix-for-memcpy-case.patch deleted file mode 100644 index 78a0a70e6..000000000 --- a/powerpc-fix-VMX-fix-for-memcpy-case.patch +++ /dev/null @@ -1,97 +0,0 @@ -From patchwork Tue Oct 2 00:59:13 2012 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: powerpc: fix VMX fix for memcpy case -Date: Mon, 01 Oct 2012 14:59:13 -0000 -From: Nishanth Aravamudan -X-Patchwork-Id: 188371 -Message-Id: <20121002005912.GA27768@linux.vnet.ibm.com> -To: Anton Blanchard -Cc: paulus@samba.org, linuxppc-dev@lists.ozlabs.org - -[urgh, sorry Anton, Ben & Paul, inadvertently hit send before adding -linuxppc-dev to the cc!] - -Hi Anton, - -In 2fae7cdb60240e2e2d9b378afbf6d9fcce8a3890 ("powerpc: Fix VMX in -interrupt check in POWER7 copy loops"), I think you inadvertently -introduced a regression for memcpy on POWER7 machines. copyuer and -memcpy diverge slightly in their use of cr1 (copyuser doesn't use it, -but memcpy does) and you end up clobbering that register with your fix. -That results in (taken from an FC18 kernel): - -[ 18.824604] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052f40 -[ 18.824618] Oops: Unrecoverable VMX/Altivec Unavailable Exception, sig: 6 [#1] -[ 18.824623] SMP NR_CPUS=1024 NUMA pSeries -[ 18.824633] Modules linked in: tg3(+) be2net(+) cxgb4(+) ipr(+) sunrpc xts lrw gf128mul dm_crypt dm_round_robin dm_multipath linear raid10 raid456 async_raid6_recov async_memcpy async_pq raid6_pq async_xor xor async_tx raid1 raid0 scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua squashfs cramfs -[ 18.824705] NIP: c000000000052f40 LR: c00000000020b874 CTR: 0000000000000512 -[ 18.824709] REGS: c000001f1fef7790 TRAP: 0f20 Not tainted (3.6.0-0.rc6.git0.2.fc18.ppc64) -[ 18.824713] MSR: 8000000000009032 CR: 4802802e XER: 20000010 -[ 18.824726] SOFTE: 0 -[ 18.824728] CFAR: 0000000000000f20 -[ 18.824731] TASK = c000000fa7128400[0] 'swapper/24' THREAD: c000000fa7480000 CPU: 24 -GPR00: 00000000ffffffc0 c000001f1fef7a10 c00000000164edc0 c000000f9b9a8120 -GPR04: c000000f9b9a8124 0000000000001438 0000000000000060 03ffffff064657ee -GPR08: 0000000080000000 0000000000000010 0000000000000020 0000000000000030 -GPR12: 0000000028028022 c00000000ff25400 0000000000000001 0000000000000000 -GPR16: 0000000000000000 7fffffffffffffff c0000000016b2180 c00000000156a500 -GPR20: c000000f968c7a90 c0000000131c31d8 c000001f1fef4000 c000000001561d00 -GPR24: 000000000000000a 0000000000000000 0000000000000001 0000000000000012 -GPR28: c000000fa5c04f80 00000000000008bc c0000000015c0a28 000000000000022e -[ 18.824792] NIP [c000000000052f40] .memcpy_power7+0x5a0/0x7c4 -[ 18.824797] LR [c00000000020b874] .pcpu_free_area+0x174/0x2d0 -[ 18.824800] Call Trace: -[ 18.824803] [c000001f1fef7a10] [c000000000052c14] .memcpy_power7+0x274/0x7c4 (unreliable) -[ 18.824809] [c000001f1fef7b10] [c00000000020b874] .pcpu_free_area+0x174/0x2d0 -[ 18.824813] [c000001f1fef7bb0] [c00000000020ba88] .free_percpu+0xb8/0x1b0 -[ 18.824819] [c000001f1fef7c50] [c00000000043d144] .throtl_pd_exit+0x94/0xd0 -[ 18.824824] [c000001f1fef7cf0] [c00000000043acf8] .blkg_free+0x88/0xe0 -[ 18.824829] [c000001f1fef7d90] [c00000000018c048] .rcu_process_callbacks+0x2e8/0x8a0 -[ 18.824835] [c000001f1fef7e90] [c0000000000a8ce8] .__do_softirq+0x158/0x4d0 -[ 18.824840] [c000001f1fef7f90] [c000000000025ecc] .call_do_softirq+0x14/0x24 -[ 18.824845] [c000000fa7483650] [c000000000010e80] .do_softirq+0x160/0x1a0 -[ 18.824850] [c000000fa74836f0] [c0000000000a94a4] .irq_exit+0xf4/0x120 -[ 18.824854] [c000000fa7483780] [c000000000020c44] .timer_interrupt+0x154/0x4d0 -[ 18.824859] [c000000fa7483830] [c000000000003be0] decrementer_common+0x160/0x180 -[ 18.824866] --- Exception: 901 at .plpar_hcall_norets+0x84/0xd4 -[ 18.824866] LR = .check_and_cede_processor+0x48/0x80 -[ 18.824871] [c000000fa7483b20] [c00000000007f018] .check_and_cede_processor+0x18/0x80 (unreliable) -[ 18.824877] [c000000fa7483b90] [c00000000007f104] .dedicated_cede_loop+0x84/0x150 -[ 18.824883] [c000000fa7483c50] [c0000000006bc030] .cpuidle_enter+0x30/0x50 -[ 18.824887] [c000000fa7483cc0] [c0000000006bc9f4] .cpuidle_idle_call+0x104/0x720 -[ 18.824892] [c000000fa7483d80] [c000000000070af8] .pSeries_idle+0x18/0x40 -[ 18.824897] [c000000fa7483df0] [c000000000019084] .cpu_idle+0x1a4/0x380 -[ 18.824902] [c000000fa7483ec0] [c0000000008a4c18] .start_secondary+0x520/0x528 -[ 18.824907] [c000000fa7483f90] [c0000000000093f0] .start_secondary_prolog+0x10/0x14 -[ 18.824911] Instruction dump: -[ 18.824914] 38840008 90030000 90e30004 38630008 7ca62850 7cc300d0 78c7e102 7cf01120 -[ 18.824923] 78c60660 39200010 39400020 39600030 <7e00200c> 7c0020ce 38840010 409f001c -[ 18.824935] ---[ end trace 0bb95124affaaa45 ]--- -[ 18.825046] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052d08 - -I believe the right fix is to make memcpy match usercopy and not use -cr1. - -Signed-off-by: Nishanth Aravamudan - ---- -I've not tested this fix yet, but I think it's logically correct. -Probably needs to go to 3.6-stable as well. - -diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S -index 7ba6c96..0663630 100644 ---- a/arch/powerpc/lib/memcpy_power7.S -+++ b/arch/powerpc/lib/memcpy_power7.S -@@ -239,8 +239,8 @@ _GLOBAL(memcpy_power7) - ori r9,r9,1 /* stream=1 */ - - srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */ -- cmpldi cr1,r7,0x3FF -- ble cr1,1f -+ cmpldi r7,0x3FF -+ ble 1f - li r7,0x3FF - 1: lis r0,0x0E00 /* depth=7 */ - sldi r7,r7,7 diff --git a/secure-boot-20120924.patch b/secure-boot-20120924.patch index a9c63de14..54825efe6 100644 --- a/secure-boot-20120924.patch +++ b/secure-boot-20120924.patch @@ -650,40 +650,6 @@ index 93978d5..e3e5f8c 100644 1.7.11.4 -From 294d339c63b0f67a362efaa62713f26d9f496da8 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 26 Jul 2012 18:00:00 -0400 -Subject: [PATCH 13/14] efi: Build EFI stub with EFI-appropriate options - -We can't assume the presence of the red zone while we're still in a boot -services environment, so we should build with -fno-red-zone to avoid -problems. Change the size of wchar at the same time to make string handling -simpler. - -Signed-off-by: Matthew Garrett ---- - arch/x86/boot/compressed/Makefile | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile -index e398bb5..8a84501 100644 ---- a/arch/x86/boot/compressed/Makefile -+++ b/arch/x86/boot/compressed/Makefile -@@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ - $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ - $(obj)/piggy.o - -+$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone -+$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone -+ - ifeq ($(CONFIG_EFI_STUB), y) - VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o - endif --- -1.7.11.4 - - - From 1cc529e97756554953187fe48b9b8cf0e24b9bc7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 diff --git a/sources b/sources index 152630c87..47fce40c3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -775f1389a934512341726f9b4aeaf661 patch-3.6.1.xz +ad1020c82a71ee1ef2416a0d12e724df patch-3.6.2.xz From d098f2b712ff2bdf0369fc741367a2f7d6dc2529 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 16 Oct 2012 09:22:02 -0500 Subject: [PATCH 066/492] Enable CONFIG_TCM_HOST (rhbz 866981) --- config-generic | 1 + kernel.spec | 3 +++ 2 files changed, 4 insertions(+) diff --git a/config-generic b/config-generic index 8f795f5d5..c7a03cf20 100644 --- a/config-generic +++ b/config-generic @@ -280,6 +280,7 @@ CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m CONFIG_VIRTIO_CONSOLE=y CONFIG_VHOST_NET=m +CONFIG_TCM_VHOST=m # # SCSI device support diff --git a/kernel.spec b/kernel.spec index c6444b63f..71644238f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2317,6 +2317,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 16 2012 Justin M. Forbes +- Enable CONFIG_TCM_VHOST (rhbz 866981) + * Mon Oct 15 2012 Justin M. Forbes 3.6.2-1 - Linux 3.6.2 From 83707cda0a791b4e0c1b80897f8d1e9c47dc5080 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Oct 2012 22:52:03 -0300 Subject: [PATCH 067/492] Fix i82975x_edac (BZ#848149) This driver was soooo broken that I needed to rewrote the entire logic for memory identification and for memory error report. While here, enable EDAC_DEBUG, on debug kernels. Signed-off-by: Mauro Carvalho Chehab --- config-arm-generic | 1 - config-debug | 2 + config-nodebug | 2 + config-powerpc-generic | 1 - config-x86-generic | 1 - i82975x-edac-fix.patch | 855 +++++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 +- 7 files changed, 867 insertions(+), 4 deletions(-) create mode 100644 i82975x-edac-fix.patch diff --git a/config-arm-generic b/config-arm-generic index 0a253eb0c..24713b969 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -258,7 +258,6 @@ CONFIG_RCU_FANOUT_LEAF=16 CONFIG_EDAC=y CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_LEGACY_SYSFS=y -# CONFIG_EDAC_DEBUG is not set CONFIG_RTC_DRV_88PM80X=m CONFIG_RTC_DRV_PL030=m diff --git a/config-debug b/config-debug index db0aa6d4e..e1b3f9db2 100644 --- a/config-debug +++ b/config-debug @@ -112,3 +112,5 @@ CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y CONFIG_MAC80211_MESSAGE_TRACING=y + +CONFIG_EDAC_DEBUG=y diff --git a/config-nodebug b/config-nodebug index 5b4187680..c471b853e 100644 --- a/config-nodebug +++ b/config-nodebug @@ -112,3 +112,5 @@ CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y # CONFIG_MAC80211_MESSAGE_TRACING is not set + +# CONFIG_EDAC_DEBUG is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 58c3393a2..a263acc80 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -181,7 +181,6 @@ CONFIG_PMAC_APM_EMU=m CONFIG_HW_RANDOM_PASEMI=m CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_PASEMI=m CONFIG_EDAC_AMD8131=m diff --git a/config-x86-generic b/config-x86-generic index de9582a01..09d63d401 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -151,7 +151,6 @@ CONFIG_DELL_RBU=m CONFIG_DCDBAS=m CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_AMD76X=m CONFIG_EDAC_AMD8111=m diff --git a/i82975x-edac-fix.patch b/i82975x-edac-fix.patch new file mode 100644 index 000000000..f44ac7791 --- /dev/null +++ b/i82975x-edac-fix.patch @@ -0,0 +1,855 @@ +commit 9370a8d717720f6b17221490fea8d798396d9f2f +Author: Mauro Carvalho Chehab +Date: Mon Oct 15 21:49:35 2012 -0300 + + i82975x_edac: Use the edac standard debug macro + + Instead of declaring its own debug macro, that requires + to uncomment part of the code, use the edac standard macro + to add the debug code, and the edac debug level to print it, + just like any other EDAC driver. + + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index a980204..f998d2c 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -435,11 +435,9 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, + } + } + +-/* #define i82975x_DEBUG_IOMEM */ +- +-#ifdef i82975x_DEBUG_IOMEM +-static void i82975x_print_dram_timings(void __iomem *mch_window) ++static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) + { ++#ifdef CONFIG_EDAC_DEBUG + /* + * The register meanings are from Intel specs; + * (shows 13-5-5-5 for 800-DDR2) +@@ -448,26 +446,63 @@ static void i82975x_print_dram_timings(void __iomem *mch_window) + */ + static const int caslats[4] = { 5, 4, 3, 6 }; + u32 dtreg[2]; ++ u8 c0drb[4]; ++ u8 c1drb[4]; ++ ++ if (!edac_debug_level) ++ return; ++ ++ i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", ++ mchbar, mch_window); ++ ++ c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); ++ c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); ++ c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); ++ c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); ++ c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); ++ c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); ++ c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); ++ c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); ++ i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); ++ i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); ++ i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); ++ i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); ++ i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); ++ i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); ++ i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); ++ i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); ++ ++ i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], ++ ((drc[0] >> 21) & 3) == 1 ? ++ "ECC enabled" : "ECC disabled"); ++ i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], ++ ((drc[1] >> 21) & 3) == 1 ? ++ "ECC enabled" : "ECC disabled"); ++ ++ i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", ++ readw(mch_window + I82975X_C0BNKARC)); ++ i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", ++ readw(mch_window + I82975X_C1BNKARC)); + + dtreg[0] = readl(mch_window + 0x114); + dtreg[1] = readl(mch_window + 0x194); +- i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n" ++ i82975x_printk(KERN_INFO, ++ "DRAM Timings : Ch0 Ch1\n" + " RAS Active Min = %d %d\n" + " CAS latency = %d %d\n" + " RAS to CAS = %d %d\n" + " RAS precharge = %d %d\n", + (dtreg[0] >> 19 ) & 0x0f, +- (dtreg[1] >> 19) & 0x0f, ++ (dtreg[1] >> 19) & 0x0f, + caslats[(dtreg[0] >> 8) & 0x03], +- caslats[(dtreg[1] >> 8) & 0x03], ++ caslats[(dtreg[1] >> 8) & 0x03], + ((dtreg[0] >> 4) & 0x07) + 2, +- ((dtreg[1] >> 4) & 0x07) + 2, ++ ((dtreg[1] >> 4) & 0x07) + 2, + (dtreg[0] & 0x07) + 2, +- (dtreg[1] & 0x07) + 2 ++ (dtreg[1] & 0x07) + 2 + ); +- +-} + #endif ++} + + static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + { +@@ -480,10 +515,6 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + u32 drc[2]; + struct i82975x_error_info discard; + int chans; +-#ifdef i82975x_DEBUG_IOMEM +- u8 c0drb[4]; +- u8 c1drb[4]; +-#endif + + edac_dbg(0, "\n"); + +@@ -495,45 +526,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ + mch_window = ioremap_nocache(mchbar, 0x1000); + +-#ifdef i82975x_DEBUG_IOMEM +- i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", +- mchbar, mch_window); +- +- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); +- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); +- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); +- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); +- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); +- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); +- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); +- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); +- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); +- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); +-#endif +- + drc[0] = readl(mch_window + I82975X_DRC_CH0M0); + drc[1] = readl(mch_window + I82975X_DRC_CH1M0); +-#ifdef i82975x_DEBUG_IOMEM +- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], +- ((drc[0] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); +- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], +- ((drc[1] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); + +- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", +- readw(mch_window + I82975X_C0BNKARC)); +- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", +- readw(mch_window + I82975X_C1BNKARC)); +- i82975x_print_dram_timings(mch_window); +- goto fail1; +-#endif ++ i82975x_print_dram_config(mch_window, mchbar, drc); ++ + if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { + i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); + goto fail1; + +commit 8992ed2f4295eab137e1713fa16be5546a759373 +Author: Mauro Carvalho Chehab +Date: Mon Oct 15 21:48:48 2012 -0300 + + i82975x_edac: Fix dimm label initialization + + The driver has only 4 hardcoded labels, but allows much more memory. + Fix it by removing the hardcoded logic, using snprintf() instead. + + [ 19.833972] general protection fault: 0000 [#1] SMP + [ 19.837733] Modules linked in: i82975x_edac(+) edac_core firewire_ohci firewire_core crc_itu_t nouveau mxm_wmi wmi video i2c_algo_bit drm_kms_helper ttm drm i2c_core + [ 19.837733] CPU 0 + [ 19.837733] Pid: 390, comm: udevd Not tainted 3.6.1-1.fc17.x86_64.debug #1 Dell Inc. Precision WorkStation 390 /0MY510 + [ 19.837733] RIP: 0010:[] [] strncpy+0x18/0x30 + [ 19.837733] RSP: 0018:ffff880078535b68 EFLAGS: 00010202 + [ 19.837733] RAX: ffff880069fa9708 RBX: ffff880078588000 RCX: ffff880069fa9708 + [ 19.837733] RDX: 000000000000001f RSI: 5f706f5f63616465 RDI: ffff880069fa9708 + [ 19.837733] RBP: ffff880078535b68 R08: ffff880069fa9727 R09: 000000000000fffe + [ 19.837733] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000003 + [ 19.837733] R13: 0000000000000000 R14: ffff880069fa9290 R15: ffff880079624a80 + [ 19.837733] FS: 00007f3de01ee840(0000) GS:ffff88007c400000(0000) knlGS:0000000000000000 + [ 19.837733] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [ 19.837733] CR2: 00007f3de00b9000 CR3: 0000000078dbc000 CR4: 00000000000007f0 + [ 19.837733] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + [ 19.837733] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 + [ 19.837733] Process udevd (pid: 390, threadinfo ffff880078534000, task ffff880079642450) + [ 19.837733] Stack: + [ 19.837733] ffff880078535c18 ffffffffa017c6b8 00040000816d627f ffff880079624a88 + [ 19.837733] ffffc90004cd6000 ffff880079624520 ffff88007ac21148 0000000000000000 + [ 19.837733] 0000000000000000 0004000000000000 feda000078535bc8 ffffffff810d696d + [ 19.837733] Call Trace: + [ 19.837733] [] i82975x_init_one+0x2e6/0x3e6 [i82975x_edac] + ... + + Fix bug reported at: + https://bugzilla.redhat.com/show_bug.cgi?id=848149 + And, very likely: + https://bbs.archlinux.org/viewtopic.php?id=148033 + https://bugzilla.kernel.org/show_bug.cgi?id=47171 + + Cc: Alan Cox + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index 069e26c..a980204 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) + static void i82975x_init_csrows(struct mem_ctl_info *mci, + struct pci_dev *pdev, void __iomem *mch_window) + { +- static const char *labels[4] = { +- "DIMM A1", "DIMM A2", +- "DIMM B1", "DIMM B2" +- }; + struct csrow_info *csrow; + unsigned long last_cumul_size; + u8 value; +@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, + dimm = mci->csrows[index]->channels[chan]->dimm; + + dimm->nr_pages = nr_pages / csrow->nr_channels; +- strncpy(csrow->channels[chan]->dimm->label, +- labels[(index >> 1) + (chan * 2)], +- EDAC_MC_LABEL_LEN); ++ ++ snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", ++ (chan == 0) ? 'A' : 'B', ++ index); + dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ + dimm->dtype = i82975x_dram_type(mch_window, index); + dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ +commit 6e7636c972951ba0c6c640758b1dcc7667cb2415 +Author: Mauro Carvalho Chehab +Date: Tue Oct 16 15:30:23 2012 -0300 + + i82975x_edac: rewrite the entire fill/report logic + + There are so many bugs at the fill/error report logic that + the code ended by being re-written. + + Issues solved: + + - DIMM labels were "randomly" filled: they won't + match the memory layout, due to a series of bugs on it; + + - The memory controller supports 3 different modes: + single, dual interleaved and dual async. The logic there were + written considering the dual interleaved one (yet, some + single mode support was there); + + - The boundary limit to decide on each channel the error happens, + at dual interleaved mode, is given by bit 6 of the error address, + and not bit 1. The practical effect is that Corrected errors + will have a 50% of chance of pointing to the right DIMM. Only + the DIMM pair logic were OK; + + - The asymetric mode weren't properly supported. The driver would + handle an asymetric mode as 'single mode', with doesn't actually + match it, creating some weird real/virtual DIMM mappings. + + - Some other random bugs got fixed. + + Tested on a Dell Precision N390, on dual interleaved mode. + + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index f998d2c..082e91e 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -6,7 +6,17 @@ + * GNU General Public License. + * + * Written by Arvind R. +- * Copied from i82875p_edac.c source: ++ * Copied from i82875p_edac.c source, ++ * ++ * (c) 2012 Mauro Carvalho Chehab ++ * Driver re-written in order to fix lots of issues on it: ++ * - Fix Single Mode; ++ * - Add support for Asymetrical mode ++ * - Fix several issues with Interleaved mode ++ * - Fix memory label logic ++ * ++ * Intel datasheet: Intel(R) 975X Express Chipset Datasheet ++ * http://www.intel.com/assets/pdf/datasheet/310158.pdf + */ + + #include +@@ -29,8 +39,8 @@ + #define PCI_DEVICE_ID_INTEL_82975_0 0x277c + #endif /* PCI_DEVICE_ID_INTEL_82975_0 */ + +-#define I82975X_NR_DIMMS 8 +-#define I82975X_NR_CSROWS(nr_chans) (I82975X_NR_DIMMS / (nr_chans)) ++#define DIMMS_PER_CHANNEL 4 ++#define NUM_CHANNELS 2 + + /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */ + #define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b) +@@ -112,7 +122,7 @@ NOTE: Only ONE of the three must be enabled + /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */ + /* Intel 82975x memory mapped register space */ + +-#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */ ++#define I82975X_DRB_SHIFT 25 /* fixed 2^25 = 32 MiB grain */ + + #define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8) + * +@@ -152,6 +162,10 @@ NOTE: Only ONE of the three must be enabled + #define I82975X_DRA_CH1R01 0x188 + #define I82975X_DRA_CH1R23 0x189 + ++/* Channels 0/1 DRAM Timing Register 1 */ ++#define I82975X_C0DRT1 0x114 ++#define I82975X_C1DRT1 0x194 ++ + + #define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b) + * +@@ -206,8 +220,16 @@ enum i82975x_chips { + I82975X = 0, + }; + ++struct mem_range { ++ u32 start, end; ++}; ++ + struct i82975x_pvt { +- void __iomem *mch_window; ++ void __iomem *mch_window; ++ int num_channels; ++ bool is_symetric; ++ u8 drb[DIMMS_PER_CHANNEL][NUM_CHANNELS]; ++ struct mem_range page[DIMMS_PER_CHANNEL][NUM_CHANNELS]; + }; + + struct i82975x_dev_info { +@@ -278,8 +300,10 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, + static int i82975x_process_error_info(struct mem_ctl_info *mci, + struct i82975x_error_info *info, int handle_errors) + { +- int row, chan; +- unsigned long offst, page; ++ struct i82975x_pvt *pvt = mci->pvt_info; ++ struct mem_range *range; ++ unsigned int row, chan, grain; ++ unsigned long offst, page; + + if (!(info->errsts2 & 0x0003)) + return 0; +@@ -293,36 +317,70 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, + info->errsts = info->errsts2; + } + ++ /* Calculate page and offset of the error */ ++ + page = (unsigned long) info->eap; + page >>= 1; ++ + if (info->xeap & 1) + page |= 0x80000000; + page >>= (PAGE_SHIFT - 1); +- row = edac_mc_find_csrow_by_page(mci, page); +- +- if (row == -1) { +- i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n" +- "\tXEAP=%u\n" +- "\t EAP=0x%08x\n" +- "\tPAGE=0x%08x\n", +- (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); +- return 0; ++ ++ if (pvt->is_symetric) ++ grain = 1 << 7; ++ else ++ grain = 1 << 6; ++ ++ offst = info->eap & ((1 << PAGE_SHIFT) - (1 << grain)); ++ ++ /* ++ * Search for the DIMM chip that match the error page. ++ * ++ * On Symmetric mode, this will always return channel = 0, as ++ * both channel A and B ranges are identical. ++ * A latter logic will determinte the channel on symetric mode ++ * ++ * On asymetric mode or single mode, there will be just one match, ++ * that will point to the csrow with the error. ++ */ ++ for (chan = 0; chan < pvt->num_channels; chan++) { ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ range = &pvt->page[row][chan]; ++ ++ if (page >= range->start && page <= range->end) ++ goto found; ++ } + } +- chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; +- offst = info->eap +- & ((1 << PAGE_SHIFT) - +- (1 << mci->csrows[row]->channels[chan]->dimm->grain)); ++ chan = -1; ++ row = -1; + +- if (info->errsts & 0x0002) ++found: ++ if (info->errsts & 0x0002) { ++ /* ++ * On uncorrected error, ECC doesn't allow do determine the ++ * channel where the error has occurred. ++ */ + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + page, offst, 0, + row, -1, -1, + "i82975x UE", ""); +- else +- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, +- page, offst, info->derrsyn, +- row, chan ? chan : 0, -1, +- "i82975x CE", ""); ++ return 1; ++ } ++ ++ if (pvt->is_symetric && row >= 0) { ++ /* ++ * On Symetric mode, the memory switch happens after each ++ * cache line (64 byte boundary). Channel 0 goes first. ++ */ ++ if (info->eap & (1 << 6)) ++ chan = 1; ++ else ++ chan = 0; ++ } ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, ++ page, offst, info->derrsyn, ++ row, chan, -1, ++ "i82975x CE", ""); + + return 1; + } +@@ -331,111 +389,143 @@ static void i82975x_check(struct mem_ctl_info *mci) + { + struct i82975x_error_info info; + +- edac_dbg(1, "MC%d\n", mci->mc_idx); ++ edac_dbg(4, "MC%d\n", mci->mc_idx); + i82975x_get_error_info(mci, &info); + i82975x_process_error_info(mci, &info, 1); + } + +-/* Return 1 if dual channel mode is active. Else return 0. */ +-static int dual_channel_active(void __iomem *mch_window) ++/** ++ * detect_memory_style - Detect on what mode the memory controller is programmed ++ * ++ * @pvt: pointer to the private structure ++ * ++ * This function detects how many channels are in use, and if the memory ++ * controller is in symetric (interleaved) or asymetric mode. There's no ++ * need to distinguish between asymetric and single mode, as the routines ++ * that fill the csrows data and handle error are written in order to handle ++ * both at the same way. ++ */ ++static void detect_memory_style(struct i82975x_pvt *pvt) + { +- /* +- * We treat interleaved-symmetric configuration as dual-channel - EAP's +- * bit-0 giving the channel of the error location. +- * +- * All other configurations are treated as single channel - the EAP's +- * bit-0 will resolve ok in symmetric area of mixed +- * (symmetric/asymmetric) configurations +- */ +- u8 drb[4][2]; + int row; +- int dualch; ++ bool has_chan_a = false; ++ bool has_chan_b = false; ++ ++ pvt->is_symetric = true; ++ pvt->num_channels = 0; ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ pvt->drb[row][0] = readb(pvt->mch_window + I82975X_DRB + row); ++ pvt->drb[row][1] = readb(pvt->mch_window + I82975X_DRB + row + 0x80); ++ ++ /* On symetric mode, both channels have the same boundaries */ ++ if (pvt->drb[row][0] != pvt->drb[row][1]) ++ pvt->is_symetric = false; + +- for (dualch = 1, row = 0; dualch && (row < 4); row++) { +- drb[row][0] = readb(mch_window + I82975X_DRB + row); +- drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80); +- dualch = dualch && (drb[row][0] == drb[row][1]); ++ if (pvt->drb[row][0]) ++ has_chan_a = true; ++ if (pvt->drb[row][1]) ++ has_chan_b = true; + } +- return dualch; +-} + +-static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) +-{ +- /* +- * ECC is possible on i92975x ONLY with DEV_X8 +- */ +- return DEV_X8; ++ if (has_chan_a) ++ pvt->num_channels++; ++ ++ if (has_chan_b) ++ pvt->num_channels++; + } + + static void i82975x_init_csrows(struct mem_ctl_info *mci, +- struct pci_dev *pdev, void __iomem *mch_window) ++ struct i82975x_pvt *pvt, ++ struct pci_dev *pdev) + { +- struct csrow_info *csrow; +- unsigned long last_cumul_size; +- u8 value; +- u32 cumul_size, nr_pages; +- int index, chan; +- struct dimm_info *dimm; +- enum dev_type dtype; +- +- last_cumul_size = 0; ++ struct dimm_info *dimm; ++ struct mem_range *range; ++ u8 boundary; ++ u32 initial_page = 0, last_page; ++ int row, chan; + + /* +- * 82875 comment: +- * The dram row boundary (DRB) reg values are boundary address +- * for each DRAM row with a granularity of 32 or 64MB (single/dual +- * channel operation). DRB regs are cumulative; therefore DRB7 will +- * contain the total memory contained in all rows. +- * ++ * This chipset provides 3 address modes: ++ * Single channel - either Channel A or channel B is filled ++ * Dual channel, interleaved: Memory is organized in pairs, ++ * where channel A gets the lower address for each pair ++ * Dual channel, asymmetric: Channel A memory goes first. ++ * In order to cover all modes, we need to start describing ++ * memories considering the dual channel, asymmetric one. + */ + +- for (index = 0; index < mci->nr_csrows; index++) { +- csrow = mci->csrows[index]; +- +- value = readb(mch_window + I82975X_DRB + index + +- ((index >= 4) ? 0x80 : 0)); +- cumul_size = value; +- cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); +- /* +- * Adjust cumul_size w.r.t number of channels +- * +- */ +- if (csrow->nr_channels > 1) +- cumul_size <<= 1; +- edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); +- +- nr_pages = cumul_size - last_cumul_size; +- if (!nr_pages) +- continue; +- ++ for (chan = 0; chan < pvt->num_channels; chan++) { + /* +- * Initialise dram labels +- * index values: +- * [0-7] for single-channel; i.e. csrow->nr_channels = 1 +- * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 ++ * On symetric mode, both channels start from address 0 + */ +- dtype = i82975x_dram_type(mch_window, index); +- for (chan = 0; chan < csrow->nr_channels; chan++) { +- dimm = mci->csrows[index]->channels[chan]->dimm; +- +- dimm->nr_pages = nr_pages / csrow->nr_channels; +- +- snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", +- (chan == 0) ? 'A' : 'B', +- index); +- dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ +- dimm->dtype = i82975x_dram_type(mch_window, index); ++ if (pvt->is_symetric) ++ initial_page = 0; ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ boundary = pvt->drb[row][chan]; ++ dimm = mci->csrows[row]->channels[chan]->dimm; ++ ++ last_page = boundary << (I82975X_DRB_SHIFT - PAGE_SHIFT); ++ dimm->nr_pages = last_page - initial_page; ++ if (!dimm->nr_pages) ++ continue; ++ ++ range = &pvt->page[row][chan]; ++ range->start = initial_page; ++ range->end = range->start + dimm->nr_pages - 1; ++ ++ /* ++ * Grain is one cache-line: ++ * On dual symetric mode, it is 128 Bytes; ++ * On single mode or asymetric, it is 64 bytes. ++ */ ++ if (pvt->is_symetric) { ++ dimm->grain = 1 << 7; ++ ++ /* ++ * In dual interleaved mode, the addresses ++ * need to be multiplied by 2, as both ++ * channels are interlaced, and the boundary ++ * limit there actually match each DIMM size ++ */ ++ range->start <<= 1; ++ range->end <<= 1; ++ } else { ++ dimm->grain = 1 << 6; ++ } ++ ++ snprintf(dimm->label, ++ EDAC_MC_LABEL_LEN, "DIMM %c%d", ++ (chan == 0) ? 'A' : 'B', row); + dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ + dimm->edac_mode = EDAC_SECDED; /* only supported */ +- } + +- csrow->first_page = last_cumul_size; +- csrow->last_page = cumul_size - 1; +- last_cumul_size = cumul_size; ++ /* ++ * This chipset supports both x8 and x16 memories, ++ * but datasheet doesn't describe how to distinguish ++ * between them. ++ * ++ * Also, the "Rank" comment at initial_page 17 says that ++ * ECC is only available with x8 memories. As this ++ * driver doesn't even initialize without ECC, better ++ * to assume that everything is x8. This is not ++ * actually true, on a mixed ECC/non-ECC scenario. ++ */ ++ dimm->dtype = DEV_X8; ++ ++ edac_dbg(1, ++ "%s: from page 0x%08x to 0x%08x (size: 0x%08x pages)\n", ++ dimm->label, ++ range->start, range->end, ++ dimm->nr_pages); ++ initial_page = last_page; ++ } + } + } + +-static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) ++static void i82975x_print_dram_config(struct i82975x_pvt *pvt, ++ u32 mchbar, u32 *drc) + { + #ifdef CONFIG_EDAC_DEBUG + /* +@@ -444,63 +534,57 @@ static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 + * Asus P5W Bios reports 15-5-4-4 + * What's your religion? + */ +- static const int caslats[4] = { 5, 4, 3, 6 }; +- u32 dtreg[2]; +- u8 c0drb[4]; +- u8 c1drb[4]; ++ static const int caslats[4] = { 5, 4, 3, 6 }; ++ u32 dtreg[2]; ++ int row; + ++ /* Show memory config if debug level is 1 or upper */ + if (!edac_debug_level) + return; + + i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", +- mchbar, mch_window); +- +- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); +- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); +- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); +- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); +- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); +- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); +- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); +- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); +- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); +- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); +- +- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], ++ mchbar, pvt->mch_window); ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ if (row) ++ /* Only show if at least one bank is filled */ ++ if ((pvt->drb[row][0] == pvt->drb[row-1][0]) && ++ (pvt->drb[row][1] == pvt->drb[row-1][1])) ++ continue; ++ ++ i82975x_printk(KERN_INFO, ++ "DRAM%i Rank Boundary Address: Channel A: 0x%08x; Channel B: 0x%08x\n", ++ row, ++ pvt->drb[row][0], ++ pvt->drb[row][1]); ++ } ++ ++ i82975x_printk(KERN_INFO, "DRAM Controller mode Channel A: = 0x%08x (%s); Channel B: 0x%08x (%s)\n", ++ drc[0], + ((drc[0] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); +- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], ++ "ECC enabled" : "ECC disabled", ++ drc[1], + ((drc[1] >> 21) & 3) == 1 ? + "ECC enabled" : "ECC disabled"); + +- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", +- readw(mch_window + I82975X_C0BNKARC)); +- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", +- readw(mch_window + I82975X_C1BNKARC)); +- +- dtreg[0] = readl(mch_window + 0x114); +- dtreg[1] = readl(mch_window + 0x194); +- i82975x_printk(KERN_INFO, +- "DRAM Timings : Ch0 Ch1\n" +- " RAS Active Min = %d %d\n" +- " CAS latency = %d %d\n" +- " RAS to CAS = %d %d\n" +- " RAS precharge = %d %d\n", +- (dtreg[0] >> 19 ) & 0x0f, +- (dtreg[1] >> 19) & 0x0f, +- caslats[(dtreg[0] >> 8) & 0x03], +- caslats[(dtreg[1] >> 8) & 0x03], +- ((dtreg[0] >> 4) & 0x07) + 2, +- ((dtreg[1] >> 4) & 0x07) + 2, ++ i82975x_printk(KERN_INFO, "Bank Architecture Channel A: 0x%08x, Channel B: 0x%08x\n", ++ readw(pvt->mch_window + I82975X_C0BNKARC), ++ readw(pvt->mch_window + I82975X_C1BNKARC)); ++ ++ dtreg[0] = readl(pvt->mch_window + I82975X_C0DRT1); ++ dtreg[1] = readl(pvt->mch_window + I82975X_C1DRT1); ++ i82975x_printk(KERN_INFO, "DRAM Timings : ChA ChB\n"); ++ i82975x_printk(KERN_INFO, " RAS Active Min = %2d %2d\n", ++ (dtreg[0] >> 19 ) & 0x0f,(dtreg[1] >> 19) & 0x0f); ++ i82975x_printk(KERN_INFO, " CAS latency = %2d %2d\n", ++ caslats[(dtreg[0] >> 8) & 0x03], ++ caslats[(dtreg[1] >> 8) & 0x03]); ++ i82975x_printk(KERN_INFO, " RAS to CAS = %2d %2d\n", ++ ((dtreg[0] >> 4) & 0x07) + 2, ++ ((dtreg[1] >> 4) & 0x07) + 2); ++ i82975x_printk(KERN_INFO, " RAS precharge = %2d %2d\n", + (dtreg[0] & 0x07) + 2, +- (dtreg[1] & 0x07) + 2 +- ); ++ (dtreg[1] & 0x07) + 2); + #endif + } + +@@ -509,12 +593,10 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + int rc = -ENODEV; + struct mem_ctl_info *mci; + struct edac_mc_layer layers[2]; +- struct i82975x_pvt *pvt; +- void __iomem *mch_window; ++ struct i82975x_pvt tmp_pvt, *pvt; + u32 mchbar; + u32 drc[2]; + struct i82975x_error_info discard; +- int chans; + + edac_dbg(0, "\n"); + +@@ -524,26 +606,35 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + goto fail0; + } + mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ +- mch_window = ioremap_nocache(mchbar, 0x1000); ++ tmp_pvt.mch_window = ioremap_nocache(mchbar, 0x1000); ++ if (!tmp_pvt.mch_window) { ++ i82975x_printk(KERN_ERR, "Couldn't map MCHBAR registers.\n"); ++ rc = -ENOMEM; ++ goto fail0; ++ } + +- drc[0] = readl(mch_window + I82975X_DRC_CH0M0); +- drc[1] = readl(mch_window + I82975X_DRC_CH1M0); ++ drc[0] = readl(tmp_pvt.mch_window + I82975X_DRC_CH0M0); ++ drc[1] = readl(tmp_pvt.mch_window + I82975X_DRC_CH1M0); ++ ++ detect_memory_style(&tmp_pvt); ++ if (!tmp_pvt.num_channels) { ++ edac_dbg(3, "No memories installed? This shouldn't be running!\n"); ++ goto fail0; ++ } + +- i82975x_print_dram_config(mch_window, mchbar, drc); ++ i82975x_print_dram_config(&tmp_pvt, mchbar, drc); + + if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { + i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); + goto fail1; + } + +- chans = dual_channel_active(mch_window) + 1; +- + /* assuming only one controller, index thus is 0 */ + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; +- layers[0].size = I82975X_NR_DIMMS; ++ layers[0].size = DIMMS_PER_CHANNEL; + layers[0].is_virt_csrow = true; + layers[1].type = EDAC_MC_LAYER_CHANNEL; +- layers[1].size = I82975X_NR_CSROWS(chans); ++ layers[1].size = tmp_pvt.num_channels; + layers[1].is_virt_csrow = false; + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); + if (!mci) { +@@ -562,10 +653,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + mci->dev_name = pci_name(pdev); + mci->edac_check = i82975x_check; + mci->ctl_page_to_phys = NULL; ++ + edac_dbg(3, "init pvt\n"); + pvt = (struct i82975x_pvt *) mci->pvt_info; +- pvt->mch_window = mch_window; +- i82975x_init_csrows(mci, pdev, mch_window); ++ *pvt = tmp_pvt; ++ ++ i82975x_init_csrows(mci, pvt, pdev); + mci->scrub_mode = SCRUB_HW_SRC; + i82975x_get_error_info(mci, &discard); /* clear counters */ + +@@ -583,7 +676,7 @@ fail2: + edac_mc_free(mci); + + fail1: +- iounmap(mch_window); ++ iounmap(tmp_pvt.mch_window); + fail0: + return rc; + } diff --git a/kernel.spec b/kernel.spec index 71644238f..32b52dd2d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,6 +727,8 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch +Patch19001: i82975x-edac-fix.patch + # ARM Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch @@ -1449,6 +1451,8 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch lis3-improve-handling-of-null-rate.patch +ApplyPatch i82975x-edac-fix.patch + ApplyPatch power-x86-destdir.patch #rhbz 754518 @@ -2317,6 +2321,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 16 2012 Mauro Carvalho Chehab - 3.6.2-2 +- Fix i82975x_edac OOPS + * Tue Oct 16 2012 Justin M. Forbes - Enable CONFIG_TCM_VHOST (rhbz 866981) From aa337a7243009b76953dd07cca6d2ebd57524b96 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:26:39 -0400 Subject: [PATCH 068/492] Apply patch to fix iwlwifi crash (rhbz 770484) --- iwlwifi-fix-6000-ch-switch.patch | 94 ++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-fix-6000-ch-switch.patch diff --git a/iwlwifi-fix-6000-ch-switch.patch b/iwlwifi-fix-6000-ch-switch.patch new file mode 100644 index 000000000..0fbca2354 --- /dev/null +++ b/iwlwifi-fix-6000-ch-switch.patch @@ -0,0 +1,94 @@ +commit a7d3a5d97acd4b8db17e1d5c3014357c9b2040f9 +Author: Johannes Berg +Date: Tue Sep 25 16:40:12 2012 +0200 + + iwlwifi: fix 6000 series channel switch command + + The channel switch command for 6000 series devices + is larger than the maximum inline command size of + 320 bytes. The command is therefore refused with a + warning. Fix this by allocating the command and + using the NOCOPY mechanism. + + Cc: stable@kernel.org + Signed-off-by: Johannes Berg + +diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c +index 349c205..da58620 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/devices.c ++++ b/drivers/net/wireless/iwlwifi/dvm/devices.c +@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + * See iwlagn_mac_channel_switch. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; +- struct iwl6000_channel_switch_cmd cmd; ++ struct iwl6000_channel_switch_cmd *cmd; + u32 switch_time_in_usec, ucode_switch_time; + u16 ch; + u32 tsf_low; +@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + struct ieee80211_vif *vif = ctx->vif; + struct iwl_host_cmd hcmd = { + .id = REPLY_CHANNEL_SWITCH, +- .len = { sizeof(cmd), }, ++ .len = { sizeof(*cmd), }, + .flags = CMD_SYNC, +- .data = { &cmd, }, ++ .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; ++ int err; + +- cmd.band = priv->band == IEEE80211_BAND_2GHZ; ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ hcmd.data[0] = cmd; ++ ++ cmd->band = priv->band == IEEE80211_BAND_2GHZ; + ch = ch_switch->channel->hw_value; + IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", + ctx->active.channel, ch); +- cmd.channel = cpu_to_le16(ch); +- cmd.rxon_flags = ctx->staging.flags; +- cmd.rxon_filter_flags = ctx->staging.filter_flags; ++ cmd->channel = cpu_to_le16(ch); ++ cmd->rxon_flags = ctx->staging.flags; ++ cmd->rxon_filter_flags = ctx->staging.filter_flags; + switch_count = ch_switch->count; + tsf_low = ch_switch->timestamp & 0x0ffffffff; + /* +@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + switch_count = 0; + } + if (switch_count <= 1) +- cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); ++ cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); + else { + switch_time_in_usec = + vif->bss_conf.beacon_int * switch_count * TIME_UNIT; + ucode_switch_time = iwl_usecs_to_beacons(priv, + switch_time_in_usec, + beacon_interval); +- cmd.switch_time = iwl_add_beacon_time(priv, +- priv->ucode_beacon_time, +- ucode_switch_time, +- beacon_interval); ++ cmd->switch_time = iwl_add_beacon_time(priv, ++ priv->ucode_beacon_time, ++ ucode_switch_time, ++ beacon_interval); + } + IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", +- cmd.switch_time); +- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; ++ cmd->switch_time); ++ cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + +- return iwl_dvm_send_cmd(priv, &hcmd); ++ err = iwl_dvm_send_cmd(priv, &hcmd); ++ kfree(cmd); ++ return err; + } + + struct iwl_lib_ops iwl6000_lib = { diff --git a/kernel.spec b/kernel.spec index 32b52dd2d..21cd802c2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -759,6 +759,9 @@ Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 770484 +Patch22071: iwlwifi-fix-6000-ch-switch.patch + # END OF PATCH DEFINITIONS %endif @@ -1469,6 +1472,9 @@ ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +#rhbz 770484 +ApplyPatch iwlwifi-fix-6000-ch-switch.patch + # END OF PATCH APPLICATIONS %endif @@ -2321,6 +2327,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 18 2012 Josh Boyer +- Apply patch to fix iwlwifi crash (rhbz 770484) + * Tue Oct 16 2012 Mauro Carvalho Chehab - 3.6.2-2 - Fix i82975x_edac OOPS From c7a63b96fedba8d24f7d3f87599f4c5d8065518a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:33:53 -0400 Subject: [PATCH 069/492] Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) --- kernel.spec | 7 ++++ mac80211_local_deauth_v3.6.patch | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 mac80211_local_deauth_v3.6.patch diff --git a/kernel.spec b/kernel.spec index 21cd802c2..009989e42 100644 --- a/kernel.spec +++ b/kernel.spec @@ -762,6 +762,9 @@ Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch #rhbz 770484 Patch22071: iwlwifi-fix-6000-ch-switch.patch +#rhbz 862168 +Patch22073: mac80211_local_deauth_v3.6.patch + # END OF PATCH DEFINITIONS %endif @@ -1475,6 +1478,9 @@ ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch #rhbz 770484 ApplyPatch iwlwifi-fix-6000-ch-switch.patch +#rhbz 862168 +ApplyPatch mac80211_local_deauth_v3.6.patch + # END OF PATCH APPLICATIONS %endif @@ -2328,6 +2334,7 @@ fi # || || %changelog * Thu Oct 18 2012 Josh Boyer +- Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) - Apply patch to fix iwlwifi crash (rhbz 770484) * Tue Oct 16 2012 Mauro Carvalho Chehab - 3.6.2-2 diff --git a/mac80211_local_deauth_v3.6.patch b/mac80211_local_deauth_v3.6.patch new file mode 100644 index 000000000..3b634860f --- /dev/null +++ b/mac80211_local_deauth_v3.6.patch @@ -0,0 +1,66 @@ +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 3d254e1..f10553c 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request { + const u8 *ie; + size_t ie_len; + u16 reason_code; ++ bool local_state_change; + }; + + /** +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index f76b833..08343c2 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3457,6 +3457,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; ++ bool tx = !req->local_state_change; + + mutex_lock(&ifmgd->mtx); + +@@ -3473,12 +3474,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + if (ifmgd->associated && + ether_addr_equal(ifmgd->associated->bssid, req->bssid)) + ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, frame_buf); ++ req->reason_code, tx, frame_buf); + else + ieee80211_send_deauth_disassoc(sdata, req->bssid, + IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, +- frame_buf); ++ req->reason_code, tx, frame_buf); + mutex_unlock(&ifmgd->mtx); + + __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 1cdb1d5..0877efb 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -457,21 +457,11 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, + .reason_code = reason, + .ie = ie, + .ie_len = ie_len, ++ .local_state_change = local_state_change, + }; + + ASSERT_WDEV_LOCK(wdev); + +- if (local_state_change) { +- if (wdev->current_bss && +- ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { +- cfg80211_unhold_bss(wdev->current_bss); +- cfg80211_put_bss(&wdev->current_bss->pub); +- wdev->current_bss = NULL; +- } +- +- return 0; +- } +- + return rdev->ops->deauth(&rdev->wiphy, dev, &req); + } + From 023c26f5184cb66b0e5ff14663a772b18f65cad2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:39:41 -0400 Subject: [PATCH 070/492] Enable VFIO (rhbz 867152) --- config-generic | 4 +++- kernel.spec | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index c7a03cf20..8fca0dc4b 100644 --- a/config-generic +++ b/config-generic @@ -4159,7 +4159,9 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set -# CONFIG_VFIO is not set +CONFIG_VFIO=m +CONFIG_VFIO_IOMMU_TYPE1=m +CONFIG_VFIO_PCI=m # LIRC diff --git a/kernel.spec b/kernel.spec index 009989e42..2fece53a1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2334,6 +2334,7 @@ fi # || || %changelog * Thu Oct 18 2012 Josh Boyer +- Enable VFIO (rhbz 867152) - Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) - Apply patch to fix iwlwifi crash (rhbz 770484) From 5a7aaca8ae0d9964ead90956f1897d678ec1c796 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:52:16 -0400 Subject: [PATCH 071/492] Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) --- kernel.spec | 7 ++ ...t-with-HT20-if-HT40-is-not-permitted.patch | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch diff --git a/kernel.spec b/kernel.spec index 2fece53a1..28a0512a5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -765,6 +765,9 @@ Patch22071: iwlwifi-fix-6000-ch-switch.patch #rhbz 862168 Patch22073: mac80211_local_deauth_v3.6.patch +#rhbz 866013 +Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch + # END OF PATCH DEFINITIONS %endif @@ -1481,6 +1484,9 @@ ApplyPatch iwlwifi-fix-6000-ch-switch.patch #rhbz 862168 ApplyPatch mac80211_local_deauth_v3.6.patch +#rhbz 866013 +ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch + # END OF PATCH APPLICATIONS %endif @@ -2334,6 +2340,7 @@ fi # || || %changelog * Thu Oct 18 2012 Josh Boyer +- Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) - Enable VFIO (rhbz 867152) - Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) - Apply patch to fix iwlwifi crash (rhbz 770484) diff --git a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch new file mode 100644 index 000000000..8c46db671 --- /dev/null +++ b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch @@ -0,0 +1,75 @@ +From 3a40414f826a8f1096d9b94c4a53ef91b25ba28d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 1 Oct 2012 15:52:00 +0200 +Subject: [PATCH] mac80211: connect with HT20 if HT40 is not permitted + +Some changes to fix issues with HT40 APs in Korea +and follow-up changes to allow using HT40 even if +the local regulatory database disallows it caused +issues with iwlwifi (and could cause issues with +other devices); iwlwifi firmware would assert if +you tried to connect to an AP that has an invalid +configuration (e.g. using HT40- on channel 140.) + +Fix this, while avoiding the "Korean AP" issue by +disabling HT40 and advertising HT20 to the AP +when connecting. + +Cc: stable@vger.kernel.org [3.6] +Reported-by: Florian Reitmeir +Tested-by: Florian Reitmeir +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- + 1 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e510a33..1b7eed2 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + ht_cfreq, ht_oper->primary_chan, + cbss->channel->band); + ht_oper = NULL; ++ } else { ++ channel_type = NL80211_CHAN_HT20; + } + } + +- if (ht_oper) { +- channel_type = NL80211_CHAN_HT20; ++ if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { ++ /* ++ * cfg80211 already verified that the channel itself can ++ * be used, but it didn't check that we can do the right ++ * HT type, so do that here as well. If HT40 isn't allowed ++ * on this channel, disable 40 MHz operation. ++ */ + +- if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { +- switch (ht_oper->ht_param & +- IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { +- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: ++ switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { ++ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: ++ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) ++ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; ++ else + channel_type = NL80211_CHAN_HT40PLUS; +- break; +- case IEEE80211_HT_PARAM_CHA_SEC_BELOW: ++ break; ++ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: ++ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) ++ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; ++ else + channel_type = NL80211_CHAN_HT40MINUS; +- break; +- } ++ break; + } + } + +-- +1.7.6.5 + From 6419bc968389dfcbfcd7dd4ade75f54c9531b4c6 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 22 Oct 2012 09:45:28 +0100 Subject: [PATCH 072/492] add patch to revert ARM misaligned access check to stop kernel OOPS, actually apply highbank sata patch --- ...missaligned-access-check-on-put_user.patch | 83 +++++++++++++++++++ kernel.spec | 15 ++-- 2 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch diff --git a/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch b/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch new file mode 100644 index 000000000..155806681 --- /dev/null +++ b/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch @@ -0,0 +1,83 @@ +commit dd945918f747f61eff384f5cb8889e524f60615a +Author: Jon Masters +Date: Fri Oct 5 22:32:29 2012 -0400 + + Revert "ARM: 7528/1: uaccess: annotate [__]{get,put}_user functions with might_fault()" + + This reverts commit ad72907acd2943304c292ae36960bb66e6dc23c9. + + Technically, the original commit is totally correct, however it exposes + a deep-rooted problem with missaligned accesses in e.g. the networking + stack and we need to revert this (sweep under rug) until we can get + a good solution in place upstream. The problem is that the compiler + believes the structs concerned are aligned (they are in the code), + however at runtime the IP structs are actually not aligned within + received network packets, and the fault handler is not guaranteed + to be entirely atomic and free of calls to the scheduler. + + Signed-off-by: Jon Masters + +diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h +index 77bd79f..6f83ad6 100644 +--- a/arch/arm/include/asm/uaccess.h ++++ b/arch/arm/include/asm/uaccess.h +@@ -118,7 +118,7 @@ extern int __get_user_4(void *); + : "0" (__p), "r" (__l) \ + : __GUP_CLOBBER_##__s) + +-#define __get_user_check(x,p) \ ++#define get_user(x,p) \ + ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ + register const typeof(*(p)) __user *__p asm("r0") = (p);\ +@@ -141,12 +141,6 @@ extern int __get_user_4(void *); + __e; \ + }) + +-#define get_user(x,p) \ +- ({ \ +- might_fault(); \ +- __get_user_check(x,p); \ +- }) +- + extern int __put_user_1(void *, unsigned int); + extern int __put_user_2(void *, unsigned int); + extern int __put_user_4(void *, unsigned int); +@@ -161,7 +155,7 @@ extern int __put_user_8(void *, unsigned long long); + : "0" (__p), "r" (__r2), "r" (__l) \ + : "ip", "lr", "cc") + +-#define __put_user_check(x,p) \ ++#define put_user(x,p) \ + ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ + register const typeof(*(p)) __r2 asm("r2") = (x); \ +@@ -186,12 +180,6 @@ extern int __put_user_8(void *, unsigned long long); + __e; \ + }) + +-#define put_user(x,p) \ +- ({ \ +- might_fault(); \ +- __put_user_check(x,p); \ +- }) +- + #else /* CONFIG_MMU */ + + /* +@@ -245,7 +233,6 @@ do { \ + unsigned long __gu_addr = (unsigned long)(ptr); \ + unsigned long __gu_val; \ + __chk_user_ptr(ptr); \ +- might_fault(); \ + switch (sizeof(*(ptr))) { \ + case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ + case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ +@@ -327,7 +314,6 @@ do { \ + unsigned long __pu_addr = (unsigned long)(ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + __chk_user_ptr(ptr); \ +- might_fault(); \ + switch (sizeof(*(ptr))) { \ + case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ + case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ diff --git a/kernel.spec b/kernel.spec index cc60adb1f..ea14cb2a7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -733,6 +733,7 @@ Patch19001: i82975x-edac-fix.patch Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch Patch21002: arm-fix_radio_shark.patch +Patch21003: arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch # OMAP # ARM tegra @@ -747,10 +748,6 @@ Patch21010: arm-highbank-sata-fix.patch Patch21020: arm-smdk310-regulator-fix.patch Patch21021: arm-origen-regulator-fix.patch -# ARM exynos4 -Patch21020: arm-smdk310-regulator-fix.patch -Patch21021: arm-origen-regulator-fix.patch - Patch21094: power-x86-destdir.patch #rhbz 754518 @@ -1356,10 +1353,8 @@ ApplyPatch arm-fix_radio_shark.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch - -ApplyPatch arm-smdk310-regulator-fix.patch -ApplyPatch arm-origen-regulator-fix.patch - +ApplyPatch arm-highbank-sata-fix.patch +ApplyPatch arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch ApplyPatch arm-smdk310-regulator-fix.patch ApplyPatch arm-origen-regulator-fix.patch @@ -2353,6 +2348,10 @@ fi # ||----w | # || || %changelog +* Mon Oct 22 2012 Peter Robinson +- Revert ARM misaligned access check to stop kernel OOPS +- Actually apply highbank sata patch + * Thu Oct 18 2012 Josh Boyer - Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) - Enable VFIO (rhbz 867152) From aefdd9811462f886255fb52b5f714fe168c30293 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 22 Oct 2012 07:22:54 -0500 Subject: [PATCH 073/492] Linux 3.6.3 --- kernel.spec | 13 ++++----- sources | 2 +- ...csi-Initialize-scatterlist-structure.patch | 28 ------------------- 3 files changed, 6 insertions(+), 37 deletions(-) delete mode 100644 virtio-scsi-Initialize-scatterlist-structure.patch diff --git a/kernel.spec b/kernel.spec index ea14cb2a7..b1487b5fd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -758,9 +758,6 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 847548 -Patch22066: virtio-scsi-Initialize-scatterlist-structure.patch - #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch @@ -1481,9 +1478,6 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 847548 -ApplyPatch virtio-scsi-Initialize-scatterlist-structure.patch - #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch @@ -2348,6 +2342,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 22 2012 Justin M. Forbes - 3.6.3-1 +- Linux 3.6.3 + * Mon Oct 22 2012 Peter Robinson - Revert ARM misaligned access check to stop kernel OOPS - Actually apply highbank sata patch diff --git a/sources b/sources index 47fce40c3..8c5ed1c19 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -ad1020c82a71ee1ef2416a0d12e724df patch-3.6.2.xz +96701113d37ef4f9b785206ab8bcc71e patch-3.6.3.xz diff --git a/virtio-scsi-Initialize-scatterlist-structure.patch b/virtio-scsi-Initialize-scatterlist-structure.patch deleted file mode 100644 index 4445d6838..000000000 --- a/virtio-scsi-Initialize-scatterlist-structure.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: "Richard W.M. Jones" - -The sg struct is used without being initialized. - -https://bugzilla.redhat.com/show_bug.cgi?id=847548 - -Signed-off-by: Richard W.M. Jones ---- - drivers/scsi/virtio_scsi.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c -index c7030fb..8a66f83 100644 ---- a/drivers/scsi/virtio_scsi.c -+++ b/drivers/scsi/virtio_scsi.c -@@ -219,7 +219,7 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi, - struct scatterlist sg; - unsigned long flags; - -- sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); -+ sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); - - spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); - --- -1.7.10.4 - - From d5d47dc0168b91f0524d9dd45f4001e15551a5e8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 08:32:00 -0400 Subject: [PATCH 074/492] Fix rt2x00 usb reset resume (rhbz 856863) --- kernel.spec | 11 ++++- rt2x00-usb-fix-reset-resume.patch | 70 +++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 rt2x00-usb-fix-reset-resume.patch diff --git a/kernel.spec b/kernel.spec index b1487b5fd..22fd5ac65 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -770,6 +770,9 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +#rhbz 856863 +Patch22075: rt2x00-usb-fix-reset-resume.patch + # END OF PATCH DEFINITIONS %endif @@ -1490,6 +1493,9 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +#rhbz 856863 +ApplyPatch rt2x00-usb-fix-reset-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -2342,6 +2348,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 22 2012 Josh Boyer +- Fix rt2x00 usb reset resume (rhbz 856863) + * Mon Oct 22 2012 Justin M. Forbes - 3.6.3-1 - Linux 3.6.3 diff --git a/rt2x00-usb-fix-reset-resume.patch b/rt2x00-usb-fix-reset-resume.patch new file mode 100644 index 000000000..07d2b4c0e --- /dev/null +++ b/rt2x00-usb-fix-reset-resume.patch @@ -0,0 +1,70 @@ +Patch fixes warnings like below happened on resume: + +WARNING: at net/mac80211/driver-ops.h:12 check_sdata_in_driver+0x32/0x34() + +Problem is that in __ieee80211_susped() we remove sdata (i.e wlan0 +interface) and then during resume we call usb_unbind_interface() -> +ieee80211_unregister_hw() with sdata removed. + +Patch fixes problem by adding .reset_resume calback, hence we do not +unbind usb device on resume. This callback can be the same as normal +.resume callback, sice we do all needed initalization during interface +start, which is performed on resume [ ieee80211_resume() -> +ieee80211_reconfig() -> rt2x00mac_start() -> rt2x00lib_start ]. + +Resolves: +https://bugzilla.kernel.org/show_bug.cgi?id=48041 + +Reported-by: David Herrmann +Reported-and-tested-by: Stephen Boyd +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2500usb.c | 1 + + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + + drivers/net/wireless/rt2x00/rt73usb.c | 1 + + 3 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c +index a12e84f..6b2e1e4 100644 +--- a/drivers/net/wireless/rt2x00/rt2500usb.c ++++ b/drivers/net/wireless/rt2x00/rt2500usb.c +@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index c9e9370..3b8fb5a 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c +index e5eb43b..24eec66 100644 +--- a/drivers/net/wireless/rt2x00/rt73usb.c ++++ b/drivers/net/wireless/rt2x00/rt73usb.c +@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 06c67c2107c3f5074f8c8c74fd3952e1ba25dc5c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 09:47:05 -0400 Subject: [PATCH 075/492] CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) --- ...tack-memory-content-leak-via-UNAME26.patch | 98 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 105 insertions(+) create mode 100644 fix-stack-memory-content-leak-via-UNAME26.patch diff --git a/fix-stack-memory-content-leak-via-UNAME26.patch b/fix-stack-memory-content-leak-via-UNAME26.patch new file mode 100644 index 000000000..5121ca06b --- /dev/null +++ b/fix-stack-memory-content-leak-via-UNAME26.patch @@ -0,0 +1,98 @@ +From 2702b1526c7278c4d65d78de209a465d4de2885e Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 19 Oct 2012 13:56:51 -0700 +Subject: [PATCH 1/2] kernel/sys.c: fix stack memory content leak via UNAME26 + +Calling uname() with the UNAME26 personality set allows a leak of kernel +stack contents. This fixes it by defensively calculating the length of +copy_to_user() call, making the len argument unsigned, and initializing +the stack buffer to zero (now technically unneeded, but hey, overkill). + +CVE-2012-0957 + +Reported-by: PaX Team +Signed-off-by: Kees Cook +Cc: Andi Kleen +Cc: PaX Team +Cc: Brad Spengler +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + kernel/sys.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/kernel/sys.c b/kernel/sys.c +index c5cb5b9..01865c6 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem); + * Work around broken programs that cannot handle "Linux 3.0". + * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 + */ +-static int override_release(char __user *release, int len) ++static int override_release(char __user *release, size_t len) + { + int ret = 0; +- char buf[65]; + + if (current->personality & UNAME26) { +- char *rest = UTS_RELEASE; ++ const char *rest = UTS_RELEASE; ++ char buf[65] = { 0 }; + int ndots = 0; + unsigned v; ++ size_t copy; + + while (*rest) { + if (*rest == '.' && ++ndots >= 3) +@@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len) + rest++; + } + v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; +- snprintf(buf, len, "2.6.%u%s", v, rest); +- ret = copy_to_user(release, buf, len); ++ copy = min(sizeof(buf), max_t(size_t, 1, len)); ++ copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); ++ ret = copy_to_user(release, buf, copy + 1); + } + return ret; + } +-- +1.7.12.1 + + +From 31fd84b95eb211d5db460a1dda85e004800a7b52 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 19 Oct 2012 18:45:53 -0700 +Subject: [PATCH 2/2] use clamp_t in UNAME26 fix + +The min/max call needed to have explicit types on some architectures +(e.g. mn10300). Use clamp_t instead to avoid the warning: + + kernel/sys.c: In function 'override_release': + kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default] + +Reported-by: Fengguang Wu +Signed-off-by: Kees Cook +Signed-off-by: Linus Torvalds +--- + kernel/sys.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sys.c b/kernel/sys.c +index 01865c6..e6e0ece 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1284,7 +1284,7 @@ static int override_release(char __user *release, size_t len) + rest++; + } + v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; +- copy = min(sizeof(buf), max_t(size_t, 1, len)); ++ copy = clamp_t(size_t, len, 1, sizeof(buf)); + copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); + ret = copy_to_user(release, buf, copy + 1); + } +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index 22fd5ac65..572be69b4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -773,6 +773,9 @@ Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch #rhbz 856863 Patch22075: rt2x00-usb-fix-reset-resume.patch +#rhbz 862877 864824 CVE-2012-0957 +Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch + # END OF PATCH DEFINITIONS %endif @@ -1496,6 +1499,9 @@ ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch #rhbz 856863 ApplyPatch rt2x00-usb-fix-reset-resume.patch +#rhbz 862877 864824 CVE-2012-0957 +ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch + # END OF PATCH APPLICATIONS %endif @@ -2349,6 +2355,7 @@ fi # || || %changelog * Mon Oct 22 2012 Josh Boyer +- CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) - Fix rt2x00 usb reset resume (rhbz 856863) * Mon Oct 22 2012 Justin M. Forbes - 3.6.3-1 From f87521dfe4bf01309eabf5a9826da57ae5417c8a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 15:46:47 -0400 Subject: [PATCH 076/492] Add patch to fix CIFS oops from Jeff Layton (rhbz 867344) --- ...ifs_lookup-on-hashed-negative-dentry.patch | 21 +++++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 28 insertions(+) create mode 100644 dont-call-cifs_lookup-on-hashed-negative-dentry.patch diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch new file mode 100644 index 000000000..88b35e2f8 --- /dev/null +++ b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -0,0 +1,21 @@ +@@ -, +, @@ + negative dentry + BUG_ON(!d_unhashed(entry)); + fs/cifs/dir.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) +--- a/fs/cifs/dir.c ++++ a/fs/cifs/dir.c +@@ -398,7 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, + * in network traffic in the other paths. + */ + if (!(oflags & O_CREAT)) { +- struct dentry *res = cifs_lookup(inode, direntry, 0); ++ struct dentry *res; ++ ++ if (!direntry->d_inode) ++ return -ENOENT; ++ ++ res = cifs_lookup(inode, direntry, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + diff --git a/kernel.spec b/kernel.spec index 572be69b4..959f40204 100644 --- a/kernel.spec +++ b/kernel.spec @@ -776,6 +776,9 @@ Patch22075: rt2x00-usb-fix-reset-resume.patch #rhbz 862877 864824 CVE-2012-0957 Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch +#rhbz 867344 +Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch + # END OF PATCH DEFINITIONS %endif @@ -1502,6 +1505,9 @@ ApplyPatch rt2x00-usb-fix-reset-resume.patch #rhbz 862877 864824 CVE-2012-0957 ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch +#rhbz 867344 +ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch + # END OF PATCH APPLICATIONS %endif @@ -2355,6 +2361,7 @@ fi # || || %changelog * Mon Oct 22 2012 Josh Boyer +- Add patch to fix CIFS oops from Jeff Layton (rhbz 867344) - CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) - Fix rt2x00 usb reset resume (rhbz 856863) From a40ef16775313110b0203c7369c3ced8daf51e90 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 22 Oct 2012 21:23:31 +0100 Subject: [PATCH 077/492] VIFO fails on ARM at the moment so disable it for the time being --- config-arm-generic | 2 ++ kernel.spec | 3 +++ 2 files changed, 5 insertions(+) diff --git a/config-arm-generic b/config-arm-generic index 24713b969..8b7f50874 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -291,6 +291,8 @@ CONFIG_REGULATOR_TPS6507X=m CONFIG_CHARGER_MANAGER=y CONFIG_EXTCON_GPIO=m +# CONFIG_VFIO is not set + # CONFIG_XIP_KERNEL is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set diff --git a/kernel.spec b/kernel.spec index 572be69b4..a5c8cd469 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2354,6 +2354,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 22 2012 Peter Robinson +- VIFO fails on ARM at the moment so disable it for the time being + * Mon Oct 22 2012 Josh Boyer - CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) - Fix rt2x00 usb reset resume (rhbz 856863) From d7bc89adf555b7b092c7cf1e1eaedb1f1a742acf Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 23 Oct 2012 09:37:06 -0500 Subject: [PATCH 078/492] bump for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 6f7731782..4363d1821 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching From a0177af7b1f437e6d9f359c4d0452527f598a240 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 23 Oct 2012 15:55:48 +0100 Subject: [PATCH 079/492] Update OMAP Video config options --- config-arm-omap | 15 ++++++++------- kernel.spec | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/config-arm-omap b/config-arm-omap index 8cda8dc2f..b35ccd1dd 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -210,22 +210,23 @@ CONFIG_DRM_OMAP_NUM_CRTCS=2 # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set # CONFIG_FB_OMAP_LCD_VGA is not set CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRAM_SIZE=0 CONFIG_OMAP2_VRFB=y -CONFIG_OMAP2_DSS=y -CONFIG_OMAP2_VRAM_SIZE=12 +# CONFIG_FB_OMAP2 is not set + +CONFIG_OMAP2_DSS=m CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y # CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set CONFIG_OMAP2_DSS_DPI=y -# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_RFBI=y CONFIG_OMAP2_DSS_VENC=y CONFIG_OMAP4_DSS_HDMI=y -# CONFIG_OMAP2_DSS_SDI is not set -# CONFIG_OMAP2_DSS_DSI is not set +CONFIG_OMAP2_DSS_SDI=y +CONFIG_OMAP2_DSS_DSI=y # CONFIG_OMAP2_DSS_FAKE_VSYNC is not set -CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y -# CONFIG_FB_OMAP2 is not set CONFIG_PANEL_TFP410=m CONFIG_PANEL_PICODLP=m diff --git a/kernel.spec b/kernel.spec index 4363d1821..ed1d3d542 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2360,6 +2360,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 23 2012 Peter Robinson +- Update OMAP Video config options + * Mon Oct 22 2012 Peter Robinson - VIFO fails on ARM at the moment so disable it for the time being From 9c72450ca1d7ca6098f0a697793b8143b57ced92 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Oct 2012 08:23:01 -0400 Subject: [PATCH 080/492] Add patch to fix corrupted text with i915 (rhbz 852210) --- ...-relocations-if-the-object-is-in-the.patch | 33 +++++++++++++++++++ kernel.spec | 11 ++++++- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch diff --git a/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch b/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch new file mode 100644 index 000000000..0e282bf04 --- /dev/null +++ b/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch @@ -0,0 +1,33 @@ +From 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 23 Aug 2012 13:12:52 +0100 +Subject: [PATCH] drm/i915: Use cpu relocations if the object is in the GTT + but not mappable + +This prevents the case of unbinding the object in order to process the +relocations through the GTT and then rebinding it only to then proceed +to use cpu relocations as the object is now in the CPU write domain. By +choosing to use cpu relocations up front, we can therefore avoid the +rebind penalty. + +Signed-off-by: Chris Wilson +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index f7346d8..dc87563 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -95,6 +95,7 @@ eb_destroy(struct eb_objects *eb) + static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) + { + return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || ++ !obj->map_and_fenceable || + obj->cache_level != I915_CACHE_NONE); + } + +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index ed1d3d542..9a47e77a1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -779,6 +779,9 @@ Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch +#rhbz 852210 +Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch + # END OF PATCH DEFINITIONS %endif @@ -1508,6 +1511,9 @@ ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch +#rhbz 852210 +ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch + # END OF PATCH APPLICATIONS %endif @@ -2360,6 +2366,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 24 2012 Josh Boyer +- Add patch to fix corrupted text with i915 (rhbz 852210) + * Tue Oct 23 2012 Peter Robinson - Update OMAP Video config options From 73a159283b7a4e80e6a9a338b64b458695f420b8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Oct 2012 14:41:23 -0400 Subject: [PATCH 081/492] Remove patch added for rhbz 856863 --- kernel.spec | 7 +--- rt2x00-usb-fix-reset-resume.patch | 70 ------------------------------- 2 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 rt2x00-usb-fix-reset-resume.patch diff --git a/kernel.spec b/kernel.spec index 9a47e77a1..c1ae25377 100644 --- a/kernel.spec +++ b/kernel.spec @@ -770,9 +770,6 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 856863 -Patch22075: rt2x00-usb-fix-reset-resume.patch - #rhbz 862877 864824 CVE-2012-0957 Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch @@ -1502,9 +1499,6 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 856863 -ApplyPatch rt2x00-usb-fix-reset-resume.patch - #rhbz 862877 864824 CVE-2012-0957 ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch @@ -2367,6 +2361,7 @@ fi # || || %changelog * Wed Oct 24 2012 Josh Boyer +- Remove patch added for rhbz 856863 - Add patch to fix corrupted text with i915 (rhbz 852210) * Tue Oct 23 2012 Peter Robinson diff --git a/rt2x00-usb-fix-reset-resume.patch b/rt2x00-usb-fix-reset-resume.patch deleted file mode 100644 index 07d2b4c0e..000000000 --- a/rt2x00-usb-fix-reset-resume.patch +++ /dev/null @@ -1,70 +0,0 @@ -Patch fixes warnings like below happened on resume: - -WARNING: at net/mac80211/driver-ops.h:12 check_sdata_in_driver+0x32/0x34() - -Problem is that in __ieee80211_susped() we remove sdata (i.e wlan0 -interface) and then during resume we call usb_unbind_interface() -> -ieee80211_unregister_hw() with sdata removed. - -Patch fixes problem by adding .reset_resume calback, hence we do not -unbind usb device on resume. This callback can be the same as normal -.resume callback, sice we do all needed initalization during interface -start, which is performed on resume [ ieee80211_resume() -> -ieee80211_reconfig() -> rt2x00mac_start() -> rt2x00lib_start ]. - -Resolves: -https://bugzilla.kernel.org/show_bug.cgi?id=48041 - -Reported-by: David Herrmann -Reported-and-tested-by: Stephen Boyd -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rt2x00/rt2500usb.c | 1 + - drivers/net/wireless/rt2x00/rt2800usb.c | 1 + - drivers/net/wireless/rt2x00/rt73usb.c | 1 + - 3 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c -index a12e84f..6b2e1e4 100644 ---- a/drivers/net/wireless/rt2x00/rt2500usb.c -+++ b/drivers/net/wireless/rt2x00/rt2500usb.c -@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - -diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c -index c9e9370..3b8fb5a 100644 ---- a/drivers/net/wireless/rt2x00/rt2800usb.c -+++ b/drivers/net/wireless/rt2x00/rt2800usb.c -@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - -diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c -index e5eb43b..24eec66 100644 ---- a/drivers/net/wireless/rt2x00/rt73usb.c -+++ b/drivers/net/wireless/rt2x00/rt73usb.c -@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 1c1fad82422e58b20bf06bb371c38154b4b965db Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 25 Oct 2012 13:14:53 -0500 Subject: [PATCH 082/492] CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) --- 0001-ext4-ext4_inode_info-diet.patch | 121 ++++ ...io_unwritten-a-more-appropriate-name.patch | 97 ++++ 0003-ext4-fix-unwritten-counter-leakage.patch | 112 ++++ 0004-ext4-completed_io-locking-cleanup.patch | 520 ++++++++++++++++++ ...io-nonlocked-reads-with-defrag-worke.patch | 144 +++++ ...ize-unlocked-dio-reads-with-truncate.patch | 65 +++ ...runcate-due-to-nonlocked-dio-readers.patch | 41 ++ ...-truncate-with-owerwrite-DIO-workers.patch | 61 ++ ...nch_hole-should-wait-for-DIO-writers.patch | 125 +++++ ...ext_remove_space-for-punch_hole-case.patch | 60 ++ ...t4_flush_completed_IO-wait-semantics.patch | 176 ++++++ ...allocate-with-ext4_convert_unwritten.patch | 46 ++ ...ion-protection-for-ext4_convert_unwr.patch | 153 ++++++ kernel.spec | 33 ++ 14 files changed, 1754 insertions(+) create mode 100644 0001-ext4-ext4_inode_info-diet.patch create mode 100644 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch create mode 100644 0003-ext4-fix-unwritten-counter-leakage.patch create mode 100644 0004-ext4-completed_io-locking-cleanup.patch create mode 100644 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch create mode 100644 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch create mode 100644 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch create mode 100644 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch create mode 100644 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch create mode 100644 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch create mode 100644 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch create mode 100644 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch create mode 100644 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch diff --git a/0001-ext4-ext4_inode_info-diet.patch b/0001-ext4-ext4_inode_info-diet.patch new file mode 100644 index 000000000..c7858ecc6 --- /dev/null +++ b/0001-ext4-ext4_inode_info-diet.patch @@ -0,0 +1,121 @@ +From 50b61634cf8d09f9ef334919b859735d381cbe39 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:21:09 -0400 +Subject: [PATCH 01/13] ext4: ext4_inode_info diet + +Generic inode has unused i_private pointer which may be used as cur_aio_dio +storage. + +TODO: If cur_aio_dio will be passed as an argument to get_block_t this allow + to have concurent AIO_DIO requests. + +Reviewed-by: Zheng Liu +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit f45ee3a1ea438af96e4fd2c0b16d195e67ef235f) +--- + fs/ext4/ext4.h | 12 ++++++++++-- + fs/ext4/extents.c | 4 ++-- + fs/ext4/inode.c | 6 +++--- + fs/ext4/super.c | 1 - + 4 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index c3411d4..80afc8f 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -912,8 +912,6 @@ struct ext4_inode_info { + struct list_head i_completed_io_list; + spinlock_t i_completed_io_lock; + atomic_t i_ioend_count; /* Number of outstanding io_end structs */ +- /* current io_end structure for async DIO write*/ +- ext4_io_end_t *cur_aio_dio; + atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ + + spinlock_t i_block_reservation_lock; +@@ -1332,6 +1330,16 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, + } + } + ++static inline ext4_io_end_t *ext4_inode_aio(struct inode *inode) ++{ ++ return inode->i_private; ++} ++ ++static inline void ext4_inode_aio_set(struct inode *inode, ext4_io_end_t *io) ++{ ++ inode->i_private = io; ++} ++ + /* + * Inode dynamic state flags + */ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index aabbb3f..51fbef1 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3600,7 +3600,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + { + int ret = 0; + int err = 0; +- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; ++ ext4_io_end_t *io = ext4_inode_aio(inode); + + ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical " + "block %llu, max_blocks %u, flags %x, allocated %u\n", +@@ -3858,7 +3858,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + unsigned int allocated = 0, offset = 0; + unsigned int allocated_clusters = 0; + struct ext4_allocation_request ar; +- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; ++ ext4_io_end_t *io = ext4_inode_aio(inode); + ext4_lblk_t cluster_offset; + + ext_debug("blocks %u/%u requested for inode %lu\n", +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index dff171c..acadd2b 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3054,7 +3054,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + * hook to the iocb. + */ + iocb->private = NULL; +- EXT4_I(inode)->cur_aio_dio = NULL; ++ ext4_inode_aio_set(inode, NULL); + if (!is_sync_kiocb(iocb)) { + ext4_io_end_t *io_end = + ext4_init_io_end(inode, GFP_NOFS); +@@ -3071,7 +3071,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + * is a unwritten extents needs to be converted + * when IO is completed. + */ +- EXT4_I(inode)->cur_aio_dio = iocb->private; ++ ext4_inode_aio_set(inode, io_end); + } + + if (overwrite) +@@ -3091,7 +3091,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + NULL, + DIO_LOCKING); + if (iocb->private) +- EXT4_I(inode)->cur_aio_dio = NULL; ++ ext4_inode_aio_set(inode, NULL); + /* + * The io_end structure takes a reference to the inode, + * that structure needs to be destroyed and the +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c6e0cb3..270e58f 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -956,7 +956,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + ei->jinode = NULL; + INIT_LIST_HEAD(&ei->i_completed_io_list); + spin_lock_init(&ei->i_completed_io_lock); +- ei->cur_aio_dio = NULL; + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; + atomic_set(&ei->i_ioend_count, 0); +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch b/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch new file mode 100644 index 000000000..cfd13f386 --- /dev/null +++ b/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -0,0 +1,97 @@ +From 027d1aa67e32c2c80851105c6d962f3db46eb476 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:24:52 -0400 +Subject: [PATCH 02/13] ext4: give i_aiodio_unwritten a more appropriate name + +AIO/DIO prefix is wrong because it account unwritten extents which +also may be scheduled from buffered write endio + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit e27f41e1b789e60e7d8cc9c81fd93ca49ef31f13) +--- + fs/ext4/ext4.h | 4 ++-- + fs/ext4/file.c | 6 +++--- + fs/ext4/page-io.c | 2 +- + fs/ext4/super.c | 2 +- + 4 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 80afc8f..28dfd9b 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -912,7 +912,7 @@ struct ext4_inode_info { + struct list_head i_completed_io_list; + spinlock_t i_completed_io_lock; + atomic_t i_ioend_count; /* Number of outstanding io_end structs */ +- atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ ++ atomic_t i_unwritten; /* Nr. of inflight conversions pending */ + + spinlock_t i_block_reservation_lock; + +@@ -1326,7 +1326,7 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, + { + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + io_end->flag |= EXT4_IO_END_UNWRITTEN; +- atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); ++ atomic_inc(&EXT4_I(inode)->i_unwritten); + } + } + +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 3b0e3bd..39335bd 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -55,11 +55,11 @@ static int ext4_release_file(struct inode *inode, struct file *filp) + return 0; + } + +-static void ext4_aiodio_wait(struct inode *inode) ++static void ext4_unwritten_wait(struct inode *inode) + { + wait_queue_head_t *wq = ext4_ioend_wq(inode); + +- wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); ++ wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_unwritten) == 0)); + } + + /* +@@ -116,7 +116,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + "performance will be poor.", + inode->i_ino, current->comm); + mutex_lock(ext4_aio_mutex(inode)); +- ext4_aiodio_wait(inode); ++ ext4_unwritten_wait(inode); + } + + BUG_ON(iocb->ki_pos != pos); +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index dcdeef1..de77e31 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -113,7 +113,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + if (io->flag & EXT4_IO_END_DIRECT) + inode_dio_done(inode); + /* Wake up anyone waiting on unwritten extent conversion */ +- if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) ++ if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) + wake_up_all(ext4_ioend_wq(io->inode)); + return ret; + } +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 270e58f..1b6b425 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -959,7 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; + atomic_set(&ei->i_ioend_count, 0); +- atomic_set(&ei->i_aiodio_unwritten, 0); ++ atomic_set(&ei->i_unwritten, 0); + + return &ei->vfs_inode; + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0003-ext4-fix-unwritten-counter-leakage.patch b/0003-ext4-fix-unwritten-counter-leakage.patch new file mode 100644 index 000000000..2f1d0d813 --- /dev/null +++ b/0003-ext4-fix-unwritten-counter-leakage.patch @@ -0,0 +1,112 @@ +From 6a0e905bb7320571ed5fdd2d5efa3d642630b4f7 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:36:25 -0400 +Subject: [PATCH 03/13] ext4: fix unwritten counter leakage + +ext4_set_io_unwritten_flag() will increment i_unwritten counter, so +once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back +on error path. + + - add missed error checks to prevent counter leakage + - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal + that conversion finished. + - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. + +Visible effect of this bug is that unaligned aio_stress may deadlock + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 82e54229118785badffb4ef5ba4803df25fe007f) +--- + fs/ext4/extents.c | 21 ++++++++++++++------- + fs/ext4/page-io.c | 6 +++++- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 51fbef1..e04eb4f 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3615,6 +3615,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { + ret = ext4_split_unwritten_extents(handle, inode, map, + path, flags); ++ if (ret <= 0) ++ goto out; + /* + * Flag the inode(non aio case) or end_io struct (aio case) + * that this IO needs to conversion to written when IO is +@@ -3860,6 +3862,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + struct ext4_allocation_request ar; + ext4_io_end_t *io = ext4_inode_aio(inode); + ext4_lblk_t cluster_offset; ++ int set_unwritten = 0; + + ext_debug("blocks %u/%u requested for inode %lu\n", + map->m_lblk, map->m_len, inode->i_ino); +@@ -4082,13 +4085,8 @@ got_allocated_blocks: + * For non asycn direct IO case, flag the inode state + * that we need to perform conversion when IO is done. + */ +- if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { +- if (io) +- ext4_set_io_unwritten_flag(inode, io); +- else +- ext4_set_inode_state(inode, +- EXT4_STATE_DIO_UNWRITTEN); +- } ++ if ((flags & EXT4_GET_BLOCKS_PRE_IO)) ++ set_unwritten = 1; + if (ext4_should_dioread_nolock(inode)) + map->m_flags |= EXT4_MAP_UNINIT; + } +@@ -4100,6 +4098,15 @@ got_allocated_blocks: + if (!err) + err = ext4_ext_insert_extent(handle, inode, path, + &newex, flags); ++ ++ if (!err && set_unwritten) { ++ if (io) ++ ext4_set_io_unwritten_flag(inode, io); ++ else ++ ext4_set_inode_state(inode, ++ EXT4_STATE_DIO_UNWRITTEN); ++ } ++ + if (err && free_on_err) { + int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? + EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0; +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index de77e31..9970022 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io) + int i; + + BUG_ON(!io); ++ BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); ++ + if (io->page) + put_page(io->page); + for (i = 0; i < io->num_io_pages; i++) +@@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + ssize_t size = io->size; + int ret = 0; + ++ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); ++ + ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," + "list->prev 0x%p\n", + io, inode->i_ino, io->list.next, io->list.prev); +@@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + "(inode %lu, offset %llu, size %zd, error %d)", + inode->i_ino, offset, size, ret); + } +- ++ io->flag &= ~EXT4_IO_END_UNWRITTEN; + if (io->iocb) + aio_complete(io->iocb, io->result, 0); + +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0004-ext4-completed_io-locking-cleanup.patch b/0004-ext4-completed_io-locking-cleanup.patch new file mode 100644 index 000000000..a358a7952 --- /dev/null +++ b/0004-ext4-completed_io-locking-cleanup.patch @@ -0,0 +1,520 @@ +From e23394806df0768ed2dac87484590d2f3a730d55 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:14:55 -0400 +Subject: [PATCH 04/13] ext4: completed_io locking cleanup + +Current unwritten extent conversion state-machine is very fuzzy. +- For unknown reason it performs conversion under i_mutex. What for? + My diagnosis: + We already protect extent tree with i_data_sem, truncate and punch_hole + should wait for DIO, so the only data we have to protect is end_io->flags + modification, but only flush_completed_IO and end_io_work modified this + flags and we can serialize them via i_completed_io_lock. + + Currently all these games with mutex_trylock result in the following deadlock + truncate: kworker: + ext4_setattr ext4_end_io_work + mutex_lock(i_mutex) + inode_dio_wait(inode) ->BLOCK + DEADLOCK<- mutex_trylock() + inode_dio_done() + #TEST_CASE1_BEGIN + MNT=/mnt_scrach + unlink $MNT/file + fallocate -l $((1024*1024*1024)) $MNT/file + aio-stress -I 100000 -O -s 100m -n -t 1 -c 10 -o 2 -o 3 $MNT/file + sleep 2 + truncate -s 0 $MNT/file + #TEST_CASE1_END + +Or use 286's xfstests https://github.com/dmonakhov/xfstests/blob/devel/286 + +This patch makes state machine simple and clean: + +(1) xxx_end_io schedule final extent conversion simply by calling + ext4_add_complete_io(), which append it to ei->i_completed_io_list + NOTE1: because of (2A) work should be queued only if + ->i_completed_io_list was empty, otherwise the work is scheduled already. + +(2) ext4_flush_completed_IO is responsible for handling all pending + end_io from ei->i_completed_io_list + Flushing sequence consists of following stages: + A) LOCKED: Atomically drain completed_io_list to local_list + B) Perform extents conversion + C) LOCKED: move converted io's to to_free list for final deletion + This logic depends on context which we was called from. + D) Final end_io context destruction + NOTE1: i_mutex is no longer required because end_io->flags modification + is protected by ei->ext4_complete_io_lock + +Full list of changes: +- Move all completion end_io related routines to page-io.c in order to improve + logic locality +- Move open coded logic from various xx_end_xx routines to ext4_add_complete_io() +- remove EXT4_IO_END_FSYNC +- Improve SMP scalability by removing useless i_mutex which does not + protect io->flags anymore. +- Reduce lock contention on i_completed_io_lock by optimizing list walk. +- Rename ext4_end_io_nolock to end4_end_io and make it static +- Check flush completion status to ext4_ext_punch_hole(). Because it is + not good idea to punch blocks from corrupted inode. + +Changes since V3 (in request to Jan's comments): + Fall back to active flush_completed_IO() approach in order to prevent + performance issues with nolocked DIO reads. +Changes since V2: + Fix use-after-free caused by race truncate vs end_io_work + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 28a535f9a0df060569dcc786e5bc2e1de43d7dc7) +--- + fs/ext4/ext4.h | 3 +- + fs/ext4/extents.c | 4 +- + fs/ext4/fsync.c | 81 ------------------------- + fs/ext4/indirect.c | 6 +- + fs/ext4/inode.c | 25 +------- + fs/ext4/page-io.c | 171 +++++++++++++++++++++++++++++++++++------------------ + 6 files changed, 121 insertions(+), 169 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 28dfd9b..7687d15 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -186,7 +186,6 @@ struct mpage_da_data { + #define EXT4_IO_END_ERROR 0x0002 + #define EXT4_IO_END_QUEUED 0x0004 + #define EXT4_IO_END_DIRECT 0x0008 +-#define EXT4_IO_END_IN_FSYNC 0x0010 + + struct ext4_io_page { + struct page *p_page; +@@ -2408,11 +2407,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, + + /* page-io.c */ + extern int __init ext4_init_pageio(void); ++extern void ext4_add_complete_io(ext4_io_end_t *io_end); + extern void ext4_exit_pageio(void); + extern void ext4_ioend_wait(struct inode *); + extern void ext4_free_io_end(ext4_io_end_t *io); + extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); +-extern int ext4_end_io_nolock(ext4_io_end_t *io); + extern void ext4_io_submit(struct ext4_io_submit *io); + extern int ext4_bio_write_page(struct ext4_io_submit *io, + struct page *page, +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index e04eb4f..1fbf2ff 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4815,7 +4815,9 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + } + + /* finish any pending end_io work */ +- ext4_flush_completed_IO(inode); ++ err = ext4_flush_completed_IO(inode); ++ if (err) ++ return err; + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c +index 2a1dcea..520b058 100644 +--- a/fs/ext4/fsync.c ++++ b/fs/ext4/fsync.c +@@ -34,87 +34,6 @@ + + #include + +-static void dump_completed_IO(struct inode * inode) +-{ +-#ifdef EXT4FS_DEBUG +- struct list_head *cur, *before, *after; +- ext4_io_end_t *io, *io0, *io1; +- unsigned long flags; +- +- if (list_empty(&EXT4_I(inode)->i_completed_io_list)){ +- ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino); +- return; +- } +- +- ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino); +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){ +- cur = &io->list; +- before = cur->prev; +- io0 = container_of(before, ext4_io_end_t, list); +- after = cur->next; +- io1 = container_of(after, ext4_io_end_t, list); +- +- ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", +- io, inode->i_ino, io0, io1); +- } +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +-#endif +-} +- +-/* +- * This function is called from ext4_sync_file(). +- * +- * When IO is completed, the work to convert unwritten extents to +- * written is queued on workqueue but may not get immediately +- * scheduled. When fsync is called, we need to ensure the +- * conversion is complete before fsync returns. +- * The inode keeps track of a list of pending/completed IO that +- * might needs to do the conversion. This function walks through +- * the list and convert the related unwritten extents for completed IO +- * to written. +- * The function return the number of pending IOs on success. +- */ +-int ext4_flush_completed_IO(struct inode *inode) +-{ +- ext4_io_end_t *io; +- struct ext4_inode_info *ei = EXT4_I(inode); +- unsigned long flags; +- int ret = 0; +- int ret2 = 0; +- +- dump_completed_IO(inode); +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- while (!list_empty(&ei->i_completed_io_list)){ +- io = list_entry(ei->i_completed_io_list.next, +- ext4_io_end_t, list); +- list_del_init(&io->list); +- io->flag |= EXT4_IO_END_IN_FSYNC; +- /* +- * Calling ext4_end_io_nolock() to convert completed +- * IO to written. +- * +- * When ext4_sync_file() is called, run_queue() may already +- * about to flush the work corresponding to this io structure. +- * It will be upset if it founds the io structure related +- * to the work-to-be schedule is freed. +- * +- * Thus we need to keep the io structure still valid here after +- * conversion finished. The io structure has a flag to +- * avoid double converting from both fsync and background work +- * queue work. +- */ +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- ret = ext4_end_io_nolock(io); +- if (ret < 0) +- ret2 = ret; +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- io->flag &= ~EXT4_IO_END_IN_FSYNC; +- } +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- return (ret2 < 0) ? ret2 : 0; +-} +- + /* + * If we're not journaling and this is a just-created file, we have to + * sync our parent directory (if it was freshly created) since +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 830e1b2..61f13e5 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -807,11 +807,9 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, + + retry: + if (rw == READ && ext4_should_dioread_nolock(inode)) { +- if (unlikely(!list_empty(&ei->i_completed_io_list))) { +- mutex_lock(&inode->i_mutex); ++ if (unlikely(!list_empty(&ei->i_completed_io_list))) + ext4_flush_completed_IO(inode); +- mutex_unlock(&inode->i_mutex); +- } ++ + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index acadd2b..dd3fd23 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2879,9 +2879,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, + { + struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; + ext4_io_end_t *io_end = iocb->private; +- struct workqueue_struct *wq; +- unsigned long flags; +- struct ext4_inode_info *ei; + + /* if not async direct IO or dio with 0 bytes write, just return */ + if (!io_end || !size) +@@ -2910,24 +2907,14 @@ out: + io_end->iocb = iocb; + io_end->result = ret; + } +- wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; +- +- /* Add the io_end to per-inode completed aio dio list*/ +- ei = EXT4_I(io_end->inode); +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &ei->i_completed_io_list); +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); + +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + } + + static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) + { + ext4_io_end_t *io_end = bh->b_private; +- struct workqueue_struct *wq; + struct inode *inode; +- unsigned long flags; + + if (!test_clear_buffer_uninit(bh) || !io_end) + goto out; +@@ -2946,15 +2933,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) + */ + inode = io_end->inode; + ext4_set_io_unwritten_flag(inode, io_end); +- +- /* Add the io_end to per-inode completed io list*/ +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +- +- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + out: + bh->b_private = NULL; + bh->b_end_io = NULL; +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 9970022..5b24c40 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -71,6 +71,7 @@ void ext4_free_io_end(ext4_io_end_t *io) + int i; + + BUG_ON(!io); ++ BUG_ON(!list_empty(&io->list)); + BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); + + if (io->page) +@@ -83,21 +84,14 @@ void ext4_free_io_end(ext4_io_end_t *io) + kmem_cache_free(io_end_cachep, io); + } + +-/* +- * check a range of space and convert unwritten extents to written. +- * +- * Called with inode->i_mutex; we depend on this when we manipulate +- * io->flag, since we could otherwise race with ext4_flush_completed_IO() +- */ +-int ext4_end_io_nolock(ext4_io_end_t *io) ++/* check a range of space and convert unwritten extents to written. */ ++static int ext4_end_io(ext4_io_end_t *io) + { + struct inode *inode = io->inode; + loff_t offset = io->offset; + ssize_t size = io->size; + int ret = 0; + +- BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); +- + ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," + "list->prev 0x%p\n", + io, inode->i_ino, io->list.next, io->list.prev); +@@ -110,7 +104,6 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + "(inode %lu, offset %llu, size %zd, error %d)", + inode->i_ino, offset, size, ret); + } +- io->flag &= ~EXT4_IO_END_UNWRITTEN; + if (io->iocb) + aio_complete(io->iocb, io->result, 0); + +@@ -122,51 +115,122 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + return ret; + } + +-/* +- * work on completed aio dio IO, to convert unwritten extents to extents +- */ +-static void ext4_end_io_work(struct work_struct *work) ++static void dump_completed_IO(struct inode *inode) ++{ ++#ifdef EXT4FS_DEBUG ++ struct list_head *cur, *before, *after; ++ ext4_io_end_t *io, *io0, *io1; ++ unsigned long flags; ++ ++ if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { ++ ext4_debug("inode %lu completed_io list is empty\n", ++ inode->i_ino); ++ return; ++ } ++ ++ ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); ++ list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { ++ cur = &io->list; ++ before = cur->prev; ++ io0 = container_of(before, ext4_io_end_t, list); ++ after = cur->next; ++ io1 = container_of(after, ext4_io_end_t, list); ++ ++ ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", ++ io, inode->i_ino, io0, io1); ++ } ++#endif ++} ++ ++/* Add the io_end to per-inode completed end_io list. */ ++void ext4_add_complete_io(ext4_io_end_t *io_end) + { +- ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); +- struct inode *inode = io->inode; +- struct ext4_inode_info *ei = EXT4_I(inode); +- unsigned long flags; ++ struct ext4_inode_info *ei = EXT4_I(io_end->inode); ++ struct workqueue_struct *wq; ++ unsigned long flags; ++ ++ BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); ++ wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; + + spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- if (io->flag & EXT4_IO_END_IN_FSYNC) +- goto requeue; +- if (list_empty(&io->list)) { +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- goto free; ++ if (list_empty(&ei->i_completed_io_list)) { ++ io_end->flag |= EXT4_IO_END_QUEUED; ++ queue_work(wq, &io_end->work); + } ++ list_add_tail(&io_end->list, &ei->i_completed_io_list); ++ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); ++} + +- if (!mutex_trylock(&inode->i_mutex)) { +- bool was_queued; +-requeue: +- was_queued = !!(io->flag & EXT4_IO_END_QUEUED); +- io->flag |= EXT4_IO_END_QUEUED; +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- /* +- * Requeue the work instead of waiting so that the work +- * items queued after this can be processed. +- */ +- queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); +- /* +- * To prevent the ext4-dio-unwritten thread from keeping +- * requeueing end_io requests and occupying cpu for too long, +- * yield the cpu if it sees an end_io request that has already +- * been requeued. +- */ +- if (was_queued) +- yield(); +- return; ++static int ext4_do_flush_completed_IO(struct inode *inode, ++ ext4_io_end_t *work_io) ++{ ++ ext4_io_end_t *io; ++ struct list_head unwritten, complete, to_free; ++ unsigned long flags; ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ int err, ret = 0; ++ ++ INIT_LIST_HEAD(&complete); ++ INIT_LIST_HEAD(&to_free); ++ ++ spin_lock_irqsave(&ei->i_completed_io_lock, flags); ++ dump_completed_IO(inode); ++ list_replace_init(&ei->i_completed_io_list, &unwritten); ++ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); ++ ++ while (!list_empty(&unwritten)) { ++ io = list_entry(unwritten.next, ext4_io_end_t, list); ++ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); ++ list_del_init(&io->list); ++ ++ err = ext4_end_io(io); ++ if (unlikely(!ret && err)) ++ ret = err; ++ ++ list_add_tail(&io->list, &complete); ++ } ++ /* It is important to update all flags for all end_io in one shot w/o ++ * dropping the lock.*/ ++ spin_lock_irqsave(&ei->i_completed_io_lock, flags); ++ while (!list_empty(&complete)) { ++ io = list_entry(complete.next, ext4_io_end_t, list); ++ io->flag &= ~EXT4_IO_END_UNWRITTEN; ++ /* end_io context can not be destroyed now because it still ++ * used by queued worker. Worker thread will destroy it later */ ++ if (io->flag & EXT4_IO_END_QUEUED) ++ list_del_init(&io->list); ++ else ++ list_move(&io->list, &to_free); ++ } ++ /* If we are called from worker context, it is time to clear queued ++ * flag, and destroy it's end_io if it was converted already */ ++ if (work_io) { ++ work_io->flag &= ~EXT4_IO_END_QUEUED; ++ if (!(work_io->flag & EXT4_IO_END_UNWRITTEN)) ++ list_add_tail(&work_io->list, &to_free); + } +- list_del_init(&io->list); + spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- (void) ext4_end_io_nolock(io); +- mutex_unlock(&inode->i_mutex); +-free: +- ext4_free_io_end(io); ++ ++ while (!list_empty(&to_free)) { ++ io = list_entry(to_free.next, ext4_io_end_t, list); ++ list_del_init(&io->list); ++ ext4_free_io_end(io); ++ } ++ return ret; ++} ++ ++/* ++ * work on completed aio dio IO, to convert unwritten extents to extents ++ */ ++static void ext4_end_io_work(struct work_struct *work) ++{ ++ ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); ++ ext4_do_flush_completed_IO(io->inode, io); ++} ++ ++int ext4_flush_completed_IO(struct inode *inode) ++{ ++ return ext4_do_flush_completed_IO(inode, NULL); + } + + ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) +@@ -199,9 +263,7 @@ static void buffer_io_error(struct buffer_head *bh) + static void ext4_end_bio(struct bio *bio, int error) + { + ext4_io_end_t *io_end = bio->bi_private; +- struct workqueue_struct *wq; + struct inode *inode; +- unsigned long flags; + int i; + sector_t bi_sector = bio->bi_sector; + +@@ -259,14 +321,7 @@ static void ext4_end_bio(struct bio *bio, int error) + return; + } + +- /* Add the io_end to per-inode completed io list*/ +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +- +- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + } + + void ext4_io_submit(struct ext4_io_submit *io) +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch b/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch new file mode 100644 index 000000000..cf53b8dab --- /dev/null +++ b/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch @@ -0,0 +1,144 @@ +From 994f567b2e99c82913a279ff438269c771b68a4b Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:41:21 -0400 +Subject: [PATCH 05/13] ext4: serialize dio nonlocked reads with defrag + workers + +Inode's block defrag and ext4_change_inode_journal_flag() may +affect nonlocked DIO reads result, so proper synchronization +required. + +- Add missed inode_dio_wait() calls where appropriate +- Check inode state under extra i_dio_count reference. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 17335dcc471199717839b2fa3492ca36f70f1168) + +Conflicts: + fs/ext4/move_extent.c +--- + fs/ext4/ext4.h | 17 +++++++++++++++++ + fs/ext4/indirect.c | 14 ++++++++++++++ + fs/ext4/inode.c | 5 +++++ + fs/ext4/move_extent.c | 8 ++++++++ + 4 files changed, 44 insertions(+) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 7687d15..3e740e9 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1352,6 +1352,8 @@ enum { + EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ + EXT4_STATE_NEWENTRY, /* File just added to dir */ + EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ ++ EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read ++ nolocking */ + }; + + #define EXT4_INODE_BIT_FNS(name, field, offset) \ +@@ -2459,6 +2461,21 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) + set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); + } + ++/* ++ * Disable DIO read nolock optimization, so new dioreaders will be forced ++ * to grab i_mutex ++ */ ++static inline void ext4_inode_block_unlocked_dio(struct inode *inode) ++{ ++ ext4_set_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); ++ smp_mb(); ++} ++static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) ++{ ++ smp_mb(); ++ ext4_clear_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); ++} ++ + #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) + + /* For ioend & aio unwritten conversion wait queues */ +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 61f13e5..8d849da 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -810,11 +810,25 @@ retry: + if (unlikely(!list_empty(&ei->i_completed_io_list))) + ext4_flush_completed_IO(inode); + ++ /* ++ * Nolock dioread optimization may be dynamically disabled ++ * via ext4_inode_block_unlocked_dio(). Check inode's state ++ * while holding extra i_dio_count ref. ++ */ ++ atomic_inc(&inode->i_dio_count); ++ smp_mb(); ++ if (unlikely(ext4_test_inode_state(inode, ++ EXT4_STATE_DIOREAD_LOCK))) { ++ inode_dio_done(inode); ++ goto locked; ++ } + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, + ext4_get_block, NULL, NULL, 0); ++ inode_dio_done(inode); + } else { ++locked: + ret = blockdev_direct_IO(rw, iocb, inode, iov, + offset, nr_segs, ext4_get_block); + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index dd3fd23..2bd7526 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4706,6 +4706,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) + return err; + } + ++ /* Wait for all existing dio workers */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + jbd2_journal_lock_updates(journal); + + /* +@@ -4725,6 +4729,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) + ext4_set_aops(inode); + + jbd2_journal_unlock_updates(journal); ++ ext4_inode_resume_unlocked_dio(inode); + + /* Finally we can mark the inode as dirty. */ + +diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c +index c5826c6..fd1e32e 100644 +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -1214,6 +1214,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, + /* Protect orig and donor inodes against a truncate */ + mext_inode_double_lock(orig_inode, donor_inode); + ++ /* Wait for all existing dio workers */ ++ ext4_inode_block_unlocked_dio(orig_inode); ++ ext4_inode_block_unlocked_dio(donor_inode); ++ inode_dio_wait(orig_inode); ++ inode_dio_wait(donor_inode); ++ + /* Protect extent tree against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); + /* Check the filesystem environment whether move_extent can be done */ +@@ -1413,6 +1419,8 @@ out: + kfree(holecheck_path); + } + double_up_write_data_sem(orig_inode, donor_inode); ++ ext4_inode_resume_unlocked_dio(orig_inode); ++ ext4_inode_resume_unlocked_dio(donor_inode); + mext_inode_double_unlock(orig_inode, donor_inode); + + return ret; +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch b/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch new file mode 100644 index 000000000..bddcc6024 --- /dev/null +++ b/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch @@ -0,0 +1,65 @@ +From 4c4679fc02744ec3955e88faf5e8b6844fa8cbd3 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:55:23 -0400 +Subject: [PATCH 06/13] ext4: serialize unlocked dio reads with truncate + +Current serialization will works only for DIO which holds +i_mutex, but nonlocked DIO following race is possible: + +dio_nolock_read_task truncate_task + ->ext4_setattr() + ->inode_dio_wait() +->ext4_ext_direct_IO + ->ext4_ind_direct_IO + ->__blockdev_direct_IO + ->ext4_get_block + ->truncate_setsize() + ->ext4_truncate() + #alloc truncated blocks + #to other inode + ->submit_io() + #INFORMATION LEAK + +In order to serialize with unlocked DIO reads we have to +rearrange wait sequence +1) update i_size first +2) if i_size about to be reduced wait for outstanding DIO requests +3) and only after that truncate inode blocks + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1c9114f9c0f10f58dd7e568a7152025af47b27e5) +--- + fs/ext4/inode.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 2bd7526..b84322d 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4277,7 +4277,6 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } + + if (attr->ia_valid & ATTR_SIZE) { +- inode_dio_wait(inode); + + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); +@@ -4326,8 +4325,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } + + if (attr->ia_valid & ATTR_SIZE) { +- if (attr->ia_size != i_size_read(inode)) ++ if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); ++ /* Inode size will be reduced, wait for dio in flight */ ++ if (orphan) ++ inode_dio_wait(inode); ++ } + ext4_truncate(inode); + } + +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch b/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch new file mode 100644 index 000000000..768215f48 --- /dev/null +++ b/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch @@ -0,0 +1,41 @@ +From ab7b8a329e12369d58e5fa59ba2e2c90370f12ef Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:56:15 -0400 +Subject: [PATCH 07/13] ext4: endless truncate due to nonlocked dio readers + +If we have enough aggressive DIO readers, truncate and other dio +waiters will wait forever inside inode_dio_wait(). It is reasonable +to disable nonlock DIO read optimization during truncate. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1b65007e9870e0021397b548e8cd6bbc584f9152) +--- + fs/ext4/inode.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b84322d..3b03dd6 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4327,9 +4327,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + if (attr->ia_valid & ATTR_SIZE) { + if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); +- /* Inode size will be reduced, wait for dio in flight */ +- if (orphan) ++ /* Inode size will be reduced, wait for dio in flight. ++ * Temporarily disable dioread_nolock to prevent ++ * livelock. */ ++ if (orphan) { ++ ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); ++ ext4_inode_resume_unlocked_dio(inode); ++ } + } + ext4_truncate(inode); + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch b/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch new file mode 100644 index 000000000..c7733ed74 --- /dev/null +++ b/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch @@ -0,0 +1,61 @@ +From 69e4026a2d104ffcf1b935bc889f8abcbfbb29ec Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:58:26 -0400 +Subject: [PATCH 08/13] ext4: serialize truncate with owerwrite DIO workers + +Jan Kara have spotted interesting issue: +There are potential data corruption issue with direct IO overwrites +racing with truncate: + Like: + dio write truncate_task + ->ext4_ext_direct_IO + ->overwrite == 1 + ->down_read(&EXT4_I(inode)->i_data_sem); + ->mutex_unlock(&inode->i_mutex); + ->ext4_setattr() + ->inode_dio_wait() + ->truncate_setsize() + ->ext4_truncate() + ->down_write(&EXT4_I(inode)->i_data_sem); + ->__blockdev_direct_IO + ->ext4_get_block + ->submit_io() + ->up_read(&EXT4_I(inode)->i_data_sem); + # truncate data blocks, allocate them to + # other inode - bad stuff happens because + # dio is still in flight. + +In order to serialize with truncate dio worker should grab extra i_dio_count +reference before drop i_mutex. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1f555cfa29e8f787d675e8390f88ce517a37271a) +--- + fs/ext4/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 3b03dd6..484a327 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3008,6 +3008,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + overwrite = *((int *)iocb->private); + + if (overwrite) { ++ atomic_inc(&inode->i_dio_count); + down_read(&EXT4_I(inode)->i_data_sem); + mutex_unlock(&inode->i_mutex); + } +@@ -3105,6 +3106,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + retake_lock: + /* take i_mutex locking again if we do a ovewrite dio */ + if (overwrite) { ++ inode_dio_done(inode); + up_read(&EXT4_I(inode)->i_data_sem); + mutex_lock(&inode->i_mutex); + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch b/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch new file mode 100644 index 000000000..4d7636668 --- /dev/null +++ b/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch @@ -0,0 +1,125 @@ +From 71a6398a4b59ddcf920dfb68872b5a771c606e3a Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sun, 30 Sep 2012 23:03:42 -0400 +Subject: [PATCH 09/13] ext4: punch_hole should wait for DIO writers + +punch_hole is the place where we have to wait for all existing writers +(writeback, aio, dio), but currently we simply flush pended end_io request +which is not sufficient. Other issue is that punch_hole performed w/o i_mutex +held which obviously result in dangerous data corruption due to +write-after-free. + +This patch performs following changes: +- Guard punch_hole with i_mutex +- Recheck inode flags under i_mutex +- Block all new dio readers in order to prevent information leak caused by + read-after-free pattern. +- punch_hole now wait for all writers in flight + NOTE: XXX write-after-free race is still possible because new dirty pages + may appear due to mmap(), and currently there is no easy way to stop + writeback while punch_hole is in progress. + +[ Fixed error return from ext4_ext_punch_hole() to make sure that we + release i_mutex before returning EPERM or ETXTBUSY -- Ted ] + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 02d262dffcf4c74e5c4612ee736bdb94f18ed5b9) +--- + fs/ext4/extents.c | 53 ++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 17 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 1fbf2ff..202eb4d 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4776,9 +4776,32 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + loff_t first_page_offset, last_page_offset; + int credits, err = 0; + ++ /* ++ * Write out all dirty pages to avoid race conditions ++ * Then release them. ++ */ ++ if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { ++ err = filemap_write_and_wait_range(mapping, ++ offset, offset + length - 1); ++ ++ if (err) ++ return err; ++ } ++ ++ mutex_lock(&inode->i_mutex); ++ /* It's not possible punch hole on append only file */ ++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { ++ err = -EPERM; ++ goto out_mutex; ++ } ++ if (IS_SWAPFILE(inode)) { ++ err = -ETXTBSY; ++ goto out_mutex; ++ } ++ + /* No need to punch hole beyond i_size */ + if (offset >= inode->i_size) +- return 0; ++ goto out_mutex; + + /* + * If the hole extends beyond i_size, set the hole +@@ -4796,33 +4819,25 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + first_page_offset = first_page << PAGE_CACHE_SHIFT; + last_page_offset = last_page << PAGE_CACHE_SHIFT; + +- /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- err = filemap_write_and_wait_range(mapping, +- offset, offset + length - 1); +- +- if (err) +- return err; +- } +- + /* Now release the pages */ + if (last_page_offset > first_page_offset) { + truncate_pagecache_range(inode, first_page_offset, + last_page_offset - 1); + } + +- /* finish any pending end_io work */ ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); + err = ext4_flush_completed_IO(inode); + if (err) +- return err; ++ goto out_dio; + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ err = PTR_ERR(handle); ++ goto out_dio; ++ } + + err = ext4_orphan_add(handle, inode); + if (err) +@@ -4916,6 +4931,10 @@ out: + inode->i_mtime = inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); ++out_dio: ++ ext4_inode_resume_unlocked_dio(inode); ++out_mutex: ++ mutex_unlock(&inode->i_mutex); + return err; + } + int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch b/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch new file mode 100644 index 000000000..d161bb765 --- /dev/null +++ b/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch @@ -0,0 +1,60 @@ +From 66d08dd92b82dabfd64853aa4edde1547fdf9ef7 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sun, 30 Sep 2012 23:03:50 -0400 +Subject: [PATCH 10/13] ext4: fix ext_remove_space for punch_hole case + +Inode is allowed to have empty leaf only if it this is blockless inode. + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 6f2080e64487b9963f9c6ff8a252e1abce98f2d4) +--- + fs/ext4/extents.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 202eb4d..b1c92c0 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2572,7 +2572,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, + struct ext4_ext_path *path = NULL; + ext4_fsblk_t partial_cluster = 0; + handle_t *handle; +- int i = 0, err; ++ int i = 0, err = 0; + + ext_debug("truncate since %u to %u\n", start, end); + +@@ -2604,12 +2604,16 @@ again: + return PTR_ERR(path); + } + depth = ext_depth(inode); ++ /* Leaf not may not exist only if inode has no blocks at all */ + ex = path[depth].p_ext; + if (!ex) { +- ext4_ext_drop_refs(path); +- kfree(path); +- path = NULL; +- goto cont; ++ if (depth) { ++ EXT4_ERROR_INODE(inode, ++ "path[%d].p_hdr == NULL", ++ depth); ++ err = -EIO; ++ } ++ goto out; + } + + ee_block = le32_to_cpu(ex->ee_block); +@@ -2641,8 +2645,6 @@ again: + goto out; + } + } +-cont: +- + /* + * We start scanning from right side, freeing all the blocks + * after i_size and walking into the tree depth-wise. +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch b/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch new file mode 100644 index 000000000..517b20129 --- /dev/null +++ b/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch @@ -0,0 +1,176 @@ +From ca6d3910cbf8854f3f3b9846391f669733899101 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:31:55 -0400 +Subject: [PATCH 11/13] ext4: fix ext4_flush_completed_IO wait semantics + +BUG #1) All places where we call ext4_flush_completed_IO are broken + because buffered io and DIO/AIO goes through three stages + 1) submitted io, + 2) completed io (in i_completed_io_list) conversion pended + 3) finished io (conversion done) + And by calling ext4_flush_completed_IO we will flush only + requests which were in (2) stage, which is wrong because: + 1) punch_hole and truncate _must_ wait for all outstanding unwritten io + regardless to it's state. + 2) fsync and nolock_dio_read should also wait because there is + a time window between end_page_writeback() and ext4_add_complete_io() + As result integrity fsync is broken in case of buffered write + to fallocated region: + fsync blkdev_completion + ->filemap_write_and_wait_range + ->ext4_end_bio + ->end_page_writeback + <-- filemap_write_and_wait_range return + ->ext4_flush_completed_IO + sees empty i_completed_io_list but pended + conversion still exist + ->ext4_add_complete_io + +BUG #2) Race window becomes wider due to the 'ext4: completed_io +locking cleanup V4' patch series + +This patch make following changes: +1) ext4_flush_completed_io() now first try to flush completed io and when + wait for any outstanding unwritten io via ext4_unwritten_wait() +2) Rename function to more appropriate name. +3) Assert that all callers of ext4_flush_unwritten_io should hold i_mutex to + prevent endless wait + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Jan Kara +(cherry picked from commit c278531d39f3158bfee93dc67da0b77e09776de2) +--- + fs/ext4/ext4.h | 3 ++- + fs/ext4/extents.c | 6 +++--- + fs/ext4/file.c | 2 +- + fs/ext4/fsync.c | 2 +- + fs/ext4/indirect.c | 8 +++++--- + fs/ext4/page-io.c | 11 +++++++---- + 6 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 3e740e9..7f13292 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1941,7 +1941,7 @@ extern void ext4_htree_free_dir_info(struct dir_private_info *p); + + /* fsync.c */ + extern int ext4_sync_file(struct file *, loff_t, loff_t, int); +-extern int ext4_flush_completed_IO(struct inode *); ++extern int ext4_flush_unwritten_io(struct inode *); + + /* hash.c */ + extern int ext4fs_dirhash(const char *name, int len, struct +@@ -2361,6 +2361,7 @@ extern const struct file_operations ext4_dir_operations; + extern const struct inode_operations ext4_file_inode_operations; + extern const struct file_operations ext4_file_operations; + extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); ++extern void ext4_unwritten_wait(struct inode *inode); + + /* namei.c */ + extern const struct inode_operations ext4_dir_inode_operations; +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index b1c92c0..37f46eb 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4250,7 +4250,7 @@ void ext4_ext_truncate(struct inode *inode) + * finish any pending end_io work so we won't run the risk of + * converting any truncated blocks to initialized later + */ +- ext4_flush_completed_IO(inode); ++ ext4_flush_unwritten_io(inode); + + /* + * probably first extent we're gonna free will be last in block +@@ -4829,10 +4829,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + + /* Wait all existing dio workers, newcomers will block on i_mutex */ + ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- err = ext4_flush_completed_IO(inode); ++ err = ext4_flush_unwritten_io(inode); + if (err) + goto out_dio; ++ inode_dio_wait(inode); + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 39335bd..ca6f07a 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -55,7 +55,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) + return 0; + } + +-static void ext4_unwritten_wait(struct inode *inode) ++void ext4_unwritten_wait(struct inode *inode) + { + wait_queue_head_t *wq = ext4_ioend_wq(inode); + +diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c +index 520b058..76051c6 100644 +--- a/fs/ext4/fsync.c ++++ b/fs/ext4/fsync.c +@@ -138,7 +138,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + if (inode->i_sb->s_flags & MS_RDONLY) + goto out; + +- ret = ext4_flush_completed_IO(inode); ++ ret = ext4_flush_unwritten_io(inode); + if (ret < 0) + goto out; + +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 8d849da..792e388 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -807,9 +807,11 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, + + retry: + if (rw == READ && ext4_should_dioread_nolock(inode)) { +- if (unlikely(!list_empty(&ei->i_completed_io_list))) +- ext4_flush_completed_IO(inode); +- ++ if (unlikely(atomic_read(&EXT4_I(inode)->i_unwritten))) { ++ mutex_lock(&inode->i_mutex); ++ ext4_flush_unwritten_io(inode); ++ mutex_unlock(&inode->i_mutex); ++ } + /* + * Nolock dioread optimization may be dynamically disabled + * via ext4_inode_block_unlocked_dio(). Check inode's state +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 5b24c40..68e896e 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -189,8 +189,6 @@ static int ext4_do_flush_completed_IO(struct inode *inode, + + list_add_tail(&io->list, &complete); + } +- /* It is important to update all flags for all end_io in one shot w/o +- * dropping the lock.*/ + spin_lock_irqsave(&ei->i_completed_io_lock, flags); + while (!list_empty(&complete)) { + io = list_entry(complete.next, ext4_io_end_t, list); +@@ -228,9 +226,14 @@ static void ext4_end_io_work(struct work_struct *work) + ext4_do_flush_completed_IO(io->inode, io); + } + +-int ext4_flush_completed_IO(struct inode *inode) ++int ext4_flush_unwritten_io(struct inode *inode) + { +- return ext4_do_flush_completed_IO(inode, NULL); ++ int ret; ++ WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && ++ !(inode->i_state & I_FREEING)); ++ ret = ext4_do_flush_completed_IO(inode, NULL); ++ ext4_unwritten_wait(inode); ++ return ret; + } + + ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch b/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch new file mode 100644 index 000000000..3fcaef1f2 --- /dev/null +++ b/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch @@ -0,0 +1,46 @@ +From 9f00d109efeaf4d12d56c8e46cd13af80e344f97 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:32:02 -0400 +Subject: [PATCH 12/13] ext4: serialize fallocate with + ext4_convert_unwritten_extents + +Fallocate should wait for pended ext4_convert_unwritten_extents() +otherwise following race may happen: + +ftruncate( ,12288); +fallocate( ,0, 4096) +io_sibmit( ,0, 4096); /* Write to fallocated area, split extent if needed */ +fallocate( ,0, 8192); /* Grow extent and broke assumption about extent */ + +Later kwork completion will do: + ->ext4_convert_unwritten_extents (0, 4096) + ->ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_IO_CONVERT_EXT); + ->ext4_ext_map_blocks() /* Will find new extent: ex = [0,2] !!!!!! */ + ->ext4_ext_handle_uninitialized_extents() + ->ext4_convert_unwritten_extents_endio() + /* convert [0,2] extent to initialized, but only[0,1] was written */ + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 60d4616f3dc63371b3dc367e5e88fd4b4f037f65) +--- + fs/ext4/extents.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 37f46eb..ea2db86 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4410,6 +4410,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) + */ + if (len <= EXT_UNINIT_MAX_LEN << blkbits) + flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; ++ ++ /* Prevent race condition between unwritten */ ++ ext4_flush_unwritten_io(inode); + retry: + while (ret >= 0 && ret < max_blocks) { + map.m_lblk = map.m_lblk + ret; +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch b/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch new file mode 100644 index 000000000..ffd7975c6 --- /dev/null +++ b/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch @@ -0,0 +1,153 @@ +From 5ff6b4cc64765e10df509a60e902561efdeb58d5 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:32:04 -0400 +Subject: [PATCH 13/13] ext4: race-condition protection for + ext4_convert_unwritten_extents_endio + +We assumed that at the time we call ext4_convert_unwritten_extents_endio() +extent in question is fully inside [map.m_lblk, map->m_len] because +it was already split during submission. But this may not be true due to +a race between writeback vs fallocate. + +If extent in question is larger than requested we will split it again. +Special precautions should being done if zeroout required because +[map.m_lblk, map->m_len] already contains valid data. + +Signed-off-by: Dmitry Monakhov +(cherry picked from commit 0d4b4ff5282d07a4f83b87b3117cd898b0a3f673) +--- + fs/ext4/extents.c | 57 ++++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 46 insertions(+), 11 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index ea2db86..ee0d61c 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -52,6 +52,9 @@ + #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ + #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ + ++#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ ++#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ ++ + static __le32 ext4_extent_block_csum(struct inode *inode, + struct ext4_extent_header *eh) + { +@@ -2897,6 +2900,9 @@ static int ext4_split_extent_at(handle_t *handle, + unsigned int ee_len, depth; + int err = 0; + ++ BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == ++ (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); ++ + ext_debug("ext4_split_extents_at: inode %lu, logical" + "block %llu\n", inode->i_ino, (unsigned long long)split); + +@@ -2955,7 +2961,14 @@ static int ext4_split_extent_at(handle_t *handle, + + err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); + if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { +- err = ext4_ext_zeroout(inode, &orig_ex); ++ if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { ++ if (split_flag & EXT4_EXT_DATA_VALID1) ++ err = ext4_ext_zeroout(inode, ex2); ++ else ++ err = ext4_ext_zeroout(inode, ex); ++ } else ++ err = ext4_ext_zeroout(inode, &orig_ex); ++ + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ +@@ -3008,12 +3021,13 @@ static int ext4_split_extent(handle_t *handle, + uninitialized = ext4_ext_is_uninitialized(ex); + + if (map->m_lblk + map->m_len < ee_block + ee_len) { +- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? +- EXT4_EXT_MAY_ZEROOUT : 0; ++ split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; + flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; + if (uninitialized) + split_flag1 |= EXT4_EXT_MARK_UNINIT1 | + EXT4_EXT_MARK_UNINIT2; ++ if (split_flag & EXT4_EXT_DATA_VALID2) ++ split_flag1 |= EXT4_EXT_DATA_VALID1; + err = ext4_split_extent_at(handle, inode, path, + map->m_lblk + map->m_len, split_flag1, flags1); + if (err) +@@ -3026,8 +3040,8 @@ static int ext4_split_extent(handle_t *handle, + return PTR_ERR(path); + + if (map->m_lblk >= ee_block) { +- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? +- EXT4_EXT_MAY_ZEROOUT : 0; ++ split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | ++ EXT4_EXT_DATA_VALID2); + if (uninitialized) + split_flag1 |= EXT4_EXT_MARK_UNINIT1; + if (split_flag & EXT4_EXT_MARK_UNINIT2) +@@ -3305,26 +3319,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, + + split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; + split_flag |= EXT4_EXT_MARK_UNINIT2; +- ++ if (flags & EXT4_GET_BLOCKS_CONVERT) ++ split_flag |= EXT4_EXT_DATA_VALID2; + flags |= EXT4_GET_BLOCKS_PRE_IO; + return ext4_split_extent(handle, inode, path, map, split_flag, flags); + } + + static int ext4_convert_unwritten_extents_endio(handle_t *handle, +- struct inode *inode, +- struct ext4_ext_path *path) ++ struct inode *inode, ++ struct ext4_map_blocks *map, ++ struct ext4_ext_path *path) + { + struct ext4_extent *ex; ++ ext4_lblk_t ee_block; ++ unsigned int ee_len; + int depth; + int err = 0; + + depth = ext_depth(inode); + ex = path[depth].p_ext; ++ ee_block = le32_to_cpu(ex->ee_block); ++ ee_len = ext4_ext_get_actual_len(ex); + + ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" + "block %llu, max_blocks %u\n", inode->i_ino, +- (unsigned long long)le32_to_cpu(ex->ee_block), +- ext4_ext_get_actual_len(ex)); ++ (unsigned long long)ee_block, ee_len); ++ ++ /* If extent is larger than requested then split is required */ ++ if (ee_block != map->m_lblk || ee_len > map->m_len) { ++ err = ext4_split_unwritten_extents(handle, inode, map, path, ++ EXT4_GET_BLOCKS_CONVERT); ++ if (err < 0) ++ goto out; ++ ext4_ext_drop_refs(path); ++ path = ext4_ext_find_extent(inode, map->m_lblk, path); ++ if (IS_ERR(path)) { ++ err = PTR_ERR(path); ++ goto out; ++ } ++ depth = ext_depth(inode); ++ ex = path[depth].p_ext; ++ } + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) +@@ -3634,7 +3669,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + } + /* IO end_io complete, convert the filled extent to written */ + if ((flags & EXT4_GET_BLOCKS_CONVERT)) { +- ret = ext4_convert_unwritten_extents_endio(handle, inode, ++ ret = ext4_convert_unwritten_extents_endio(handle, inode, map, + path); + if (ret >= 0) { + ext4_update_inode_fsync_trans(handle, inode, 1); +-- +1.7.12.rc0.22.gcdd159b + diff --git a/kernel.spec b/kernel.spec index c1ae25377..9ce042ea9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,21 @@ Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch #rhbz 852210 Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch +#rhbz 869904 869909 CVE-2012-4508 +Patch22080: 0001-ext4-ext4_inode_info-diet.patch +Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +Patch22082: 0003-ext4-fix-unwritten-counter-leakage.patch +Patch22083: 0004-ext4-completed_io-locking-cleanup.patch +Patch22084: 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +Patch22085: 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +Patch22086: 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +Patch22087: 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +Patch22092: 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch + # END OF PATCH DEFINITIONS %endif @@ -1508,6 +1523,21 @@ ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch #rhbz 852210 ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch +#rhbz 869904 869909 CVE-2012-4508 +ApplyPatch 0001-ext4-ext4_inode_info-diet.patch +ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +ApplyPatch 0003-ext4-fix-unwritten-counter-leakage.patch +ApplyPatch 0004-ext4-completed_io-locking-cleanup.patch +ApplyPatch 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +ApplyPatch 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +ApplyPatch 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +ApplyPatch 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +ApplyPatch 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch + # END OF PATCH APPLICATIONS %endif @@ -2360,6 +2390,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 25 2012 Justin M. Forbes +- CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) + * Wed Oct 24 2012 Josh Boyer - Remove patch added for rhbz 856863 - Add patch to fix corrupted text with i915 (rhbz 852210) From a0a8db50e5d801bf3fd2dad3681d8031bda4da3f Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 29 Oct 2012 08:57:00 -0500 Subject: [PATCH 083/492] Linux 3.6.4 --- ...ion-protection-for-ext4_convert_unwr.patch | 153 ------------------ ...-relocations-if-the-object-is-in-the.patch | 33 ---- ...tack-memory-content-leak-via-UNAME26.patch | 98 ----------- kernel.spec | 21 +-- sources | 2 +- 5 files changed, 6 insertions(+), 301 deletions(-) delete mode 100644 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch delete mode 100644 drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch delete mode 100644 fix-stack-memory-content-leak-via-UNAME26.patch diff --git a/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch b/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch deleted file mode 100644 index ffd7975c6..000000000 --- a/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 5ff6b4cc64765e10df509a60e902561efdeb58d5 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 5 Oct 2012 11:32:04 -0400 -Subject: [PATCH 13/13] ext4: race-condition protection for - ext4_convert_unwritten_extents_endio - -We assumed that at the time we call ext4_convert_unwritten_extents_endio() -extent in question is fully inside [map.m_lblk, map->m_len] because -it was already split during submission. But this may not be true due to -a race between writeback vs fallocate. - -If extent in question is larger than requested we will split it again. -Special precautions should being done if zeroout required because -[map.m_lblk, map->m_len] already contains valid data. - -Signed-off-by: Dmitry Monakhov -(cherry picked from commit 0d4b4ff5282d07a4f83b87b3117cd898b0a3f673) ---- - fs/ext4/extents.c | 57 ++++++++++++++++++++++++++++++++++++++++++++----------- - 1 file changed, 46 insertions(+), 11 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index ea2db86..ee0d61c 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -52,6 +52,9 @@ - #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ - #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ - -+#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ -+#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ -+ - static __le32 ext4_extent_block_csum(struct inode *inode, - struct ext4_extent_header *eh) - { -@@ -2897,6 +2900,9 @@ static int ext4_split_extent_at(handle_t *handle, - unsigned int ee_len, depth; - int err = 0; - -+ BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == -+ (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); -+ - ext_debug("ext4_split_extents_at: inode %lu, logical" - "block %llu\n", inode->i_ino, (unsigned long long)split); - -@@ -2955,7 +2961,14 @@ static int ext4_split_extent_at(handle_t *handle, - - err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); - if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { -- err = ext4_ext_zeroout(inode, &orig_ex); -+ if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { -+ if (split_flag & EXT4_EXT_DATA_VALID1) -+ err = ext4_ext_zeroout(inode, ex2); -+ else -+ err = ext4_ext_zeroout(inode, ex); -+ } else -+ err = ext4_ext_zeroout(inode, &orig_ex); -+ - if (err) - goto fix_extent_len; - /* update the extent length and mark as initialized */ -@@ -3008,12 +3021,13 @@ static int ext4_split_extent(handle_t *handle, - uninitialized = ext4_ext_is_uninitialized(ex); - - if (map->m_lblk + map->m_len < ee_block + ee_len) { -- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? -- EXT4_EXT_MAY_ZEROOUT : 0; -+ split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; - flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; - if (uninitialized) - split_flag1 |= EXT4_EXT_MARK_UNINIT1 | - EXT4_EXT_MARK_UNINIT2; -+ if (split_flag & EXT4_EXT_DATA_VALID2) -+ split_flag1 |= EXT4_EXT_DATA_VALID1; - err = ext4_split_extent_at(handle, inode, path, - map->m_lblk + map->m_len, split_flag1, flags1); - if (err) -@@ -3026,8 +3040,8 @@ static int ext4_split_extent(handle_t *handle, - return PTR_ERR(path); - - if (map->m_lblk >= ee_block) { -- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? -- EXT4_EXT_MAY_ZEROOUT : 0; -+ split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | -+ EXT4_EXT_DATA_VALID2); - if (uninitialized) - split_flag1 |= EXT4_EXT_MARK_UNINIT1; - if (split_flag & EXT4_EXT_MARK_UNINIT2) -@@ -3305,26 +3319,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, - - split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; - split_flag |= EXT4_EXT_MARK_UNINIT2; -- -+ if (flags & EXT4_GET_BLOCKS_CONVERT) -+ split_flag |= EXT4_EXT_DATA_VALID2; - flags |= EXT4_GET_BLOCKS_PRE_IO; - return ext4_split_extent(handle, inode, path, map, split_flag, flags); - } - - static int ext4_convert_unwritten_extents_endio(handle_t *handle, -- struct inode *inode, -- struct ext4_ext_path *path) -+ struct inode *inode, -+ struct ext4_map_blocks *map, -+ struct ext4_ext_path *path) - { - struct ext4_extent *ex; -+ ext4_lblk_t ee_block; -+ unsigned int ee_len; - int depth; - int err = 0; - - depth = ext_depth(inode); - ex = path[depth].p_ext; -+ ee_block = le32_to_cpu(ex->ee_block); -+ ee_len = ext4_ext_get_actual_len(ex); - - ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" - "block %llu, max_blocks %u\n", inode->i_ino, -- (unsigned long long)le32_to_cpu(ex->ee_block), -- ext4_ext_get_actual_len(ex)); -+ (unsigned long long)ee_block, ee_len); -+ -+ /* If extent is larger than requested then split is required */ -+ if (ee_block != map->m_lblk || ee_len > map->m_len) { -+ err = ext4_split_unwritten_extents(handle, inode, map, path, -+ EXT4_GET_BLOCKS_CONVERT); -+ if (err < 0) -+ goto out; -+ ext4_ext_drop_refs(path); -+ path = ext4_ext_find_extent(inode, map->m_lblk, path); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ goto out; -+ } -+ depth = ext_depth(inode); -+ ex = path[depth].p_ext; -+ } - - err = ext4_ext_get_access(handle, inode, path + depth); - if (err) -@@ -3634,7 +3669,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, - } - /* IO end_io complete, convert the filled extent to written */ - if ((flags & EXT4_GET_BLOCKS_CONVERT)) { -- ret = ext4_convert_unwritten_extents_endio(handle, inode, -+ ret = ext4_convert_unwritten_extents_endio(handle, inode, map, - path); - if (ret >= 0) { - ext4_update_inode_fsync_trans(handle, inode, 1); --- -1.7.12.rc0.22.gcdd159b - diff --git a/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch b/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch deleted file mode 100644 index 0e282bf04..000000000 --- a/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Thu, 23 Aug 2012 13:12:52 +0100 -Subject: [PATCH] drm/i915: Use cpu relocations if the object is in the GTT - but not mappable - -This prevents the case of unbinding the object in order to process the -relocations through the GTT and then rebinding it only to then proceed -to use cpu relocations as the object is now in the CPU write domain. By -choosing to use cpu relocations up front, we can therefore avoid the -rebind penalty. - -Signed-off-by: Chris Wilson -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -index f7346d8..dc87563 100644 ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -95,6 +95,7 @@ eb_destroy(struct eb_objects *eb) - static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) - { - return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || -+ !obj->map_and_fenceable || - obj->cache_level != I915_CACHE_NONE); - } - --- -1.7.12.1 - diff --git a/fix-stack-memory-content-leak-via-UNAME26.patch b/fix-stack-memory-content-leak-via-UNAME26.patch deleted file mode 100644 index 5121ca06b..000000000 --- a/fix-stack-memory-content-leak-via-UNAME26.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 2702b1526c7278c4d65d78de209a465d4de2885e Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Fri, 19 Oct 2012 13:56:51 -0700 -Subject: [PATCH 1/2] kernel/sys.c: fix stack memory content leak via UNAME26 - -Calling uname() with the UNAME26 personality set allows a leak of kernel -stack contents. This fixes it by defensively calculating the length of -copy_to_user() call, making the len argument unsigned, and initializing -the stack buffer to zero (now technically unneeded, but hey, overkill). - -CVE-2012-0957 - -Reported-by: PaX Team -Signed-off-by: Kees Cook -Cc: Andi Kleen -Cc: PaX Team -Cc: Brad Spengler -Cc: -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - kernel/sys.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/kernel/sys.c b/kernel/sys.c -index c5cb5b9..01865c6 100644 ---- a/kernel/sys.c -+++ b/kernel/sys.c -@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem); - * Work around broken programs that cannot handle "Linux 3.0". - * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 - */ --static int override_release(char __user *release, int len) -+static int override_release(char __user *release, size_t len) - { - int ret = 0; -- char buf[65]; - - if (current->personality & UNAME26) { -- char *rest = UTS_RELEASE; -+ const char *rest = UTS_RELEASE; -+ char buf[65] = { 0 }; - int ndots = 0; - unsigned v; -+ size_t copy; - - while (*rest) { - if (*rest == '.' && ++ndots >= 3) -@@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len) - rest++; - } - v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; -- snprintf(buf, len, "2.6.%u%s", v, rest); -- ret = copy_to_user(release, buf, len); -+ copy = min(sizeof(buf), max_t(size_t, 1, len)); -+ copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); -+ ret = copy_to_user(release, buf, copy + 1); - } - return ret; - } --- -1.7.12.1 - - -From 31fd84b95eb211d5db460a1dda85e004800a7b52 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Fri, 19 Oct 2012 18:45:53 -0700 -Subject: [PATCH 2/2] use clamp_t in UNAME26 fix - -The min/max call needed to have explicit types on some architectures -(e.g. mn10300). Use clamp_t instead to avoid the warning: - - kernel/sys.c: In function 'override_release': - kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default] - -Reported-by: Fengguang Wu -Signed-off-by: Kees Cook -Signed-off-by: Linus Torvalds ---- - kernel/sys.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kernel/sys.c b/kernel/sys.c -index 01865c6..e6e0ece 100644 ---- a/kernel/sys.c -+++ b/kernel/sys.c -@@ -1284,7 +1284,7 @@ static int override_release(char __user *release, size_t len) - rest++; - } - v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; -- copy = min(sizeof(buf), max_t(size_t, 1, len)); -+ copy = clamp_t(size_t, len, 1, sizeof(buf)); - copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); - ret = copy_to_user(release, buf, copy + 1); - } --- -1.7.12.1 - diff --git a/kernel.spec b/kernel.spec index 9ce042ea9..16dfe9b5c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -770,15 +770,9 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 862877 864824 CVE-2012-0957 -Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch - #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch -#rhbz 852210 -Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch - #rhbz 869904 869909 CVE-2012-4508 Patch22080: 0001-ext4-ext4_inode_info-diet.patch Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -792,7 +786,6 @@ Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -Patch22092: 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch # END OF PATCH DEFINITIONS @@ -1514,15 +1507,9 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 862877 864824 CVE-2012-0957 -ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch - #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch -#rhbz 852210 -ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch - #rhbz 869904 869909 CVE-2012-4508 ApplyPatch 0001-ext4-ext4_inode_info-diet.patch ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -1536,7 +1523,6 @@ ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -ApplyPatch 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch # END OF PATCH APPLICATIONS @@ -2390,6 +2376,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 29 2012 Justin M. Forbes 3.6.4-1 +- Linux 3.6.4 + * Thu Oct 25 2012 Justin M. Forbes - CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) diff --git a/sources b/sources index 8c5ed1c19..965397c16 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -96701113d37ef4f9b785206ab8bcc71e patch-3.6.3.xz +d7efab4da2682c44662b684026b059f7 patch-3.6.4.xz From 39c7bf392f92af6bd430f8b9db2936f56254666f Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 29 Oct 2012 18:04:05 +0000 Subject: [PATCH 084/492] Update ARM alignment patch to upstream --- arm-alignment-faults.patch | 127 ++++++++++++++++++ ...missaligned-access-check-on-put_user.patch | 83 ------------ config-arm-generic | 3 - kernel.spec | 7 +- 4 files changed, 132 insertions(+), 88 deletions(-) create mode 100644 arm-alignment-faults.patch delete mode 100644 arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch diff --git a/arm-alignment-faults.patch b/arm-alignment-faults.patch new file mode 100644 index 000000000..d386a5c3e --- /dev/null +++ b/arm-alignment-faults.patch @@ -0,0 +1,127 @@ + arch/arm/kernel/traps.c | 34 +++++++--------------------------- + arch/arm/mm/alignment.c | 11 ++++------- + 2 files changed, 11 insertions(+), 34 deletions(-) + +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index b0179b8..62f429e 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -89,17 +89,8 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, + unsigned long top) + { + unsigned long first; +- mm_segment_t fs; + int i; + +- /* +- * We need to switch to kernel mode so that we can use __get_user +- * to safely read from kernel space. Note that we now dump the +- * code first, just in case the backtrace kills us. +- */ +- fs = get_fs(); +- set_fs(KERNEL_DS); +- + printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top); + + for (first = bottom & ~31; first < top; first += 32) { +@@ -112,7 +103,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, + for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { + if (p >= bottom && p < top) { + unsigned long val; +- if (__get_user(val, (unsigned long *)p) == 0) ++ if (probe_kernel_address(p, val) == 0) + sprintf(str + i * 9, " %08lx", val); + else + sprintf(str + i * 9, " ????????"); +@@ -120,8 +111,6 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, + } + printk("%s%04lx:%s\n", lvl, first & 0xffff, str); + } +- +- set_fs(fs); + } + + static void dump_instr(const char *lvl, struct pt_regs *regs) +@@ -129,25 +118,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) + unsigned long addr = instruction_pointer(regs); + const int thumb = thumb_mode(regs); + const int width = thumb ? 4 : 8; +- mm_segment_t fs; + char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; + int i; + +- /* +- * We need to switch to kernel mode so that we can use __get_user +- * to safely read from kernel space. Note that we now dump the +- * code first, just in case the backtrace kills us. +- */ +- fs = get_fs(); +- set_fs(KERNEL_DS); +- + for (i = -4; i < 1 + !!thumb; i++) { + unsigned int val, bad; + +- if (thumb) +- bad = __get_user(val, &((u16 *)addr)[i]); +- else +- bad = __get_user(val, &((u32 *)addr)[i]); ++ if (thumb) { ++ u16 instr; ++ bad = probe_kernel_address(addr, instr); ++ val = instr; ++ } else ++ bad = probe_kernel_address(addr, val); + + if (!bad) + p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", +@@ -158,8 +140,6 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) + } + } + printk("%sCode: %s\n", lvl, str); +- +- set_fs(fs); + } + + #ifdef CONFIG_ARM_UNWIND +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index b9f60eb..f8f14fc 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -749,7 +749,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + unsigned long instr = 0, instrptr; + int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); + unsigned int type; +- mm_segment_t fs; + unsigned int fault; + u16 tinstr = 0; + int isize = 4; +@@ -760,16 +759,15 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + + instrptr = instruction_pointer(regs); + +- fs = get_fs(); +- set_fs(KERNEL_DS); + if (thumb_mode(regs)) { +- fault = __get_user(tinstr, (u16 *)(instrptr & ~1)); ++ unsigned long ptr = instrptr; ++ fault = probe_kernel_address(ptr, tinstr); + if (!fault) { + if (cpu_architecture() >= CPU_ARCH_ARMv7 && + IS_T32(tinstr)) { + /* Thumb-2 32-bit */ + u16 tinst2 = 0; +- fault = __get_user(tinst2, (u16 *)(instrptr+2)); ++ fault = probe_kernel_address(ptr + 2, tinst2); + instr = (tinstr << 16) | tinst2; + thumb2_32b = 1; + } else { +@@ -778,8 +776,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + } + } + } else +- fault = __get_user(instr, (u32 *)instrptr); +- set_fs(fs); ++ fault = probe_kernel_address(instrptr, instr); + + if (fault) { + type = TYPE_FAULT; diff --git a/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch b/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch deleted file mode 100644 index 155806681..000000000 --- a/arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch +++ /dev/null @@ -1,83 +0,0 @@ -commit dd945918f747f61eff384f5cb8889e524f60615a -Author: Jon Masters -Date: Fri Oct 5 22:32:29 2012 -0400 - - Revert "ARM: 7528/1: uaccess: annotate [__]{get,put}_user functions with might_fault()" - - This reverts commit ad72907acd2943304c292ae36960bb66e6dc23c9. - - Technically, the original commit is totally correct, however it exposes - a deep-rooted problem with missaligned accesses in e.g. the networking - stack and we need to revert this (sweep under rug) until we can get - a good solution in place upstream. The problem is that the compiler - believes the structs concerned are aligned (they are in the code), - however at runtime the IP structs are actually not aligned within - received network packets, and the fault handler is not guaranteed - to be entirely atomic and free of calls to the scheduler. - - Signed-off-by: Jon Masters - -diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index 77bd79f..6f83ad6 100644 ---- a/arch/arm/include/asm/uaccess.h -+++ b/arch/arm/include/asm/uaccess.h -@@ -118,7 +118,7 @@ extern int __get_user_4(void *); - : "0" (__p), "r" (__l) \ - : __GUP_CLOBBER_##__s) - --#define __get_user_check(x,p) \ -+#define get_user(x,p) \ - ({ \ - unsigned long __limit = current_thread_info()->addr_limit - 1; \ - register const typeof(*(p)) __user *__p asm("r0") = (p);\ -@@ -141,12 +141,6 @@ extern int __get_user_4(void *); - __e; \ - }) - --#define get_user(x,p) \ -- ({ \ -- might_fault(); \ -- __get_user_check(x,p); \ -- }) -- - extern int __put_user_1(void *, unsigned int); - extern int __put_user_2(void *, unsigned int); - extern int __put_user_4(void *, unsigned int); -@@ -161,7 +155,7 @@ extern int __put_user_8(void *, unsigned long long); - : "0" (__p), "r" (__r2), "r" (__l) \ - : "ip", "lr", "cc") - --#define __put_user_check(x,p) \ -+#define put_user(x,p) \ - ({ \ - unsigned long __limit = current_thread_info()->addr_limit - 1; \ - register const typeof(*(p)) __r2 asm("r2") = (x); \ -@@ -186,12 +180,6 @@ extern int __put_user_8(void *, unsigned long long); - __e; \ - }) - --#define put_user(x,p) \ -- ({ \ -- might_fault(); \ -- __put_user_check(x,p); \ -- }) -- - #else /* CONFIG_MMU */ - - /* -@@ -245,7 +233,6 @@ do { \ - unsigned long __gu_addr = (unsigned long)(ptr); \ - unsigned long __gu_val; \ - __chk_user_ptr(ptr); \ -- might_fault(); \ - switch (sizeof(*(ptr))) { \ - case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ - case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ -@@ -327,7 +314,6 @@ do { \ - unsigned long __pu_addr = (unsigned long)(ptr); \ - __typeof__(*(ptr)) __pu_val = (x); \ - __chk_user_ptr(ptr); \ -- might_fault(); \ - switch (sizeof(*(ptr))) { \ - case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ - case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ diff --git a/config-arm-generic b/config-arm-generic index 8b7f50874..e0507a0f1 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -88,9 +88,6 @@ CONFIG_STRICT_DEVMEM=y CONFIG_SPARSE_IRQ=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - # Generic HW for all ARM platforms CONFIG_LEDS=y CONFIG_LEDS_CPU=y diff --git a/kernel.spec b/kernel.spec index 16dfe9b5c..f1749a51a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -733,7 +733,7 @@ Patch19001: i82975x-edac-fix.patch Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch Patch21002: arm-fix_radio_shark.patch -Patch21003: arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch +Patch21003: arm-alignment-faults.patch # OMAP # ARM tegra @@ -1368,7 +1368,7 @@ ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch ApplyPatch arm-highbank-sata-fix.patch -ApplyPatch arm-linux-3.6-revert-missaligned-access-check-on-put_user.patch +ApplyPatch arm-alignment-faults.patch ApplyPatch arm-smdk310-regulator-fix.patch ApplyPatch arm-origen-regulator-fix.patch @@ -2376,6 +2376,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 29 2012 Peter Robinson +- Update ARM alignment patch to upstream + * Mon Oct 29 2012 Justin M. Forbes 3.6.4-1 - Linux 3.6.4 From ddc5dcdcdfaac4d11143b384422d3bee2b92b1b1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 29 Oct 2012 23:31:32 -0500 Subject: [PATCH 085/492] Uprobes backports from upstream --- kernel.spec | 7 + uprobes-upstream-backport.patch | 1376 +++++++++++++++++++++++++++++++ 2 files changed, 1383 insertions(+) create mode 100644 uprobes-upstream-backport.patch diff --git a/kernel.spec b/kernel.spec index f1749a51a..d2bd5cf12 100644 --- a/kernel.spec +++ b/kernel.spec @@ -787,6 +787,8 @@ Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +Patch22100: uprobes-upstream-backport.patch + # END OF PATCH DEFINITIONS %endif @@ -1524,6 +1526,8 @@ ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +ApplyPatch uprobes-upstream-backport.patch + # END OF PATCH APPLICATIONS %endif @@ -2376,6 +2380,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 29 2012 Justin M. Forbes +- Uprobes backports from upstream + * Mon Oct 29 2012 Peter Robinson - Update ARM alignment patch to upstream diff --git a/uprobes-upstream-backport.patch b/uprobes-upstream-backport.patch new file mode 100644 index 000000000..9614e41b9 --- /dev/null +++ b/uprobes-upstream-backport.patch @@ -0,0 +1,1376 @@ +Hello, + +Test builds: + f18: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635065 + f17: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635062 + +The split-out series is available in the git repository at: + http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git + +Just jistone's patch is not upstream that exports functions. +Yes, I know it must go to upstream. :-) I will try to do what I can before +the next uprobes update. + +--------------------------------------------------------------- +Josh Stone (1): + uprobes: add exports necessary for uprobes use by modules + +Oleg Nesterov (35): + uprobes: Kill uprobes_state->count + uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap + uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending() + uprobes: Do not use -EEXIST in install_breakpoint() paths + uprobes: Introduce MMF_HAS_UPROBES + uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap() + uprobes: Remove "verify" argument from set_orig_insn() + uprobes: uprobes_treelock should not disable irqs + uprobes: Introduce MMF_RECALC_UPROBES + uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES + ptrace/x86: Introduce set_task_blockstep() helper + ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic + uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping + uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set + uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction + uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int" + uprobes: Do not leak UTASK_BP_HIT if find_active_uprobe() fails + uprobes: Do not setup ->active_uprobe/state prematurely + uprobes: Fix UPROBE_SKIP_SSTEP checks in handle_swbp() + uprobes: Kill UTASK_BP_HIT state + uprobes: Move clear_thread_flag(TIF_UPROBE) to uprobe_notify_resume() + uprobes: Change write_opcode() to use FOLL_FORCE + uprobes: Change valid_vma() to demand VM_MAYEXEC rather than VM_EXEC + uprobes: Restrict valid_vma(false) to skip VM_SHARED vmas + uprobes: Kill set_swbp()->is_swbp_at_addr() + uprobes: Introduce copy_opcode(), kill read_opcode() + uprobes: Kill set_orig_insn()->is_swbp_at_addr() + uprobes: Simplify is_swbp_at_addr(), remove stale comments + uprobes/x86: Only rep+nop can be emulated correctly + uprobes: Don't return success if alloc_uprobe() fails + uprobes: Do not delete uprobe if uprobe_unregister() fails + uprobes: Fix handle_swbp() vs unregister() + register() race + uprobes: Introduce prepare_uprobe() + uprobes: Fix prepare_uprobe() race with itself + uprobes: Fix the racy uprobe->flags manipulation + +Sebastian Andrzej Siewior (4): + uprobes: Remove check for uprobe variable in handle_swbp() + uprobes: Don't put NULL pointer in uprobe_register() + uprobes: Introduce arch_uprobe_enable/disable_step() + uprobes/x86: Implement x86 specific arch_uprobe_*_step + +Srikar Dronamraju (1): + uprobes: Remove redundant lock_page/unlock_page + + arch/x86/include/asm/processor.h | 2 + + arch/x86/include/asm/uprobes.h | 3 +- + arch/x86/kernel/signal.c | 4 +- + arch/x86/kernel/step.c | 53 ++-- + arch/x86/kernel/uprobes.c | 64 ++++- + include/linux/sched.h | 3 + + include/linux/uprobes.h | 26 +- + kernel/events/uprobes.c | 564 ++++++++++++++++++--------------------- + kernel/fork.c | 6 +- + kernel/ptrace.c | 6 + + 10 files changed, 375 insertions(+), 356 deletions(-) + +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index d048cad..433d2e5 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -759,6 +759,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); + } + ++extern void set_task_blockstep(struct task_struct *task, bool on); ++ + /* + * from system description table in BIOS. Mostly for MCA use, but + * others may find it useful: +diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h +index f3971bb..8ff8be7 100644 +--- a/arch/x86/include/asm/uprobes.h ++++ b/arch/x86/include/asm/uprobes.h +@@ -42,10 +42,11 @@ struct arch_uprobe { + }; + + struct arch_uprobe_task { +- unsigned long saved_trap_nr; + #ifdef CONFIG_X86_64 + unsigned long saved_scratch_register; + #endif ++ unsigned int saved_trap_nr; ++ unsigned int saved_tf; + }; + + extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); +diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c +index b280908..0041e5a 100644 +--- a/arch/x86/kernel/signal.c ++++ b/arch/x86/kernel/signal.c +@@ -785,10 +785,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) + mce_notify_process(); + #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ + +- if (thread_info_flags & _TIF_UPROBE) { +- clear_thread_flag(TIF_UPROBE); ++ if (thread_info_flags & _TIF_UPROBE) + uprobe_notify_resume(regs); +- } + + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) +diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c +index c346d11..cd3b243 100644 +--- a/arch/x86/kernel/step.c ++++ b/arch/x86/kernel/step.c +@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) + return 1; + } + ++void set_task_blockstep(struct task_struct *task, bool on) ++{ ++ unsigned long debugctl; ++ ++ /* ++ * Ensure irq/preemption can't change debugctl in between. ++ * Note also that both TIF_BLOCKSTEP and debugctl should ++ * be changed atomically wrt preemption. ++ * FIXME: this means that set/clear TIF_BLOCKSTEP is simply ++ * wrong if task != current, SIGKILL can wakeup the stopped ++ * tracee and set/clear can play with the running task, this ++ * can confuse the next __switch_to_xtra(). ++ */ ++ local_irq_disable(); ++ debugctl = get_debugctlmsr(); ++ if (on) { ++ debugctl |= DEBUGCTLMSR_BTF; ++ set_tsk_thread_flag(task, TIF_BLOCKSTEP); ++ } else { ++ debugctl &= ~DEBUGCTLMSR_BTF; ++ clear_tsk_thread_flag(task, TIF_BLOCKSTEP); ++ } ++ if (task == current) ++ update_debugctlmsr(debugctl); ++ local_irq_enable(); ++} ++ + /* + * Enable single or block step. + */ +@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) + * So no one should try to use debugger block stepping in a program + * that uses user-mode single stepping itself. + */ +- if (enable_single_step(child) && block) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl |= DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- set_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl &= ~DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } ++ if (enable_single_step(child) && block) ++ set_task_blockstep(child, true); ++ else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) ++ set_task_blockstep(child, false); + } + + void user_enable_single_step(struct task_struct *child) +@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) + /* + * Make sure block stepping (BTF) is disabled. + */ +- if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl &= ~DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } ++ if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) ++ set_task_blockstep(child, false); + + /* Always clear TIF_SINGLESTEP... */ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +index 36fd420..aafa555 100644 +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -41,6 +41,9 @@ + /* Adjust the return address of a call insn */ + #define UPROBE_FIX_CALL 0x2 + ++/* Instruction will modify TF, don't change it */ ++#define UPROBE_FIX_SETF 0x4 ++ + #define UPROBE_FIX_RIP_AX 0x8000 + #define UPROBE_FIX_RIP_CX 0x4000 + +@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) + insn_get_opcode(insn); /* should be a nop */ + + switch (OPCODE1(insn)) { ++ case 0x9d: ++ /* popf */ ++ auprobe->fixups |= UPROBE_FIX_SETF; ++ break; + case 0xc3: /* ret/lret */ + case 0xcb: + case 0xc2: +@@ -644,32 +651,63 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) + + /* + * Skip these instructions as per the currently known x86 ISA. +- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } ++ * rep=0x66*; nop=0x90 + */ +-bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ++static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) + { + int i; + + for (i = 0; i < MAX_UINSN_BYTES; i++) { +- if ((auprobe->insn[i] == 0x66)) ++ if (auprobe->insn[i] == 0x66) + continue; + + if (auprobe->insn[i] == 0x90) + return true; + +- if (i == (MAX_UINSN_BYTES - 1)) +- break; ++ break; ++ } ++ return false; ++} + +- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) +- return true; ++bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ bool ret = __skip_sstep(auprobe, regs); ++ if (ret && (regs->flags & X86_EFLAGS_TF)) ++ send_sig(SIGTRAP, current, 0); ++ return ret; ++} + +- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) +- return true; ++void arch_uprobe_enable_step(struct arch_uprobe *auprobe) ++{ ++ struct task_struct *task = current; ++ struct arch_uprobe_task *autask = &task->utask->autask; ++ struct pt_regs *regs = task_pt_regs(task); + +- if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) +- return true; ++ autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); + +- break; ++ regs->flags |= X86_EFLAGS_TF; ++ if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) ++ set_task_blockstep(task, false); ++} ++ ++void arch_uprobe_disable_step(struct arch_uprobe *auprobe) ++{ ++ struct task_struct *task = current; ++ struct arch_uprobe_task *autask = &task->utask->autask; ++ bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); ++ struct pt_regs *regs = task_pt_regs(task); ++ /* ++ * The state of TIF_BLOCKSTEP was not saved so we can get an extra ++ * SIGTRAP if we do not clear TF. We need to examine the opcode to ++ * make it right. ++ */ ++ if (unlikely(trapped)) { ++ if (!autask->saved_tf) ++ regs->flags &= ~X86_EFLAGS_TF; ++ } else { ++ if (autask->saved_tf) ++ send_sig(SIGTRAP, task, 0); ++ else if (!(auprobe->fixups & UPROBE_FIX_SETF)) ++ regs->flags &= ~X86_EFLAGS_TF; + } +- return false; + } +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 23bddac..ba300be 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -446,6 +446,9 @@ extern int get_dumpable(struct mm_struct *mm); + #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ + #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ + ++#define MMF_HAS_UPROBES 19 /* has uprobes */ ++#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ ++ + #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) + + struct sighand_struct { +diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h +index efe4b33..2459457 100644 +--- a/include/linux/uprobes.h ++++ b/include/linux/uprobes.h +@@ -35,16 +35,6 @@ struct inode; + # include + #endif + +-/* flags that denote/change uprobes behaviour */ +- +-/* Have a copy of original instruction */ +-#define UPROBE_COPY_INSN 0x1 +- +-/* Dont run handlers when first register/ last unregister in progress*/ +-#define UPROBE_RUN_HANDLER 0x2 +-/* Can skip singlestep */ +-#define UPROBE_SKIP_SSTEP 0x4 +- + struct uprobe_consumer { + int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); + /* +@@ -59,7 +49,6 @@ struct uprobe_consumer { + #ifdef CONFIG_UPROBES + enum uprobe_task_state { + UTASK_RUNNING, +- UTASK_BP_HIT, + UTASK_SSTEP, + UTASK_SSTEP_ACK, + UTASK_SSTEP_TRAPPED, +@@ -99,25 +88,27 @@ struct xol_area { + + struct uprobes_state { + struct xol_area *xol_area; +- atomic_t count; + }; ++ + extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); +-extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); ++extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); + extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); + extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); + extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); + extern int uprobe_mmap(struct vm_area_struct *vma); + extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); ++extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); + extern void uprobe_free_utask(struct task_struct *t); + extern void uprobe_copy_process(struct task_struct *t); + extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); ++extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); ++extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); + extern int uprobe_post_sstep_notifier(struct pt_regs *regs); + extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); + extern void uprobe_notify_resume(struct pt_regs *regs); + extern bool uprobe_deny_signal(void); + extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); + extern void uprobe_clear_state(struct mm_struct *mm); +-extern void uprobe_reset_state(struct mm_struct *mm); + #else /* !CONFIG_UPROBES */ + struct uprobes_state { + }; +@@ -138,6 +129,10 @@ static inline void + uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) + { + } ++static inline void ++uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) ++{ ++} + static inline void uprobe_notify_resume(struct pt_regs *regs) + { + } +@@ -158,8 +153,5 @@ static inline void uprobe_copy_process(struct task_struct *t) + static inline void uprobe_clear_state(struct mm_struct *mm) + { + } +-static inline void uprobe_reset_state(struct mm_struct *mm) +-{ +-} + #endif /* !CONFIG_UPROBES */ + #endif /* _LINUX_UPROBES_H */ +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index c08a22d..e933f65 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -27,6 +27,7 @@ + #include /* read_mapping_page */ + #include + #include ++#include + #include /* anon_vma_prepare */ + #include /* set_pte_at_notify */ + #include /* try_to_free_swap */ +@@ -78,15 +79,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; + */ + static atomic_t uprobe_events = ATOMIC_INIT(0); + ++/* Have a copy of original instruction */ ++#define UPROBE_COPY_INSN 0 ++/* Dont run handlers when first register/ last unregister in progress*/ ++#define UPROBE_RUN_HANDLER 1 ++/* Can skip singlestep */ ++#define UPROBE_SKIP_SSTEP 2 ++ + struct uprobe { + struct rb_node rb_node; /* node in the rb tree */ + atomic_t ref; + struct rw_semaphore consumer_rwsem; ++ struct mutex copy_mutex; /* TODO: kill me and UPROBE_COPY_INSN */ + struct list_head pending_list; + struct uprobe_consumer *consumers; + struct inode *inode; /* Also hold a ref to inode */ + loff_t offset; +- int flags; ++ unsigned long flags; + struct arch_uprobe arch; + }; + +@@ -100,17 +109,12 @@ struct uprobe { + */ + static bool valid_vma(struct vm_area_struct *vma, bool is_register) + { +- if (!vma->vm_file) +- return false; ++ vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED; + +- if (!is_register) +- return true; ++ if (is_register) ++ flags |= VM_WRITE; + +- if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) +- == (VM_READ|VM_EXEC)) +- return true; +- +- return false; ++ return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC; + } + + static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) +@@ -188,19 +192,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) + return *insn == UPROBE_SWBP_INSN; + } + ++static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode) ++{ ++ void *kaddr = kmap_atomic(page); ++ memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE); ++ kunmap_atomic(kaddr); ++} ++ ++static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode) ++{ ++ uprobe_opcode_t old_opcode; ++ bool is_swbp; ++ ++ copy_opcode(page, vaddr, &old_opcode); ++ is_swbp = is_swbp_insn(&old_opcode); ++ ++ if (is_swbp_insn(new_opcode)) { ++ if (is_swbp) /* register: already installed? */ ++ return 0; ++ } else { ++ if (!is_swbp) /* unregister: was it changed by us? */ ++ return 0; ++ } ++ ++ return 1; ++} ++ + /* + * NOTE: + * Expect the breakpoint instruction to be the smallest size instruction for + * the architecture. If an arch has variable length instruction and the + * breakpoint instruction is not of the smallest length instruction +- * supported by that architecture then we need to modify read_opcode / ++ * supported by that architecture then we need to modify is_swbp_at_addr and + * write_opcode accordingly. This would never be a problem for archs that + * have fixed length instructions. + */ + + /* + * write_opcode - write the opcode at a given virtual address. +- * @auprobe: arch breakpointing information. + * @mm: the probed process address space. + * @vaddr: the virtual address to store the opcode. + * @opcode: opcode to be written at @vaddr. +@@ -211,8 +240,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) + * For mm @mm, write the opcode at @vaddr. + * Return 0 (success) or a negative errno. + */ +-static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, +- unsigned long vaddr, uprobe_opcode_t opcode) ++static int write_opcode(struct mm_struct *mm, unsigned long vaddr, ++ uprobe_opcode_t opcode) + { + struct page *old_page, *new_page; + void *vaddr_old, *vaddr_new; +@@ -221,10 +250,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + + retry: + /* Read the page with vaddr into memory */ +- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); ++ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); + if (ret <= 0) + return ret; + ++ ret = verify_opcode(old_page, vaddr, &opcode); ++ if (ret <= 0) ++ goto put_old; ++ + ret = -ENOMEM; + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); + if (!new_page) +@@ -259,65 +292,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + } + + /** +- * read_opcode - read the opcode at a given virtual address. +- * @mm: the probed process address space. +- * @vaddr: the virtual address to read the opcode. +- * @opcode: location to store the read opcode. +- * +- * Called with mm->mmap_sem held (for read and with a reference to +- * mm. +- * +- * For mm @mm, read the opcode at @vaddr and store it in @opcode. +- * Return 0 (success) or a negative errno. +- */ +-static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) +-{ +- struct page *page; +- void *vaddr_new; +- int ret; +- +- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); +- if (ret <= 0) +- return ret; +- +- lock_page(page); +- vaddr_new = kmap_atomic(page); +- vaddr &= ~PAGE_MASK; +- memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); +- kunmap_atomic(vaddr_new); +- unlock_page(page); +- +- put_page(page); +- +- return 0; +-} +- +-static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) +-{ +- uprobe_opcode_t opcode; +- int result; +- +- if (current->mm == mm) { +- pagefault_disable(); +- result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, +- sizeof(opcode)); +- pagefault_enable(); +- +- if (likely(result == 0)) +- goto out; +- } +- +- result = read_opcode(mm, vaddr, &opcode); +- if (result) +- return result; +-out: +- if (is_swbp_insn(&opcode)) +- return 1; +- +- return 0; +-} +- +-/** + * set_swbp - store breakpoint at a given address. + * @auprobe: arch specific probepoint information. + * @mm: the probed process address space. +@@ -328,18 +302,7 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) + */ + int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) + { +- int result; +- /* +- * See the comment near uprobes_hash(). +- */ +- result = is_swbp_at_addr(mm, vaddr); +- if (result == 1) +- return -EEXIST; +- +- if (result) +- return result; +- +- return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); ++ return write_opcode(mm, vaddr, UPROBE_SWBP_INSN); + } + + /** +@@ -347,25 +310,14 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned + * @mm: the probed process address space. + * @auprobe: arch specific probepoint information. + * @vaddr: the virtual address to insert the opcode. +- * @verify: if true, verify existance of breakpoint instruction. + * + * For mm @mm, restore the original opcode (opcode) at @vaddr. + * Return 0 (success) or a negative errno. + */ + int __weak +-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) ++set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) + { +- if (verify) { +- int result; +- +- result = is_swbp_at_addr(mm, vaddr); +- if (!result) +- return -EINVAL; +- +- if (result != 1) +- return result; +- } +- return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); ++ return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); + } + + static int match_uprobe(struct uprobe *l, struct uprobe *r) +@@ -415,11 +367,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) + static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) + { + struct uprobe *uprobe; +- unsigned long flags; + +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + uprobe = __find_uprobe(inode, offset); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + + return uprobe; + } +@@ -466,15 +417,14 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) + */ + static struct uprobe *insert_uprobe(struct uprobe *uprobe) + { +- unsigned long flags; + struct uprobe *u; + +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + u = __insert_uprobe(uprobe); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + + /* For now assume that the instruction need not be single-stepped */ +- uprobe->flags |= UPROBE_SKIP_SSTEP; ++ __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); + + return u; + } +@@ -496,6 +446,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) + uprobe->inode = igrab(inode); + uprobe->offset = offset; + init_rwsem(&uprobe->consumer_rwsem); ++ mutex_init(&uprobe->copy_mutex); + + /* add to uprobes_tree, sorted on inode:offset */ + cur_uprobe = insert_uprobe(uprobe); +@@ -516,7 +467,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) + { + struct uprobe_consumer *uc; + +- if (!(uprobe->flags & UPROBE_RUN_HANDLER)) ++ if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags)) + return; + + down_read(&uprobe->consumer_rwsem); +@@ -622,33 +573,48 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) + return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); + } + +-/* +- * How mm->uprobes_state.count gets updated +- * uprobe_mmap() increments the count if +- * - it successfully adds a breakpoint. +- * - it cannot add a breakpoint, but sees that there is a underlying +- * breakpoint (via a is_swbp_at_addr()). +- * +- * uprobe_munmap() decrements the count if +- * - it sees a underlying breakpoint, (via is_swbp_at_addr) +- * (Subsequent uprobe_unregister wouldnt find the breakpoint +- * unless a uprobe_mmap kicks in, since the old vma would be +- * dropped just after uprobe_munmap.) +- * +- * uprobe_register increments the count if: +- * - it successfully adds a breakpoint. +- * +- * uprobe_unregister decrements the count if: +- * - it sees a underlying breakpoint and removes successfully. +- * (via is_swbp_at_addr) +- * (Subsequent uprobe_munmap wouldnt find the breakpoint +- * since there is no underlying breakpoint after the +- * breakpoint removal.) +- */ ++static int prepare_uprobe(struct uprobe *uprobe, struct file *file, ++ struct mm_struct *mm, unsigned long vaddr) ++{ ++ int ret = 0; ++ ++ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) ++ return ret; ++ ++ mutex_lock(&uprobe->copy_mutex); ++ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) ++ goto out; ++ ++ ret = copy_insn(uprobe, file); ++ if (ret) ++ goto out; ++ ++ ret = -ENOTSUPP; ++ if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) ++ goto out; ++ ++ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); ++ if (ret) ++ goto out; ++ ++ /* write_opcode() assumes we don't cross page boundary */ ++ BUG_ON((uprobe->offset & ~PAGE_MASK) + ++ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); ++ ++ smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ ++ set_bit(UPROBE_COPY_INSN, &uprobe->flags); ++ ++ out: ++ mutex_unlock(&uprobe->copy_mutex); ++ ++ return ret; ++} ++ + static int + install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + struct vm_area_struct *vma, unsigned long vaddr) + { ++ bool first_uprobe; + int ret; + + /* +@@ -659,48 +625,38 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + * Hence behave as if probe already existed. + */ + if (!uprobe->consumers) +- return -EEXIST; +- +- if (!(uprobe->flags & UPROBE_COPY_INSN)) { +- ret = copy_insn(uprobe, vma->vm_file); +- if (ret) +- return ret; +- +- if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) +- return -ENOTSUPP; +- +- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); +- if (ret) +- return ret; +- +- /* write_opcode() assumes we don't cross page boundary */ +- BUG_ON((uprobe->offset & ~PAGE_MASK) + +- UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); ++ return 0; + +- uprobe->flags |= UPROBE_COPY_INSN; +- } ++ ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr); ++ if (ret) ++ return ret; + + /* +- * Ideally, should be updating the probe count after the breakpoint +- * has been successfully inserted. However a thread could hit the +- * breakpoint we just inserted even before the probe count is +- * incremented. If this is the first breakpoint placed, breakpoint +- * notifier might ignore uprobes and pass the trap to the thread. +- * Hence increment before and decrement on failure. ++ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), ++ * the task can hit this breakpoint right after __replace_page(). + */ +- atomic_inc(&mm->uprobes_state.count); ++ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); ++ if (first_uprobe) ++ set_bit(MMF_HAS_UPROBES, &mm->flags); ++ + ret = set_swbp(&uprobe->arch, mm, vaddr); +- if (ret) +- atomic_dec(&mm->uprobes_state.count); ++ if (!ret) ++ clear_bit(MMF_RECALC_UPROBES, &mm->flags); ++ else if (first_uprobe) ++ clear_bit(MMF_HAS_UPROBES, &mm->flags); + + return ret; + } + +-static void ++static int + remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) + { +- if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) +- atomic_dec(&mm->uprobes_state.count); ++ /* can happen if uprobe_register() fails */ ++ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) ++ return 0; ++ ++ set_bit(MMF_RECALC_UPROBES, &mm->flags); ++ return set_orig_insn(&uprobe->arch, mm, vaddr); + } + + /* +@@ -710,11 +666,9 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad + */ + static void delete_uprobe(struct uprobe *uprobe) + { +- unsigned long flags; +- +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + rb_erase(&uprobe->rb_node, &uprobes_tree); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + iput(uprobe->inode); + put_uprobe(uprobe); + atomic_dec(&uprobe_events); +@@ -818,7 +772,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) + struct mm_struct *mm = info->mm; + struct vm_area_struct *vma; + +- if (err) ++ if (err && is_register) + goto free; + + down_write(&mm->mmap_sem); +@@ -831,17 +785,11 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) + vaddr_to_offset(vma, info->vaddr) != uprobe->offset) + goto unlock; + +- if (is_register) { ++ if (is_register) + err = install_breakpoint(uprobe, mm, vma, info->vaddr); +- /* +- * We can race against uprobe_mmap(), see the +- * comment near uprobe_hash(). +- */ +- if (err == -EEXIST) +- err = 0; +- } else { +- remove_breakpoint(uprobe, mm, info->vaddr); +- } ++ else ++ err |= remove_breakpoint(uprobe, mm, info->vaddr); ++ + unlock: + up_write(&mm->mmap_sem); + free: +@@ -897,21 +845,25 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * + mutex_lock(uprobes_hash(inode)); + uprobe = alloc_uprobe(inode, offset); + +- if (uprobe && !consumer_add(uprobe, uc)) { ++ if (!uprobe) { ++ ret = -ENOMEM; ++ } else if (!consumer_add(uprobe, uc)) { + ret = __uprobe_register(uprobe); + if (ret) { + uprobe->consumers = NULL; + __uprobe_unregister(uprobe); + } else { +- uprobe->flags |= UPROBE_RUN_HANDLER; ++ set_bit(UPROBE_RUN_HANDLER, &uprobe->flags); + } + } + + mutex_unlock(uprobes_hash(inode)); +- put_uprobe(uprobe); ++ if (uprobe) ++ put_uprobe(uprobe); + + return ret; + } ++EXPORT_SYMBOL_GPL(uprobe_register); + + /* + * uprobe_unregister - unregister a already registered probe. +@@ -935,7 +887,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume + if (consumer_del(uprobe, uc)) { + if (!uprobe->consumers) { + __uprobe_unregister(uprobe); +- uprobe->flags &= ~UPROBE_RUN_HANDLER; ++ clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags); + } + } + +@@ -943,6 +895,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume + if (uprobe) + put_uprobe(uprobe); + } ++EXPORT_SYMBOL_GPL(uprobe_unregister); + + static struct rb_node * + find_node_in_range(struct inode *inode, loff_t min, loff_t max) +@@ -978,7 +931,6 @@ static void build_probe_list(struct inode *inode, + struct list_head *head) + { + loff_t min, max; +- unsigned long flags; + struct rb_node *n, *t; + struct uprobe *u; + +@@ -986,7 +938,7 @@ static void build_probe_list(struct inode *inode, + min = vaddr_to_offset(vma, start); + max = min + (end - start) - 1; + +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + n = find_node_in_range(inode, min, max); + if (n) { + for (t = n; t; t = rb_prev(t)) { +@@ -1004,27 +956,20 @@ static void build_probe_list(struct inode *inode, + atomic_inc(&u->ref); + } + } +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + } + + /* +- * Called from mmap_region. +- * called with mm->mmap_sem acquired. +- * +- * Return -ve no if we fail to insert probes and we cannot +- * bail-out. +- * Return 0 otherwise. i.e: ++ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. + * +- * - successful insertion of probes +- * - (or) no possible probes to be inserted. +- * - (or) insertion of probes failed but we can bail-out. ++ * Currently we ignore all errors and always return 0, the callers ++ * can't handle the failure anyway. + */ + int uprobe_mmap(struct vm_area_struct *vma) + { + struct list_head tmp_list; + struct uprobe *uprobe, *u; + struct inode *inode; +- int ret, count; + + if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) + return 0; +@@ -1036,44 +981,35 @@ int uprobe_mmap(struct vm_area_struct *vma) + mutex_lock(uprobes_mmap_hash(inode)); + build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); + +- ret = 0; +- count = 0; +- + list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- if (!ret) { ++ if (!fatal_signal_pending(current)) { + unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); +- +- ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); +- /* +- * We can race against uprobe_register(), see the +- * comment near uprobe_hash(). +- */ +- if (ret == -EEXIST) { +- ret = 0; +- +- if (!is_swbp_at_addr(vma->vm_mm, vaddr)) +- continue; +- +- /* +- * Unable to insert a breakpoint, but +- * breakpoint lies underneath. Increment the +- * probe count. +- */ +- atomic_inc(&vma->vm_mm->uprobes_state.count); +- } +- +- if (!ret) +- count++; ++ install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + } + put_uprobe(uprobe); + } +- + mutex_unlock(uprobes_mmap_hash(inode)); + +- if (ret) +- atomic_sub(count, &vma->vm_mm->uprobes_state.count); ++ return 0; ++} + +- return ret; ++static bool ++vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) ++{ ++ loff_t min, max; ++ struct inode *inode; ++ struct rb_node *n; ++ ++ inode = vma->vm_file->f_mapping->host; ++ ++ min = vaddr_to_offset(vma, start); ++ max = min + (end - start) - 1; ++ ++ spin_lock(&uprobes_treelock); ++ n = find_node_in_range(inode, min, max); ++ spin_unlock(&uprobes_treelock); ++ ++ return !!n; + } + + /* +@@ -1081,37 +1017,18 @@ int uprobe_mmap(struct vm_area_struct *vma) + */ + void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) + { +- struct list_head tmp_list; +- struct uprobe *uprobe, *u; +- struct inode *inode; +- + if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) + return; + + if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ + return; + +- if (!atomic_read(&vma->vm_mm->uprobes_state.count)) +- return; +- +- inode = vma->vm_file->f_mapping->host; +- if (!inode) ++ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || ++ test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) + return; + +- mutex_lock(uprobes_mmap_hash(inode)); +- build_probe_list(inode, vma, start, end, &tmp_list); +- +- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); +- /* +- * An unregister could have removed the probe before +- * unmap. So check before we decrement the count. +- */ +- if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) +- atomic_dec(&vma->vm_mm->uprobes_state.count); +- put_uprobe(uprobe); +- } +- mutex_unlock(uprobes_mmap_hash(inode)); ++ if (vma_has_uprobes(vma, start, end)) ++ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); + } + + /* Slot allocation for XOL */ +@@ -1213,13 +1130,15 @@ void uprobe_clear_state(struct mm_struct *mm) + kfree(area); + } + +-/* +- * uprobe_reset_state - Free the area allocated for slots. +- */ +-void uprobe_reset_state(struct mm_struct *mm) ++void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) + { +- mm->uprobes_state.xol_area = NULL; +- atomic_set(&mm->uprobes_state.count, 0); ++ newmm->uprobes_state.xol_area = NULL; ++ ++ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { ++ set_bit(MMF_HAS_UPROBES, &newmm->flags); ++ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ ++ set_bit(MMF_RECALC_UPROBES, &newmm->flags); ++ } + } + + /* +@@ -1430,13 +1349,57 @@ bool uprobe_deny_signal(void) + */ + static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) + { +- if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) +- return true; +- +- uprobe->flags &= ~UPROBE_SKIP_SSTEP; ++ if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) { ++ if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) ++ return true; ++ clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); ++ } + return false; + } + ++static void mmf_recalc_uprobes(struct mm_struct *mm) ++{ ++ struct vm_area_struct *vma; ++ ++ for (vma = mm->mmap; vma; vma = vma->vm_next) { ++ if (!valid_vma(vma, false)) ++ continue; ++ /* ++ * This is not strictly accurate, we can race with ++ * uprobe_unregister() and see the already removed ++ * uprobe if delete_uprobe() was not yet called. ++ */ ++ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) ++ return; ++ } ++ ++ clear_bit(MMF_HAS_UPROBES, &mm->flags); ++} ++ ++static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) ++{ ++ struct page *page; ++ uprobe_opcode_t opcode; ++ int result; ++ ++ pagefault_disable(); ++ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, ++ sizeof(opcode)); ++ pagefault_enable(); ++ ++ if (likely(result == 0)) ++ goto out; ++ ++ result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); ++ if (result < 0) ++ return result; ++ ++ copy_opcode(page, vaddr, &opcode); ++ put_page(page); ++ out: ++ return is_swbp_insn(&opcode); ++} ++ + static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) + { + struct mm_struct *mm = current->mm; +@@ -1458,11 +1421,24 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) + } else { + *is_swbp = -EFAULT; + } ++ ++ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) ++ mmf_recalc_uprobes(mm); + up_read(&mm->mmap_sem); + + return uprobe; + } + ++void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) ++{ ++ user_enable_single_step(current); ++} ++ ++void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) ++{ ++ user_disable_single_step(current); ++} ++ + /* + * Run handler and ask thread to singlestep. + * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. +@@ -1494,41 +1470,42 @@ static void handle_swbp(struct pt_regs *regs) + } + return; + } ++ /* ++ * TODO: move copy_insn/etc into _register and remove this hack. ++ * After we hit the bp, _unregister + _register can install the ++ * new and not-yet-analyzed uprobe at the same address, restart. ++ */ ++ smp_rmb(); /* pairs with wmb() in install_breakpoint() */ ++ if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) ++ goto restart; + + utask = current->utask; + if (!utask) { + utask = add_utask(); + /* Cannot allocate; re-execute the instruction. */ + if (!utask) +- goto cleanup_ret; ++ goto restart; + } +- utask->active_uprobe = uprobe; ++ + handler_chain(uprobe, regs); +- if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) +- goto cleanup_ret; ++ if (can_skip_sstep(uprobe, regs)) ++ goto out; + +- utask->state = UTASK_SSTEP; + if (!pre_ssout(uprobe, regs, bp_vaddr)) { +- user_enable_single_step(current); ++ arch_uprobe_enable_step(&uprobe->arch); ++ utask->active_uprobe = uprobe; ++ utask->state = UTASK_SSTEP; + return; + } + +-cleanup_ret: +- if (utask) { +- utask->active_uprobe = NULL; +- utask->state = UTASK_RUNNING; +- } +- if (uprobe) { +- if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) +- +- /* +- * cannot singlestep; cannot skip instruction; +- * re-execute the instruction. +- */ +- instruction_pointer_set(regs, bp_vaddr); +- +- put_uprobe(uprobe); +- } ++restart: ++ /* ++ * cannot singlestep; cannot skip instruction; ++ * re-execute the instruction. ++ */ ++ instruction_pointer_set(regs, bp_vaddr); ++out: ++ put_uprobe(uprobe); + } + + /* +@@ -1547,10 +1524,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) + else + WARN_ON_ONCE(1); + ++ arch_uprobe_disable_step(&uprobe->arch); + put_uprobe(uprobe); + utask->active_uprobe = NULL; + utask->state = UTASK_RUNNING; +- user_disable_single_step(current); + xol_free_insn_slot(current); + + spin_lock_irq(¤t->sighand->siglock); +@@ -1559,13 +1536,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) + } + + /* +- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on +- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and +- * allows the thread to return from interrupt. ++ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and ++ * allows the thread to return from interrupt. After that handle_swbp() ++ * sets utask->active_uprobe. + * +- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and +- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from +- * interrupt. ++ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag ++ * and allows the thread to return from interrupt. + * + * While returning to userspace, thread notices the TIF_UPROBE flag and calls + * uprobe_notify_resume(). +@@ -1574,11 +1550,13 @@ void uprobe_notify_resume(struct pt_regs *regs) + { + struct uprobe_task *utask; + ++ clear_thread_flag(TIF_UPROBE); ++ + utask = current->utask; +- if (!utask || utask->state == UTASK_BP_HIT) +- handle_swbp(regs); +- else ++ if (utask && utask->active_uprobe) + handle_singlestep(utask, regs); ++ else ++ handle_swbp(regs); + } + + /* +@@ -1587,18 +1565,10 @@ void uprobe_notify_resume(struct pt_regs *regs) + */ + int uprobe_pre_sstep_notifier(struct pt_regs *regs) + { +- struct uprobe_task *utask; +- +- if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) +- /* task is currently not uprobed */ ++ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) + return 0; + +- utask = current->utask; +- if (utask) +- utask->state = UTASK_BP_HIT; +- + set_thread_flag(TIF_UPROBE); +- + return 1; + } + +diff --git a/kernel/fork.c b/kernel/fork.c +index 2c8857e..2343c9e 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -353,6 +353,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + down_write(&oldmm->mmap_sem); + flush_cache_dup_mm(oldmm); ++ uprobe_dup_mmap(oldmm, mm); + /* + * Not linked in yet - no deadlock potential: + */ +@@ -454,9 +455,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + if (retval) + goto out; +- +- if (file) +- uprobe_mmap(tmp); + } + /* a new mm has just been created */ + arch_dup_mmap(oldmm, mm); +@@ -839,8 +837,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + mm->pmd_huge_pte = NULL; + #endif +- uprobe_reset_state(mm); +- + if (!mm_init(mm, tsk)) + goto fail_nomem; + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index a232bb5..764fcd1 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags) + } + + /* ++ * This is declared in linux/regset.h and defined in machine-dependent ++ * code. We put the export here to ensure no machine forgets it. ++ */ ++EXPORT_SYMBOL_GPL(task_user_regset_view); ++ ++/* + * ptrace a task: make the debugger its new parent and + * move it to the ptrace list. + * +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel From 8eac4e9c082b025dde905aa3957c023c03c4c5c6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Oct 2012 13:06:45 -0400 Subject: [PATCH 086/492] Update patch for 867344 --- ...ifs_lookup-on-hashed-negative-dentry.patch | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch index 88b35e2f8..4e25f9d20 100644 --- a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch +++ b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -1,21 +1,19 @@ @@ -, +, @@ - negative dentry - BUG_ON(!d_unhashed(entry)); - fs/cifs/dir.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) + cifs_atomic_open + fs/cifs/dir.c | 6 ++++++ + 1 file changed, 6 insertions(+) --- a/fs/cifs/dir.c +++ a/fs/cifs/dir.c -@@ -398,7 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, +@@ -398,6 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { -- struct dentry *res = cifs_lookup(inode, direntry, 0); -+ struct dentry *res; -+ -+ if (!direntry->d_inode) ++ /* Check for hashed negative dentry. We have already revalidated ++ * the dentry and it is fine. No need to perform another lookup. ++ */ ++ if (!d_unhashed(direntry)) + return -ENOENT; + -+ res = cifs_lookup(inode, direntry, 0); + struct dentry *res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); - From 4acebb2503939a1021ea56b2914c435b511c27ed Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Oct 2012 14:01:39 -0400 Subject: [PATCH 087/492] Move power-x86-destdir.patch to apply on vanilla kernels (thanks knurd) --- kernel.spec | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index d2bd5cf12..9a442cfee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,6 +644,8 @@ Patch04: linux-2.6-compile-fixes.patch # build tweak for build ID magic, even for -vanilla Patch05: linux-2.6-makefile-after_link.patch +Patch06: power-x86-destdir.patch + %if !%{nopatches} @@ -748,8 +750,6 @@ Patch21010: arm-highbank-sata-fix.patch Patch21020: arm-smdk310-regulator-fix.patch Patch21021: arm-origen-regulator-fix.patch -Patch21094: power-x86-destdir.patch - #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1344,6 +1344,8 @@ ApplyPatch linux-2.6-makefile-after_link.patch # ApplyOptionalPatch linux-2.6-compile-fixes.patch +ApplyPatch power-x86-destdir.patch + %if !%{nopatches} # revert patches from upstream that conflict or that we get via other means @@ -1487,8 +1489,6 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch i82975x-edac-fix.patch -ApplyPatch power-x86-destdir.patch - #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -2380,6 +2380,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 30 2012 Josh Boyer +- Move power-x86-destdir.patch to apply on vanilla kernels (thanks knurd) + * Mon Oct 29 2012 Justin M. Forbes - Uprobes backports from upstream From 1e3ce1064cae70d9570a9ec495f8bd0214a4e530 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 31 Oct 2012 13:58:56 -0400 Subject: [PATCH 088/492] CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) --- kernel.spec | 9 ++ ...de-by-zero-in-tcp-algorithm-illinois.patch | 117 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch diff --git a/kernel.spec b/kernel.spec index 9a442cfee..d35d03682 100644 --- a/kernel.spec +++ b/kernel.spec @@ -787,6 +787,9 @@ Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +#rhbz 871923 871848 CVE-2012-4565 +Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch + Patch22100: uprobes-upstream-backport.patch # END OF PATCH DEFINITIONS @@ -1526,6 +1529,9 @@ ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +#rhbz 871923 871848 CVE-2012-4565 +ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch + ApplyPatch uprobes-upstream-backport.patch # END OF PATCH APPLICATIONS @@ -2380,6 +2386,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 30 2012 Josh Boyer +- CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) + * Tue Oct 30 2012 Josh Boyer - Move power-x86-destdir.patch to apply on vanilla kernels (thanks knurd) diff --git a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch new file mode 100644 index 000000000..109ee17b4 --- /dev/null +++ b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch @@ -0,0 +1,117 @@ +Path: news.gmane.org!not-for-mail +From: Jesper Dangaard Brouer +Newsgroups: gmane.linux.network +Subject: [net PATCH V2] net: fix divide by zero in tcp algorithm illinois +Date: Wed, 31 Oct 2012 13:45:32 +0100 +Lines: 63 +Approved: news@gmane.org +Message-ID: <20121031124318.30915.32293.stgit@dragon> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1351687472 19921 80.91.229.3 (31 Oct 2012 12:44:32 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 31 Oct 2012 12:44:32 +0000 (UTC) +Cc: Jesper Dangaard Brouer , netdev@vger.kernel.org, + Petr Matousek , + Stephen Hemminger , + Eric Dumazet +To: "David S. Miller" +Original-X-From: netdev-owner@vger.kernel.org Wed Oct 31 13:44:40 2012 +Return-path: +Envelope-to: linux-netdev-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1TTXex-0002V3-Qk + for linux-netdev-2@plane.gmane.org; Wed, 31 Oct 2012 13:44:40 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S932565Ab2JaMo0 (ORCPT ); + Wed, 31 Oct 2012 08:44:26 -0400 +Original-Received: from mx1.redhat.com ([209.132.183.28]:57345 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751941Ab2JaMoZ (ORCPT ); + Wed, 31 Oct 2012 08:44:25 -0400 +Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9VCiOkC014655 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Wed, 31 Oct 2012 08:44:24 -0400 +Original-Received: from dragon.localdomain (ovpn-116-61.ams2.redhat.com [10.36.116.61]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9VCiMuW008440; + Wed, 31 Oct 2012 08:44:23 -0400 +Original-Received: from [127.0.0.1] (localhost [IPv6:::1]) + by dragon.localdomain (Postfix) with ESMTP id 416D0E40666; + Wed, 31 Oct 2012 13:45:32 +0100 (CET) +User-Agent: StGIT/0.14.3 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:247871 +Archived-At: + +Reading TCP stats when using TCP Illinois congestion control algorithm +can cause a divide by zero kernel oops. + +The division by zero occur in tcp_illinois_info() at: + do_div(t, ca->cnt_rtt); +where ca->cnt_rtt can become zero (when rtt_reset is called) + +Steps to Reproduce: + 1. Register tcp_illinois: + # sysctl -w net.ipv4.tcp_congestion_control=illinois + 2. Monitor internal TCP information via command "ss -i" + # watch -d ss -i + 3. Establish new TCP conn to machine + +Either it fails at the initial conn, or else it needs to wait +for a loss or a reset. + +This is only related to reading stats. The function avg_delay() also +performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its +calling point in update_params(). Thus, simply fix tcp_illinois_info(). + +Function tcp_illinois_info() / get_info() is called without +socket lock. Thus, eliminate any race condition on ca->cnt_rtt +by using a local stack variable. Simply reuse info.tcpv_rttcnt, +as its already set to ca->cnt_rtt. +Function avg_delay() is not affected by this race condition, as +its called with the socket lock. + +Cc: Petr Matousek +Signed-off-by: Jesper Dangaard Brouer + +--- +V2: + Address Eric Dumazets input: + - Save 2 bytes of stack, by using info.tcpv_rttcnt. + - Help compiler, and define "u64 t" inside if() lexical scope. + + + net/ipv4/tcp_illinois.c | 8 +++++--- + 1 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c +index 813b43a..834857f 100644 +--- a/net/ipv4/tcp_illinois.c ++++ b/net/ipv4/tcp_illinois.c +@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, + .tcpv_rttcnt = ca->cnt_rtt, + .tcpv_minrtt = ca->base_rtt, + }; +- u64 t = ca->sum_rtt; + +- do_div(t, ca->cnt_rtt); +- info.tcpv_rtt = t; ++ if (info.tcpv_rttcnt > 0) { ++ u64 t = ca->sum_rtt; + ++ do_div(t, info.tcpv_rttcnt); ++ info.tcpv_rtt = t; ++ } + nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); + } + } + From f1dd1c43f80dec68bcf3a230e7d2b8071d323cc6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 31 Oct 2012 14:04:46 -0400 Subject: [PATCH 089/492] Linux v3.6.5 --- iwlwifi-fix-6000-ch-switch.patch | 94 ------------------- kernel.spec | 23 +---- ...t-with-HT20-if-HT40-is-not-permitted.patch | 75 --------------- mac80211_local_deauth_v3.6.patch | 66 ------------- sources | 2 +- 5 files changed, 4 insertions(+), 256 deletions(-) delete mode 100644 iwlwifi-fix-6000-ch-switch.patch delete mode 100644 mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch delete mode 100644 mac80211_local_deauth_v3.6.patch diff --git a/iwlwifi-fix-6000-ch-switch.patch b/iwlwifi-fix-6000-ch-switch.patch deleted file mode 100644 index 0fbca2354..000000000 --- a/iwlwifi-fix-6000-ch-switch.patch +++ /dev/null @@ -1,94 +0,0 @@ -commit a7d3a5d97acd4b8db17e1d5c3014357c9b2040f9 -Author: Johannes Berg -Date: Tue Sep 25 16:40:12 2012 +0200 - - iwlwifi: fix 6000 series channel switch command - - The channel switch command for 6000 series devices - is larger than the maximum inline command size of - 320 bytes. The command is therefore refused with a - warning. Fix this by allocating the command and - using the NOCOPY mechanism. - - Cc: stable@kernel.org - Signed-off-by: Johannes Berg - -diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c -index 349c205..da58620 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/devices.c -+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c -@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - * See iwlagn_mac_channel_switch. - */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -- struct iwl6000_channel_switch_cmd cmd; -+ struct iwl6000_channel_switch_cmd *cmd; - u32 switch_time_in_usec, ucode_switch_time; - u16 ch; - u32 tsf_low; -@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - struct ieee80211_vif *vif = ctx->vif; - struct iwl_host_cmd hcmd = { - .id = REPLY_CHANNEL_SWITCH, -- .len = { sizeof(cmd), }, -+ .len = { sizeof(*cmd), }, - .flags = CMD_SYNC, -- .data = { &cmd, }, -+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - }; -+ int err; - -- cmd.band = priv->band == IEEE80211_BAND_2GHZ; -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (!cmd) -+ return -ENOMEM; -+ -+ hcmd.data[0] = cmd; -+ -+ cmd->band = priv->band == IEEE80211_BAND_2GHZ; - ch = ch_switch->channel->hw_value; - IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", - ctx->active.channel, ch); -- cmd.channel = cpu_to_le16(ch); -- cmd.rxon_flags = ctx->staging.flags; -- cmd.rxon_filter_flags = ctx->staging.filter_flags; -+ cmd->channel = cpu_to_le16(ch); -+ cmd->rxon_flags = ctx->staging.flags; -+ cmd->rxon_filter_flags = ctx->staging.filter_flags; - switch_count = ch_switch->count; - tsf_low = ch_switch->timestamp & 0x0ffffffff; - /* -@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - switch_count = 0; - } - if (switch_count <= 1) -- cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); -+ cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); - else { - switch_time_in_usec = - vif->bss_conf.beacon_int * switch_count * TIME_UNIT; - ucode_switch_time = iwl_usecs_to_beacons(priv, - switch_time_in_usec, - beacon_interval); -- cmd.switch_time = iwl_add_beacon_time(priv, -- priv->ucode_beacon_time, -- ucode_switch_time, -- beacon_interval); -+ cmd->switch_time = iwl_add_beacon_time(priv, -+ priv->ucode_beacon_time, -+ ucode_switch_time, -+ beacon_interval); - } - IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", -- cmd.switch_time); -- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; -+ cmd->switch_time); -+ cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - -- return iwl_dvm_send_cmd(priv, &hcmd); -+ err = iwl_dvm_send_cmd(priv, &hcmd); -+ kfree(cmd); -+ return err; - } - - struct iwl_lib_ops iwl6000_lib = { diff --git a/kernel.spec b/kernel.spec index d35d03682..c28447297 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -761,15 +761,6 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 770484 -Patch22071: iwlwifi-fix-6000-ch-switch.patch - -#rhbz 862168 -Patch22073: mac80211_local_deauth_v3.6.patch - -#rhbz 866013 -Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch - #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -1503,15 +1494,6 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 770484 -ApplyPatch iwlwifi-fix-6000-ch-switch.patch - -#rhbz 862168 -ApplyPatch mac80211_local_deauth_v3.6.patch - -#rhbz 866013 -ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch - #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -2386,7 +2368,8 @@ fi # ||----w | # || || %changelog -* Wed Oct 30 2012 Josh Boyer +* Wed Oct 30 2012 Josh Boyer - 3.6.5-1 +- Linux v3.6.5 - CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) * Tue Oct 30 2012 Josh Boyer diff --git a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch deleted file mode 100644 index 8c46db671..000000000 --- a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 3a40414f826a8f1096d9b94c4a53ef91b25ba28d Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 1 Oct 2012 15:52:00 +0200 -Subject: [PATCH] mac80211: connect with HT20 if HT40 is not permitted - -Some changes to fix issues with HT40 APs in Korea -and follow-up changes to allow using HT40 even if -the local regulatory database disallows it caused -issues with iwlwifi (and could cause issues with -other devices); iwlwifi firmware would assert if -you tried to connect to an AP that has an invalid -configuration (e.g. using HT40- on channel 140.) - -Fix this, while avoiding the "Korean AP" issue by -disabling HT40 and advertising HT20 to the AP -when connecting. - -Cc: stable@vger.kernel.org [3.6] -Reported-by: Florian Reitmeir -Tested-by: Florian Reitmeir -Signed-off-by: Johannes Berg ---- - net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- - 1 files changed, 20 insertions(+), 10 deletions(-) - -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index e510a33..1b7eed2 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, - ht_cfreq, ht_oper->primary_chan, - cbss->channel->band); - ht_oper = NULL; -+ } else { -+ channel_type = NL80211_CHAN_HT20; - } - } - -- if (ht_oper) { -- channel_type = NL80211_CHAN_HT20; -+ if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -+ /* -+ * cfg80211 already verified that the channel itself can -+ * be used, but it didn't check that we can do the right -+ * HT type, so do that here as well. If HT40 isn't allowed -+ * on this channel, disable 40 MHz operation. -+ */ - -- if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -- switch (ht_oper->ht_param & -- IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: -+ switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: -+ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) -+ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; -+ else - channel_type = NL80211_CHAN_HT40PLUS; -- break; -- case IEEE80211_HT_PARAM_CHA_SEC_BELOW: -+ break; -+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: -+ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) -+ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; -+ else - channel_type = NL80211_CHAN_HT40MINUS; -- break; -- } -+ break; - } - } - --- -1.7.6.5 - diff --git a/mac80211_local_deauth_v3.6.patch b/mac80211_local_deauth_v3.6.patch deleted file mode 100644 index 3b634860f..000000000 --- a/mac80211_local_deauth_v3.6.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 3d254e1..f10553c 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request { - const u8 *ie; - size_t ie_len; - u16 reason_code; -+ bool local_state_change; - }; - - /** -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index f76b833..08343c2 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3457,6 +3457,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 frame_buf[DEAUTH_DISASSOC_LEN]; -+ bool tx = !req->local_state_change; - - mutex_lock(&ifmgd->mtx); - -@@ -3473,12 +3474,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - if (ifmgd->associated && - ether_addr_equal(ifmgd->associated->bssid, req->bssid)) - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, -- req->reason_code, true, frame_buf); -+ req->reason_code, tx, frame_buf); - else - ieee80211_send_deauth_disassoc(sdata, req->bssid, - IEEE80211_STYPE_DEAUTH, -- req->reason_code, true, -- frame_buf); -+ req->reason_code, tx, frame_buf); - mutex_unlock(&ifmgd->mtx); - - __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); -diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c -index 1cdb1d5..0877efb 100644 ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -457,21 +457,11 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, - .reason_code = reason, - .ie = ie, - .ie_len = ie_len, -+ .local_state_change = local_state_change, - }; - - ASSERT_WDEV_LOCK(wdev); - -- if (local_state_change) { -- if (wdev->current_bss && -- ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { -- cfg80211_unhold_bss(wdev->current_bss); -- cfg80211_put_bss(&wdev->current_bss->pub); -- wdev->current_bss = NULL; -- } -- -- return 0; -- } -- - return rdev->ops->deauth(&rdev->wiphy, dev, &req); - } - diff --git a/sources b/sources index 965397c16..3800ac99f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -d7efab4da2682c44662b684026b059f7 patch-3.6.4.xz +6ad8ceebb9b5c1bf69a0c07ef7cc81f2 patch-3.6.5.xz From f8f8ccfe1686ac627785e4bcf0e874c5a584a95a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 16:11:56 -0400 Subject: [PATCH 090/492] Update modsign to what is currently in 3.7-rc2 Update secure boot support for UEFI cert importing. --- config-x86-generic | 2 + kernel.spec | 26 +- mod-extra-sign.sh | 2 +- modsign-post-KS-jwb.patch | 9240 +------------ modsign-upstream-3.7.patch | 10963 ++++++++++++++++ ...120924.patch => secure-boot-20121026.patch | 691 + 6 files changed, 11686 insertions(+), 9238 deletions(-) create mode 100644 modsign-upstream-3.7.patch rename secure-boot-20120924.patch => secure-boot-20121026.patch (52%) diff --git a/config-x86-generic b/config-x86-generic index 09d63d401..b26f42d9f 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -430,3 +430,5 @@ CONFIG_MODULE_SIG=y # CONFIG_MODULE_SIG_SHA1 is not set CONFIG_MODULE_SIG_SHA256=y # CONFIG_MODULE_SIG_FORCE is not set +CONFIG_MODULE_SIG_BLACKLIST=y +CONFIG_MODULE_SIG_UEFI=y diff --git a/kernel.spec b/kernel.spec index c28447297..55ff8d5f4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -683,10 +683,11 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-post-KS-jwb.patch +Patch900: modsign-upstream-3.7.patch +Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20120924.patch +Patch1000: secure-boot-20121026.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -1436,10 +1437,11 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ +ApplyPatch modsign-upstream-3.7.patch ApplyPatch modsign-post-KS-jwb.patch # secure boot -ApplyPatch secure-boot-20120924.patch +ApplyPatch secure-boot-20121026.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1563,10 +1565,6 @@ find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null # remove unnecessary SCM files find . -name .gitignore -exec rm -f {} \; >/dev/null -%if %{signmodules} -cp %{SOURCE11} . -%endif - cd .. ### @@ -1636,6 +1634,12 @@ BuildKernel() { make -s mrproper cp configs/$Config .config + %if %{signmodules} + cp %{SOURCE11} . + %endif + + chmod +x scripts/sign-file + Arch=`head -1 .config | cut -b 3-` echo USING ARCH=$Arch @@ -2368,7 +2372,11 @@ fi # ||----w | # || || %changelog -* Wed Oct 30 2012 Josh Boyer - 3.6.5-1 +* Wed Oct 31 2012 Josh Boyer - 3.6.5-2 +- Update modsign to what is currently in 3.7-rc2 +- Update secure boot support for UEFI cert importing. + +* Wed Oct 31 2012 Josh Boyer - 3.6.5-1 - Linux v3.6.5 - CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) diff --git a/mod-extra-sign.sh b/mod-extra-sign.sh index a4b2c8cf7..9b24a4098 100755 --- a/mod-extra-sign.sh +++ b/mod-extra-sign.sh @@ -21,7 +21,7 @@ do dir=`dirname $mod` file=`basename $mod` - sh ./scripts/sign-file ${MODSECKEY} ${MODPUBKEY} ${dir}/${file} \ + ./scripts/sign-file ${MODSECKEY} ${MODPUBKEY} ${dir}/${file} \ ${dir}/${file}.signed mv ${dir}/${file}.signed ${dir}/${file} rm -f ${dir}/${file}.{sig,dig} diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch index ec61f3472..ba942170f 100644 --- a/modsign-post-KS-jwb.patch +++ b/modsign-post-KS-jwb.patch @@ -1,8800 +1,7 @@ -From 2cdfd353ac1a5b9f62398ef59b4a08b5b55ac089 Mon Sep 17 00:00:00 2001 -From: Rusty Russell -Date: Wed, 5 Sep 2012 12:32:17 +0930 -Subject: [PATCH 01/26] module: signature checking hook - -We do a very simple search for a particular string appended to the module -(which is cache-hot and about to be SHA'd anyway). There's both a config -option and a boot parameter which control whether we accept (and taint) or -fail with unsigned modules. - -Signed-off-by: Rusty Russell ---- - Documentation/kernel-parameters.txt | 6 +++ - include/linux/module.h | 8 ++++ - init/Kconfig | 14 ++++++ - kernel/module.c | 88 ++++++++++++++++++++++++++++++++++++- - 4 files changed, 115 insertions(+), 1 deletion(-) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index ad7e2e5..9b2b8d3 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - log everything. Information is printed at KERN_DEBUG - so loglevel=8 may also need to be specified. - -+ module.sig_enforce -+ [KNL] When CONFIG_MODULE_SIG is set, this means that -+ modules without (valid) signatures will fail to load. -+ Note that if CONFIG_MODULE_SIG_ENFORCE is set, that -+ is always true, so this option does nothing. -+ - mousedev.tap_time= - [MOUSE] Maximum time between finger touching and - leaving touchpad surface for touch to be considered -diff --git a/include/linux/module.h b/include/linux/module.h -index fbcafe2..7760c6d 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -21,6 +21,9 @@ - #include - #include - -+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ -+#define MODULE_SIG_STRING "~Module signature appended~\n" -+ - /* Not Yet Implemented */ - #define MODULE_SUPPORTED_DEVICE(name) - -@@ -260,6 +263,11 @@ struct module - const unsigned long *unused_gpl_crcs; - #endif - -+#ifdef CONFIG_MODULE_SIG -+ /* Signature was verified. */ -+ bool sig_ok; -+#endif -+ - /* symbols that will be GPL-only in the near future. */ - const struct kernel_symbol *gpl_future_syms; - const unsigned long *gpl_future_crcs; -diff --git a/init/Kconfig b/init/Kconfig -index af6c7f8..7452e19 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL - the version). With this option, such a "srcversion" field - will be created for all modules. If unsure, say N. - -+config MODULE_SIG -+ bool "Module signature verification" -+ depends on MODULES -+ help -+ Check modules for valid signatures upon load: the signature -+ is simply appended to the module. For more information see -+ Documentation/module-signing.txt. -+ -+config MODULE_SIG_FORCE -+ bool "Require modules to be validly signed" -+ depends on MODULE_SIG -+ help -+ Reject unsigned modules or signed modules for which we don't have a -+ key. Without this, such modules will simply taint the kernel. - endif # MODULES - - config INIT_ALL_POSSIBLE -diff --git a/kernel/module.c b/kernel/module.c -index 4edbd9c..5c6f65c 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -102,6 +102,43 @@ static LIST_HEAD(modules); - struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - #endif /* CONFIG_KGDB_KDB */ - -+#ifdef CONFIG_MODULE_SIG -+#ifdef CONFIG_MODULE_SIG_FORCE -+static bool sig_enforce = true; -+#else -+static bool sig_enforce = false; -+ -+static int param_set_bool_enable_only(const char *val, -+ const struct kernel_param *kp) -+{ -+ int err; -+ bool test; -+ struct kernel_param dummy_kp = *kp; -+ -+ dummy_kp.arg = &test; -+ -+ err = param_set_bool(val, &dummy_kp); -+ if (err) -+ return err; -+ -+ /* Don't let them unset it once it's set! */ -+ if (!test && sig_enforce) -+ return -EROFS; -+ -+ if (test) -+ sig_enforce = true; -+ return 0; -+} -+ -+static const struct kernel_param_ops param_ops_bool_enable_only = { -+ .set = param_set_bool_enable_only, -+ .get = param_get_bool, -+}; -+#define param_check_bool_enable_only param_check_bool -+ -+module_param(sig_enforce, bool_enable_only, 0644); -+#endif /* !CONFIG_MODULE_SIG_FORCE */ -+#endif /* CONFIG_MODULE_SIG */ - - /* Block module loading/unloading? */ - int modules_disabled = 0; -@@ -136,6 +173,7 @@ struct load_info { - unsigned long symoffs, stroffs; - struct _ddebug *debug; - unsigned int num_debug; -+ bool sig_ok; - struct { - unsigned int sym, str, mod, vers, info, pcpu; - } index; -@@ -2399,7 +2437,45 @@ static inline void kmemleak_load_module(const struct module *mod, - } - #endif - --/* Sets info->hdr and info->len. */ -+#ifdef CONFIG_MODULE_SIG -+static int module_sig_check(struct load_info *info, -+ const void *mod, unsigned long *len) -+{ -+ int err = 0; -+ const unsigned long markerlen = strlen(MODULE_SIG_STRING); -+ const void *p = mod, *end = mod + *len; -+ -+ /* Poor man's memmem. */ -+ while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -+ if (p + markerlen > end) -+ break; -+ -+ if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -+ const void *sig = p + markerlen; -+ /* Truncate module up to signature. */ -+ *len = p - mod; -+ err = mod_verify_sig(mod, *len, -+ sig, end - sig, -+ &info->sig_ok); -+ break; -+ } -+ p++; -+ } -+ -+ /* Not having a signature is only an error if we're strict. */ -+ if (!err && !info->sig_ok && sig_enforce) -+ err = -EKEYREJECTED; -+ return err; -+} -+#else /* !CONFIG_MODULE_SIG */ -+static int module_sig_check(struct load_info *info, -+ void *mod, unsigned long *len) -+{ -+ return 0; -+} -+#endif /* !CONFIG_MODULE_SIG */ -+ -+/* Sets info->hdr, info->len and info->sig_ok. */ - static int copy_and_check(struct load_info *info, - const void __user *umod, unsigned long len, - const char __user *uargs) -@@ -2419,6 +2495,10 @@ static int copy_and_check(struct load_info *info, - goto free_hdr; - } - -+ err = module_sig_check(info, hdr, &len); -+ if (err) -+ goto free_hdr; -+ - /* Sanity checks against insmoding binaries or wrong arch, - weird elf version */ - if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 -@@ -2886,6 +2966,12 @@ static struct module *load_module(void __user *umod, - goto free_copy; - } - -+#ifdef CONFIG_MODULE_SIG -+ mod->sig_ok = info.sig_ok; -+ if (!mod->sig_ok) -+ add_taint_module(mod, TAINT_FORCED_MODULE); -+#endif -+ - /* Now module is in final location, initialize linked lists, etc. */ - err = module_unload_init(mod); - if (err) --- -1.7.11.4 - - -From d4f65b5d2497b2fd9c45f06b71deb4ab084a5b66 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 13:06:29 +0100 -Subject: [PATCH 02/26] KEYS: Add payload preparsing opportunity prior to key - instantiate or update - -Give the key type the opportunity to preparse the payload prior to the -instantiation and update routines being called. This is done with the -provision of two new key type operations: - - int (*preparse)(struct key_preparsed_payload *prep); - void (*free_preparse)(struct key_preparsed_payload *prep); - -If the first operation is present, then it is called before key creation (in -the add/update case) or before the key semaphore is taken (in the update and -instantiate cases). The second operation is called to clean up if the first -was called. - -preparse() is given the opportunity to fill in the following structure: - - struct key_preparsed_payload { - char *description; - void *type_data[2]; - void *payload; - const void *data; - size_t datalen; - size_t quotalen; - }; - -Before the preparser is called, the first three fields will have been cleared, -the payload pointer and size will be stored in data and datalen and the default -quota size from the key_type struct will be stored into quotalen. - -The preparser may parse the payload in any way it likes and may store data in -the type_data[] and payload fields for use by the instantiate() and update() -ops. - -The preparser may also propose a description for the key by attaching it as a -string to the description field. This can be used by passing a NULL or "" -description to the add_key() system call or the key_create_or_update() -function. This cannot work with request_key() as that required the description -to tell the upcall about the key to be created. - -This, for example permits keys that store PGP public keys to generate their own -name from the user ID and public key fingerprint in the key. - -The instantiate() and update() operations are then modified to look like this: - - int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - int (*update)(struct key *key, struct key_preparsed_payload *prep); - -and the new payload data is passed in *prep, whether or not it was preparsed. - -Signed-off-by: David Howells ---- - Documentation/security/keys.txt | 50 +++++++++++++- - fs/cifs/cifs_spnego.c | 6 +- - fs/cifs/cifsacl.c | 8 +-- - include/keys/user-type.h | 6 +- - include/linux/key-type.h | 35 +++++++++- - net/ceph/crypto.c | 9 +-- - net/dns_resolver/dns_key.c | 6 +- - net/rxrpc/ar-key.c | 40 +++++------ - security/keys/encrypted-keys/encrypted.c | 16 +++-- - security/keys/key.c | 114 ++++++++++++++++++++++--------- - security/keys/keyctl.c | 18 +++-- - security/keys/keyring.c | 6 +- - security/keys/request_key_auth.c | 8 +-- - security/keys/trusted.c | 16 +++-- - security/keys/user_defined.c | 14 ++-- - 15 files changed, 250 insertions(+), 102 deletions(-) - -diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt -index aa0dbd7..7d9ca92 100644 ---- a/Documentation/security/keys.txt -+++ b/Documentation/security/keys.txt -@@ -412,6 +412,10 @@ The main syscalls are: - to the keyring. In this case, an error will be generated if the process - does not have permission to write to the keyring. - -+ If the key type supports it, if the description is NULL or an empty -+ string, the key type will try and generate a description from the content -+ of the payload. -+ - The payload is optional, and the pointer can be NULL if not required by - the type. The payload is plen in size, and plen can be zero for an empty - payload. -@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: - it should return 0. - - -- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ (*) int (*preparse)(struct key_preparsed_payload *prep); -+ -+ This optional method permits the key type to attempt to parse payload -+ before a key is created (add key) or the key semaphore is taken (update or -+ instantiate key). The structure pointed to by prep looks like: -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ Before calling the method, the caller will fill in data and datalen with -+ the payload blob parameters; quotalen will be filled in with the default -+ quota size from the key type and the rest will be cleared. -+ -+ If a description can be proposed from the payload contents, that should be -+ attached as a string to the description field. This will be used for the -+ key description if the caller of add_key() passes NULL or "". -+ -+ The method can attach anything it likes to type_data[] and payload. These -+ are merely passed along to the instantiate() or update() operations. -+ -+ The method should return 0 if success ful or a negative error code -+ otherwise. -+ -+ -+ (*) void (*free_preparse)(struct key_preparsed_payload *prep); -+ -+ This method is only required if the preparse() method is provided, -+ otherwise it is unused. It cleans up anything attached to the -+ description, type_data and payload fields of the key_preparsed_payload -+ struct as filled in by the preparse() method. -+ -+ -+ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - This method is called to attach a payload to a key during construction. - The payload attached need not bear any relation to the data passed to this - function. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - If the amount of data attached to the key differs from the size in - keytype->def_datalen, then key_payload_reserve() should be called. - -@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: - If this type of key can be updated, then this method should be provided. - It is called to update a key's payload from the blob of data provided. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - key_payload_reserve() should be called if the data length might change - before any changes are actually made. Note that if this succeeds, the type - is committed to changing the key because it's already been altered, so all -diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c -index e622863..086f381 100644 ---- a/fs/cifs/cifs_spnego.c -+++ b/fs/cifs/cifs_spnego.c -@@ -31,18 +31,18 @@ - - /* create a new cifs key */ - static int --cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - int ret; - - ret = -ENOMEM; -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - goto error; - - /* attach the data */ -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; - ret = 0; - -diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c -index 05f4dc2..f3c60e2 100644 ---- a/fs/cifs/cifsacl.c -+++ b/fs/cifs/cifsacl.c -@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { - }; - - static int --cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - return -ENOMEM; - -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; -- key->datalen = datalen; -+ key->datalen = prep->datalen; - return 0; - } - -diff --git a/include/keys/user-type.h b/include/keys/user-type.h -index bc9ec1d..5e452c8 100644 ---- a/include/keys/user-type.h -+++ b/include/keys/user-type.h -@@ -35,8 +35,10 @@ struct user_key_payload { - extern struct key_type key_type_user; - extern struct key_type key_type_logon; - --extern int user_instantiate(struct key *key, const void *data, size_t datalen); --extern int user_update(struct key *key, const void *data, size_t datalen); -+struct key_preparsed_payload; -+ -+extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); -+extern int user_update(struct key *key, struct key_preparsed_payload *prep); - extern int user_match(const struct key *key, const void *criterion); - extern void user_revoke(struct key *key); - extern void user_destroy(struct key *key); -diff --git a/include/linux/key-type.h b/include/linux/key-type.h -index f0c651c..518a53a 100644 ---- a/include/linux/key-type.h -+++ b/include/linux/key-type.h -@@ -26,6 +26,27 @@ struct key_construction { - struct key *authkey;/* authorisation for key being constructed */ - }; - -+/* -+ * Pre-parsed payload, used by key add, update and instantiate. -+ * -+ * This struct will be cleared and data and datalen will be set with the data -+ * and length parameters from the caller and quotalen will be set from -+ * def_datalen from the key type. Then if the preparse() op is provided by the -+ * key type, that will be called. Then the struct will be passed to the -+ * instantiate() or the update() op. -+ * -+ * If the preparse() op is given, the free_preparse() op will be called to -+ * clear the contents. -+ */ -+struct key_preparsed_payload { -+ char *description; /* Proposed key description (or NULL) */ -+ void *type_data[2]; /* Private key-type data */ -+ void *payload; /* Proposed payload */ -+ const void *data; /* Raw data */ -+ size_t datalen; /* Raw datalen */ -+ size_t quotalen; /* Quota length for proposed payload */ -+}; -+ - typedef int (*request_key_actor_t)(struct key_construction *key, - const char *op, void *aux); - -@@ -45,18 +66,28 @@ struct key_type { - /* vet a description */ - int (*vet_description)(const char *description); - -+ /* Preparse the data blob from userspace that is to be the payload, -+ * generating a proposed description and payload that will be handed to -+ * the instantiate() and update() ops. -+ */ -+ int (*preparse)(struct key_preparsed_payload *prep); -+ -+ /* Free a preparse data structure. -+ */ -+ void (*free_preparse)(struct key_preparsed_payload *prep); -+ - /* instantiate a key of this type - * - this method should call key_payload_reserve() to determine if the - * user's quota will hold the payload - */ -- int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - /* update a key of this type (optional) - * - this method should call key_payload_reserve() to recalculate the - * quota consumption - * - the key must be locked against read when modifying - */ -- int (*update)(struct key *key, const void *data, size_t datalen); -+ int (*update)(struct key *key, struct key_preparsed_payload *prep); - - /* match a key against a description */ - int (*match)(const struct key *key, const void *desc); -diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c -index 9da7fdd..af14cb4 100644 ---- a/net/ceph/crypto.c -+++ b/net/ceph/crypto.c -@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, - } - } - --int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) -+int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct ceph_crypto_key *ckey; -+ size_t datalen = prep->datalen; - int ret; - void *p; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto err; - - ret = key_payload_reserve(key, datalen); -@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) - goto err; - - /* TODO ceph_crypto_key_decode should really take const input */ -- p = (void *)data; -- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); -+ p = (void *)prep->data; -+ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); - if (ret < 0) - goto err_ckey; - -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index d9507dd..859ab8b 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; - * "ip1,ip2,...#foo=bar" - */ - static int --dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) -+dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; - unsigned long derrno; - int ret; -- size_t result_len = 0; -- const char *data = _data, *end, *opt; -+ size_t datalen = prep->datalen, result_len = 0; -+ const char *data = prep->data, *end, *opt; - - kenter("%%%d,%s,'%*.*s',%zu", - key->serial, key->description, -diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c -index 8b1f9f4..106c5a6 100644 ---- a/net/rxrpc/ar-key.c -+++ b/net/rxrpc/ar-key.c -@@ -26,8 +26,8 @@ - #include "ar-internal.h" - - static int rxrpc_vet_description_s(const char *); --static int rxrpc_instantiate(struct key *, const void *, size_t); --static int rxrpc_instantiate_s(struct key *, const void *, size_t); -+static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); -+static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); - static void rxrpc_destroy(struct key *); - static void rxrpc_destroy_s(struct key *); - static void rxrpc_describe(const struct key *, struct seq_file *); -@@ -678,7 +678,7 @@ error: - * - * if no data is provided, then a no-security key is made - */ --static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) -+static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - const struct rxrpc_key_data_v1 *v1; - struct rxrpc_key_token *token, **pp; -@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - u32 kver; - int ret; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - - /* handle a no-security key */ -- if (!data && datalen == 0) -+ if (!prep->data && prep->datalen == 0) - return 0; - - /* determine if the XDR payload format is being used */ -- if (datalen > 7 * 4) { -- ret = rxrpc_instantiate_xdr(key, data, datalen); -+ if (prep->datalen > 7 * 4) { -+ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); - if (ret != -EPROTO) - return ret; - } - - /* get the key interface version number */ - ret = -EINVAL; -- if (datalen <= 4 || !data) -+ if (prep->datalen <= 4 || !prep->data) - goto error; -- memcpy(&kver, data, sizeof(kver)); -- data += sizeof(kver); -- datalen -= sizeof(kver); -+ memcpy(&kver, prep->data, sizeof(kver)); -+ prep->data += sizeof(kver); -+ prep->datalen -= sizeof(kver); - - _debug("KEY I/F VERSION: %u", kver); - -@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - - /* deal with a version 1 key */ - ret = -EINVAL; -- if (datalen < sizeof(*v1)) -+ if (prep->datalen < sizeof(*v1)) - goto error; - -- v1 = data; -- if (datalen != sizeof(*v1) + v1->ticket_length) -+ v1 = prep->data; -+ if (prep->datalen != sizeof(*v1) + v1->ticket_length) - goto error; - - _debug("SCIX: %u", v1->security_index); -@@ -784,17 +784,17 @@ error: - * instantiate a server secret key - * data should be a pointer to the 8-byte secret key - */ --static int rxrpc_instantiate_s(struct key *key, const void *data, -- size_t datalen) -+static int rxrpc_instantiate_s(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct crypto_blkcipher *ci; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - -- if (datalen != 8) -+ if (prep->datalen != 8) - return -EINVAL; - -- memcpy(&key->type_data, data, 8); -+ memcpy(&key->type_data, prep->data, 8); - - ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(ci)) { -@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, - return PTR_ERR(ci); - } - -- if (crypto_blkcipher_setkey(ci, data, 8) < 0) -+ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) - BUG(); - - key->payload.data = ci; -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 2d1bb8a..9e1e005 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int encrypted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = NULL; - char *datablob = NULL; -@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, - char *master_desc = NULL; - char *decrypted_datalen = NULL; - char *hex_encoded_iv = NULL; -+ size_t datalen = prep->datalen; - int ret; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; - datablob[datalen] = 0; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - ret = datablob_parse(datablob, &format, &master_desc, - &decrypted_datalen, &hex_encoded_iv); - if (ret < 0) -@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_update(struct key *key, const void *data, size_t datalen) -+static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = key->payload.data; - struct encrypted_key_payload *new_epayload; - char *buf; - char *new_master_desc = NULL; - const char *format = NULL; -+ size_t datalen = prep->datalen; - int ret = 0; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - buf = kmalloc(datalen + 1, GFP_KERNEL); -@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) - return -ENOMEM; - - buf[datalen] = 0; -- memcpy(buf, data, datalen); -+ memcpy(buf, prep->data, datalen); - ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); - if (ret < 0) - goto out; -diff --git a/security/keys/key.c b/security/keys/key.c -index 50d96d4..1d039af 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); - * key_construction_mutex. - */ - static int __key_instantiate_and_link(struct key *key, -- const void *data, -- size_t datalen, -+ struct key_preparsed_payload *prep, - struct key *keyring, - struct key *authkey, - unsigned long *_prealloc) -@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, - /* can't instantiate twice */ - if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { - /* instantiate the key */ -- ret = key->type->instantiate(key, data, datalen); -+ ret = key->type->instantiate(key, prep); - - if (ret == 0) { - /* mark the key as being instantiated */ -@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, - struct key *keyring, - struct key *authkey) - { -+ struct key_preparsed_payload prep; - unsigned long prealloc; - int ret; - -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = data; -+ prep.datalen = datalen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; -+ } -+ - if (keyring) { - ret = __key_link_begin(keyring, key->type, key->description, - &prealloc); - if (ret < 0) -- return ret; -+ goto error_free_preparse; - } - -- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, -+ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, - &prealloc); - - if (keyring) - __key_link_end(keyring, key->type, prealloc); - -+error_free_preparse: -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - -@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) - * if we get an error. - */ - static inline key_ref_t __key_update(key_ref_t key_ref, -- const void *payload, size_t plen) -+ struct key_preparsed_payload *prep) - { - struct key *key = key_ref_to_ptr(key_ref); - int ret; -@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, - - down_write(&key->sem); - -- ret = key->type->update(key, payload, plen); -+ ret = key->type->update(key, prep); - if (ret == 0) - /* updating a negative key instantiates it */ - clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - unsigned long flags) - { - unsigned long prealloc; -+ struct key_preparsed_payload prep; - const struct cred *cred = current_cred(); - struct key_type *ktype; - struct key *keyring, *key = NULL; -@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - } - - key_ref = ERR_PTR(-EINVAL); -- if (!ktype->match || !ktype->instantiate) -- goto error_2; -+ if (!ktype->match || !ktype->instantiate || -+ (!description && !ktype->preparse)) -+ goto error_put_type; - - keyring = key_ref_to_ptr(keyring_ref); - -@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - - key_ref = ERR_PTR(-ENOTDIR); - if (keyring->type != &key_type_keyring) -- goto error_2; -+ goto error_put_type; -+ -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = ktype->def_datalen; -+ if (ktype->preparse) { -+ ret = ktype->preparse(&prep); -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_put_type; -+ } -+ if (!description) -+ description = prep.description; -+ key_ref = ERR_PTR(-EINVAL); -+ if (!description) -+ goto error_free_prep; -+ } - - ret = __key_link_begin(keyring, ktype, description, &prealloc); -- if (ret < 0) -- goto error_2; -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_free_prep; -+ } - - /* if we're going to allocate a new key, we're going to have - * to modify the keyring */ - ret = key_permission(keyring_ref, KEY_WRITE); - if (ret < 0) { - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - /* if it's possible to update this type of key, search for an existing -@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - perm, flags); - if (IS_ERR(key)) { - key_ref = ERR_CAST(key); -- goto error_3; -+ goto error_link_end; - } - - /* instantiate it and link it into the target keyring */ -- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, -- &prealloc); -+ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); - if (ret < 0) { - key_put(key); - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); - -- error_3: -+error_link_end: - __key_link_end(keyring, ktype, prealloc); -- error_2: -+error_free_prep: -+ if (ktype->preparse) -+ ktype->free_preparse(&prep); -+error_put_type: - key_type_put(ktype); -- error: -+error: - return key_ref; - - found_matching_key: -@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - * - we can drop the locks first as we have the key pinned - */ - __key_link_end(keyring, ktype, prealloc); -- key_type_put(ktype); - -- key_ref = __key_update(key_ref, payload, plen); -- goto error; -+ key_ref = __key_update(key_ref, &prep); -+ goto error_free_prep; - } - EXPORT_SYMBOL(key_create_or_update); - -@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); - */ - int key_update(key_ref_t key_ref, const void *payload, size_t plen) - { -+ struct key_preparsed_payload prep; - struct key *key = key_ref_to_ptr(key_ref); - int ret; - -@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - - /* attempt to update it if supported */ - ret = -EOPNOTSUPP; -- if (key->type->update) { -- down_write(&key->sem); -- -- ret = key->type->update(key, payload, plen); -- if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ if (!key->type->update) -+ goto error; - -- up_write(&key->sem); -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; - } - -- error: -+ down_write(&key->sem); -+ -+ ret = key->type->update(key, &prep); -+ if (ret == 0) -+ /* updating a negative key instantiates it */ -+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ -+ up_write(&key->sem); -+ -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - EXPORT_SYMBOL(key_update); -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 3364fbf..505d40b 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, - * Extract the description of a new key from userspace and either add it as a - * new key to the specified keyring or update a matching key in that keyring. - * -+ * If the description is NULL or an empty string, the key type is asked to -+ * generate one from the payload. -+ * - * The keyring must be writable so that we can attach the key to it. - * - * If successful, the new key's serial number is returned, otherwise an error -@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, - if (ret < 0) - goto error; - -- description = strndup_user(_description, PAGE_SIZE); -- if (IS_ERR(description)) { -- ret = PTR_ERR(description); -- goto error; -+ description = NULL; -+ if (_description) { -+ description = strndup_user(_description, PAGE_SIZE); -+ if (IS_ERR(description)) { -+ ret = PTR_ERR(description); -+ goto error; -+ } -+ if (!*description) { -+ kfree(description); -+ description = NULL; -+ } - } - - /* pull the payload in if one was supplied */ -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index 81e7852..f04d8cf 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) - * operations. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen); -+ struct key_preparsed_payload *prep); - static int keyring_match(const struct key *keyring, const void *criterion); - static void keyring_revoke(struct key *keyring); - static void keyring_destroy(struct key *keyring); -@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) - * Returns 0 on success, -EINVAL if given any data. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen) -+ struct key_preparsed_payload *prep) - { - int ret; - - ret = -EINVAL; -- if (datalen == 0) { -+ if (prep->datalen == 0) { - /* make the keyring available by name if it has one */ - keyring_publish_name(keyring); - ret = 0; -diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c -index 60d4e3f..85730d5 100644 ---- a/security/keys/request_key_auth.c -+++ b/security/keys/request_key_auth.c -@@ -19,7 +19,8 @@ - #include - #include "internal.h" - --static int request_key_auth_instantiate(struct key *, const void *, size_t); -+static int request_key_auth_instantiate(struct key *, -+ struct key_preparsed_payload *); - static void request_key_auth_describe(const struct key *, struct seq_file *); - static void request_key_auth_revoke(struct key *); - static void request_key_auth_destroy(struct key *); -@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { - * Instantiate a request-key authorisation key. - */ - static int request_key_auth_instantiate(struct key *key, -- const void *data, -- size_t datalen) -+ struct key_preparsed_payload *prep) - { -- key->payload.data = (struct request_key_auth *) data; -+ key->payload.data = (struct request_key_auth *)prep->data; - return 0; - } - -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 2d5d041..42036c7 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) - * - * On success, return 0. Otherwise return errno. - */ --static int trusted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int trusted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct trusted_key_payload *payload = NULL; - struct trusted_key_options *options = NULL; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - int key_cmd; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - - options = trusted_options_alloc(); -@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) - /* - * trusted_update - reseal an existing key with new PCR values - */ --static int trusted_update(struct key *key, const void *data, size_t datalen) -+static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct trusted_key_payload *p = key->payload.data; - struct trusted_key_payload *new_p; - struct trusted_key_options *new_o; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - - if (!p->migratable) - return -EPERM; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); -@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) - goto out; - } - -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { -diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c -index c7660a2..55dc889 100644 ---- a/security/keys/user_defined.c -+++ b/security/keys/user_defined.c -@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); - /* - * instantiate a user defined key - */ --int user_instantiate(struct key *key, const void *data, size_t datalen) -+int user_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - ret = key_payload_reserve(key, datalen); -@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) - - /* attach the data */ - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - rcu_assign_keypointer(key, upayload); - ret = 0; - -@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); - * update a user defined key - * - the key's semaphore is write-locked - */ --int user_update(struct key *key, const void *data, size_t datalen) -+int user_update(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload, *zap; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - /* construct a replacement payload */ -@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) - goto error; - - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - - /* check the quota and attach the new data */ - zap = upayload; --- -1.7.11.4 - - -From a3f7dff6cbc2eb6be871a58fef34cacf7f78abf8 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 13:09:33 +0100 -Subject: [PATCH 03/26] MPILIB: Provide count_leading/trailing_zeros() based - on arch functions - -Provide count_leading/trailing_zeros() macros based on extant arch bit scanning -functions rather than reimplementing from scratch in MPILIB. - -Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). - -Also move the definition to asm-generic as other people may be interested in -using it. - -Signed-off-by: David Howells -Cc: David S. Miller -Cc: Dmitry Kasatkin -Cc: Arnd Bergmann ---- - include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ - lib/mpi/longlong.h | 138 +------------------------------ - lib/mpi/mpi-bit.c | 2 +- - lib/mpi/mpi-pow.c | 4 +- - 4 files changed, 62 insertions(+), 139 deletions(-) - create mode 100644 include/asm-generic/bitops/count_zeros.h - -diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h -new file mode 100644 -index 0000000..97520d2 ---- /dev/null -+++ b/include/asm-generic/bitops/count_zeros.h -@@ -0,0 +1,57 @@ -+/* Count leading and trailing zeros functions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+ -+#include -+ -+/** -+ * count_leading_zeros - Count the number of zeros from the MSB back -+ * @x: The value -+ * -+ * Count the number of leading zeros from the MSB going towards the LSB in @x. -+ * -+ * If the MSB of @x is set, the result is 0. -+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. -+ */ -+static inline int count_leading_zeros(unsigned long x) -+{ -+ if (sizeof(x) == 4) -+ return BITS_PER_LONG - fls(x); -+ else -+ return BITS_PER_LONG - fls64(x); -+} -+ -+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG -+ -+/** -+ * count_trailing_zeros - Count the number of zeros from the LSB forwards -+ * @x: The value -+ * -+ * Count the number of trailing zeros from the LSB going towards the MSB in @x. -+ * -+ * If the LSB of @x is set, the result is 0. -+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. -+ */ -+static inline int count_trailing_zeros(unsigned long x) -+{ -+#define COUNT_TRAILING_ZEROS_0 (-1) -+ -+ if (sizeof(x) == 4) -+ return ffs(x); -+ else -+ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; -+} -+ -+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ -diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h -index 29f9862..678ce4f 100644 ---- a/lib/mpi/longlong.h -+++ b/lib/mpi/longlong.h -@@ -19,6 +19,8 @@ - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. */ - -+#include -+ - /* You have to define the following before including this file: - * - * UWtype -- An unsigned type, default type for operations (typically a "word") -@@ -146,12 +148,6 @@ do { \ - : "1" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))) -- --#define count_leading_zeros(count, x) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #endif /* __a29k__ */ - - #if defined(__alpha) && W_TYPE_SIZE == 64 -@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); - : "1" ((USItype)(nh)), \ - "0" ((USItype)(nl)), \ - "g" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bsch/1 %1,%0" \ -- : "=g" (count) \ -- : "g" ((USItype)(x)), \ -- "0" ((USItype)0)) - #endif - - /*************************************** -@@ -354,27 +345,6 @@ do { USItype __r; \ - } while (0) - extern USItype __udiv_qrnnd(); - #endif /* LONGLONG_STANDALONE */ --#define count_leading_zeros(count, x) \ --do { \ -- USItype __tmp; \ -- __asm__ ( \ -- "ldi 1,%0\n" \ -- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ -- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ -- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ -- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ -- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ -- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ -- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ -- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ -- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ -- "extru %1,30,1,%1 ; Extract bit 1.\n" \ -- "sub %0,%1,%0 ; Subtract it. " \ -- : "=r" (count), "=r" (__tmp) : "1" (x)); \ --} while (0) - #endif /* hppa */ - - /*************************************** -@@ -457,15 +427,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "rm" ((USItype)(d))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("bsrl %1,%0" \ -- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define count_trailing_zeros(count, x) \ -- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) - #ifndef UMUL_TIME - #define UMUL_TIME 40 - #endif -@@ -536,15 +497,6 @@ do { \ - "dI" ((USItype)(d))); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("scanbit %1,%0" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ - #if defined(__i960mx) /* what is the proper symbol to test??? */ - #define rshift_rhlc(r, h, l, c) \ - do { \ -@@ -603,11 +555,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bfffo %1{%b2:%b2},%0" \ -- : "=d" ((USItype)(count)) \ -- : "od" ((USItype)(x)), "n" (0)) --#define COUNT_LEADING_ZEROS_0 32 - #else /* not mc68020 */ - #define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ -@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ - "rJ" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("ff1 %0,%1" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 63 /* sic */ - #if defined(__m88110__) - #define umul_ppmm(wh, wl, u, v) \ - do { \ -@@ -779,12 +717,6 @@ do { \ - : "0" (__xx.__ll), \ - "g" ((USItype)(d))); \ - (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) --#define count_trailing_zeros(count, x) \ --do { \ -- __asm__("ffsd %2,%0" \ -- : "=r"((USItype) (count)) \ -- : "0"((USItype) 0), "r"((USItype) (x))); \ -- } while (0) - #endif /* __ns32000__ */ - - /*************************************** -@@ -855,11 +787,6 @@ do { \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - } while (0) --#define count_leading_zeros(count, x) \ -- __asm__ ("{cntlz|cntlzw} %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #if defined(_ARCH_PPC) - #define umul_ppmm(ph, pl, m0, m1) \ - do { \ -@@ -1001,19 +928,6 @@ do { \ - } while (0) - #define UMUL_TIME 20 - #define UDIV_TIME 200 --#define count_leading_zeros(count, x) \ --do { \ -- if ((x) >= 0x10000) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x) >> 16)); \ -- else { \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))); \ -- (count) += 16; \ -- } \ --} while (0) - #endif /* RT/ROMP */ - - /*************************************** -@@ -1142,13 +1056,6 @@ do { \ - "rI" ((USItype)(d)) \ - : "%g1" __AND_CLOBBER_CC) - #define UDIV_TIME 37 --#define count_leading_zeros(count, x) \ -- __asm__ ("scan %1,0,%0" \ -- : "=r" ((USItype)(x)) \ -- : "r" ((USItype)(count))) --/* Early sparclites return 63 for an argument of 0, but they warn that future -- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 -- undefined. */ - #endif /* __sparclite__ */ - #endif /* __sparc_v8__ */ - /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -@@ -1454,47 +1361,6 @@ do { \ - #define udiv_qrnnd __udiv_qrnnd_c - #endif - --#undef count_leading_zeros --#if !defined(count_leading_zeros) -- extern --#ifdef __STDC__ -- const --#endif -- unsigned char __clz_tab[]; --#define count_leading_zeros(count, x) \ --do { \ -- UWtype __xr = (x); \ -- UWtype __a; \ -- \ -- if (W_TYPE_SIZE <= 32) { \ -- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ -- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ -- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ -- } \ -- else { \ -- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ -- if (((__xr >> __a) & 0xff) != 0) \ -- break; \ -- } \ -- \ -- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ --} while (0) -- /* This version gives a well-defined value for zero. */ --#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE --#endif -- --#if !defined(count_trailing_zeros) --/* Define count_trailing_zeros using count_leading_zeros. The latter might be -- defined in asm, but if it is not, the C version above is good enough. */ --#define count_trailing_zeros(count, x) \ --do { \ -- UWtype __ctz_x = (x); \ -- UWtype __ctz_c; \ -- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ -- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ --} while (0) --#endif -- - #ifndef UDIV_NEEDS_NORMALIZATION - #define UDIV_NEEDS_NORMALIZATION 0 - #endif -diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c -index 5687248..503537e 100644 ---- a/lib/mpi/mpi-bit.c -+++ b/lib/mpi/mpi-bit.c -@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) - if (a->nlimbs) { - mpi_limb_t alimb = a->d[a->nlimbs - 1]; - if (alimb) -- count_leading_zeros(n, alimb); -+ n = count_leading_zeros(alimb); - else - n = BITS_PER_MPI_LIMB; - n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index 67f3e79..5464c87 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - mp = mp_marker = mpi_alloc_limb_space(msize); - if (!mp) - goto enomem; -- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); -+ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); - if (mod_shift_cnt) - mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); - else -@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - - i = esize - 1; - e = ep[i]; -- count_leading_zeros(c, e); -+ c = count_leading_zeros(e); - e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ - c = BITS_PER_MPI_LIMB - 1 - c; - --- -1.7.11.4 - - -From 79e4c942f35117b405402acf0f075ff79260e546 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 04/26] KEYS: Document asymmetric key type - -In-source documentation for the asymmetric key type. This will be located in: - - Documentation/crypto/asymmetric-keys.txt - -Signed-off-by: David Howells ---- - Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++ - 1 file changed, 312 insertions(+) - create mode 100644 Documentation/crypto/asymmetric-keys.txt - -diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt -new file mode 100644 -index 0000000..b767590 ---- /dev/null -+++ b/Documentation/crypto/asymmetric-keys.txt -@@ -0,0 +1,312 @@ -+ ============================================= -+ ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE -+ ============================================= -+ -+Contents: -+ -+ - Overview. -+ - Key identification. -+ - Accessing asymmetric keys. -+ - Signature verification. -+ - Asymmetric key subtypes. -+ - Instantiation data parsers. -+ -+ -+======== -+OVERVIEW -+======== -+ -+The "asymmetric" key type is designed to be a container for the keys used in -+public-key cryptography, without imposing any particular restrictions on the -+form or mechanism of the cryptography or form of the key. -+ -+The asymmetric key is given a subtype that defines what sort of data is -+associated with the key and provides operations to describe and destroy it. -+However, no requirement is made that the key data actually be stored in the -+key. -+ -+A completely in-kernel key retention and operation subtype can be defined, but -+it would also be possible to provide access to cryptographic hardware (such as -+a TPM) that might be used to both retain the relevant key and perform -+operations using that key. In such a case, the asymmetric key would then -+merely be an interface to the TPM driver. -+ -+Also provided is the concept of a data parser. Data parsers are responsible -+for extracting information from the blobs of data passed to the instantiation -+function. The first data parser that recognises the blob gets to set the -+subtype of the key and define the operations that can be done on that key. -+ -+A data parser may interpret the data blob as containing the bits representing a -+key, or it may interpret it as a reference to a key held somewhere else in the -+system (for example, a TPM). -+ -+ -+================== -+KEY IDENTIFICATION -+================== -+ -+If a key is added with an empty name, the instantiation data parsers are given -+the opportunity to pre-parse a key and to determine the description the key -+should be given from the content of the key. -+ -+This can then be used to refer to the key, either by complete match or by -+partial match. The key type may also use other criteria to refer to a key. -+ -+The asymmetric key type's match function can then perform a wider range of -+comparisons than just the straightforward comparison of the description with -+the criterion string: -+ -+ (1) If the criterion string is of the form "id:" then the match -+ function will examine a key's fingerprint to see if the hex digits given -+ after the "id:" match the tail. For instance: -+ -+ keyctl search @s asymmetric id:5acc2142 -+ -+ will match a key with fingerprint: -+ -+ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 -+ -+ (2) If the criterion string is of the form ":" then the -+ match will match the ID as in (1), but with the added restriction that -+ only keys of the specified subtype (e.g. tpm) will be matched. For -+ instance: -+ -+ keyctl search @s asymmetric tpm:5acc2142 -+ -+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are -+displayed, along with the subtype: -+ -+ 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] -+ -+ -+========================= -+ACCESSING ASYMMETRIC KEYS -+========================= -+ -+For general access to asymmetric keys from within the kernel, the following -+inclusion is required: -+ -+ #include -+ -+This gives access to functions for dealing with asymmetric / public keys. -+Three enums are defined there for representing public-key cryptography -+algorithms: -+ -+ enum pkey_algo -+ -+digest algorithms used by those: -+ -+ enum pkey_hash_algo -+ -+and key identifier representations: -+ -+ enum pkey_id_type -+ -+Note that the key type representation types are required because key -+identifiers from different standards aren't necessarily compatible. For -+instance, PGP generates key identifiers by hashing the key data plus some -+PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. -+ -+The operations defined upon a key are: -+ -+ (1) Signature verification. -+ -+Other operations are possible (such as encryption) with the same key data -+required for verification, but not currently supported, and others -+(eg. decryption and signature generation) require extra key data. -+ -+ -+SIGNATURE VERIFICATION -+---------------------- -+ -+An operation is provided to perform cryptographic signature verification, using -+an asymmetric key to provide or to provide access to the public key. -+ -+ int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ -+The caller must have already obtained the key from some source and can then use -+it to check the signature. The caller must have parsed the signature and -+transferred the relevant bits to the structure pointed to by sig. -+ -+ struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ u8 nr_mpi; -+ union { -+ MPI mpi[2]; -+ ... -+ }; -+ }; -+ -+The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that -+make up the actual signature must be stored in sig->mpi[] and the count of MPIs -+placed in sig->nr_mpi. -+ -+In addition, the data must have been digested by the caller and the resulting -+hash must be pointed to by sig->digest and the size of the hash be placed in -+sig->digest_size. -+ -+The function will return 0 upon success or -EKEYREJECTED if the signature -+doesn't match. -+ -+The function may also return -ENOTSUPP if an unsupported public-key algorithm -+or public-key/hash algorithm combination is specified or the key doesn't -+support the operation; -EBADMSG or -ERANGE if some of the parameters have weird -+data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned -+if the key argument is the wrong type or is incompletely set up. -+ -+ -+======================= -+ASYMMETRIC KEY SUBTYPES -+======================= -+ -+Asymmetric keys have a subtype that defines the set of operations that can be -+performed on that key and that determines what data is attached as the key -+payload. The payload format is entirely at the whim of the subtype. -+ -+The subtype is selected by the key data parser and the parser must initialise -+the data required for it. The asymmetric key retains a reference on the -+subtype module. -+ -+The subtype definition structure can be found in: -+ -+ #include -+ -+and looks like the following: -+ -+ struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ void (*destroy)(void *payload); -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+ }; -+ -+Asymmetric keys point to this with their type_data[0] member. -+ -+The owner and name fields should be set to the owning module and the name of -+the subtype. Currently, the name is only used for print statements. -+ -+There are a number of operations defined by the subtype: -+ -+ (1) describe(). -+ -+ Mandatory. This allows the subtype to display something in /proc/keys -+ against the key. For instance the name of the public key algorithm type -+ could be displayed. The key type will display the tail of the key -+ identity string after this. -+ -+ (2) destroy(). -+ -+ Mandatory. This should free the memory associated with the key. The -+ asymmetric key will look after freeing the fingerprint and releasing the -+ reference on the subtype module. -+ -+ (3) verify_signature(). -+ -+ Optional. These are the entry points for the key usage operations. -+ Currently there is only the one defined. If not set, the caller will be -+ given -ENOTSUPP. The subtype may do anything it likes to implement an -+ operation, including offloading to hardware. -+ -+ -+========================== -+INSTANTIATION DATA PARSERS -+========================== -+ -+The asymmetric key type doesn't generally want to store or to deal with a raw -+blob of data that holds the key data. It would have to parse it and error -+check it each time it wanted to use it. Further, the contents of the blob may -+have various checks that can be performed on it (eg. self-signatures, validity -+dates) and may contain useful data about the key (identifiers, capabilities). -+ -+Also, the blob may represent a pointer to some hardware containing the key -+rather than the key itself. -+ -+Examples of blob formats for which parsers could be implemented include: -+ -+ - OpenPGP packet stream [RFC 4880]. -+ - X.509 ASN.1 stream. -+ - Pointer to TPM key. -+ - Pointer to UEFI key. -+ -+During key instantiation each parser in the list is tried until one doesn't -+return -EBADMSG. -+ -+The parser definition structure can be found in: -+ -+ #include -+ -+and looks like the following: -+ -+ struct asymmetric_key_parser { -+ struct module *owner; -+ const char *name; -+ -+ int (*parse)(struct key_preparsed_payload *prep); -+ }; -+ -+The owner and name fields should be set to the owning module and the name of -+the parser. -+ -+There is currently only a single operation defined by the parser, and it is -+mandatory: -+ -+ (1) parse(). -+ -+ This is called to preparse the key from the key creation and update paths. -+ In particular, it is called during the key creation _before_ a key is -+ allocated, and as such, is permitted to provide the key's description in -+ the case that the caller declines to do so. -+ -+ The caller passes a pointer to the following struct with all of the fields -+ cleared, except for data, datalen and quotalen [see -+ Documentation/security/keys.txt]. -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ The instantiation data is in a blob pointed to by data and is datalen in -+ size. The parse() function is not permitted to change these two values at -+ all, and shouldn't change any of the other values _unless_ they are -+ recognise the blob format and will not return -EBADMSG to indicate it is -+ not theirs. -+ -+ If the parser is happy with the blob, it should propose a description for -+ the key and attach it to ->description, ->type_data[0] should be set to -+ point to the subtype to be used, ->payload should be set to point to the -+ initialised data for that subtype, ->type_data[1] should point to a hex -+ fingerprint and quotalen should be updated to indicate how much quota this -+ key should account for. -+ -+ When clearing up, the data attached to ->type_data[1] and ->description -+ will be kfree()'d and the data attached to ->payload will be passed to the -+ subtype's ->destroy() method to be disposed of. A module reference for -+ the subtype pointed to by ->type_data[0] will be put. -+ -+ -+ If the data format is not recognised, -EBADMSG should be returned. If it -+ is recognised, but the key cannot for some reason be set up, some other -+ negative error code should be returned. On success, 0 should be returned. -+ -+ The key's fingerprint string may be partially matched upon. For a -+ public-key algorithm such as RSA and DSA this will likely be a printable -+ hex version of the key's fingerprint. -+ -+Functions are provided to register and unregister parsers: -+ -+ int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); -+ void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); -+ -+Parsers may not have the same name. The names are otherwise only used for -+displaying in debugging messages. --- -1.7.11.4 - - -From 2fb78e0d337ac41f2cddad18fc5c34374e5298ab Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 05/26] KEYS: Implement asymmetric key type - -Create a key type that can be used to represent an asymmetric key type for use -in appropriate cryptographic operations, such as encryption, decryption, -signature generation and signature verification. - -The key type is "asymmetric" and can provide access to a variety of -cryptographic algorithms. - -Possibly, this would be better as "public_key" - but that has the disadvantage -that "public key" is an overloaded term. - -Signed-off-by: David Howells ---- - crypto/Kconfig | 1 + - crypto/Makefile | 1 + - crypto/asymmetric_keys/Kconfig | 13 +++ - crypto/asymmetric_keys/Makefile | 7 ++ - crypto/asymmetric_keys/asymmetric_keys.h | 15 +++ - crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++ - include/keys/asymmetric-subtype.h | 55 +++++++++++ - include/keys/asymmetric-type.h | 25 +++++ - 8 files changed, 273 insertions(+) - create mode 100644 crypto/asymmetric_keys/Kconfig - create mode 100644 crypto/asymmetric_keys/Makefile - create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h - create mode 100644 crypto/asymmetric_keys/asymmetric_type.c - create mode 100644 include/keys/asymmetric-subtype.h - create mode 100644 include/keys/asymmetric-type.h - -diff --git a/crypto/Kconfig b/crypto/Kconfig -index a323805..1ca0b24 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER - key cipher algorithms. - - source "drivers/crypto/Kconfig" -+source crypto/asymmetric_keys/Kconfig - - endif # if CRYPTO -diff --git a/crypto/Makefile b/crypto/Makefile -index 30f33d6..ced472e 100644 ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o - # - obj-$(CONFIG_XOR_BLOCKS) += xor.o - obj-$(CONFIG_ASYNC_CORE) += async_tx/ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -new file mode 100644 -index 0000000..cad29b3 ---- /dev/null -+++ b/crypto/asymmetric_keys/Kconfig -@@ -0,0 +1,13 @@ -+menuconfig ASYMMETRIC_KEY_TYPE -+ tristate "Asymmetric (public-key cryptographic) key type" -+ depends on KEYS -+ help -+ This option provides support for a key type that holds the data for -+ the asymmetric keys used for public key cryptographic operations such -+ as encryption, decryption, signature generation and signature -+ verification. -+ -+if ASYMMETRIC_KEY_TYPE -+ -+ -+endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -new file mode 100644 -index 0000000..b725bcc ---- /dev/null -+++ b/crypto/asymmetric_keys/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for asymmetric cryptographic keys -+# -+ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o -+ -+asymmetric_keys-y := asymmetric_type.o -diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h -new file mode 100644 -index 0000000..515b634 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_keys.h -@@ -0,0 +1,15 @@ -+/* Internal definitions for asymmetric key type -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+static inline const char *asymmetric_key_id(const struct key *key) -+{ -+ return key->type_data.p[1]; -+} -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -new file mode 100644 -index 0000000..bfb0424 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -0,0 +1,156 @@ -+/* Asymmetric public-key cryptography key type -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Match asymmetric keys on (part of) their name -+ * We have some shorthand methods for matching keys. We allow: -+ * -+ * "" - request a key by description -+ * "id:" - request a key matching the ID -+ * ":" - request a key of a subtype -+ */ -+static int asymmetric_key_match(const struct key *key, const void *description) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *spec = description; -+ const char *id, *kid; -+ ptrdiff_t speclen; -+ size_t idlen, kidlen; -+ -+ if (!subtype || !spec || !*spec) -+ return 0; -+ -+ /* See if the full key description matches as is */ -+ if (key->description && strcmp(key->description, description) == 0) -+ return 1; -+ -+ /* All tests from here on break the criterion description into a -+ * specifier, a colon and then an identifier. -+ */ -+ id = strchr(spec, ':'); -+ if (!id) -+ return 0; -+ -+ speclen = id - spec; -+ id++; -+ -+ /* Anything after here requires a partial match on the ID string */ -+ kid = asymmetric_key_id(key); -+ if (!kid) -+ return 0; -+ -+ idlen = strlen(id); -+ kidlen = strlen(kid); -+ if (idlen > kidlen) -+ return 0; -+ -+ kid += kidlen - idlen; -+ if (strcasecmp(id, kid) != 0) -+ return 0; -+ -+ if (speclen == 2 && -+ memcmp(spec, "id", 2) == 0) -+ return 1; -+ -+ if (speclen == subtype->name_len && -+ memcmp(spec, subtype->name, speclen) == 0) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Describe the asymmetric key -+ */ -+static void asymmetric_key_describe(const struct key *key, struct seq_file *m) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *kid = asymmetric_key_id(key); -+ size_t n; -+ -+ seq_puts(m, key->description); -+ -+ if (subtype) { -+ seq_puts(m, ": "); -+ subtype->describe(key, m); -+ -+ if (kid) { -+ seq_putc(m, ' '); -+ n = strlen(kid); -+ if (n <= 8) -+ seq_puts(m, kid); -+ else -+ seq_puts(m, kid + n - 8); -+ } -+ -+ seq_puts(m, " ["); -+ /* put something here to indicate the key's capabilities */ -+ seq_putc(m, ']'); -+ } -+} -+ -+/* -+ * Instantiate a asymmetric_key defined key. The key was preparsed, so we just -+ * have to transfer the data here. -+ */ -+static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) -+{ -+ return -EOPNOTSUPP; -+} -+ -+/* -+ * dispose of the data dangling from the corpse of a asymmetric key -+ */ -+static void asymmetric_key_destroy(struct key *key) -+{ -+ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ if (subtype) { -+ subtype->destroy(key->payload.data); -+ module_put(subtype->owner); -+ key->type_data.p[0] = NULL; -+ } -+ kfree(key->type_data.p[1]); -+ key->type_data.p[1] = NULL; -+} -+ -+struct key_type key_type_asymmetric = { -+ .name = "asymmetric", -+ .instantiate = asymmetric_key_instantiate, -+ .match = asymmetric_key_match, -+ .destroy = asymmetric_key_destroy, -+ .describe = asymmetric_key_describe, -+}; -+EXPORT_SYMBOL_GPL(key_type_asymmetric); -+ -+/* -+ * Module stuff -+ */ -+static int __init asymmetric_key_init(void) -+{ -+ return register_key_type(&key_type_asymmetric); -+} -+ -+static void __exit asymmetric_key_cleanup(void) -+{ -+ unregister_key_type(&key_type_asymmetric); -+} -+ -+module_init(asymmetric_key_init); -+module_exit(asymmetric_key_cleanup); -diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h -new file mode 100644 -index 0000000..4b840e8 ---- /dev/null -+++ b/include/keys/asymmetric-subtype.h -@@ -0,0 +1,55 @@ -+/* Asymmetric public-key cryptography key subtype -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H -+#define _KEYS_ASYMMETRIC_SUBTYPE_H -+ -+#include -+#include -+ -+struct public_key_signature; -+ -+/* -+ * Keys of this type declare a subtype that indicates the handlers and -+ * capabilities. -+ */ -+struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ unsigned short name_len; /* length of name */ -+ -+ /* Describe a key of this subtype for /proc/keys */ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ -+ /* Destroy a key of this subtype */ -+ void (*destroy)(void *payload); -+ -+ /* Verify the signature on a key of this subtype (optional) */ -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+}; -+ -+/** -+ * asymmetric_key_subtype - Get the subtype from an asymmetric key -+ * @key: The key of interest. -+ * -+ * Retrieves and returns the subtype pointer of the asymmetric key from the -+ * type-specific data attached to the key. -+ */ -+static inline -+struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) -+{ -+ return key->type_data.p[0]; -+} -+ -+#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ -diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h -new file mode 100644 -index 0000000..7dd4734 ---- /dev/null -+++ b/include/keys/asymmetric-type.h -@@ -0,0 +1,25 @@ -+/* Asymmetric Public-key cryptography key type interface -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_TYPE_H -+#define _KEYS_ASYMMETRIC_TYPE_H -+ -+#include -+ -+extern struct key_type key_type_asymmetric; -+ -+/* -+ * The payload is at the discretion of the subtype. -+ */ -+ -+#endif /* _KEYS_ASYMMETRIC_TYPE_H */ --- -1.7.11.4 - - -From d28ffd9e0c8987e5af59ae38bb48779b0d221f00 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:32 +0100 -Subject: [PATCH 06/26] KEYS: Asymmetric key pluggable data parsers - -The instantiation data passed to the asymmetric key type are expected to be -formatted in some way, and there are several possible standard ways to format -the data. - -The two obvious standards are OpenPGP keys and X.509 certificates. The latter -is especially useful when dealing with UEFI, and the former might be useful -when dealing with, say, eCryptfs. - -Further, it might be desirable to provide formatted blobs that indicate -hardware is to be accessed to retrieve the keys or that the keys live -unretrievably in a hardware store, but that the keys can be used by means of -the hardware. - -From userspace, the keys can be loaded using the keyctl command, for example, -an X.509 binary certificate: - - keyctl padd asymmetric foo @s ---- - crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++- - include/keys/asymmetric-parser.h | 37 ++++++++++ - 2 files changed, 156 insertions(+), 1 deletion(-) - create mode 100644 include/keys/asymmetric-parser.h - -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -index bfb0424..cf80765 100644 ---- a/crypto/asymmetric_keys/asymmetric_type.c -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -11,6 +11,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - #include -+#include - #include - #include - #include -@@ -18,6 +19,9 @@ - - MODULE_LICENSE("GPL"); - -+static LIST_HEAD(asymmetric_key_parsers); -+static DECLARE_RWSEM(asymmetric_key_parsers_sem); -+ - /* - * Match asymmetric keys on (part of) their name - * We have some shorthand methods for matching keys. We allow: -@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) - } - - /* -+ * Preparse a asymmetric payload to get format the contents appropriately for the -+ * internal payload to cut down on the number of scans of the data performed. -+ * -+ * We also generate a proposed description from the contents of the key that -+ * can be used to name the key if the user doesn't want to provide one. -+ */ -+static int asymmetric_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_parser *parser; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (prep->datalen == 0) -+ return -EINVAL; -+ -+ down_read(&asymmetric_key_parsers_sem); -+ -+ ret = -EBADMSG; -+ list_for_each_entry(parser, &asymmetric_key_parsers, link) { -+ pr_debug("Trying parser '%s'\n", parser->name); -+ -+ ret = parser->parse(prep); -+ if (ret != -EBADMSG) { -+ pr_debug("Parser recognised the format (ret %d)\n", -+ ret); -+ break; -+ } -+ } -+ -+ up_read(&asymmetric_key_parsers_sem); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Clean up the preparse data -+ */ -+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_subtype *subtype = prep->type_data[0]; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (subtype) { -+ subtype->destroy(prep->payload); -+ module_put(subtype->owner); -+ } -+ kfree(prep->type_data[1]); -+ kfree(prep->description); -+} -+ -+/* - * Instantiate a asymmetric_key defined key. The key was preparsed, so we just - * have to transfer the data here. - */ - static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { -- return -EOPNOTSUPP; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ ret = key_payload_reserve(key, prep->quotalen); -+ if (ret == 0) { -+ key->type_data.p[0] = prep->type_data[0]; -+ key->type_data.p[1] = prep->type_data[1]; -+ key->payload.data = prep->payload; -+ prep->type_data[0] = NULL; -+ prep->type_data[1] = NULL; -+ prep->payload = NULL; -+ } -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } - - /* -@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) - - struct key_type key_type_asymmetric = { - .name = "asymmetric", -+ .preparse = asymmetric_key_preparse, -+ .free_preparse = asymmetric_key_free_preparse, - .instantiate = asymmetric_key_instantiate, - .match = asymmetric_key_match, - .destroy = asymmetric_key_destroy, -@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { - }; - EXPORT_SYMBOL_GPL(key_type_asymmetric); - -+/** -+ * register_asymmetric_key_parser - Register a asymmetric key blob parser -+ * @parser: The parser to register -+ */ -+int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ struct asymmetric_key_parser *cursor; -+ int ret; -+ -+ down_write(&asymmetric_key_parsers_sem); -+ -+ list_for_each_entry(cursor, &asymmetric_key_parsers, link) { -+ if (strcmp(cursor->name, parser->name) == 0) { -+ pr_err("Asymmetric key parser '%s' already registered\n", -+ parser->name); -+ ret = -EEXIST; -+ goto out; -+ } -+ } -+ -+ list_add_tail(&parser->link, &asymmetric_key_parsers); -+ -+ pr_notice("Asymmetric key parser '%s' registered\n", parser->name); -+ ret = 0; -+ -+out: -+ up_write(&asymmetric_key_parsers_sem); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); -+ -+/** -+ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser -+ * @parser: The parser to unregister -+ */ -+void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ down_write(&asymmetric_key_parsers_sem); -+ list_del(&parser->link); -+ up_write(&asymmetric_key_parsers_sem); -+ -+ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); -+} -+EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); -+ - /* - * Module stuff - */ -diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h -new file mode 100644 -index 0000000..09b3b48 ---- /dev/null -+++ b/include/keys/asymmetric-parser.h -@@ -0,0 +1,37 @@ -+/* Asymmetric public-key cryptography data parser -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_PARSER_H -+#define _KEYS_ASYMMETRIC_PARSER_H -+ -+/* -+ * Key data parser. Called during key instantiation. -+ */ -+struct asymmetric_key_parser { -+ struct list_head link; -+ struct module *owner; -+ const char *name; -+ -+ /* Attempt to parse a key from the data blob passed to add_key() or -+ * keyctl_instantiate(). Should also generate a proposed description -+ * that the caller can optionally use for the key. -+ * -+ * Return EBADMSG if not recognised. -+ */ -+ int (*parse)(struct key_preparsed_payload *prep); -+}; -+ -+extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); -+extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); -+ -+#endif /* _KEYS_ASYMMETRIC_PARSER_H */ --- -1.7.11.4 - - -From 171881bb3693176db4d0f85f78066fcdb6266525 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:24:55 +0100 -Subject: [PATCH 07/26] KEYS: Asymmetric public-key algorithm crypto key - subtype - -Add a subtype for supporting asymmetric public-key encryption algorithms such -as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Kconfig | 8 +++ - crypto/asymmetric_keys/Makefile | 2 + - crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/public_key.h | 28 ++++++++++ - include/crypto/public_key.h | 104 ++++++++++++++++++++++++++++++++++ - 5 files changed, 250 insertions(+) - create mode 100644 crypto/asymmetric_keys/public_key.c - create mode 100644 crypto/asymmetric_keys/public_key.h - create mode 100644 include/crypto/public_key.h - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index cad29b3..bbfccaa 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE - - if ASYMMETRIC_KEY_TYPE - -+config ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ tristate "Asymmetric public-key crypto algorithm subtype" -+ select MPILIB -+ help -+ This option provides support for asymmetric public key type handling. -+ If signature generation and/or verification are to be used, -+ appropriate hash algorithms (such as SHA-1) must be available. -+ ENOPKG will be reported if the requisite algorithm is unavailable. - - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index b725bcc..5ed46ee 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -5,3 +5,5 @@ - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - - asymmetric_keys-y := asymmetric_type.o -+ -+obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -new file mode 100644 -index 0000000..cb2e291 ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.c -@@ -0,0 +1,108 @@ -+/* In-software asymmetric public-key crypto subtype -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PKEY: "fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+ -+const char *const pkey_algo[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = "DSA", -+ [PKEY_ALGO_RSA] = "RSA", -+}; -+EXPORT_SYMBOL_GPL(pkey_algo); -+ -+const char *const pkey_hash_algo[PKEY_HASH__LAST] = { -+ [PKEY_HASH_MD4] = "md4", -+ [PKEY_HASH_MD5] = "md5", -+ [PKEY_HASH_SHA1] = "sha1", -+ [PKEY_HASH_RIPE_MD_160] = "rmd160", -+ [PKEY_HASH_SHA256] = "sha256", -+ [PKEY_HASH_SHA384] = "sha384", -+ [PKEY_HASH_SHA512] = "sha512", -+ [PKEY_HASH_SHA224] = "sha224", -+}; -+EXPORT_SYMBOL_GPL(pkey_hash_algo); -+ -+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { -+ [PKEY_ID_PGP] = "PGP", -+ [PKEY_ID_X509] = "X509", -+}; -+EXPORT_SYMBOL_GPL(pkey_id_type); -+ -+/* -+ * Provide a part of a description of the key for /proc/keys. -+ */ -+static void public_key_describe(const struct key *asymmetric_key, -+ struct seq_file *m) -+{ -+ struct public_key *key = asymmetric_key->payload.data; -+ -+ if (key) -+ seq_printf(m, "%s.%s", -+ pkey_id_type[key->id_type], key->algo->name); -+} -+ -+/* -+ * Destroy a public key algorithm key. -+ */ -+void public_key_destroy(void *payload) -+{ -+ struct public_key *key = payload; -+ int i; -+ -+ if (key) { -+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) -+ mpi_free(key->mpi[i]); -+ kfree(key); -+ } -+} -+EXPORT_SYMBOL_GPL(public_key_destroy); -+ -+/* -+ * Verify a signature using a public key. -+ */ -+static int public_key_verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct public_key *pk = key->payload.data; -+ -+ if (!pk->algo->verify_signature) -+ return -ENOTSUPP; -+ -+ if (sig->nr_mpi != pk->algo->n_sig_mpi) { -+ pr_debug("Signature has %u MPI not %u\n", -+ sig->nr_mpi, pk->algo->n_sig_mpi); -+ return -EINVAL; -+ } -+ -+ return pk->algo->verify_signature(pk, sig); -+} -+ -+/* -+ * Public key algorithm asymmetric key subtype -+ */ -+struct asymmetric_key_subtype public_key_subtype = { -+ .owner = THIS_MODULE, -+ .name = "public_key", -+ .describe = public_key_describe, -+ .destroy = public_key_destroy, -+ .verify_signature = public_key_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(public_key_subtype); -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -new file mode 100644 -index 0000000..1f86aad ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.h -@@ -0,0 +1,28 @@ -+/* Public key algorithm internals -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+ -+extern struct asymmetric_key_subtype public_key_subtype; -+ -+/* -+ * Public key algorithm definition. -+ */ -+struct public_key_algorithm { -+ const char *name; -+ u8 n_pub_mpi; /* Number of MPIs in public key */ -+ u8 n_sec_mpi; /* Number of MPIs in secret key */ -+ u8 n_sig_mpi; /* Number of MPIs in a signature */ -+ int (*verify_signature)(const struct public_key *key, -+ const struct public_key_signature *sig); -+}; -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -new file mode 100644 -index 0000000..4b8b6c1 ---- /dev/null -+++ b/include/crypto/public_key.h -@@ -0,0 +1,104 @@ -+/* Asymmetric public-key algorithm definitions -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_PUBLIC_KEY_H -+#define _LINUX_PUBLIC_KEY_H -+ -+#include -+ -+enum pkey_algo { -+ PKEY_ALGO_DSA, -+ PKEY_ALGO_RSA, -+ PKEY_ALGO__LAST -+}; -+ -+extern const char *const pkey_algo[PKEY_ALGO__LAST]; -+ -+enum pkey_hash_algo { -+ PKEY_HASH_MD4, -+ PKEY_HASH_MD5, -+ PKEY_HASH_SHA1, -+ PKEY_HASH_RIPE_MD_160, -+ PKEY_HASH_SHA256, -+ PKEY_HASH_SHA384, -+ PKEY_HASH_SHA512, -+ PKEY_HASH_SHA224, -+ PKEY_HASH__LAST -+}; -+ -+extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; -+ -+enum pkey_id_type { -+ PKEY_ID_PGP, /* OpenPGP generated key ID */ -+ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ -+ PKEY_ID_TYPE__LAST -+}; -+ -+extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; -+ -+/* -+ * Cryptographic data for the public-key subtype of the asymmetric key type. -+ * -+ * Note that this may include private part of the key as well as the public -+ * part. -+ */ -+struct public_key { -+ const struct public_key_algorithm *algo; -+ u8 capabilities; -+#define PKEY_CAN_ENCRYPT 0x01 -+#define PKEY_CAN_DECRYPT 0x02 -+#define PKEY_CAN_SIGN 0x04 -+#define PKEY_CAN_VERIFY 0x08 -+ enum pkey_id_type id_type : 8; -+ union { -+ MPI mpi[5]; -+ struct { -+ MPI p; /* DSA prime */ -+ MPI q; /* DSA group order */ -+ MPI g; /* DSA group generator */ -+ MPI y; /* DSA public-key value = g^x mod p */ -+ MPI x; /* DSA secret exponent (if present) */ -+ } dsa; -+ struct { -+ MPI n; /* RSA public modulus */ -+ MPI e; /* RSA public encryption exponent */ -+ MPI d; /* RSA secret encryption exponent (if present) */ -+ MPI p; /* RSA secret prime (if present) */ -+ MPI q; /* RSA secret prime (if present) */ -+ } rsa; -+ }; -+}; -+ -+extern void public_key_destroy(void *payload); -+ -+/* -+ * Public key cryptography signature data -+ */ -+struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; /* Number of bytes in digest */ -+ u8 nr_mpi; /* Occupancy of mpi[] */ -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ union { -+ MPI mpi[2]; -+ struct { -+ MPI s; /* m^d mod n */ -+ } rsa; -+ struct { -+ MPI r; -+ MPI s; -+ } dsa; -+ }; -+}; -+ -+#endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.11.4 - - -From 8e45e274bb3f8bb90306e0102a2c48ea1ef179fb Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:04 +0100 -Subject: [PATCH 08/26] KEYS: Provide signature verification with an - asymmetric key - -Provide signature verification using an asymmetric-type key to indicate the -public key to be used. - -The API is a single function that can be found in crypto/public_key.h: - - int verify_signature(const struct key *key, - const struct public_key_signature *sig) - -The first argument is the appropriate key to be used and the second argument -is the parsed signature data: - - struct public_key_signature { - u8 *digest; - u16 digest_size; - enum pkey_hash_algo pkey_hash_algo : 8; - union { - MPI mpi[2]; - struct { - MPI s; /* m^d mod n */ - } rsa; - struct { - MPI r; - MPI s; - } dsa; - }; - }; - -This should be filled in prior to calling the function. The hash algorithm -should already have been called and the hash finalised and the output should -be in a buffer pointed to by the 'digest' member. - -Any extra data to be added to the hash by the hash format (eg. PGP) should -have been added by the caller prior to finalising the hash. - -It is assumed that the signature is made up of a number of MPI values. If an -algorithm becomes available for which this is not the case, the above structure -will have to change. - -It is also assumed that it will have been checked that the signature algorithm -matches the key algorithm. - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Makefile | 2 +- - crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++ - include/crypto/public_key.h | 4 ++++ - 3 files changed, 54 insertions(+), 1 deletion(-) - create mode 100644 crypto/asymmetric_keys/signature.c - -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 5ed46ee..8dcdf0c 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -4,6 +4,6 @@ - - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - --asymmetric_keys-y := asymmetric_type.o -+asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c -new file mode 100644 -index 0000000..50b3f88 ---- /dev/null -+++ b/crypto/asymmetric_keys/signature.c -@@ -0,0 +1,49 @@ -+/* Signature verification with an asymmetric key -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+ -+/** -+ * verify_signature - Initiate the use of an asymmetric key to verify a signature -+ * @key: The asymmetric key to verify against -+ * @sig: The signature to check -+ * -+ * Returns 0 if successful or else an error. -+ */ -+int verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct asymmetric_key_subtype *subtype; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (key->type != &key_type_asymmetric) -+ return -EINVAL; -+ subtype = asymmetric_key_subtype(key); -+ if (!subtype || -+ !key->payload.data) -+ return -EINVAL; -+ if (!subtype->verify_signature) -+ return -ENOTSUPP; -+ -+ ret = subtype->verify_signature(key, sig); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(verify_signature); -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 4b8b6c1..f5b0224 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -101,4 +101,8 @@ struct public_key_signature { - }; - }; - -+struct key; -+extern int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ - #endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.11.4 - - -From 941e72448fc68f41a56798112a6f20df6bcd0ad0 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:22 +0100 -Subject: [PATCH 09/26] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA - signature verification - -Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by -RSA signature verification as per RFC3447 section 5.2.2 step 1. - -Signed-off-by: David Howells ---- - lib/mpi/Makefile | 1 + - lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) - create mode 100644 lib/mpi/mpi-cmp.c - -diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile -index 45ca90a..019a68c 100644 ---- a/lib/mpi/Makefile -+++ b/lib/mpi/Makefile -@@ -14,6 +14,7 @@ mpi-y = \ - generic_mpih-add1.o \ - mpicoder.o \ - mpi-bit.o \ -+ mpi-cmp.o \ - mpih-cmp.o \ - mpih-div.o \ - mpih-mul.o \ -diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c -new file mode 100644 -index 0000000..1871e7b ---- /dev/null -+++ b/lib/mpi/mpi-cmp.c -@@ -0,0 +1,70 @@ -+/* mpi-cmp.c - MPI functions -+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. -+ * -+ * This file is part of GnuPG. -+ * -+ * GnuPG is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * GnuPG 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ */ -+ -+#include "mpi-internal.h" -+ -+int mpi_cmp_ui(MPI u, unsigned long v) -+{ -+ mpi_limb_t limb = v; -+ -+ mpi_normalize(u); -+ if (!u->nlimbs && !limb) -+ return 0; -+ if (u->sign) -+ return -1; -+ if (u->nlimbs > 1) -+ return 1; -+ -+ if (u->d[0] == limb) -+ return 0; -+ else if (u->d[0] > limb) -+ return 1; -+ else -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp_ui); -+ -+int mpi_cmp(MPI u, MPI v) -+{ -+ mpi_size_t usize, vsize; -+ int cmp; -+ -+ mpi_normalize(u); -+ mpi_normalize(v); -+ usize = u->nlimbs; -+ vsize = v->nlimbs; -+ if (!u->sign && v->sign) -+ return 1; -+ if (u->sign && !v->sign) -+ return -1; -+ if (usize != vsize && !u->sign && !v->sign) -+ return usize - vsize; -+ if (usize != vsize && u->sign && v->sign) -+ return vsize + usize; -+ if (!usize) -+ return 0; -+ cmp = mpihelp_cmp(u->d, v->d, usize); -+ if (!cmp) -+ return 0; -+ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) -+ return 1; -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp); --- -1.7.11.4 - - -From ca876ff8fde3c6febb8a8578ca0e1608576071bf Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:40 +0100 -Subject: [PATCH 10/26] RSA: Implement signature verification algorithm - [PKCS#1 / RFC3447] - -Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only -the signature verification algorithm is supported. This uses the asymmetric -public key subtype to hold its key data. - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Kconfig | 7 + - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/public_key.h | 2 + - crypto/asymmetric_keys/rsa.c | 269 ++++++++++++++++++++++++++++++++++++ - 4 files changed, 279 insertions(+) - create mode 100644 crypto/asymmetric_keys/rsa.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index bbfccaa..561759d 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE - appropriate hash algorithms (such as SHA-1) must be available. - ENOPKG will be reported if the requisite algorithm is unavailable. - -+config PUBLIC_KEY_ALGO_RSA -+ tristate "RSA public-key algorithm" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select MPILIB_EXTRA -+ help -+ This option enables support for the RSA algorithm (PKCS#1, RFC3447). -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 8dcdf0c..7c92691 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -+obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -index 1f86aad..5e5e356 100644 ---- a/crypto/asymmetric_keys/public_key.h -+++ b/crypto/asymmetric_keys/public_key.h -@@ -26,3 +26,5 @@ struct public_key_algorithm { - int (*verify_signature)(const struct public_key *key, - const struct public_key_signature *sig); - }; -+ -+extern const struct public_key_algorithm RSA_public_key_algorithm; -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -new file mode 100644 -index 0000000..9b31ee2 ---- /dev/null -+++ b/crypto/asymmetric_keys/rsa.c -@@ -0,0 +1,269 @@ -+/* RSA asymmetric public-key algorithm [RFC3447] -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "RSA: "fmt -+#include -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("RSA Public Key Algorithm"); -+ -+#define kenter(FMT, ...) \ -+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -+#define kleave(FMT, ...) \ -+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) -+ -+/* -+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. -+ */ -+static const u8 RSA_digest_info_MD5[] = { -+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, -+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ -+ 0x05, 0x00, 0x04, 0x10 -+}; -+ -+static const u8 RSA_digest_info_SHA1[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_RIPE_MD_160[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x24, 0x03, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_SHA224[] = { -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C -+}; -+ -+static const u8 RSA_digest_info_SHA256[] = { -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20 -+}; -+ -+static const u8 RSA_digest_info_SHA384[] = { -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30 -+}; -+ -+static const u8 RSA_digest_info_SHA512[] = { -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40 -+}; -+ -+static const struct { -+ const u8 *data; -+ size_t size; -+} RSA_ASN1_templates[PKEY_HASH__LAST] = { -+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } -+ [PKEY_HASH_MD5] = _(MD5), -+ [PKEY_HASH_SHA1] = _(SHA1), -+ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), -+ [PKEY_HASH_SHA256] = _(SHA256), -+ [PKEY_HASH_SHA384] = _(SHA384), -+ [PKEY_HASH_SHA512] = _(SHA512), -+ [PKEY_HASH_SHA224] = _(SHA224), -+#undef _ -+}; -+ -+/* -+ * RSAVP1() function [RFC3447 sec 5.2.2] -+ */ -+static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) -+{ -+ MPI m; -+ int ret; -+ -+ /* (1) Validate 0 <= s < n */ -+ if (mpi_cmp_ui(s, 0) < 0) { -+ kleave(" = -EBADMSG [s < 0]"); -+ return -EBADMSG; -+ } -+ if (mpi_cmp(s, key->rsa.n) >= 0) { -+ kleave(" = -EBADMSG [s >= n]"); -+ return -EBADMSG; -+ } -+ -+ m = mpi_alloc(0); -+ if (!m) -+ return -ENOMEM; -+ -+ /* (2) m = s^e mod n */ -+ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); -+ if (ret < 0) { -+ mpi_free(m); -+ return ret; -+ } -+ -+ *_m = m; -+ return 0; -+} -+ -+/* -+ * Integer to Octet String conversion [RFC3447 sec 4.1] -+ */ -+static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) -+{ -+ unsigned X_size, x_size; -+ int X_sign; -+ u8 *X; -+ -+ /* Make sure the string is the right length. The number should begin -+ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero -+ * bits not being reported by MPI. -+ */ -+ x_size = mpi_get_nbits(x); -+ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); -+ if (x_size != xLen * 8 - 15) -+ return -ERANGE; -+ -+ X = mpi_get_buffer(x, &X_size, &X_sign); -+ if (!X) -+ return -ENOMEM; -+ if (X_sign < 0) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ if (X_size != xLen - 1) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ -+ *_X = X; -+ return 0; -+} -+ -+/* -+ * Perform the RSA signature verification. -+ * @H: Value of hash of data and metadata -+ * @EM: The computed signature value -+ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) -+ * @hash_size: The size of H -+ * @asn1_template: The DigestInfo ASN.1 template -+ * @asn1_size: Size of asm1_template[] -+ */ -+static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, -+ const u8 *asn1_template, size_t asn1_size) -+{ -+ unsigned PS_end, T_offset, i; -+ -+ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); -+ -+ if (k < 2 + 1 + asn1_size + hash_size) -+ return -EBADMSG; -+ -+ /* Decode the EMSA-PKCS1-v1_5 */ -+ if (EM[1] != 0x01) { -+ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); -+ return -EBADMSG; -+ } -+ -+ T_offset = k - (asn1_size + hash_size); -+ PS_end = T_offset - 1; -+ if (EM[PS_end] != 0x00) { -+ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); -+ return -EBADMSG; -+ } -+ -+ for (i = 2; i < PS_end; i++) { -+ if (EM[i] != 0xff) { -+ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); -+ return -EBADMSG; -+ } -+ } -+ -+ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { -+ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); -+ return -EBADMSG; -+ } -+ -+ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { -+ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); -+ return -EKEYREJECTED; -+ } -+ -+ kleave(" = 0"); -+ return 0; -+} -+ -+/* -+ * Perform the verification step [RFC3447 sec 8.2.2]. -+ */ -+static int RSA_verify_signature(const struct public_key *key, -+ const struct public_key_signature *sig) -+{ -+ size_t tsize; -+ int ret; -+ -+ /* Variables as per RFC3447 sec 8.2.2 */ -+ const u8 *H = sig->digest; -+ u8 *EM = NULL; -+ MPI m = NULL; -+ size_t k; -+ -+ kenter(""); -+ -+ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) -+ return -ENOTSUPP; -+ -+ /* (1) Check the signature size against the public key modulus size */ -+ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ -+ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -+ if (tsize != k) { -+ ret = -EBADMSG; -+ goto error; -+ } -+ -+ /* (2b) Apply the RSAVP1 verification primitive to the public key */ -+ ret = RSAVP1(key, sig->rsa.s, &m); -+ if (ret < 0) -+ goto error; -+ -+ /* (2c) Convert the message representative (m) to an encoded message -+ * (EM) of length k octets. -+ * -+ * NOTE! The leading zero byte is suppressed by MPI, so we pass a -+ * pointer to the _preceding_ byte to RSA_verify()! -+ */ -+ ret = RSA_I2OSP(m, k, &EM); -+ if (ret < 0) -+ goto error; -+ -+ ret = RSA_verify(H, EM - 1, k, sig->digest_size, -+ RSA_ASN1_templates[sig->pkey_hash_algo].data, -+ RSA_ASN1_templates[sig->pkey_hash_algo].size); -+ -+error: -+ kfree(EM); -+ mpi_free(m); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+const struct public_key_algorithm RSA_public_key_algorithm = { -+ .name = "RSA", -+ .n_pub_mpi = 2, -+ .n_sec_mpi = 3, -+ .n_sig_mpi = 1, -+ .verify_signature = RSA_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); --- -1.7.11.4 - - -From e179a9b04469ea018a8fdb53f11c57222ba540a0 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:28:05 +0100 -Subject: [PATCH 11/26] RSA: Fix signature verification for shorter signatures - -gpg can produce a signature file where length of signature is less than the -modulus size because the amount of space an MPI takes up is kept as low as -possible by discarding leading zeros. This regularly happens for several -modules during the build. - -Fix it by relaxing check in RSA verification code. - -Thanks to Tomas Mraz and Miloslav Trmac for help. - -Signed-off-by: Milan Broz -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/rsa.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -index 9b31ee2..4a6a069 100644 ---- a/crypto/asymmetric_keys/rsa.c -+++ b/crypto/asymmetric_keys/rsa.c -@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key, - return -ENOTSUPP; - - /* (1) Check the signature size against the public key modulus size */ -- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ k = mpi_get_nbits(key->rsa.n); -+ tsize = mpi_get_nbits(sig->rsa.s); - -- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ /* According to RFC 4880 sec 3.2, length of MPI is computed starting -+ * from most significant bit. So the RFC 3447 sec 8.2.2 size check -+ * must be relaxed to conform with shorter signatures - so we fail here -+ * only if signature length is longer than modulus size. -+ */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -- if (tsize != k) { -+ if (k < tsize) { - ret = -EBADMSG; - goto error; - } - -+ /* Round up and convert to octets */ -+ k = (k + 7) / 8; -+ - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); - if (ret < 0) --- -1.7.11.4 - - -From d412c256ea6170b6aeceb9f1eb1737d991473634 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:30:46 +0100 -Subject: [PATCH 12/26] X.509: Implement simple static OID registry - -Implement a simple static OID registry that allows the mapping of an encoded -OID to an enum value for ease of use. - -The OID registry index enum appears in the: - - linux/oid_registry.h - -header file. A script generates the registry from lines in the header file -that look like: - - OID_foo,/*1.2.3.4*/ - -The actual OID is taken to be represented by the numbers with interpolated -dots in the comment. - -All other lines in the header are ignored. - -The registry is queries by calling: - - OID look_up_oid(const void *data, size_t datasize); - -This returns a number from the registry enum representing the OID if found or -OID__NR if not. - -Signed-off-by: David Howells ---- - include/linux/oid_registry.h | 90 +++++++++++++++++++ - lib/.gitignore | 2 +- - lib/Kconfig | 5 ++ - lib/Makefile | 16 ++++ - lib/build_OID_registry | 209 +++++++++++++++++++++++++++++++++++++++++++ - lib/oid_registry.c | 89 ++++++++++++++++++ - 6 files changed, 410 insertions(+), 1 deletion(-) - create mode 100644 include/linux/oid_registry.h - create mode 100755 lib/build_OID_registry - create mode 100644 lib/oid_registry.c - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -new file mode 100644 -index 0000000..5928546 ---- /dev/null -+++ b/include/linux/oid_registry.h -@@ -0,0 +1,90 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_OID_REGISTRY_H -+#define _LINUX_OID_REGISTRY_H -+ -+#include -+ -+/* -+ * OIDs are turned into these values if possible, or OID__NR if not held here. -+ * -+ * NOTE! Do not mess with the format of each line as this is read by -+ * build_OID_registry.pl to generate the data for look_up_OID(). -+ */ -+enum OID { -+ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ -+ OID_id_dsa, /* 1.2.840.10040.4.1 */ -+ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ -+ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ -+ -+ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ -+ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ -+ OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ -+ OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ -+ OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ -+ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ -+ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ -+ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ -+ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ -+ OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ -+ /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ -+ OID_data, /* 1.2.840.113549.1.7.1 */ -+ OID_signed_data, /* 1.2.840.113549.1.7.2 */ -+ /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ -+ OID_email_address, /* 1.2.840.113549.1.9.1 */ -+ OID_content_type, /* 1.2.840.113549.1.9.3 */ -+ OID_messageDigest, /* 1.2.840.113549.1.9.4 */ -+ OID_signingTime, /* 1.2.840.113549.1.9.5 */ -+ OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ -+ OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ -+ -+ /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ -+ OID_md2, /* 1.2.840.113549.2.2 */ -+ OID_md4, /* 1.2.840.113549.2.4 */ -+ OID_md5, /* 1.2.840.113549.2.5 */ -+ -+ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ -+ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ -+ OID_sha1, /* 1.3.14.3.2.26 */ -+ -+ /* Distinguished Name attribute IDs [RFC 2256] */ -+ OID_commonName, /* 2.5.4.3 */ -+ OID_surname, /* 2.5.4.4 */ -+ OID_countryName, /* 2.5.4.6 */ -+ OID_locality, /* 2.5.4.7 */ -+ OID_stateOrProvinceName, /* 2.5.4.8 */ -+ OID_organizationName, /* 2.5.4.10 */ -+ OID_organizationUnitName, /* 2.5.4.11 */ -+ OID_title, /* 2.5.4.12 */ -+ OID_description, /* 2.5.4.13 */ -+ OID_name, /* 2.5.4.41 */ -+ OID_givenName, /* 2.5.4.42 */ -+ OID_initials, /* 2.5.4.43 */ -+ OID_generationalQualifier, /* 2.5.4.44 */ -+ -+ /* Certificate extension IDs */ -+ OID_subjectKeyIdentifier, /* 2.5.29.14 */ -+ OID_keyUsage, /* 2.5.29.15 */ -+ OID_subjectAltName, /* 2.5.29.17 */ -+ OID_issuerAltName, /* 2.5.29.18 */ -+ OID_basicConstraints, /* 2.5.29.19 */ -+ OID_crlDistributionPoints, /* 2.5.29.31 */ -+ OID_certPolicies, /* 2.5.29.32 */ -+ OID_authorityKeyIdentifier, /* 2.5.29.35 */ -+ OID_extKeyUsage, /* 2.5.29.37 */ -+ -+ OID__NR -+}; -+ -+extern enum OID look_up_OID(const void *data, size_t datasize); -+ -+#endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/.gitignore b/lib/.gitignore -index 3bef1ea..09aae85 100644 ---- a/lib/.gitignore -+++ b/lib/.gitignore -@@ -3,4 +3,4 @@ - # - gen_crc32table - crc32table.h -- -+oid_registry_data.c -diff --git a/lib/Kconfig b/lib/Kconfig -index bb94c1b..4b31a46 100644 ---- a/lib/Kconfig -+++ b/lib/Kconfig -@@ -396,4 +396,9 @@ config SIGNATURE - config LIBFDT - bool - -+config OID_REGISTRY -+ tristate -+ help -+ Enable fast lookup object identifier registry. -+ - endmenu -diff --git a/lib/Makefile b/lib/Makefile -index 42d283e..b042896 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN $@ - - $(obj)/crc32table.h: $(obj)/gen_crc32table - $(call cmd,crc32) -+ -+# -+# Build a fast OID lookip registry from include/linux/oid_registry.h -+# -+obj-$(CONFIG_OID_REGISTRY) += oid_registry.o -+ -+$(obj)/oid_registry.c: $(obj)/oid_registry_data.c -+ -+$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ -+ $(src)/build_OID_registry -+ $(call cmd,build_OID_registry) -+ -+quiet_cmd_build_OID_registry = GEN $@ -+ cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ -+ -+clean-files += oid_registry_data.c -diff --git a/lib/build_OID_registry b/lib/build_OID_registry -new file mode 100755 -index 0000000..dfbdaab ---- /dev/null -+++ b/lib/build_OID_registry -@@ -0,0 +1,209 @@ -+#!/usr/bin/perl -w -+# -+# Build a static ASN.1 Object Identified (OID) registry -+# -+# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+# Written by David Howells (dhowells@redhat.com) -+# -+# This program is free software; you can redistribute it and/or -+# modify it under the terms of the GNU General Public Licence -+# as published by the Free Software Foundation; either version -+# 2 of the Licence, or (at your option) any later version. -+# -+ -+use strict; -+ -+my @names = (); -+my @oids = (); -+ -+if ($#ARGV != 1) { -+ print STDERR "Format: ", $0, " \n"; -+ exit(2); -+} -+ -+# -+# Open the file to read from -+# -+open IN_FILE, "<$ARGV[0]" || die; -+while () { -+ chomp; -+ if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { -+ push @names, $1; -+ push @oids, $2; -+ } -+} -+close IN_FILE || die; -+ -+# -+# Open the files to write into -+# -+open C_FILE, ">$ARGV[1]" or die; -+print C_FILE "/*\n"; -+print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; -+print C_FILE " */\n"; -+ -+# -+# Split the data up into separate lists and also determine the lengths of the -+# encoded data arrays. -+# -+my @indices = (); -+my @lengths = (); -+my $total_length = 0; -+ -+print "Compiling ", $#names + 1, " OIDs\n"; -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my $name = $names[$i]; -+ my $oid = $oids[$i]; -+ -+ my @components = split(/[.]/, $oid); -+ -+ # Determine the encoded length of this OID -+ my $size = $#components; -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # We will base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ $size += $tmp; -+ } -+ push @lengths, $size; -+ push @indices, $total_length; -+ $total_length += $size; -+} -+ -+# -+# Emit the look-up-by-OID index table -+# -+print C_FILE "\n"; -+if ($total_length <= 255) { -+ print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; -+} else { -+ print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; -+} -+for (my $i = 0; $i <= $#names; $i++) { -+ print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" -+} -+print C_FILE "\t[OID__NR] = ", $total_length, "\n"; -+print C_FILE "};\n"; -+ -+# -+# Encode the OIDs -+# -+my @encoded_oids = (); -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = (); -+ -+ my @components = split(/[.]/, $oids[$i]); -+ -+ push @octets, $components[0] * 40 + $components[1]; -+ -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # Base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ -+ for (; $tmp > 0; $tmp--) { -+ push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; -+ } -+ push @octets, $c & 0x7f; -+ } -+ -+ push @encoded_oids, \@octets; -+} -+ -+# -+# Create a hash value for each OID -+# -+my @hash_values = (); -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ -+ my $hash = $#octets; -+ foreach (@octets) { -+ $hash += $_ * 33; -+ } -+ -+ $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); -+ -+ push @hash_values, $hash & 0xff; -+} -+ -+# -+# Emit the OID data -+# -+print C_FILE "\n"; -+print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ print C_FILE "\t"; -+ print C_FILE $_, ", " foreach (@octets); -+ print C_FILE "\t// ", $names[$i]; -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Build the search index table (ordered by length then hash then content) -+# -+my @index_table = ( 0 .. $#names ); -+ -+@index_table = sort { -+ my @octets_a = @{$encoded_oids[$a]}; -+ my @octets_b = @{$encoded_oids[$b]}; -+ -+ return $hash_values[$a] <=> $hash_values[$b] -+ if ($hash_values[$a] != $hash_values[$b]); -+ return $#octets_a <=> $#octets_b -+ if ($#octets_a != $#octets_b); -+ for (my $i = $#octets_a; $i >= 0; $i--) { -+ return $octets_a[$i] <=> $octets_b[$i] -+ if ($octets_a[$i] != $octets_b[$i]); -+ } -+ return 0; -+ -+} @index_table; -+ -+# -+# Emit the search index and hash value table -+# -+print C_FILE "\n"; -+print C_FILE "static const struct {\n"; -+print C_FILE "\tunsigned char hash;\n"; -+if ($#names <= 255) { -+ print C_FILE "\tenum OID oid : 8;\n"; -+} else { -+ print C_FILE "\tenum OID oid : 16;\n"; -+} -+print C_FILE "} oid_search_table[OID__NR] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$index_table[$i]]}; -+ printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", -+ $i, -+ $hash_values[$index_table[$i]], -+ $names[$index_table[$i]]); -+ printf C_FILE "%02x", $_ foreach (@octets); -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Emit the OID debugging name table -+# -+#print C_FILE "\n"; -+#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; -+# -+#for (my $i = 0; $i <= $#names; $i++) { -+# print C_FILE "\t\"", $names[$i], "\",\n" -+#} -+#print C_FILE "\t\"Unknown-OID\"\n"; -+#print C_FILE "};\n"; -+ -+# -+# Polish off -+# -+close C_FILE or die; -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -new file mode 100644 -index 0000000..33cfd17 ---- /dev/null -+++ b/lib/oid_registry.c -@@ -0,0 +1,89 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include "oid_registry_data.c" -+ -+/** -+ * look_up_OID - Find an OID registration for the specified data -+ * @data: Binary representation of the OID -+ * @datasize: Size of the binary representation -+ */ -+enum OID look_up_OID(const void *data, size_t datasize) -+{ -+ const unsigned char *octets = data; -+ enum OID oid; -+ unsigned char xhash; -+ unsigned i, j, k, hash; -+ size_t len; -+ -+ /* Hash the OID data */ -+ hash = datasize - 1; -+ -+ for (i = 0; i < datasize; i++) -+ hash += octets[i] * 33; -+ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; -+ hash &= 0xff; -+ -+ /* Binary search the OID registry. OIDs are stored in ascending order -+ * of hash value then ascending order of size and then in ascending -+ * order of reverse value. -+ */ -+ i = 0; -+ k = OID__NR; -+ while (i < k) { -+ j = (i + k) / 2; -+ -+ xhash = oid_search_table[j].hash; -+ if (xhash > hash) { -+ k = j; -+ continue; -+ } -+ if (xhash < hash) { -+ i = j + 1; -+ continue; -+ } -+ -+ oid = oid_search_table[j].oid; -+ len = oid_index[oid + 1] - oid_index[oid]; -+ if (len > datasize) { -+ k = j; -+ continue; -+ } -+ if (len < datasize) { -+ i = j + 1; -+ continue; -+ } -+ -+ /* Variation is most likely to be at the tail end of the -+ * OID, so do the comparison in reverse. -+ */ -+ while (len > 0) { -+ unsigned char a = oid_data[oid_index[oid] + --len]; -+ unsigned char b = octets[len]; -+ if (a > b) { -+ k = j; -+ goto next; -+ } -+ if (a < b) { -+ i = j + 1; -+ goto next; -+ } -+ } -+ return oid; -+ next: -+ ; -+ } -+ -+ return OID__NR; -+} -+EXPORT_SYMBOL_GPL(look_up_OID); --- -1.7.11.4 - - -From 098335ed1edc5ec7ae7a346416654e12bb9bcd65 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:30:51 +0100 -Subject: [PATCH 13/26] X.509: Add utility functions to render OIDs as strings - -Add a pair of utility functions to render OIDs as strings. The first takes an -encoded OID and turns it into a "a.b.c.d" form string: - - int sprint_oid(const void *data, size_t datasize, - char *buffer, size_t bufsize); - -The second takes an OID enum index and calls the first on the data held -therein: - - int sprint_OID(enum OID oid, char *buffer, size_t bufsize); - -Signed-off-by: David Howells ---- - include/linux/oid_registry.h | 2 ++ - lib/oid_registry.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 83 insertions(+) - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -index 5928546..6926db7 100644 ---- a/include/linux/oid_registry.h -+++ b/include/linux/oid_registry.h -@@ -86,5 +86,7 @@ enum OID { - }; - - extern enum OID look_up_OID(const void *data, size_t datasize); -+extern int sprint_oid(const void *, size_t, char *, size_t); -+extern int sprint_OID(enum OID, char *, size_t); - - #endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -index 33cfd17..d8de11f 100644 ---- a/lib/oid_registry.c -+++ b/lib/oid_registry.c -@@ -11,6 +11,9 @@ - - #include - #include -+#include -+#include -+#include - #include "oid_registry_data.c" - - /** -@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize) - return OID__NR; - } - EXPORT_SYMBOL_GPL(look_up_OID); -+ -+/* -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @data: The encoded OID to print -+ * @datasize: The size of the encoded OID -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -EBADMSG is returned if the data could not be intepreted -+ * and -ENOBUFS if the buffer was too small. -+ */ -+int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) -+{ -+ const unsigned char *v = data, *end = v + datasize; -+ unsigned long num; -+ unsigned char n; -+ size_t ret; -+ int count; -+ -+ if (v >= end) -+ return -EBADMSG; -+ -+ n = *v++; -+ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ -+ while (v < end) { -+ num = 0; -+ n = *v++; -+ if (!(n & 0x80)) { -+ num = n; -+ } else { -+ num = n & 0x7f; -+ do { -+ if (v >= end) -+ return -EBADMSG; -+ n = *v++; -+ num <<= 7; -+ num |= n & 0x7f; -+ } while (n & 0x80); -+ } -+ ret += count = snprintf(buffer, bufsize, ".%lu", num); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_oid); -+ -+/** -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @oid: The OID to print -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -+ */ -+int sprint_OID(enum OID oid, char *buffer, size_t bufsize) -+{ -+ int ret; -+ -+ BUG_ON(oid >= OID__NR); -+ -+ ret = sprint_oid(oid_data + oid_index[oid], -+ oid_index[oid + 1] - oid_index[oid], -+ buffer, bufsize); -+ BUG_ON(ret == -EBADMSG); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_OID); --- -1.7.11.4 - - -From 3ddb8a2f1fe420777491641d39328741d9a28565 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:31:13 +0100 -Subject: [PATCH 14/26] X.509: Add simple ASN.1 grammar compiler - -Add a simple ASN.1 grammar compiler. This produces a bytecode output that can -be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it -is trying to parse. - -Action functions can be specified in the grammar by interpolating: - - ({ foo }) - -after a type, for example: - - SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - subjectPublicKey BIT STRING ({ do_key_data }) - } - -The decoder is expected to call these after matching this type and parsing the -contents if it is a constructed type. - -The grammar compiler does not currently support the SET type (though it does -support SET OF) as I can't see a good way of tracking which members have been -encountered yet without using up extra stack space. - -Currently, the grammar compiler will fail if more than 256 bytes of bytecode -would be produced or more than 256 actions have been specified as it uses -8-bit jump values and action indices to keep space usage down. - -Signed-off-by: David Howells ---- - include/linux/asn1.h | 67 ++ - include/linux/asn1_ber_bytecode.h | 87 +++ - init/Kconfig | 8 + - scripts/.gitignore | 1 + - scripts/Makefile | 2 + - scripts/Makefile.build | 11 + - scripts/asn1_compiler.c | 1545 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 1721 insertions(+) - create mode 100644 include/linux/asn1.h - create mode 100644 include/linux/asn1_ber_bytecode.h - create mode 100644 scripts/asn1_compiler.c - -diff --git a/include/linux/asn1.h b/include/linux/asn1.h -new file mode 100644 -index 0000000..5c3f4e4 ---- /dev/null -+++ b/include/linux/asn1.h -@@ -0,0 +1,67 @@ -+/* ASN.1 BER/DER/CER encoding definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_H -+#define _LINUX_ASN1_H -+ -+/* Class */ -+enum asn1_class { -+ ASN1_UNIV = 0, /* Universal */ -+ ASN1_APPL = 1, /* Application */ -+ ASN1_CONT = 2, /* Context */ -+ ASN1_PRIV = 3 /* Private */ -+}; -+#define ASN1_CLASS_BITS 0xc0 -+ -+ -+enum asn1_method { -+ ASN1_PRIM = 0, /* Primitive */ -+ ASN1_CONS = 1 /* Constructed */ -+}; -+#define ASN1_CONS_BIT 0x20 -+ -+/* Tag */ -+enum asn1_tag { -+ ASN1_EOC = 0, /* End Of Contents or N/A */ -+ ASN1_BOOL = 1, /* Boolean */ -+ ASN1_INT = 2, /* Integer */ -+ ASN1_BTS = 3, /* Bit String */ -+ ASN1_OTS = 4, /* Octet String */ -+ ASN1_NULL = 5, /* Null */ -+ ASN1_OID = 6, /* Object Identifier */ -+ ASN1_ODE = 7, /* Object Description */ -+ ASN1_EXT = 8, /* External */ -+ ASN1_REAL = 9, /* Real float */ -+ ASN1_ENUM = 10, /* Enumerated */ -+ ASN1_EPDV = 11, /* Embedded PDV */ -+ ASN1_UTF8STR = 12, /* UTF8 String */ -+ ASN1_RELOID = 13, /* Relative OID */ -+ /* 14 - Reserved */ -+ /* 15 - Reserved */ -+ ASN1_SEQ = 16, /* Sequence and Sequence of */ -+ ASN1_SET = 17, /* Set and Set of */ -+ ASN1_NUMSTR = 18, /* Numerical String */ -+ ASN1_PRNSTR = 19, /* Printable String */ -+ ASN1_TEXSTR = 20, /* T61 String / Teletext String */ -+ ASN1_VIDSTR = 21, /* Videotex String */ -+ ASN1_IA5STR = 22, /* IA5 String */ -+ ASN1_UNITIM = 23, /* Universal Time */ -+ ASN1_GENTIM = 24, /* General Time */ -+ ASN1_GRASTR = 25, /* Graphic String */ -+ ASN1_VISSTR = 26, /* Visible String */ -+ ASN1_GENSTR = 27, /* General String */ -+ ASN1_UNISTR = 28, /* Universal String */ -+ ASN1_CHRSTR = 29, /* Character String */ -+ ASN1_BMPSTR = 30, /* BMP String */ -+ ASN1_LONG_TAG = 31 /* Long form tag */ -+}; -+ -+#endif /* _LINUX_ASN1_H */ -diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h -new file mode 100644 -index 0000000..945d44a ---- /dev/null -+++ b/include/linux/asn1_ber_bytecode.h -@@ -0,0 +1,87 @@ -+/* ASN.1 BER/DER/CER parsing state machine internal definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_BER_BYTECODE_H -+#define _LINUX_ASN1_BER_BYTECODE_H -+ -+#ifdef __KERNEL__ -+#include -+#endif -+#include -+ -+typedef int (*asn1_action_t)(void *context, -+ size_t hdrlen, /* In case of ANY type */ -+ unsigned char tag, /* In case of ANY type */ -+ const void *value, size_t vlen); -+ -+struct asn1_decoder { -+ const unsigned char *machine; -+ size_t machlen; -+ const asn1_action_t *actions; -+}; -+ -+enum asn1_opcode { -+ /* The tag-matching ops come first and the odd-numbered slots -+ * are for OR_SKIP ops. -+ */ -+#define ASN1_OP_MATCH__SKIP 0x01 -+#define ASN1_OP_MATCH__ACT 0x02 -+#define ASN1_OP_MATCH__JUMP 0x04 -+#define ASN1_OP_MATCH__ANY 0x08 -+#define ASN1_OP_MATCH__COND 0x10 -+ -+ ASN1_OP_MATCH = 0x00, -+ ASN1_OP_MATCH_OR_SKIP = 0x01, -+ ASN1_OP_MATCH_ACT = 0x02, -+ ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, -+ ASN1_OP_MATCH_JUMP = 0x04, -+ ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, -+ ASN1_OP_MATCH_ANY = 0x08, -+ ASN1_OP_MATCH_ANY_ACT = 0x0a, -+ /* Everything before here matches unconditionally */ -+ -+ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, -+ ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, -+ ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, -+ ASN1_OP_COND_MATCH_ANY = 0x18, -+ ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, -+ -+ /* Everything before here will want a tag from the data */ -+#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT -+ -+ /* These are here to help fill up space */ -+ ASN1_OP_COND_FAIL = 0x1b, -+ ASN1_OP_COMPLETE = 0x1c, -+ ASN1_OP_ACT = 0x1d, -+ ASN1_OP_RETURN = 0x1e, -+ -+ /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ -+ ASN1_OP_END_SEQ = 0x20, -+ ASN1_OP_END_SET = 0x21, -+ ASN1_OP_END_SEQ_OF = 0x22, -+ ASN1_OP_END_SET_OF = 0x23, -+ ASN1_OP_END_SEQ_ACT = 0x24, -+ ASN1_OP_END_SET_ACT = 0x25, -+ ASN1_OP_END_SEQ_OF_ACT = 0x26, -+ ASN1_OP_END_SET_OF_ACT = 0x27, -+#define ASN1_OP_END__SET 0x01 -+#define ASN1_OP_END__OF 0x02 -+#define ASN1_OP_END__ACT 0x04 -+ -+ ASN1_OP__NR -+}; -+ -+#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) -+#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) -+#define _jump_target(N) (N) -+#define _action(N) (N) -+ -+#endif /* _LINUX_ASN1_BER_BYTECODE_H */ -diff --git a/init/Kconfig b/init/Kconfig -index af6c7f8..66cc885 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1612,4 +1612,12 @@ config PADATA - depends on SMP - bool - -+config ASN1 -+ tristate -+ help -+ Build a simple ASN.1 grammar compiler that produces a bytecode output -+ that can be interpreted by the ASN.1 stream decoder and used to -+ inform it as to what tags are to be expected in a stream and what -+ functions to call on what tags. -+ - source "kernel/Kconfig.locks" -diff --git a/scripts/.gitignore b/scripts/.gitignore -index 65f362d..fb070fa 100644 ---- a/scripts/.gitignore -+++ b/scripts/.gitignore -@@ -10,3 +10,4 @@ ihex2fw - recordmcount - docproc - sortextable -+asn1_compiler -diff --git a/scripts/Makefile b/scripts/Makefile -index a55b006..01e7adb 100644 ---- a/scripts/Makefile -+++ b/scripts/Makefile -@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash - hostprogs-$(CONFIG_IKCONFIG) += bin2c - hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount - hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable -+hostprogs-$(CONFIG_ASN1) += asn1_compiler - - HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include -+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include - - always := $(hostprogs-y) $(hostprogs-m) - -diff --git a/scripts/Makefile.build b/scripts/Makefile.build -index ff1720d..0e801c3 100644 ---- a/scripts/Makefile.build -+++ b/scripts/Makefile.build -@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ - $(obj)/%.lds: $(src)/%.lds.S FORCE - $(call if_changed_dep,cpp_lds_S) - -+# ASN.1 grammar -+# --------------------------------------------------------------------------- -+quiet_cmd_asn1_compiler = ASN.1 $@ -+ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ -+ $(subst .h,.c,$@) $(subst .c,.h,$@) -+ -+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h -+ -+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler -+ $(call cmd,asn1_compiler) -+ - # Build the compiled-in targets - # --------------------------------------------------------------------------- - -diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c -new file mode 100644 -index 0000000..db0e5cd ---- /dev/null -+++ b/scripts/asn1_compiler.c -@@ -0,0 +1,1545 @@ -+/* Simplified ASN.1 notation parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum token_type { -+ DIRECTIVE_ABSENT, -+ DIRECTIVE_ALL, -+ DIRECTIVE_ANY, -+ DIRECTIVE_APPLICATION, -+ DIRECTIVE_AUTOMATIC, -+ DIRECTIVE_BEGIN, -+ DIRECTIVE_BIT, -+ DIRECTIVE_BMPString, -+ DIRECTIVE_BOOLEAN, -+ DIRECTIVE_BY, -+ DIRECTIVE_CHARACTER, -+ DIRECTIVE_CHOICE, -+ DIRECTIVE_CLASS, -+ DIRECTIVE_COMPONENT, -+ DIRECTIVE_COMPONENTS, -+ DIRECTIVE_CONSTRAINED, -+ DIRECTIVE_CONTAINING, -+ DIRECTIVE_DEFAULT, -+ DIRECTIVE_DEFINED, -+ DIRECTIVE_DEFINITIONS, -+ DIRECTIVE_EMBEDDED, -+ DIRECTIVE_ENCODED, -+ DIRECTIVE_ENCODING_CONTROL, -+ DIRECTIVE_END, -+ DIRECTIVE_ENUMERATED, -+ DIRECTIVE_EXCEPT, -+ DIRECTIVE_EXPLICIT, -+ DIRECTIVE_EXPORTS, -+ DIRECTIVE_EXTENSIBILITY, -+ DIRECTIVE_EXTERNAL, -+ DIRECTIVE_FALSE, -+ DIRECTIVE_FROM, -+ DIRECTIVE_GeneralString, -+ DIRECTIVE_GeneralizedTime, -+ DIRECTIVE_GraphicString, -+ DIRECTIVE_IA5String, -+ DIRECTIVE_IDENTIFIER, -+ DIRECTIVE_IMPLICIT, -+ DIRECTIVE_IMPLIED, -+ DIRECTIVE_IMPORTS, -+ DIRECTIVE_INCLUDES, -+ DIRECTIVE_INSTANCE, -+ DIRECTIVE_INSTRUCTIONS, -+ DIRECTIVE_INTEGER, -+ DIRECTIVE_INTERSECTION, -+ DIRECTIVE_ISO646String, -+ DIRECTIVE_MAX, -+ DIRECTIVE_MIN, -+ DIRECTIVE_MINUS_INFINITY, -+ DIRECTIVE_NULL, -+ DIRECTIVE_NumericString, -+ DIRECTIVE_OBJECT, -+ DIRECTIVE_OCTET, -+ DIRECTIVE_OF, -+ DIRECTIVE_OPTIONAL, -+ DIRECTIVE_ObjectDescriptor, -+ DIRECTIVE_PATTERN, -+ DIRECTIVE_PDV, -+ DIRECTIVE_PLUS_INFINITY, -+ DIRECTIVE_PRESENT, -+ DIRECTIVE_PRIVATE, -+ DIRECTIVE_PrintableString, -+ DIRECTIVE_REAL, -+ DIRECTIVE_RELATIVE_OID, -+ DIRECTIVE_SEQUENCE, -+ DIRECTIVE_SET, -+ DIRECTIVE_SIZE, -+ DIRECTIVE_STRING, -+ DIRECTIVE_SYNTAX, -+ DIRECTIVE_T61String, -+ DIRECTIVE_TAGS, -+ DIRECTIVE_TRUE, -+ DIRECTIVE_TeletexString, -+ DIRECTIVE_UNION, -+ DIRECTIVE_UNIQUE, -+ DIRECTIVE_UNIVERSAL, -+ DIRECTIVE_UTCTime, -+ DIRECTIVE_UTF8String, -+ DIRECTIVE_UniversalString, -+ DIRECTIVE_VideotexString, -+ DIRECTIVE_VisibleString, -+ DIRECTIVE_WITH, -+ NR__DIRECTIVES, -+ TOKEN_ASSIGNMENT = NR__DIRECTIVES, -+ TOKEN_OPEN_CURLY, -+ TOKEN_CLOSE_CURLY, -+ TOKEN_OPEN_SQUARE, -+ TOKEN_CLOSE_SQUARE, -+ TOKEN_OPEN_ACTION, -+ TOKEN_CLOSE_ACTION, -+ TOKEN_COMMA, -+ TOKEN_NUMBER, -+ TOKEN_TYPE_NAME, -+ TOKEN_ELEMENT_NAME, -+ NR__TOKENS -+}; -+ -+static const unsigned char token_to_tag[NR__TOKENS] = { -+ /* EOC goes first */ -+ [DIRECTIVE_BOOLEAN] = ASN1_BOOL, -+ [DIRECTIVE_INTEGER] = ASN1_INT, -+ [DIRECTIVE_BIT] = ASN1_BTS, -+ [DIRECTIVE_OCTET] = ASN1_OTS, -+ [DIRECTIVE_NULL] = ASN1_NULL, -+ [DIRECTIVE_OBJECT] = ASN1_OID, -+ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, -+ [DIRECTIVE_EXTERNAL] = ASN1_EXT, -+ [DIRECTIVE_REAL] = ASN1_REAL, -+ [DIRECTIVE_ENUMERATED] = ASN1_ENUM, -+ [DIRECTIVE_EMBEDDED] = 0, -+ [DIRECTIVE_UTF8String] = ASN1_UTF8STR, -+ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, -+ /* 14 */ -+ /* 15 */ -+ [DIRECTIVE_SEQUENCE] = ASN1_SEQ, -+ [DIRECTIVE_SET] = ASN1_SET, -+ [DIRECTIVE_NumericString] = ASN1_NUMSTR, -+ [DIRECTIVE_PrintableString] = ASN1_PRNSTR, -+ [DIRECTIVE_T61String] = ASN1_TEXSTR, -+ [DIRECTIVE_TeletexString] = ASN1_TEXSTR, -+ [DIRECTIVE_VideotexString] = ASN1_VIDSTR, -+ [DIRECTIVE_IA5String] = ASN1_IA5STR, -+ [DIRECTIVE_UTCTime] = ASN1_UNITIM, -+ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, -+ [DIRECTIVE_GraphicString] = ASN1_GRASTR, -+ [DIRECTIVE_VisibleString] = ASN1_VISSTR, -+ [DIRECTIVE_GeneralString] = ASN1_GENSTR, -+ [DIRECTIVE_UniversalString] = ASN1_UNITIM, -+ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, -+ [DIRECTIVE_BMPString] = ASN1_BMPSTR, -+}; -+ -+static const char asn1_classes[4][5] = { -+ [ASN1_UNIV] = "UNIV", -+ [ASN1_APPL] = "APPL", -+ [ASN1_CONT] = "CONT", -+ [ASN1_PRIV] = "PRIV" -+}; -+ -+static const char asn1_methods[2][5] = { -+ [ASN1_UNIV] = "PRIM", -+ [ASN1_APPL] = "CONS" -+}; -+ -+static const char *const asn1_universal_tags[32] = { -+ "EOC", -+ "BOOL", -+ "INT", -+ "BTS", -+ "OTS", -+ "NULL", -+ "OID", -+ "ODE", -+ "EXT", -+ "REAL", -+ "ENUM", -+ "EPDV", -+ "UTF8STR", -+ "RELOID", -+ NULL, /* 14 */ -+ NULL, /* 15 */ -+ "SEQ", -+ "SET", -+ "NUMSTR", -+ "PRNSTR", -+ "TEXSTR", -+ "VIDSTR", -+ "IA5STR", -+ "UNITIM", -+ "GENTIM", -+ "GRASTR", -+ "VISSTR", -+ "GENSTR", -+ "UNISTR", -+ "CHRSTR", -+ "BMPSTR", -+ NULL /* 31 */ -+}; -+ -+static const char *filename; -+static const char *grammar_name; -+static const char *outputname; -+static const char *headername; -+ -+static const char *const directives[NR__DIRECTIVES] = { -+#define _(X) [DIRECTIVE_##X] = #X -+ _(ABSENT), -+ _(ALL), -+ _(ANY), -+ _(APPLICATION), -+ _(AUTOMATIC), -+ _(BEGIN), -+ _(BIT), -+ _(BMPString), -+ _(BOOLEAN), -+ _(BY), -+ _(CHARACTER), -+ _(CHOICE), -+ _(CLASS), -+ _(COMPONENT), -+ _(COMPONENTS), -+ _(CONSTRAINED), -+ _(CONTAINING), -+ _(DEFAULT), -+ _(DEFINED), -+ _(DEFINITIONS), -+ _(EMBEDDED), -+ _(ENCODED), -+ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", -+ _(END), -+ _(ENUMERATED), -+ _(EXCEPT), -+ _(EXPLICIT), -+ _(EXPORTS), -+ _(EXTENSIBILITY), -+ _(EXTERNAL), -+ _(FALSE), -+ _(FROM), -+ _(GeneralString), -+ _(GeneralizedTime), -+ _(GraphicString), -+ _(IA5String), -+ _(IDENTIFIER), -+ _(IMPLICIT), -+ _(IMPLIED), -+ _(IMPORTS), -+ _(INCLUDES), -+ _(INSTANCE), -+ _(INSTRUCTIONS), -+ _(INTEGER), -+ _(INTERSECTION), -+ _(ISO646String), -+ _(MAX), -+ _(MIN), -+ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", -+ [DIRECTIVE_NULL] = "NULL", -+ _(NumericString), -+ _(OBJECT), -+ _(OCTET), -+ _(OF), -+ _(OPTIONAL), -+ _(ObjectDescriptor), -+ _(PATTERN), -+ _(PDV), -+ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", -+ _(PRESENT), -+ _(PRIVATE), -+ _(PrintableString), -+ _(REAL), -+ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", -+ _(SEQUENCE), -+ _(SET), -+ _(SIZE), -+ _(STRING), -+ _(SYNTAX), -+ _(T61String), -+ _(TAGS), -+ _(TRUE), -+ _(TeletexString), -+ _(UNION), -+ _(UNIQUE), -+ _(UNIVERSAL), -+ _(UTCTime), -+ _(UTF8String), -+ _(UniversalString), -+ _(VideotexString), -+ _(VisibleString), -+ _(WITH) -+}; -+ -+struct action { -+ struct action *next; -+ unsigned char index; -+ char name[]; -+}; -+ -+static struct action *action_list; -+static unsigned nr_actions; -+ -+struct token { -+ unsigned short line; -+ enum token_type token_type : 8; -+ unsigned char size; -+ struct action *action; -+ const char *value; -+ struct type *type; -+}; -+ -+static struct token *token_list; -+static unsigned nr_tokens; -+ -+static int directive_compare(const void *_key, const void *_pdir) -+{ -+ const struct token *token = _key; -+ const char *const *pdir = _pdir, *dir = *pdir; -+ size_t dlen, clen; -+ int val; -+ -+ dlen = strlen(dir); -+ clen = (dlen < token->size) ? dlen : token->size; -+ -+ //printf("cmp(%*.*s,%s) = ", -+ // (int)token->size, (int)token->size, token->value, -+ // dir); -+ -+ val = memcmp(token->value, dir, clen); -+ if (val != 0) { -+ //printf("%d [cmp]\n", val); -+ return val; -+ } -+ -+ if (dlen == token->size) { -+ //printf("0\n"); -+ return 0; -+ } -+ //printf("%d\n", (int)dlen - (int)token->size); -+ return dlen - token->size; /* shorter -> negative */ -+} -+ -+/* -+ * Tokenise an ASN.1 grammar -+ */ -+static void tokenise(char *buffer, char *end) -+{ -+ struct token *tokens; -+ char *line, *nl, *p, *q; -+ unsigned tix, lineno; -+ -+ /* Assume we're going to have half as many tokens as we have -+ * characters -+ */ -+ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); -+ if (!tokens) { -+ perror(NULL); -+ exit(1); -+ } -+ tix = 0; -+ -+ lineno = 0; -+ while (buffer < end) { -+ /* First of all, break out a line */ -+ lineno++; -+ line = buffer; -+ nl = memchr(line, '\n', end - buffer); -+ if (!nl) { -+ buffer = nl = end; -+ } else { -+ buffer = nl + 1; -+ *nl = '\0'; -+ } -+ -+ /* Remove "--" comments */ -+ p = line; -+ next_comment: -+ while ((p = memchr(p, '-', nl - p))) { -+ if (p[1] == '-') { -+ /* Found a comment; see if there's a terminator */ -+ q = p + 2; -+ while ((q = memchr(q, '-', nl - q))) { -+ if (q[1] == '-') { -+ /* There is - excise the comment */ -+ q += 2; -+ memmove(p, q, nl - q); -+ goto next_comment; -+ } -+ q++; -+ } -+ *p = '\0'; -+ nl = p; -+ break; -+ } else { -+ p++; -+ } -+ } -+ -+ p = line; -+ while (p < nl) { -+ /* Skip white space */ -+ while (p < nl && isspace(*p)) -+ *(p++) = 0; -+ if (p >= nl) -+ break; -+ -+ tokens[tix].line = lineno; -+ tokens[tix].value = p; -+ -+ /* Handle string tokens */ -+ if (isalpha(*p)) { -+ const char **dir; -+ -+ /* Can be a directive, type name or element -+ * name. Find the end of the name. -+ */ -+ q = p + 1; -+ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ -+ /* If it begins with a lowercase letter then -+ * it's an element name -+ */ -+ if (islower(tokens[tix].value[0])) { -+ tokens[tix++].token_type = TOKEN_ELEMENT_NAME; -+ continue; -+ } -+ -+ /* Otherwise we need to search the directive -+ * table -+ */ -+ dir = bsearch(&tokens[tix], directives, -+ sizeof(directives) / sizeof(directives[1]), -+ sizeof(directives[1]), -+ directive_compare); -+ if (dir) { -+ tokens[tix++].token_type = dir - directives; -+ continue; -+ } -+ -+ tokens[tix++].token_type = TOKEN_TYPE_NAME; -+ continue; -+ } -+ -+ /* Handle numbers */ -+ if (isdigit(*p)) { -+ /* Find the end of the number */ -+ q = p + 1; -+ while (q < nl && (isdigit(*q))) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ tokens[tix++].token_type = TOKEN_NUMBER; -+ continue; -+ } -+ -+ if (nl - p >= 3) { -+ if (memcmp(p, "::=", 3) == 0) { -+ p += 3; -+ tokens[tix].size = 3; -+ tokens[tix++].token_type = TOKEN_ASSIGNMENT; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 2) { -+ if (memcmp(p, "({", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_OPEN_ACTION; -+ continue; -+ } -+ if (memcmp(p, "})", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_CLOSE_ACTION; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 1) { -+ tokens[tix].size = 1; -+ switch (*p) { -+ case '{': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_CURLY; -+ continue; -+ case '}': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_CURLY; -+ continue; -+ case '[': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_SQUARE; -+ continue; -+ case ']': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; -+ continue; -+ case ',': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_COMMA; -+ continue; -+ default: -+ break; -+ } -+ } -+ -+ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", -+ filename, lineno, *p); -+ exit(1); -+ } -+ } -+ -+ nr_tokens = tix; -+ printf("Extracted %u tokens\n", nr_tokens); -+ -+#if 0 -+ { -+ int n; -+ for (n = 0; n < nr_tokens; n++) -+ printf("Token %3u: '%*.*s'\n", -+ n, -+ (int)token_list[n].size, (int)token_list[n].size, -+ token_list[n].value); -+ } -+#endif -+} -+ -+static void build_type_list(void); -+static void parse(void); -+static void render(FILE *out, FILE *hdr); -+ -+/* -+ * -+ */ -+int main(int argc, char **argv) -+{ -+ struct stat st; -+ ssize_t readlen; -+ FILE *out, *hdr; -+ char *buffer, *p; -+ int fd; -+ -+ if (argc != 4) { -+ fprintf(stderr, "Format: %s \n", -+ argv[0]); -+ exit(2); -+ } -+ -+ filename = argv[1]; -+ outputname = argv[2]; -+ headername = argv[3]; -+ -+ fd = open(filename, O_RDONLY); -+ if (fd < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (fstat(fd, &st) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (!(buffer = malloc(st.st_size + 1))) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ if ((readlen = read(fd, buffer, st.st_size)) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (close(fd) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (readlen != st.st_size) { -+ fprintf(stderr, "%s: Short read\n", filename); -+ exit(1); -+ } -+ -+ p = strrchr(argv[1], '/'); -+ p = p ? p + 1 : argv[1]; -+ grammar_name = strdup(p); -+ if (!p) { -+ perror(NULL); -+ exit(1); -+ } -+ p = strchr(grammar_name, '.'); -+ if (p) -+ *p = '\0'; -+ -+ buffer[readlen] = 0; -+ tokenise(buffer, buffer + readlen); -+ build_type_list(); -+ parse(); -+ -+ out = fopen(outputname, "w"); -+ if (!out) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ hdr = fopen(headername, "w"); -+ if (!out) { -+ perror(headername); -+ exit(1); -+ } -+ -+ render(out, hdr); -+ -+ if (fclose(out) < 0) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ if (fclose(hdr) < 0) { -+ perror(headername); -+ exit(1); -+ } -+ -+ return 0; -+} -+ -+enum compound { -+ NOT_COMPOUND, -+ SET, -+ SET_OF, -+ SEQUENCE, -+ SEQUENCE_OF, -+ CHOICE, -+ ANY, -+ TYPE_REF, -+ TAG_OVERRIDE -+}; -+ -+struct element { -+ struct type *type_def; -+ struct token *name; -+ struct token *type; -+ struct action *action; -+ struct element *children; -+ struct element *next; -+ struct element *render_next; -+ struct element *list_next; -+ uint8_t n_elements; -+ enum compound compound : 8; -+ enum asn1_class class : 8; -+ enum asn1_method method : 8; -+ uint8_t tag; -+ unsigned entry_index; -+ unsigned flags; -+#define ELEMENT_IMPLICIT 0x0001 -+#define ELEMENT_EXPLICIT 0x0002 -+#define ELEMENT_MARKED 0x0004 -+#define ELEMENT_RENDERED 0x0008 -+#define ELEMENT_SKIPPABLE 0x0010 -+#define ELEMENT_CONDITIONAL 0x0020 -+}; -+ -+struct type { -+ struct token *name; -+ struct token *def; -+ struct element *element; -+ unsigned ref_count; -+ unsigned flags; -+#define TYPE_STOP_MARKER 0x0001 -+#define TYPE_BEGIN 0x0002 -+}; -+ -+static struct type *type_list; -+static struct type **type_index; -+static unsigned nr_types; -+ -+static int type_index_compare(const void *_a, const void *_b) -+{ -+ const struct type *const *a = _a, *const *b = _b; -+ -+ if ((*a)->name->size != (*b)->name->size) -+ return (*a)->name->size - (*b)->name->size; -+ else -+ return memcmp((*a)->name->value, (*b)->name->value, -+ (*a)->name->size); -+} -+ -+static int type_finder(const void *_key, const void *_ti) -+{ -+ const struct token *token = _key; -+ const struct type *const *ti = _ti; -+ const struct type *type = *ti; -+ -+ if (token->size != type->name->size) -+ return token->size - type->name->size; -+ else -+ return memcmp(token->value, type->name->value, -+ token->size); -+} -+ -+/* -+ * Build up a list of types and a sorted index to that list. -+ */ -+static void build_type_list(void) -+{ -+ struct type *types; -+ unsigned nr, t, n; -+ -+ nr = 0; -+ for (n = 0; n < nr_tokens - 1; n++) -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) -+ nr++; -+ -+ if (nr == 0) { -+ fprintf(stderr, "%s: No defined types\n", filename); -+ exit(1); -+ } -+ -+ nr_types = nr; -+ types = type_list = calloc(nr + 1, sizeof(type_list[0])); -+ if (!type_list) { -+ perror(NULL); -+ exit(1); -+ } -+ type_index = calloc(nr, sizeof(type_index[0])); -+ if (!type_index) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ t = 0; -+ types[t].flags |= TYPE_BEGIN; -+ for (n = 0; n < nr_tokens - 1; n++) { -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { -+ types[t].name = &token_list[n]; -+ type_index[t] = &types[t]; -+ t++; -+ } -+ } -+ types[t].name = &token_list[n + 1]; -+ types[t].flags |= TYPE_STOP_MARKER; -+ -+ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); -+ -+ printf("Extracted %u types\n", nr_types); -+#if 0 -+ for (n = 0; n < nr_types; n++) { -+ struct type *type = type_index[n]; -+ printf("- %*.*s\n", -+ (int)type->name->size, -+ (int)type->name->size, -+ type->name->value); -+ } -+#endif -+} -+ -+static struct element *parse_type(struct token **_cursor, struct token *stop, -+ struct token *name); -+ -+/* -+ * Parse the token stream -+ */ -+static void parse(void) -+{ -+ struct token *cursor; -+ struct type *type; -+ -+ /* Parse one type definition statement at a time */ -+ type = type_list; -+ do { -+ cursor = type->name; -+ -+ if (cursor[0].token_type != TOKEN_TYPE_NAME || -+ cursor[1].token_type != TOKEN_ASSIGNMENT) -+ abort(); -+ cursor += 2; -+ -+ type->element = parse_type(&cursor, type[1].name, NULL); -+ type->element->type_def = type; -+ -+ if (cursor != type[1].name) { -+ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ } while (type++, !(type->flags & TYPE_STOP_MARKER)); -+ -+ printf("Extracted %u actions\n", nr_actions); -+} -+ -+static struct element *element_list; -+ -+static struct element *alloc_elem(struct token *type) -+{ -+ struct element *e = calloc(1, sizeof(*e)); -+ if (!e) { -+ perror(NULL); -+ exit(1); -+ } -+ e->list_next = element_list; -+ element_list = e; -+ return e; -+} -+ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates); -+ -+/* -+ * Parse one type definition statement -+ */ -+static struct element *parse_type(struct token **_cursor, struct token *end, -+ struct token *name) -+{ -+ struct element *top, *element; -+ struct action *action, **ppaction; -+ struct token *cursor = *_cursor; -+ struct type **ref; -+ char *p; -+ int labelled = 0, implicit = 0; -+ -+ top = element = alloc_elem(cursor); -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ -+ /* Extract the tag value if one given */ -+ if (cursor->token_type == TOKEN_OPEN_SQUARE) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ switch (cursor->token_type) { -+ case DIRECTIVE_UNIVERSAL: -+ element->class = ASN1_UNIV; -+ cursor++; -+ break; -+ case DIRECTIVE_APPLICATION: -+ element->class = ASN1_APPL; -+ cursor++; -+ break; -+ case TOKEN_NUMBER: -+ element->class = ASN1_CONT; -+ break; -+ case DIRECTIVE_PRIVATE: -+ element->class = ASN1_PRIV; -+ cursor++; -+ break; -+ default: -+ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_NUMBER) { -+ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ element->tag &= ~0x1f; -+ element->tag |= strtoul(cursor->value, &p, 10); -+ if (p - cursor->value != cursor->size) -+ abort(); -+ cursor++; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_SQUARE) { -+ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ labelled = 1; -+ } -+ -+ /* Handle implicit and explicit markers */ -+ if (cursor->token_type == DIRECTIVE_IMPLICIT) { -+ element->flags |= ELEMENT_IMPLICIT; -+ implicit = 1; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { -+ element->flags |= ELEMENT_EXPLICIT; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ if (labelled) { -+ if (!implicit) -+ element->method |= ASN1_CONS; -+ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; -+ element->children = alloc_elem(cursor); -+ element = element->children; -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ } -+ -+ /* Extract the type we're expecting here */ -+ element->type = cursor; -+ switch (cursor->token_type) { -+ case DIRECTIVE_ANY: -+ element->compound = ANY; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_NULL: -+ case DIRECTIVE_BOOLEAN: -+ case DIRECTIVE_ENUMERATED: -+ case DIRECTIVE_INTEGER: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_EXTERNAL: -+ element->method = ASN1_CONS; -+ -+ case DIRECTIVE_BMPString: -+ case DIRECTIVE_GeneralString: -+ case DIRECTIVE_GraphicString: -+ case DIRECTIVE_IA5String: -+ case DIRECTIVE_ISO646String: -+ case DIRECTIVE_NumericString: -+ case DIRECTIVE_PrintableString: -+ case DIRECTIVE_T61String: -+ case DIRECTIVE_TeletexString: -+ case DIRECTIVE_UniversalString: -+ case DIRECTIVE_UTF8String: -+ case DIRECTIVE_VideotexString: -+ case DIRECTIVE_VisibleString: -+ case DIRECTIVE_ObjectDescriptor: -+ case DIRECTIVE_GeneralizedTime: -+ case DIRECTIVE_UTCTime: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_BIT: -+ case DIRECTIVE_OCTET: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_STRING) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_OBJECT: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_IDENTIFIER) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case TOKEN_TYPE_NAME: -+ element->compound = TYPE_REF; -+ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), -+ type_finder); -+ if (!ref) { -+ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor->type = *ref; -+ (*ref)->ref_count++; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_CHOICE: -+ element->compound = CHOICE; -+ cursor++; -+ element->children = parse_compound(&cursor, end, 1); -+ break; -+ -+ case DIRECTIVE_SEQUENCE: -+ element->compound = SEQUENCE; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SEQUENCE_OF; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 0); -+ } -+ break; -+ -+ case DIRECTIVE_SET: -+ element->compound = SET; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SET_OF; -+ cursor++; -+ if (cursor >= end) -+ goto parse_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 1); -+ } -+ break; -+ -+ default: -+ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ /* Handle elements that are optional */ -+ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || -+ cursor->token_type == DIRECTIVE_DEFAULT) -+ ) { -+ cursor++; -+ top->flags |= ELEMENT_SKIPPABLE; -+ } -+ -+ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_ELEMENT_NAME) { -+ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ action = malloc(sizeof(struct action) + cursor->size + 1); -+ if (!action) { -+ perror(NULL); -+ exit(1); -+ } -+ action->index = 0; -+ memcpy(action->name, cursor->value, cursor->size); -+ action->name[cursor->size] = 0; -+ -+ for (ppaction = &action_list; -+ *ppaction; -+ ppaction = &(*ppaction)->next -+ ) { -+ int cmp = strcmp(action->name, (*ppaction)->name); -+ if (cmp == 0) { -+ free(action); -+ action = *ppaction; -+ goto found; -+ } -+ if (cmp < 0) { -+ action->next = *ppaction; -+ *ppaction = action; -+ nr_actions++; -+ goto found; -+ } -+ } -+ action->next = NULL; -+ *ppaction = action; -+ nr_actions++; -+ found: -+ -+ element->action = action; -+ cursor->action = action; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_ACTION) { -+ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ } -+ -+ *_cursor = cursor; -+ return top; -+ -+parse_error: -+ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+/* -+ * Parse a compound type list -+ */ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates) -+{ -+ struct element *children, **child_p = &children, *element; -+ struct token *cursor = *_cursor, *name; -+ -+ if (cursor->token_type != TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ -+ if (cursor->token_type == TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Empty compound\n", -+ filename, cursor->line); -+ exit(1); -+ } -+ -+ for (;;) { -+ name = NULL; -+ if (cursor->token_type == TOKEN_ELEMENT_NAME) { -+ name = cursor; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ element = parse_type(&cursor, end, name); -+ if (alternates) -+ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; -+ -+ *child_p = element; -+ child_p = &element->next; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_COMMA) -+ break; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ children->flags &= ~ELEMENT_CONDITIONAL; -+ -+ if (cursor->token_type != TOKEN_CLOSE_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ -+ *_cursor = cursor; -+ return children; -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+static void render_element(FILE *out, struct element *e, struct element *tag); -+static void render_out_of_line_list(FILE *out); -+ -+static int nr_entries; -+static int render_depth = 1; -+static struct element *render_list, **render_list_p = &render_list; -+ -+__attribute__((format(printf, 2, 3))) -+static void render_opcode(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+ nr_entries++; -+} -+ -+__attribute__((format(printf, 2, 3))) -+static void render_more(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+} -+ -+/* -+ * Render the grammar into a state machine definition. -+ */ -+static void render(FILE *out, FILE *hdr) -+{ -+ struct element *e; -+ struct action *action; -+ struct type *root; -+ int index; -+ -+ fprintf(hdr, "/*\n"); -+ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(hdr, " *\n"); -+ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(hdr, " */\n"); -+ fprintf(hdr, "#include \n"); -+ fprintf(hdr, "\n"); -+ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); -+ if (ferror(hdr)) { -+ perror(headername); -+ exit(1); -+ } -+ -+ fprintf(out, "/*\n"); -+ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(out, " *\n"); -+ fprintf(out, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(out, " */\n"); -+ fprintf(out, "#include \n"); -+ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); -+ fprintf(out, "\n"); -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* Tabulate the action functions we might have to call */ -+ fprintf(hdr, "\n"); -+ index = 0; -+ for (action = action_list; action; action = action->next) { -+ action->index = index++; -+ fprintf(hdr, -+ "extern int %s(void *, size_t, unsigned char," -+ " const void *, size_t);\n", -+ action->name); -+ } -+ fprintf(hdr, "\n"); -+ -+ fprintf(out, "enum %s_actions {\n", grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\tACT_%s = %u,\n", -+ action->name, action->index); -+ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", -+ grammar_name, grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); -+ fprintf(out, "};\n"); -+ -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* We do two passes - the first one calculates all the offsets */ -+ printf("Pass 1\n"); -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(NULL, root->element, NULL); -+ render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(NULL); -+ -+ for (e = element_list; e; e = e->list_next) -+ e->flags &= ~ELEMENT_RENDERED; -+ -+ /* And then we actually render */ -+ printf("Pass 2\n"); -+ fprintf(out, "\n"); -+ fprintf(out, "static const unsigned char %s_machine[] = {\n", -+ grammar_name); -+ -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(out, root->element, NULL); -+ render_opcode(out, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(out); -+ -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); -+ fprintf(out, "\t.machine = %s_machine,\n", grammar_name); -+ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); -+ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); -+ fprintf(out, "};\n"); -+} -+ -+/* -+ * Render the out-of-line elements -+ */ -+static void render_out_of_line_list(FILE *out) -+{ -+ struct element *e, *ce; -+ const char *act; -+ int entry; -+ -+ while ((e = render_list)) { -+ render_list = e->render_next; -+ if (!render_list) -+ render_list_p = &render_list; -+ -+ render_more(out, "\n"); -+ e->entry_index = entry = nr_entries; -+ render_depth++; -+ for (ce = e->children; ce; ce = ce->next) -+ render_element(out, ce, NULL); -+ render_depth--; -+ -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case SEQUENCE: -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ break; -+ case SEQUENCE_OF: -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ case SET: -+ render_opcode(out, "ASN1_OP_END_SET%s,\n", act); -+ break; -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ } -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", -+ e->action->name); -+ render_opcode(out, "ASN1_OP_RETURN,\n"); -+ } -+} -+ -+/* -+ * Render an element. -+ */ -+static void render_element(FILE *out, struct element *e, struct element *tag) -+{ -+ struct element *ec; -+ const char *cond, *act; -+ int entry, skippable = 0, outofline = 0; -+ -+ if (e->flags & ELEMENT_SKIPPABLE || -+ (tag && tag->flags & ELEMENT_SKIPPABLE)) -+ skippable = 1; -+ -+ if ((e->type_def && e->type_def->ref_count > 1) || -+ skippable) -+ outofline = 1; -+ -+ if (e->type_def && out) { -+ render_more(out, "\t// %*.*s\n", -+ (int)e->type_def->name->size, (int)e->type_def->name->size, -+ e->type_def->name->value); -+ } -+ -+ /* Render the operation */ -+ cond = (e->flags & ELEMENT_CONDITIONAL || -+ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case ANY: -+ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ goto dont_render_tag; -+ -+ case TAG_OVERRIDE: -+ render_element(out, e->children, e); -+ return; -+ -+ case SEQUENCE: -+ case SEQUENCE_OF: -+ case SET: -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, -+ outofline ? "_JUMP" : "", -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ -+ case CHOICE: -+ goto dont_render_tag; -+ -+ case TYPE_REF: -+ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) -+ goto dont_render_tag; -+ default: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, act, -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ } -+ -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ -+ /* Render the tag */ -+ if (!tag) -+ tag = e; -+ if (tag->class == ASN1_UNIV && -+ tag->tag != 14 && -+ tag->tag != 15 && -+ tag->tag != 31) -+ render_opcode(out, "_tag(%s, %s, %s),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ asn1_universal_tags[tag->tag]); -+ else -+ render_opcode(out, "_tagn(%s, %s, %2u),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ tag->tag); -+ tag = NULL; -+dont_render_tag: -+ -+ /* Deal with compound types */ -+ switch (e->compound) { -+ case TYPE_REF: -+ render_element(out, e->type->type->element, tag); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ case SEQUENCE: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ render_depth++; -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ render_depth--; -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ } -+ break; -+ -+ case SEQUENCE_OF: -+ case SET_OF: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ entry = nr_entries; -+ render_depth++; -+ render_element(out, e->children, NULL); -+ render_depth--; -+ if (e->compound == SEQUENCE_OF) -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ else -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ } -+ break; -+ -+ case SET: -+ /* I can't think of a nice way to do SET support without having -+ * a stack of bitmasks to make sure no element is repeated. -+ * The bitmask has also to be checked that no non-optional -+ * elements are left out whilst not preventing optional -+ * elements from being left out. -+ */ -+ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); -+ exit(1); -+ -+ case CHOICE: -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ if (!skippable) -+ render_opcode(out, "ASN1_OP_COND_FAIL,\n"); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", e->action->name); -+} --- -1.7.11.4 - - -From 8ea3f94cc16a23e3edbebf12f4223e654eb8219d Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:16 +0100 -Subject: [PATCH 15/26] X.509: Add an ASN.1 decoder - -Add an ASN.1 BER/DER/CER decoder. This uses the bytecode from the ASN.1 -compiler in the previous patch to inform it as to what to expect to find in the -encoded byte stream. The output from the compiler also tells it what functions -to call on what tags, thus allowing the caller to retrieve information. - -The decoder is called as follows: - - int asn1_decoder(const struct asn1_decoder *decoder, - void *context, - const unsigned char *data, - size_t datalen); - -The decoder argument points to the bytecode from the ASN.1 compiler. context -is the caller's context and is passed to the action functions. data and -datalen define the byte stream to be decoded. - - -Note that the decoder is currently limited to datalen being less than 64K. -This reduces the amount of stack space used by the decoder because ASN.1 is a -nested construct. Similarly, the decoder is limited to a maximum of 10 levels -of constructed data outside of a leaf node also in an effort to keep stack -usage down. - -These restrictions can be raised if necessary. - -Signed-off-by: David Howells ---- - include/linux/asn1_decoder.h | 24 +++ - lib/Makefile | 2 + - lib/asn1_decoder.c | 477 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 503 insertions(+) - create mode 100644 include/linux/asn1_decoder.h - create mode 100644 lib/asn1_decoder.c - -diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h -new file mode 100644 -index 0000000..fa2ff5b ---- /dev/null -+++ b/include/linux/asn1_decoder.h -@@ -0,0 +1,24 @@ -+/* ASN.1 decoder -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_DECODER_H -+#define _LINUX_ASN1_DECODER_H -+ -+#include -+ -+struct asn1_decoder; -+ -+extern int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen); -+ -+#endif /* _LINUX_ASN1_DECODER_H */ -diff --git a/lib/Makefile b/lib/Makefile -index b042896..ca856b6 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \ - $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) - lib-$(CONFIG_LIBFDT) += $(libfdt_files) - -+obj-$(CONFIG_ASN1) += asn1_decoder.o -+ - hostprogs-y := gen_crc32table - clean-files := crc32table.h - -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -new file mode 100644 -index 0000000..2e4196d ---- /dev/null -+++ b/lib/asn1_decoder.c -@@ -0,0 +1,477 @@ -+/* Decoder for ASN.1 BER/DER/CER encoded bytestream -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { -+ /* OPC TAG JMP ACT */ -+ [ASN1_OP_MATCH] = 1 + 1, -+ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ANY] = 1, -+ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_ANY] = 1, -+ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_FAIL] = 1, -+ [ASN1_OP_COMPLETE] = 1, -+ [ASN1_OP_ACT] = 1 + 1, -+ [ASN1_OP_RETURN] = 1, -+ [ASN1_OP_END_SEQ] = 1, -+ [ASN1_OP_END_SEQ_OF] = 1 + 1, -+ [ASN1_OP_END_SET] = 1, -+ [ASN1_OP_END_SET_OF] = 1 + 1, -+ [ASN1_OP_END_SEQ_ACT] = 1 + 1, -+ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, -+ [ASN1_OP_END_SET_ACT] = 1 + 1, -+ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, -+}; -+ -+/* -+ * Find the length of an indefinite length object -+ */ -+static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, -+ const char **_errmsg, size_t *_err_dp) -+{ -+ unsigned char tag, tmp; -+ size_t dp = 0, len, n; -+ int indef_level = 1; -+ -+next_tag: -+ if (unlikely(datalen - dp < 2)) { -+ if (datalen == dp) -+ goto missing_eoc; -+ goto data_overrun_error; -+ } -+ -+ /* Extract a tag from the data */ -+ tag = data[dp++]; -+ if (tag == 0) { -+ /* It appears to be an EOC. */ -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ if (--indef_level <= 0) -+ return dp; -+ goto next_tag; -+ } -+ -+ if (unlikely((tag & 0x1f) == 0x1f)) { -+ do { -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ tmp = data[dp++]; -+ } while (tmp & 0x80); -+ } -+ -+ /* Extract the length */ -+ len = data[dp++]; -+ if (len < 0x7f) { -+ dp += len; -+ goto next_tag; -+ } -+ -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) -+ goto indefinite_len_primitive; -+ indef_level++; -+ goto next_tag; -+ } -+ -+ n = len - 0x80; -+ if (unlikely(n > sizeof(size_t) - 1)) -+ goto length_too_long; -+ if (unlikely(n > datalen - dp)) -+ goto data_overrun_error; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ dp += len; -+ goto next_tag; -+ -+length_too_long: -+ *_errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ *_errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+invalid_eoc: -+ *_errmsg = "Invalid length EOC"; -+ goto error; -+data_overrun_error: -+ *_errmsg = "Data overrun error"; -+ goto error; -+missing_eoc: -+ *_errmsg = "Missing EOC in indefinite len cons"; -+error: -+ *_err_dp = dp; -+ return -1; -+} -+ -+/** -+ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern -+ * @decoder: The decoder definition (produced by asn1_compiler) -+ * @context: The caller's context (to be passed to the action functions) -+ * @data: The encoded data -+ * @datasize: The size of the encoded data -+ * -+ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern -+ * produced by asn1_compiler. Action functions are called on marked tags to -+ * allow the caller to retrieve significant data. -+ * -+ * LIMITATIONS: -+ * -+ * To keep down the amount of stack used by this function, the following limits -+ * have been imposed: -+ * -+ * (1) This won't handle datalen > 65535 without increasing the size of the -+ * cons stack elements and length_too_long checking. -+ * -+ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf -+ * constructed types exceeds this, the decode will fail. -+ * -+ * (3) The SET type (not the SET OF type) isn't really supported as tracking -+ * what members of the set have been seen is a pain. -+ */ -+int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen) -+{ -+ const unsigned char *machine = decoder->machine; -+ const asn1_action_t *actions = decoder->actions; -+ size_t machlen = decoder->machlen; -+ enum asn1_opcode op; -+ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; -+ const char *errmsg; -+ size_t pc = 0, dp = 0, tdp = 0, len = 0; -+ int ret; -+ -+ unsigned char flags = 0; -+#define FLAG_INDEFINITE_LENGTH 0x01 -+#define FLAG_MATCHED 0x02 -+#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag -+ * - ie. whether or not we are going to parse -+ * a compound type. -+ */ -+ -+#define NR_CONS_STACK 10 -+ unsigned short cons_dp_stack[NR_CONS_STACK]; -+ unsigned short cons_datalen_stack[NR_CONS_STACK]; -+ unsigned char cons_hdrlen_stack[NR_CONS_STACK]; -+#define NR_JUMP_STACK 10 -+ unsigned char jump_stack[NR_JUMP_STACK]; -+ -+ if (datalen > 65535) -+ return -EMSGSIZE; -+ -+next_op: -+ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", -+ pc, machlen, dp, datalen, csp, jsp); -+ if (unlikely(pc >= machlen)) -+ goto machine_overrun_error; -+ op = machine[pc]; -+ if (unlikely(pc + asn1_op_lengths[op] > machlen)) -+ goto machine_overrun_error; -+ -+ /* If this command is meant to match a tag, then do that before -+ * evaluating the command. -+ */ -+ if (op <= ASN1_OP__MATCHES_TAG) { -+ unsigned char tmp; -+ -+ /* Skip conditional matches if possible */ -+ if ((op & ASN1_OP_MATCH__COND && -+ flags & FLAG_MATCHED) || -+ dp == datalen) { -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ } -+ -+ flags = 0; -+ hdr = 2; -+ -+ /* Extract a tag from the data */ -+ if (unlikely(dp >= datalen - 1)) -+ goto data_overrun_error; -+ tag = data[dp++]; -+ if (unlikely((tag & 0x1f) == 0x1f)) -+ goto long_tag_not_supported; -+ -+ if (op & ASN1_OP_MATCH__ANY) { -+ pr_debug("- any %02x\n", tag); -+ } else { -+ /* Extract the tag from the machine -+ * - Either CONS or PRIM are permitted in the data if -+ * CONS is not set in the op stream, otherwise CONS -+ * is mandatory. -+ */ -+ optag = machine[pc + 1]; -+ flags |= optag & FLAG_CONS; -+ -+ /* Determine whether the tag matched */ -+ tmp = optag ^ tag; -+ tmp &= ~(optag & ASN1_CONS_BIT); -+ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); -+ if (tmp != 0) { -+ /* All odd-numbered tags are MATCH_OR_SKIP. */ -+ if (op & ASN1_OP_MATCH__SKIP) { -+ pc += asn1_op_lengths[op]; -+ dp--; -+ goto next_op; -+ } -+ goto tag_mismatch; -+ } -+ } -+ flags |= FLAG_MATCHED; -+ -+ len = data[dp++]; -+ if (len > 0x7f) { -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely(!(tag & ASN1_CONS_BIT))) -+ goto indefinite_len_primitive; -+ flags |= FLAG_INDEFINITE_LENGTH; -+ if (unlikely(2 > datalen - dp)) -+ goto data_overrun_error; -+ } else { -+ int n = len - 0x80; -+ if (unlikely(n > 2)) -+ goto length_too_long; -+ if (unlikely(dp >= datalen - n)) -+ goto data_overrun_error; -+ hdr += n; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ if (unlikely(len > datalen - dp)) -+ goto data_overrun_error; -+ } -+ } -+ -+ if (flags & FLAG_CONS) { -+ /* For expected compound forms, we stack the positions -+ * of the start and end of the data. -+ */ -+ if (unlikely(csp >= NR_CONS_STACK)) -+ goto cons_stack_overflow; -+ cons_dp_stack[csp] = dp; -+ cons_hdrlen_stack[csp] = hdr; -+ if (!(flags & FLAG_INDEFINITE_LENGTH)) { -+ cons_datalen_stack[csp] = datalen; -+ datalen = dp + len; -+ } else { -+ cons_datalen_stack[csp] = 0; -+ } -+ csp++; -+ } -+ -+ pr_debug("- TAG: %02x %zu%s\n", -+ tag, len, flags & FLAG_CONS ? " CONS" : ""); -+ tdp = dp; -+ } -+ -+ /* Decide how to handle the operation */ -+ switch (op) { -+ case ASN1_OP_MATCH_ANY_ACT: -+ case ASN1_OP_COND_MATCH_ANY_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH_ACT: -+ case ASN1_OP_MATCH_ACT_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: -+ ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH: -+ case ASN1_OP_MATCH_OR_SKIP: -+ case ASN1_OP_MATCH_ANY: -+ case ASN1_OP_COND_MATCH_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ANY: -+ skip_data: -+ if (!(flags & FLAG_CONS)) { -+ if (flags & FLAG_INDEFINITE_LENGTH) { -+ len = asn1_find_indefinite_length( -+ data + dp, datalen - dp, &errmsg, &dp); -+ if (len < 0) -+ goto error; -+ } -+ pr_debug("- LEAF: %zu\n", len); -+ dp += len; -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_MATCH_JUMP: -+ case ASN1_OP_MATCH_JUMP_OR_SKIP: -+ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: -+ pr_debug("- MATCH_JUMP\n"); -+ if (unlikely(jsp == NR_JUMP_STACK)) -+ goto jump_stack_overflow; -+ jump_stack[jsp++] = pc + asn1_op_lengths[op]; -+ pc = machine[pc + 2]; -+ goto next_op; -+ -+ case ASN1_OP_COND_FAIL: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_COMPLETE: -+ if (unlikely(jsp != 0 || csp != 0)) { -+ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", -+ jsp, csp); -+ return -EBADMSG; -+ } -+ return 0; -+ -+ case ASN1_OP_END_SET: -+ case ASN1_OP_END_SET_ACT: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ case ASN1_OP_END_SEQ: -+ case ASN1_OP_END_SET_OF: -+ case ASN1_OP_END_SEQ_OF: -+ case ASN1_OP_END_SEQ_ACT: -+ case ASN1_OP_END_SET_OF_ACT: -+ case ASN1_OP_END_SEQ_OF_ACT: -+ if (unlikely(csp <= 0)) -+ goto cons_stack_underflow; -+ csp--; -+ tdp = cons_dp_stack[csp]; -+ hdr = cons_hdrlen_stack[csp]; -+ len = datalen; -+ datalen = cons_datalen_stack[csp]; -+ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", -+ tdp, dp, len, datalen); -+ if (datalen == 0) { -+ /* Indefinite length - check for the EOC. */ -+ datalen = len; -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ if (data[dp++] != 0) { -+ if (op & ASN1_OP_END__OF) { -+ dp--; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ goto missing_eoc; -+ } -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ len = dp - tdp - 2; -+ } else { -+ if (dp < len && (op & ASN1_OP_END__OF)) { -+ datalen = len; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ if (dp != len) -+ goto cons_length_error; -+ len -= tdp; -+ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); -+ } -+ -+ if (op & ASN1_OP_END__ACT) { -+ unsigned char act; -+ if (op & ASN1_OP_END__OF) -+ act = machine[pc + 2]; -+ else -+ act = machine[pc + 1]; -+ ret = actions[act](context, hdr, 0, data + tdp, len); -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_RETURN: -+ if (unlikely(jsp <= 0)) -+ goto jump_stack_underflow; -+ pc = jump_stack[--jsp]; -+ goto next_op; -+ -+ default: -+ break; -+ } -+ -+ /* Shouldn't reach here */ -+ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); -+ return -EBADMSG; -+ -+data_overrun_error: -+ errmsg = "Data overrun error"; -+ goto error; -+machine_overrun_error: -+ errmsg = "Machine overrun error"; -+ goto error; -+jump_stack_underflow: -+ errmsg = "Jump stack underflow"; -+ goto error; -+jump_stack_overflow: -+ errmsg = "Jump stack overflow"; -+ goto error; -+cons_stack_underflow: -+ errmsg = "Cons stack underflow"; -+ goto error; -+cons_stack_overflow: -+ errmsg = "Cons stack overflow"; -+ goto error; -+cons_length_error: -+ errmsg = "Cons length error"; -+ goto error; -+missing_eoc: -+ errmsg = "Missing EOC in indefinite len cons"; -+ goto error; -+invalid_eoc: -+ errmsg = "Invalid length EOC"; -+ goto error; -+length_too_long: -+ errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+tag_mismatch: -+ errmsg = "Unexpected tag"; -+ goto error; -+long_tag_not_supported: -+ errmsg = "Long tag not supported"; -+error: -+ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", -+ errmsg, pc, dp, optag, tag, len); -+ return -EBADMSG; -+} -+EXPORT_SYMBOL_GPL(asn1_ber_decoder); --- -1.7.11.4 - - -From f055a9091c35be0171d39ca8e76bb4677d89eef1 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:27 +0100 -Subject: [PATCH 16/26] MPILIB: Provide a function to read raw data into an - MPI - -Provide a function to read raw data of a predetermined size into an MPI rather -than expecting the size to be encoded within the data. The data is assumed to -represent an unsigned integer, and the resulting MPI will be positive. - -The function looks like this: - - MPI mpi_read_raw_data(const void *, size_t); - -This is useful for reading ASN.1 integer primitives where the length is encoded -in the ASN.1 metadata. - -Signed-off-by: David Howells ---- - include/linux/mpi.h | 1 + - lib/mpi/mpicoder.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 56 insertions(+) - -diff --git a/include/linux/mpi.h b/include/linux/mpi.h -index d02cca6..5af1b81 100644 ---- a/include/linux/mpi.h -+++ b/include/linux/mpi.h -@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); - - /*-- mpicoder.c --*/ - MPI do_encode_md(const void *sha_buffer, unsigned nbits); -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); - MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); - int mpi_fromstr(MPI val, const char *str); - u32 mpi_get_keyid(MPI a, u32 *keyid); -diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c -index f0fa659..3962b7f 100644 ---- a/lib/mpi/mpicoder.c -+++ b/lib/mpi/mpicoder.c -@@ -18,10 +18,65 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -+#include -+#include - #include "mpi-internal.h" - - #define MAX_EXTERN_MPI_BITS 16384 - -+/** -+ * mpi_read_raw_data - Read a raw byte stream as a positive integer -+ * @xbuffer: The data to read -+ * @nbytes: The amount of data to read -+ */ -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) -+{ -+ const uint8_t *buffer = xbuffer; -+ int i, j; -+ unsigned nbits, nlimbs; -+ mpi_limb_t a; -+ MPI val = NULL; -+ -+ while (nbytes >= 0 && buffer[0] == 0) { -+ buffer++; -+ nbytes--; -+ } -+ -+ nbits = nbytes * 8; -+ if (nbits > MAX_EXTERN_MPI_BITS) { -+ pr_info("MPI: mpi too large (%u bits)\n", nbits); -+ return NULL; -+ } -+ if (nbytes > 0) -+ nbits -= count_leading_zeros(buffer[0]); -+ else -+ nbits = 0; -+ -+ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; -+ val = mpi_alloc(nlimbs); -+ if (!val) -+ return NULL; -+ val->nbits = nbits; -+ val->sign = 0; -+ val->nlimbs = nlimbs; -+ -+ if (nbytes > 0) { -+ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; -+ i %= BYTES_PER_MPI_LIMB; -+ for (j = nlimbs; j > 0; j--) { -+ a = 0; -+ for (; i < BYTES_PER_MPI_LIMB; i++) { -+ a <<= 8; -+ a |= *buffer++; -+ } -+ i = 0; -+ val->d[j - 1] = a; -+ } -+ } -+ return val; -+} -+EXPORT_SYMBOL_GPL(mpi_read_raw_data); -+ - MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) - { - const uint8_t *buffer = xbuffer; --- -1.7.11.4 - - -From 3d816cdad8cdd5412ecc8f539bb09daef52ba361 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:48 +0100 -Subject: [PATCH 17/26] X.509: Add a crypto key parser for binary (DER) X.509 - certificates - -Add a crypto key parser for binary (DER) encoded X.509 certificates. The -certificate is parsed and, if possible, the signature is verified. - -An X.509 key can be added like this: - - # keyctl padd crypto bar @s ---- - crypto/asymmetric_keys/.gitignore | 1 + - crypto/asymmetric_keys/Kconfig | 10 + - crypto/asymmetric_keys/Makefile | 17 + - crypto/asymmetric_keys/x509.asn1 | 60 ++++ - crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/x509_parser.h | 36 +++ - crypto/asymmetric_keys/x509_public_key.c | 207 +++++++++++++ - crypto/asymmetric_keys/x509_rsakey.asn1 | 4 + - 8 files changed, 832 insertions(+) - create mode 100644 crypto/asymmetric_keys/.gitignore - create mode 100644 crypto/asymmetric_keys/x509.asn1 - create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c - create mode 100644 crypto/asymmetric_keys/x509_parser.h - create mode 100644 crypto/asymmetric_keys/x509_public_key.c - create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 - -diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore -new file mode 100644 -index 0000000..ee32837 ---- /dev/null -+++ b/crypto/asymmetric_keys/.gitignore -@@ -0,0 +1 @@ -+*-asn1.[ch] -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 561759d..6d2c2ea 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). - -+config X509_CERTIFICATE_PARSER -+ tristate "X.509 certificate parser" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select ASN1 -+ select OID_REGISTRY -+ help -+ This option procides support for parsing X.509 format blobs for key -+ data and provides the ability to instantiate a crypto key from a -+ public key packet found inside the certificate. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 7c92691..0727204 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+ -+# -+# X.509 Certificate handling -+# -+obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o -+x509_key_parser-y := \ -+ x509-asn1.o \ -+ x509_rsakey-asn1.o \ -+ x509_cert_parser.o \ -+ x509_public_key.o -+ -+$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h -+$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h -+$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h -+ -+clean-files += x509-asn1.c x509-asn1.h -+clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h -diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 -new file mode 100644 -index 0000000..bf32b3d ---- /dev/null -+++ b/crypto/asymmetric_keys/x509.asn1 -@@ -0,0 +1,60 @@ -+Certificate ::= SEQUENCE { -+ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), -+ signatureAlgorithm AlgorithmIdentifier, -+ signature BIT STRING ({ x509_note_signature }) -+ } -+ -+TBSCertificate ::= SEQUENCE { -+ version [ 0 ] Version DEFAULT, -+ serialNumber CertificateSerialNumber, -+ signature AlgorithmIdentifier ({ x509_note_pkey_algo }), -+ issuer Name ({ x509_note_issuer }), -+ validity Validity, -+ subject Name ({ x509_note_subject }), -+ subjectPublicKeyInfo SubjectPublicKeyInfo, -+ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ extensions [ 3 ] Extensions OPTIONAL -+ } -+ -+Version ::= INTEGER -+CertificateSerialNumber ::= INTEGER -+ -+AlgorithmIdentifier ::= SEQUENCE { -+ algorithm OBJECT IDENTIFIER ({ x509_note_OID }), -+ parameters ANY OPTIONAL -+} -+ -+Name ::= SEQUENCE OF RelativeDistinguishedName -+ -+RelativeDistinguishedName ::= SET OF AttributeValueAssertion -+ -+AttributeValueAssertion ::= SEQUENCE { -+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }), -+ attributeValue ANY ({ x509_extract_name_segment }) -+ } -+ -+Validity ::= SEQUENCE { -+ notBefore Time ({ x509_note_not_before }), -+ notAfter Time ({ x509_note_not_after }) -+ } -+ -+Time ::= CHOICE { -+ utcTime UTCTime, -+ generalTime GeneralizedTime -+ } -+ -+SubjectPublicKeyInfo ::= SEQUENCE { -+ algorithm AlgorithmIdentifier, -+ subjectPublicKey BIT STRING ({ x509_extract_key_data }) -+ } -+ -+UniqueIdentifier ::= BIT STRING -+ -+Extensions ::= SEQUENCE OF Extension -+ -+Extension ::= SEQUENCE { -+ extnid OBJECT IDENTIFIER ({ x509_note_OID }), -+ critical BOOLEAN DEFAULT, -+ extnValue OCTET STRING ({ x509_process_extension }) -+ } -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -new file mode 100644 -index 0000000..8fcac94 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -0,0 +1,497 @@ -+/* X.509 certificate parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "X.509: "fmt -+#include -+#include -+#include -+#include -+#include "public_key.h" -+#include "x509_parser.h" -+#include "x509-asn1.h" -+#include "x509_rsakey-asn1.h" -+ -+struct x509_parse_context { -+ struct x509_certificate *cert; /* Certificate being constructed */ -+ unsigned long data; /* Start of data */ -+ const void *cert_start; /* Start of cert content */ -+ const void *key; /* Key data */ -+ size_t key_size; /* Size of key data */ -+ enum OID last_oid; /* Last OID encountered */ -+ enum OID algo_oid; /* Algorithm OID */ -+ unsigned char nr_mpi; /* Number of MPIs stored */ -+ u8 o_size; /* Size of organizationName (O) */ -+ u8 cn_size; /* Size of commonName (CN) */ -+ u8 email_size; /* Size of emailAddress */ -+ u16 o_offset; /* Offset of organizationName (O) */ -+ u16 cn_offset; /* Offset of commonName (CN) */ -+ u16 email_offset; /* Offset of emailAddress */ -+}; -+ -+/* -+ * Free an X.509 certificate -+ */ -+void x509_free_certificate(struct x509_certificate *cert) -+{ -+ if (cert) { -+ public_key_destroy(cert->pub); -+ kfree(cert->issuer); -+ kfree(cert->subject); -+ kfree(cert->fingerprint); -+ kfree(cert->authority); -+ kfree(cert); -+ } -+} -+ -+/* -+ * Parse an X.509 certificate -+ */ -+struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) -+{ -+ struct x509_certificate *cert; -+ struct x509_parse_context *ctx; -+ long ret; -+ -+ ret = -ENOMEM; -+ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); -+ if (!cert) -+ goto error_no_cert; -+ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); -+ if (!cert->pub) -+ goto error_no_ctx; -+ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); -+ if (!ctx) -+ goto error_no_ctx; -+ -+ ctx->cert = cert; -+ ctx->data = (unsigned long)data; -+ -+ /* Attempt to decode the certificate */ -+ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); -+ if (ret < 0) -+ goto error_decode; -+ -+ /* Decode the public key */ -+ ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, -+ ctx->key, ctx->key_size); -+ if (ret < 0) -+ goto error_decode; -+ -+ kfree(ctx); -+ return cert; -+ -+error_decode: -+ kfree(ctx); -+error_no_ctx: -+ x509_free_certificate(cert); -+error_no_cert: -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Note an OID when we find one for later processing when we know how -+ * to interpret it. -+ */ -+int x509_note_OID(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ ctx->last_oid = look_up_OID(value, vlen); -+ if (ctx->last_oid == OID__NR) { -+ char buffer[50]; -+ sprint_oid(value, vlen, buffer, sizeof(buffer)); -+ pr_debug("Unknown OID: [%zu] %s\n", -+ (unsigned long)value - ctx->data, buffer); -+ } -+ return 0; -+} -+ -+/* -+ * Save the position of the TBS data so that we can check the signature over it -+ * later. -+ */ -+int x509_note_tbs_certificate(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", -+ hdrlen, tag, (unsigned long)value - ctx->data, vlen); -+ -+ ctx->cert->tbs = value - hdrlen; -+ ctx->cert->tbs_size = vlen + hdrlen; -+ return 0; -+} -+ -+/* -+ * Record the public key algorithm -+ */ -+int x509_note_pkey_algo(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("PubKey Algo: %u\n", ctx->last_oid); -+ -+ switch (ctx->last_oid) { -+ case OID_md2WithRSAEncryption: -+ case OID_md3WithRSAEncryption: -+ default: -+ return -ENOPKG; /* Unsupported combination */ -+ -+ case OID_md4WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_MD5; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha1WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha256WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha384WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha512WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha224WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ } -+ -+ ctx->algo_oid = ctx->last_oid; -+ return 0; -+} -+ -+/* -+ * Note the whereabouts and type of the signature. -+ */ -+int x509_note_signature(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); -+ -+ if (ctx->last_oid != ctx->algo_oid) { -+ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", -+ ctx->algo_oid, ctx->last_oid); -+ return -EINVAL; -+ } -+ -+ ctx->cert->sig = value; -+ ctx->cert->sig_size = vlen; -+ return 0; -+} -+ -+/* -+ * Note some of the name segments from which we'll fabricate a name. -+ */ -+int x509_extract_name_segment(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ switch (ctx->last_oid) { -+ case OID_commonName: -+ ctx->cn_size = vlen; -+ ctx->cn_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_organizationName: -+ ctx->o_size = vlen; -+ ctx->o_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_email_address: -+ ctx->email_size = vlen; -+ ctx->email_offset = (unsigned long)value - ctx->data; -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Fabricate and save the issuer and subject names -+ */ -+static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, -+ unsigned char tag, -+ char **_name, size_t vlen) -+{ -+ const void *name, *data = (const void *)ctx->data; -+ size_t namesize; -+ char *buffer; -+ -+ if (*_name) -+ return -EINVAL; -+ -+ /* Empty name string if no material */ -+ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { -+ buffer = kmalloc(1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ buffer[0] = 0; -+ goto done; -+ } -+ -+ if (ctx->cn_size && ctx->o_size) { -+ /* Consider combining O and CN, but use only the CN if it is -+ * prefixed by the O, or a significant portion thereof. -+ */ -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ if (ctx->cn_size >= ctx->o_size && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, -+ ctx->o_size) == 0) -+ goto single_component; -+ if (ctx->cn_size >= 7 && -+ ctx->o_size >= 7 && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) -+ goto single_component; -+ -+ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, -+ GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ -+ memcpy(buffer, -+ data + ctx->o_offset, ctx->o_size); -+ buffer[ctx->o_size + 0] = ':'; -+ buffer[ctx->o_size + 1] = ' '; -+ memcpy(buffer + ctx->o_size + 2, -+ data + ctx->cn_offset, ctx->cn_size); -+ buffer[ctx->o_size + 2 + ctx->cn_size] = 0; -+ goto done; -+ -+ } else if (ctx->cn_size) { -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ } else if (ctx->o_size) { -+ namesize = ctx->o_size; -+ name = data + ctx->o_offset; -+ } else { -+ namesize = ctx->email_size; -+ name = data + ctx->email_offset; -+ } -+ -+single_component: -+ buffer = kmalloc(namesize + 1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ memcpy(buffer, name, namesize); -+ buffer[namesize] = 0; -+ -+done: -+ *_name = buffer; -+ ctx->cn_size = 0; -+ ctx->o_size = 0; -+ ctx->email_size = 0; -+ return 0; -+} -+ -+int x509_note_issuer(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); -+} -+ -+int x509_note_subject(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); -+} -+ -+/* -+ * Extract the data for the public key algorithm -+ */ -+int x509_extract_key_data(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ if (ctx->last_oid != OID_rsaEncryption) -+ return -ENOPKG; -+ -+ /* There seems to be an extraneous 0 byte on the front of the data */ -+ ctx->cert->pkey_algo = PKEY_ALGO_RSA; -+ ctx->key = value + 1; -+ ctx->key_size = vlen - 1; -+ return 0; -+} -+ -+/* -+ * Extract a RSA public key value -+ */ -+int rsa_extract_mpi(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ MPI mpi; -+ -+ if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { -+ pr_err("Too many public key MPIs in certificate\n"); -+ return -EBADMSG; -+ } -+ -+ mpi = mpi_read_raw_data(value, vlen); -+ if (!mpi) -+ return -ENOMEM; -+ -+ ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; -+ return 0; -+} -+ -+/* -+ * Process certificate extensions that are used to qualify the certificate. -+ */ -+int x509_process_extension(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ const unsigned char *v = value; -+ char *f; -+ int i; -+ -+ pr_debug("Extension: %u\n", ctx->last_oid); -+ -+ if (ctx->last_oid == OID_subjectKeyIdentifier) { -+ /* Get hold of the key fingerprint */ -+ if (vlen < 3) -+ return -EBADMSG; -+ if (v[0] != ASN1_OTS || v[1] != vlen - 2) -+ return -EBADMSG; -+ v += 2; -+ vlen -= 2; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("fingerprint %s\n", f); -+ ctx->cert->fingerprint = f; -+ return 0; -+ } -+ -+ if (ctx->last_oid == OID_authorityKeyIdentifier) { -+ /* Get hold of the CA key fingerprint */ -+ if (vlen < 5) -+ return -EBADMSG; -+ if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || -+ v[1] != vlen - 2 || -+ v[2] != (ASN1_CONT << 6) || -+ v[3] != vlen - 4) -+ return -EBADMSG; -+ v += 4; -+ vlen -= 4; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("authority %s\n", f); -+ ctx->cert->authority = f; -+ return 0; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Record a certificate time. -+ */ -+static int x509_note_time(time_t *_time, size_t hdrlen, -+ unsigned char tag, -+ const unsigned char *value, size_t vlen) -+{ -+ unsigned YY, MM, DD, hh, mm, ss; -+ const unsigned char *p = value; -+ -+#define dec2bin(X) ((X) - '0') -+#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) -+ -+ if (tag == ASN1_UNITIM) { -+ /* UTCTime: YYMMDDHHMMSSZ */ -+ if (vlen != 13) -+ goto unsupported_time; -+ YY = DD2bin(p); -+ if (YY > 50) -+ YY += 1900; -+ else -+ YY += 2000; -+ } else if (tag == ASN1_GENTIM) { -+ /* GenTime: YYYYMMDDHHMMSSZ */ -+ if (vlen != 15) -+ goto unsupported_time; -+ YY = DD2bin(p) * 100 + DD2bin(p); -+ } else { -+ goto unsupported_time; -+ } -+ -+ MM = DD2bin(p); -+ DD = DD2bin(p); -+ hh = DD2bin(p); -+ mm = DD2bin(p); -+ ss = DD2bin(p); -+ -+ if (*p != 'Z') -+ goto unsupported_time; -+ -+ *_time = mktime(YY, MM, DD, hh, mm, ss); -+ return 0; -+ -+unsupported_time: -+ pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", -+ tag, (int)vlen, (int)vlen, value); -+ return -EBADMSG; -+} -+ -+int x509_note_not_before(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); -+} -+ -+int x509_note_not_after(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); -+} -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -new file mode 100644 -index 0000000..635053f ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -0,0 +1,36 @@ -+/* X.509 certificate parser internal definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+ -+struct x509_certificate { -+ struct x509_certificate *next; -+ struct public_key *pub; /* Public key details */ -+ char *issuer; /* Name of certificate issuer */ -+ char *subject; /* Name of certificate subject */ -+ char *fingerprint; /* Key fingerprint as hex */ -+ char *authority; /* Authority key fingerprint as hex */ -+ time_t valid_from; -+ time_t valid_to; -+ enum pkey_algo pkey_algo : 8; /* Public key algorithm */ -+ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ -+ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -+ const void *tbs; /* Signed data */ -+ size_t tbs_size; /* Size of signed data */ -+ const void *sig; /* Signature data */ -+ size_t sig_size; /* Size of sigature */ -+}; -+ -+/* -+ * x509_cert_parser.c -+ */ -+extern void x509_free_certificate(struct x509_certificate *cert); -+extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -new file mode 100644 -index 0000000..716917c ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -0,0 +1,207 @@ -+/* Instantiate a public key crypto key from an X.509 Certificate -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "X.509: "fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+#include "public_key.h" -+#include "x509_parser.h" -+ -+static const -+struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = NULL, -+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ -+ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) -+ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -+#endif -+}; -+ -+/* -+ * Check the signature on a certificate using the provided public key -+ */ -+static int x509_check_signature(const struct public_key *pub, -+ const struct x509_certificate *cert) -+{ -+ struct public_key_signature *sig; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data. -+ */ -+ ret = -ENOMEM; -+ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -+ if (!sig) -+ goto error_no_sig; -+ -+ sig->pkey_hash_algo = cert->sig_hash_algo; -+ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; -+ sig->digest_size = digest_size; -+ -+ desc = (void *)sig + sizeof(*sig); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = -ENOMEM; -+ sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); -+ if (!sig->rsa.s) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); -+ if (ret < 0) -+ goto error_mpi; -+ -+ ret = pub->algo->verify_signature(pub, sig); -+ -+ pr_debug("Cert Verification: %d\n", ret); -+ -+error_mpi: -+ mpi_free(sig->rsa.s); -+error: -+ kfree(sig); -+error_no_sig: -+ crypto_free_shash(tfm); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Attempt to parse a data blob for a key as an X509 certificate. -+ */ -+static int x509_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct x509_certificate *cert; -+ time_t now; -+ size_t srlen, sulen; -+ char *desc = NULL; -+ int ret; -+ -+ cert = x509_cert_parse(prep->data, prep->datalen); -+ if (IS_ERR(cert)) -+ return PTR_ERR(cert); -+ -+ pr_devel("Cert Issuer: %s\n", cert->issuer); -+ pr_devel("Cert Subject: %s\n", cert->subject); -+ pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -+ pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ pr_devel("Cert Signature: %s + %s\n", -+ pkey_algo[cert->sig_pkey_algo], -+ pkey_hash_algo[cert->sig_hash_algo]); -+ -+ if (!cert->fingerprint || !cert->authority) { -+ pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", -+ cert->subject); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ -+ now = CURRENT_TIME.tv_sec; -+ if (now < cert->valid_from) { -+ pr_warn("Cert %s is not yet valid\n", cert->fingerprint); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ if (now >= cert->valid_to) { -+ pr_warn("Cert %s has expired\n", cert->fingerprint); -+ ret = -EKEYEXPIRED; -+ goto error_free_cert; -+ } -+ -+ cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; -+ cert->pub->id_type = PKEY_ID_X509; -+ -+ /* Check the signature on the key */ -+ if (strcmp(cert->fingerprint, cert->authority) == 0) { -+ ret = x509_check_signature(cert->pub, cert); -+ if (ret < 0) -+ goto error_free_cert; -+ } -+ -+ /* Propose a description */ -+ sulen = strlen(cert->subject); -+ srlen = strlen(cert->fingerprint); -+ ret = -ENOMEM; -+ desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); -+ if (!desc) -+ goto error_free_cert; -+ memcpy(desc, cert->subject, sulen); -+ desc[sulen] = ':'; -+ desc[sulen + 1] = ' '; -+ memcpy(desc + sulen + 2, cert->fingerprint, srlen); -+ desc[sulen + 2 + srlen] = 0; -+ -+ /* We're pinning the module by being linked against it */ -+ __module_get(public_key_subtype.owner); -+ prep->type_data[0] = &public_key_subtype; -+ prep->type_data[1] = cert->fingerprint; -+ prep->payload = cert->pub; -+ prep->description = desc; -+ prep->quotalen = 100; -+ -+ /* We've finished with the certificate */ -+ cert->pub = NULL; -+ cert->fingerprint = NULL; -+ desc = NULL; -+ ret = 0; -+ -+error_free_cert: -+ x509_free_certificate(cert); -+ return ret; -+} -+ -+static struct asymmetric_key_parser x509_key_parser = { -+ .owner = THIS_MODULE, -+ .name = "x509", -+ .parse = x509_key_preparse, -+}; -+ -+/* -+ * Module stuff -+ */ -+static int __init x509_key_init(void) -+{ -+ return register_asymmetric_key_parser(&x509_key_parser); -+} -+ -+static void __exit x509_key_exit(void) -+{ -+ unregister_asymmetric_key_parser(&x509_key_parser); -+} -+ -+module_init(x509_key_init); -+module_exit(x509_key_exit); -diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 -new file mode 100644 -index 0000000..4ec7cc6 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_rsakey.asn1 -@@ -0,0 +1,4 @@ -+RSAPublicKey ::= SEQUENCE { -+ modulus INTEGER ({ rsa_extract_mpi }), -- n -+ publicExponent INTEGER ({ rsa_extract_mpi }) -- e -+ } --- -1.7.11.4 - - -From 955fc6ec995f6bec6c487eb46027e108e240ebe3 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:25 +0100 -Subject: [PATCH 18/26] MOD: Fix Rusty's module_sig_check() - -Make the following fixes to Rusty's module_sig_check() function: - - (1) mod_verify_sig() is not defined, resulting in a compilation error and - thereby breaking git bisect, so provide a dummy that returns an error. - - (2) Using strlen() on a static string is a waste of resources. Further, you - may end up with two copies of the string emitted. - - (3) Doing a memchr() of the bytes beyond the last position that the marker - can be in is a waste of resources. - -While we're at it, push responsibility for the return value entirely off to -mod_verify_sig() if we find a signature. - -Signed-off-by: David Howells ---- - kernel/Makefile | 1 + - kernel/module-internal.h | 14 ++++++++++++++ - kernel/module.c | 41 +++++++++++++++++++++++------------------ - kernel/module_signing.c | 23 +++++++++++++++++++++++ - 4 files changed, 61 insertions(+), 18 deletions(-) - create mode 100644 kernel/module-internal.h - create mode 100644 kernel/module_signing.c - -diff --git a/kernel/Makefile b/kernel/Makefile -index c0cc67a..08ba8a6 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -new file mode 100644 -index 0000000..14da0ea ---- /dev/null -+++ b/kernel/module-internal.h -@@ -0,0 +1,14 @@ -+/* Module internals -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+extern int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen, -+ bool *_sig_ok); -diff --git a/kernel/module.c b/kernel/module.c -index 5c6f65c..ab69599 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include "module-internal.h" - - #define CREATE_TRACE_POINTS - #include -@@ -2438,34 +2439,38 @@ static inline void kmemleak_load_module(const struct module *mod, - #endif - - #ifdef CONFIG_MODULE_SIG -+ - static int module_sig_check(struct load_info *info, - const void *mod, unsigned long *len) - { -+ static const char module_sig_string[] = MODULE_SIG_STRING; - int err = 0; -- const unsigned long markerlen = strlen(MODULE_SIG_STRING); -- const void *p = mod, *end = mod + *len; -- -- /* Poor man's memmem. */ -- while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -- if (p + markerlen > end) -- break; -- -- if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -- const void *sig = p + markerlen; -- /* Truncate module up to signature. */ -- *len = p - mod; -- err = mod_verify_sig(mod, *len, -- sig, end - sig, -- &info->sig_ok); -- break; -- } -- p++; -+ const unsigned long markerlen = sizeof(module_sig_string) - 1; -+ const void *p = mod, *end = mod + *len, *sig; -+ const void *limit = end - markerlen - 1; -+ -+ if (markerlen < *len) { -+ /* Poor man's memmem. */ -+ do { -+ p = memchr(p, MODULE_SIG_STRING[0], limit - p); -+ if (!p) -+ break; -+ if (memcmp(p, module_sig_string, markerlen) != 0) -+ continue; -+ goto found_marker; -+ } while (++p < limit); - } - - /* Not having a signature is only an error if we're strict. */ - if (!err && !info->sig_ok && sig_enforce) - err = -EKEYREJECTED; - return err; -+ -+found_marker: -+ sig = p + markerlen; -+ /* Truncate module up to signature. */ -+ *len = p - mod; -+ return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); - } - #else /* !CONFIG_MODULE_SIG */ - static int module_sig_check(struct load_info *info, -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -new file mode 100644 -index 0000000..0af10a5 ---- /dev/null -+++ b/kernel/module_signing.c -@@ -0,0 +1,23 @@ -+/* Module signature checker -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include "module-internal.h" -+ -+/* -+ * Verify the signature on a module. -+ */ -+int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen, -+ bool *_sig_ok) -+{ -+ return -EKEYREJECTED; -+} --- -1.7.11.4 - - -From 4c31831859550149cdba65a37d72416c87dbbef6 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:25 +0100 -Subject: [PATCH 19/26] MODSIGN: Provide gitignore and make clean rules for - extra files - -Provide gitignore and make clean rules for extra files to hide and clean up the -extra files produced by module signing stuff once it is added. Also add a -clean up rule for the module content extractor program used to extract the data -to be signed. - -Signed-off-by: David Howells ---- - .gitignore | 13 +++++++++++++ - Makefile | 1 + - 2 files changed, 14 insertions(+) - -diff --git a/.gitignore b/.gitignore -index 57af07c..9736304 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,6 +14,10 @@ - *.o.* - *.a - *.s -+*.ko.unsigned -+*.ko.stripped -+*.ko.stripped.dig -+*.ko.stripped.sig - *.ko - *.so - *.so.dbg -@@ -84,3 +88,12 @@ GTAGS - *.orig - *~ - \#*# -+ -+# -+# Leavings from module signing -+# -+extra_certificates -+signing_key.priv -+signing_key.x509 -+signing_key.x509.keyid -+signing_key.x509.signer -diff --git a/Makefile b/Makefile -index 371ce88..644048d 100644 ---- a/Makefile -+++ b/Makefile -@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -+ -o -name '*.ko.*' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ - -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ --- -1.7.11.4 - - -From 6977e69eef4379f34a2ad264856d74ac292284df Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:25 +0100 -Subject: [PATCH 20/26] MODSIGN: Provide Kconfig options - -Provide kernel configuration options for module signing. - -The following configuration options are added: - - CONFIG_MODULE_SIG_SHA1 - CONFIG_MODULE_SIG_SHA224 - CONFIG_MODULE_SIG_SHA256 - CONFIG_MODULE_SIG_SHA384 - CONFIG_MODULE_SIG_SHA512 - -These select the cryptographic hash used to digest the data prior to signing. -Additionally, the crypto module selected will be built into the kernel as it -won't be possible to load it as a module without incurring a circular -dependency when the kernel tries to check its signature. - -Signed-off-by: David Howells ---- - init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/init/Kconfig b/init/Kconfig -index fa8ccad..00d4579 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1593,12 +1593,50 @@ config MODULE_SIG - is simply appended to the module. For more information see - Documentation/module-signing.txt. - -+ !!!WARNING!!! If you enable this option, you MUST make sure that the -+ module DOES NOT get stripped after being signed. This includes the -+ debuginfo strip done by some packagers (such as rpmbuild) and -+ inclusion into an initramfs that wants the module size reduced. -+ - config MODULE_SIG_FORCE - bool "Require modules to be validly signed" - depends on MODULE_SIG - help - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. -+ -+choice -+ prompt "Which hash algorithm should modules be signed with?" -+ depends on MODULE_SIG -+ help -+ This determines which sort of hashing algorithm will be used during -+ signature generation. This algorithm _must_ be built into the kernel -+ directly so that signature verification can take place. It is not -+ possible to load a signed module containing the algorithm to check -+ the signature on that module. -+ -+config MODULE_SIG_SHA1 -+ bool "Sign modules with SHA-1" -+ select CRYPTO_SHA1 -+ -+config MODULE_SIG_SHA224 -+ bool "Sign modules with SHA-224" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA256 -+ bool "Sign modules with SHA-256" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA384 -+ bool "Sign modules with SHA-384" -+ select CRYPTO_SHA512 -+ -+config MODULE_SIG_SHA512 -+ bool "Sign modules with SHA-512" -+ select CRYPTO_SHA512 -+ -+endchoice -+ - endif # MODULES - - config INIT_ALL_POSSIBLE --- -1.7.11.4 - - -From 60378703cf88ed221ee602727c37ae241565d44a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:25 +0100 -Subject: [PATCH 21/26] MODSIGN: Automatically generate module signing keys if - missing - -Automatically generate keys for module signing if they're absent so that -allyesconfig doesn't break. The builder should consider generating their own -key and certificate, however, so that the keys are appropriately named. - -The private key for the module signer should be placed in signing_key.priv -(unencrypted!) and the public key in an X.509 certificate as signing_key.x509. - -If a transient key is desired for signing the modules, a config file for -'openssl req' can be placed in x509.genkey, looking something like the -following: - - [ req ] - default_bits = 4096 - distinguished_name = req_distinguished_name - prompt = no - x509_extensions = myexts - - [ req_distinguished_name ] - O = Magarathea - CN = Glacier signing key - emailAddress = slartibartfast@magrathea.h2g2 - - [ myexts ] - basicConstraints=critical,CA:FALSE - keyUsage=digitalSignature - subjectKeyIdentifier=hash - authorityKeyIdentifier=hash - -The build process will use this to configure: - - openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ - -x509 -config x509.genkey \ - -outform DER -out signing_key.x509 \ - -keyout signing_key.priv - -to generate the key. - -Note that it is required that the X.509 certificate have a subjectKeyIdentifier -and an authorityKeyIdentifier. Without those, the certificate will be -rejected. These can be used to check the validity of a certificate. - -Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey, -whether or not they were generated automatically. - -Signed-off-by: David Howells ---- - kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 08ba8a6..83f1565 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ - targets += timeconst.h - $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) -+ -+ifeq ($(CONFIG_MODULE_SIG),y) -+ -+############################################################################### -+# -+# If module signing is requested, say by allyesconfig, but a key has not been -+# supplied, then one will need to be generated to make sure the build does not -+# fail and that the kernel may be used afterwards. -+# -+############################################################################### -+signing_key.priv signing_key.x509: x509.genkey -+ @echo "###" -+ @echo "### Now generating an X.509 key pair to be used for signing modules." -+ @echo "###" -+ @echo "### If this takes a long time, you might wish to run rngd in the" -+ @echo "### background to keep the supply of entropy topped up. It" -+ @echo "### needs to be run as root, and should use a hardware random" -+ @echo "### number generator if one is available, eg:" -+ @echo "###" -+ @echo "### rngd -r /dev/hwrandom" -+ @echo "###" -+ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ -+ -x509 -config x509.genkey \ -+ -outform DER -out signing_key.x509 \ -+ -keyout signing_key.priv -+ @echo "###" -+ @echo "### Key pair generated." -+ @echo "###" -+ -+x509.genkey: -+ @echo Generating X.509 key generation config -+ @echo >x509.genkey "[ req ]" -+ @echo >>x509.genkey "default_bits = 4096" -+ @echo >>x509.genkey "distinguished_name = req_distinguished_name" -+ @echo >>x509.genkey "prompt = no" -+ @echo >>x509.genkey "x509_extensions = myexts" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ req_distinguished_name ]" -+ @echo >>x509.genkey "O = Magarathea" -+ @echo >>x509.genkey "CN = Glacier signing key" -+ @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ myexts ]" -+ @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" -+ @echo >>x509.genkey "keyUsage=digitalSignature" -+ @echo >>x509.genkey "subjectKeyIdentifier=hash" -+ @echo >>x509.genkey "authorityKeyIdentifier=keyid" -+endif -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey --- -1.7.11.4 - - -From 798049d9df83c8fd87fd5ddb97a77054558f4361 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:25 +0100 -Subject: [PATCH 22/26] MODSIGN: Provide module signing public keys to the - kernel - -Include a PGP keyring containing the public keys required to perform module -verification in the kernel image during build and create a special keyring -during boot which is then populated with keys of crypto type holding the public -keys found in the PGP keyring. - -These can be seen by root: - -[root@andromeda ~]# cat /proc/keys -07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] -15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 -... - -It is probably worth permitting root to invalidate these keys, resulting in -their removal and preventing further modules from being loaded with that key. - -Signed-off-by: David Howells ---- - kernel/Makefile | 11 ++++- - kernel/modsign_pubkey.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-internal.h | 2 + - 3 files changed, 123 insertions(+), 2 deletions(-) - create mode 100644 kernel/modsign_pubkey.c - -diff --git a/kernel/Makefile b/kernel/Makefile -index 83f1565..63f8386 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,7 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o --obj-$(CONFIG_MODULE_SIG) += module_signing.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) - - ifeq ($(CONFIG_MODULE_SIG),y) -+# -+# Pull the signing certificate and any extra certificates into the kernel -+# -+extra_certificates: -+ touch $@ -+ -+kernel/modsign_pubkey.o: signing_key.x509 extra_certificates - - ############################################################################### - # -@@ -180,4 +187,4 @@ x509.genkey: - @echo >>x509.genkey "subjectKeyIdentifier=hash" - @echo >>x509.genkey "authorityKeyIdentifier=keyid" - endif --CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -new file mode 100644 -index 0000000..f504d9f ---- /dev/null -+++ b/kernel/modsign_pubkey.c -@@ -0,0 +1,112 @@ -+/* Public keys for module signature verification -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "module-internal.h" -+ -+struct key *modsign_keyring; -+ -+extern __initdata const u8 modsign_certificate_list[]; -+extern __initdata const u8 modsign_certificate_list_end[]; -+asm(".section .init.data,\"aw\"\n" -+ "modsign_certificate_list:\n" -+ ".incbin \"signing_key.x509\"\n" -+ ".incbin \"extra_certificates\"\n" -+ "modsign_certificate_list_end:" -+ ); -+ -+/* -+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice -+ * if modsign.pub changes. -+ */ -+static __initdata const char annoy_ccache[] = __TIME__ "foo"; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int module_verify_init(void) -+{ -+ pr_notice("Initialise module verification\n"); -+ -+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", -+ 0, 0, current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_keyring)) -+ panic("Can't allocate module signing keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(module_verify_init); -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int load_module_signing_keys(void) -+{ -+ key_ref_t key; -+ const u8 *p, *end; -+ size_t plen; -+ -+ pr_notice("Loading module verification certificates\n"); -+ -+ end = modsign_certificate_list_end; -+ p = modsign_certificate_list; -+ while (p < end) { -+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more -+ * than 256 bytes in size. -+ */ -+ if (end - p < 4) -+ goto dodgy_cert; -+ if (p[0] != 0x30 && -+ p[1] != 0x82) -+ goto dodgy_cert; -+ plen = (p[2] << 8) | p[3]; -+ plen += 4; -+ if (plen > end - p) -+ goto dodgy_cert; -+ -+ key = key_create_or_update(make_key_ref(modsign_keyring, 1), -+ "asymmetric", -+ NULL, -+ p, -+ plen, -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(key)) -+ pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("MODSIGN: Loaded cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ p += plen; -+ } -+ -+ return 0; -+ -+dodgy_cert: -+ pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); -+ return 0; -+} -+late_initcall(load_module_signing_keys); -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 14da0ea..648f481 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -9,6 +9,8 @@ - * 2 of the Licence, or (at your option) any later version. - */ - -+extern struct key *modsign_keyring; -+ - extern int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen, - bool *_sig_ok); --- -1.7.11.4 - - -From dcac300c703bc9a237deab7c7f0301f3803a3a9a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:26 +0100 -Subject: [PATCH 23/26] MODSIGN: Implement module signature checking - -Check the signature on the module against the keys compiled into the kernel or -available in a hardware key store. - -Currently, only RSA keys are supported - though that's easy enough to change, -and the signature is expected to contain raw components (so not a PGP or -PKCS#7 formatted blob). - -The signature blob is expected to consist of the following pieces in order: - - (1) The binary identifier for the key. This is expected to match the - SubjectKeyIdentifier from an X.509 certificate. Only X.509 type - identifiers are currently supported. - - (2) The signature data, consisting of a series of MPIs in which each is in - the format of a 2-byte BE word sizes followed by the content data. - - (3) A 12 byte information block of the form: - - struct module_signature { - enum pkey_algo algo : 8; - enum pkey_hash_algo hash : 8; - enum pkey_id_type id_type : 8; - u8 __pad; - __be32 id_length; - __be32 sig_length; - }; - - The three enums are defined in crypto/public_key.h. - - 'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA). - - 'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1, - etc.). - - 'id_type' contains the public-key identifier type (0->PGP, 1->X.509). - - '__pad' should be 0. - - 'id_length' should contain in the binary identifier length in BE form. - - 'sig_length' should contain in the signature data length in BE form. - - The lengths are in BE order rather than CPU order to make dealing with - cross-compilation easier. - -Signed-off-by: David Howells ---- - init/Kconfig | 8 ++ - kernel/module_signing.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 230 insertions(+), 1 deletion(-) - -diff --git a/init/Kconfig b/init/Kconfig -index 00d4579..63fcbeb 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL - config MODULE_SIG - bool "Module signature verification" - depends on MODULES -+ select CONFIG_KEYS -+ select CONFIG_CRYPTO -+ select ASYMMETRIC_KEY_TYPE -+ select ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select PUBLIC_KEY_ALGO_RSA -+ select ASN1 -+ select OID_REGISTRY -+ select X509_CERTIFICATE_PARSER - help - Check modules for valid signatures upon load: the signature - is simply appended to the module. For more information see -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 0af10a5..83eb505 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -10,14 +10,235 @@ - */ - - #include -+#include -+#include -+#include -+#include - #include "module-internal.h" - - /* -+ * Module signature information block. -+ * -+ * The constituents of the signature section are, in order: -+ * -+ * - Signer's name -+ * - Key identifier -+ * - Signature data -+ * - Information block -+ */ -+struct module_signature { -+ enum pkey_algo algo : 8; /* Public-key crypto algorithm */ -+ enum pkey_hash_algo hash : 8; /* Digest algorithm */ -+ enum pkey_id_type id_type : 8; /* Key identifier type */ -+ u8 signer_len; /* Length of signer's name */ -+ u8 key_id_len; /* Length of key identifier */ -+ u8 __pad[3]; -+ __be32 sig_len; /* Length of signature data */ -+}; -+ -+/* -+ * Digest the module contents. -+ */ -+static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, -+ const void *mod, -+ unsigned long modlen) -+{ -+ struct public_key_signature *pks; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data and the digest output buffer on the end of that. -+ */ -+ ret = -ENOMEM; -+ pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); -+ if (!pks) -+ goto error_no_pks; -+ -+ pks->pkey_hash_algo = hash; -+ pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; -+ pks->digest_size = digest_size; -+ -+ desc = (void *)pks + sizeof(*pks); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, mod, modlen, pks->digest); -+ if (ret < 0) -+ goto error; -+ -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = ok\n", __func__); -+ return pks; -+ -+error: -+ kfree(pks); -+error_no_pks: -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Extract an MPI array from the signature data. This represents the actual -+ * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the -+ * size of the MPI in bytes. -+ * -+ * RSA signatures only have one MPI, so currently we only read one. -+ */ -+static int mod_extract_mpi_array(struct public_key_signature *pks, -+ const void *data, size_t len) -+{ -+ size_t nbytes; -+ MPI mpi; -+ -+ if (len < 3) -+ return -EBADMSG; -+ nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; -+ data += 2; -+ len -= 2; -+ if (len != nbytes) -+ return -EBADMSG; -+ -+ mpi = mpi_read_raw_data(data, nbytes); -+ if (!mpi) -+ return -ENOMEM; -+ pks->mpi[0] = mpi; -+ pks->nr_mpi = 1; -+ return 0; -+} -+ -+/* -+ * Request an asymmetric key. -+ */ -+static struct key *request_asymmetric_key(const char *signer, size_t signer_len, -+ const u8 *key_id, size_t key_id_len) -+{ -+ key_ref_t key; -+ size_t i; -+ char *id, *q; -+ -+ pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); -+ -+ /* Construct an identifier. */ -+ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); -+ if (!id) -+ return ERR_PTR(-ENOKEY); -+ -+ memcpy(id, signer, signer_len); -+ -+ q = id + signer_len; -+ *q++ = ':'; -+ *q++ = ' '; -+ for (i = 0; i < key_id_len; i++) { -+ *q++ = hex_asc[*key_id >> 4]; -+ *q++ = hex_asc[*key_id++ & 0x0f]; -+ } -+ -+ *q = 0; -+ -+ pr_debug("Look up: \"%s\"\n", id); -+ -+ key = keyring_search(make_key_ref(modsign_keyring, 1), -+ &key_type_asymmetric, id); -+ kfree(id); -+ -+ if (IS_ERR(key)) { -+ switch (PTR_ERR(key)) { -+ /* Hide some search errors */ -+ case -EACCES: -+ case -ENOTDIR: -+ case -EAGAIN: -+ return ERR_PTR(-ENOKEY); -+ default: -+ return ERR_CAST(key); -+ } -+ } -+ -+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); -+ return key_ref_to_ptr(key); -+} -+ -+/* - * Verify the signature on a module. - */ - int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen, - bool *_sig_ok) - { -- return -EKEYREJECTED; -+ struct public_key_signature *pks; -+ struct module_signature ms; -+ struct key *key; -+ size_t sig_len; -+ int ret; -+ -+ pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); -+ -+ if (siglen <= sizeof(ms)) -+ return -EBADMSG; -+ -+ memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); -+ siglen -= sizeof(ms); -+ -+ sig_len = be32_to_cpu(ms.sig_len); -+ if (sig_len >= siglen || -+ siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) -+ return -EBADMSG; -+ -+ /* For the moment, only support RSA and X.509 identifiers */ -+ if (ms.algo != PKEY_ALGO_RSA || -+ ms.id_type != PKEY_ID_X509) -+ return -ENOPKG; -+ -+ if (ms.hash >= PKEY_HASH__LAST || -+ !pkey_hash_algo[ms.hash]) -+ return -ENOPKG; -+ -+ key = request_asymmetric_key(sig, ms.signer_len, -+ sig + ms.signer_len, ms.key_id_len); -+ if (IS_ERR(key)) -+ return PTR_ERR(key); -+ -+ pks = mod_make_digest(ms.hash, mod, modlen); -+ if (IS_ERR(pks)) { -+ ret = PTR_ERR(pks); -+ goto error_put_key; -+ } -+ -+ ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, -+ sig_len); -+ if (ret < 0) -+ goto error_free_pks; -+ -+ ret = verify_signature(key, pks); -+ pr_devel("verify_signature() = %d\n", ret); -+ -+ if (ret == 0) -+ *_sig_ok = true; -+ -+error_free_pks: -+ mpi_free(pks->rsa.s); -+ kfree(pks); -+error_put_key: -+ key_put(key); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } --- -1.7.11.4 - - -From 89fbf1de73ed1ef29a3943d9f3bcf69a433191da Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:13:26 +0100 -Subject: [PATCH 24/26] MODSIGN: Provide a script for generating a key ID from - an X.509 cert - -Provide a script to parse an X.509 certificate and certain pieces of -information from it in order to generate a key identifier to be included within -a module signature. - -The script takes the Subject Name and extracts (if present) the -organizationName (O), the commonName (CN) and the emailAddress and fabricates -the signer's name from them: - - (1) If both O and CN exist, then the name will be "O: CN", unless: - - (a) CN is prefixed by O, in which case only CN is used. - - (b) CN and O share at least the first 7 characters, in which case only CN - is used. - - (2) Otherwise, CN is used if present. - - (3) Otherwise, O is used if present. - - (4) Otherwise the emailAddress is used, if present. - - (5) Otherwise a blank name is used. - -The script emits a binary encoded identifier in the following form: - - - 2 BE bytes indicating the length of the signer's name. - - - 2 BE bytes indicating the length of the subject key identifier. - - - The characters of the signer's name. - - - The bytes of the subject key identifier. - -Signed-off-by: David Howells ---- - scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 268 insertions(+) - create mode 100755 scripts/x509keyid - -diff --git a/scripts/x509keyid b/scripts/x509keyid -new file mode 100755 -index 0000000..c8e91a4 ---- /dev/null -+++ b/scripts/x509keyid -@@ -0,0 +1,268 @@ -+#!/usr/bin/perl -w -+# -+# Generate an identifier from an X.509 certificate that can be placed in a -+# module signature to indentify the key to use. -+# -+# Format: -+# -+# ./scripts/x509keyid -+# -+# We read the DER-encoded X509 certificate and parse it to extract the Subject -+# name and Subject Key Identifier. The provide the data we need to build the -+# certificate identifier. -+# -+# The signer's name part of the identifier is fabricated from the commonName, -+# the organizationName or the emailAddress components of the X.509 subject -+# name and written to the second named file. -+# -+# The subject key ID to select which of that signer's certificates we're -+# intending to use to sign the module is written to the third named file. -+# -+use strict; -+ -+my $raw_data; -+ -+die "Need three filenames\n" if ($#ARGV != 2); -+ -+my $src = $ARGV[0]; -+ -+open(FD, "<$src") || die $src; -+binmode FD; -+my @st = stat(FD); -+die $src if (!@st); -+read(FD, $raw_data, $st[7]) || die $src; -+close(FD); -+ -+my $UNIV = 0 << 6; -+my $APPL = 1 << 6; -+my $CONT = 2 << 6; -+my $PRIV = 3 << 6; -+ -+my $CONS = 0x20; -+ -+my $BOOLEAN = 0x01; -+my $INTEGER = 0x02; -+my $BIT_STRING = 0x03; -+my $OCTET_STRING = 0x04; -+my $NULL = 0x05; -+my $OBJ_ID = 0x06; -+my $UTF8String = 0x0c; -+my $SEQUENCE = 0x10; -+my $SET = 0x11; -+my $UTCTime = 0x17; -+my $GeneralizedTime = 0x18; -+ -+my %OIDs = ( -+ pack("CCC", 85, 4, 3) => "commonName", -+ pack("CCC", 85, 4, 6) => "countryName", -+ pack("CCC", 85, 4, 10) => "organizationName", -+ pack("CCC", 85, 4, 11) => "organizationUnitName", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -+ pack("CCC", 85, 29, 19) => "basicConstraints" -+); -+ -+############################################################################### -+# -+# Extract an ASN.1 element from a string and return information about it. -+# -+############################################################################### -+sub asn1_extract($$@) -+{ -+ my ($cursor, $expected_tag, $optional) = @_; -+ -+ return [ -1 ] -+ if ($cursor->[1] == 0 && $optional); -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -+ if ($cursor->[1] < 2); -+ -+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ -+ if ($expected_tag != -1 && $tag != $expected_tag) { -+ return [ -1 ] -+ if ($optional); -+ die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -+ " not ", $expected_tag, ")\n"; -+ } -+ -+ $cursor->[0] += 2; -+ $cursor->[1] -= 2; -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" -+ if (($tag & 0x1f) == 0x1f); -+ die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -+ if ($len == 0x80); -+ -+ if ($len > 0x80) { -+ my $l = $len - 0x80; -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -+ if ($cursor->[1] < $l); -+ -+ if ($l == 0x1) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -+ } elsif ($l = 0x2) { -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ } elsif ($l = 0x3) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -+ } elsif ($l = 0x4) { -+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -+ } else { -+ die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -+ } -+ -+ $cursor->[0] += $l; -+ $cursor->[1] -= $l; -+ } -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -+ if ($cursor->[1] < $len); -+ -+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -+ $cursor->[0] += $len; -+ $cursor->[1] -= $len; -+ -+ return $ret; -+} -+ -+############################################################################### -+# -+# Retrieve the data referred to by a cursor -+# -+############################################################################### -+sub asn1_retrieve($) -+{ -+ my ($cursor) = @_; -+ my ($offset, $len, $data) = @$cursor; -+ return substr($$data, $offset, $len); -+} -+ -+############################################################################### -+# -+# Roughly parse the X.509 certificate -+# -+############################################################################### -+my $cursor = [ 0, length($raw_data), \$raw_data ]; -+ -+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -+ -+my $subject_key_id = (); -+my $authority_key_id = (); -+ -+# -+# Parse the extension list -+# -+if ($extension_list->[0] != -1) { -+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -+ -+ while ($extensions->[1]->[1] > 0) { -+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -+ -+ my $raw_oid = asn1_retrieve($x_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $x_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($x_val->[1]); -+ -+ if ($x_type eq "subjectKeyIdentifier") { -+ my $vcursor = [ 0, length($raw_value), \$raw_value ]; -+ -+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -+ } -+ } -+} -+ -+############################################################################### -+# -+# Determine what we're going to use as the signer's name. In order of -+# preference, take one of: commonName, organizationName or emailAddress. -+# -+############################################################################### -+my $org = ""; -+my $cn = ""; -+my $email = ""; -+ -+while ($subject->[1]->[1] > 0) { -+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -+ my $n_val = asn1_extract($attr->[1], -1); -+ -+ my $raw_oid = asn1_retrieve($n_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $n_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($n_val->[1]); -+ -+ if ($n_type eq "organizationName") { -+ $org = $raw_value; -+ } elsif ($n_type eq "commonName") { -+ $cn = $raw_value; -+ } elsif ($n_type eq "emailAddress") { -+ $email = $raw_value; -+ } -+} -+ -+my $id_name = $email; -+ -+if ($org && $cn) { -+ # Don't use the organizationName if the commonName repeats it -+ if (length($org) <= length($cn) && -+ substr($cn, 0, length($org)) eq $org) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ # Or a signifcant chunk of it -+ if (length($org) >= 7 && -+ length($cn) >= 7 && -+ substr($cn, 0, 7) eq substr($org, 0, 7)) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ $id_name = $org . ": " . $cn; -+} elsif ($org) { -+ $id_name = $org; -+} elsif ($cn) { -+ $id_name = $cn; -+} -+ -+got_id_name: -+ -+############################################################################### -+# -+# Output the signer's name and the key identifier that we're going to include -+# in module signatures. -+# -+############################################################################### -+die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -+ if (!$subject_key_id); -+ -+my $id_key_id = asn1_retrieve($subject_key_id->[1]); -+ -+open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; -+print OUTFD $id_name; -+close OUTFD || die $ARGV[1]; -+ -+open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; -+print OUTFD $id_key_id; -+close OUTFD || die $ARGV[2]; --- -1.7.11.4 - - -From 007c8fc3412f0a55cd3a32c5e42236703a17d1c1 Mon Sep 17 00:00:00 2001 +From f1fa90d02f50078a89da602d73dc9ab7743439ba Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Sep 2012 10:46:36 -0400 -Subject: [PATCH 25/26] MODSIGN: Add modules_sign make target +Subject: [PATCH 2/2] MODSIGN: Add modules_sign make target If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this patch will cause the modules to get a signature installed. The make target @@ -8839,18 +46,16 @@ packaging tools (such as rpmbuild) and initramfs composition tools. Based heavily on work by: David Howells Signed-off-by: Josh Boyer --- - Makefile | 6 +++ - scripts/Makefile.modsign | 72 +++++++++++++++++++++++++++++ - scripts/sign-file | 115 +++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 193 insertions(+) + Makefile | 6 ++++++ + scripts/Makefile.modsign | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) create mode 100644 scripts/Makefile.modsign - create mode 100644 scripts/sign-file diff --git a/Makefile b/Makefile -index 644048d..4479147 100644 +index 89a2e2c..ac04c11 100644 --- a/Makefile +++ b/Makefile -@@ -965,6 +965,12 @@ _modinst_post: _modinst_ +@@ -981,6 +981,12 @@ _modinst_post: _modinst_ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst $(call cmd,depmod) @@ -8865,10 +70,10 @@ index 644048d..4479147 100644 # Modules not configured diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign new file mode 100644 -index 0000000..17326bc +index 0000000..670d5dc --- /dev/null +++ b/scripts/Makefile.modsign -@@ -0,0 +1,72 @@ +@@ -0,0 +1,32 @@ +# ========================================================================== +# Signing modules +# ========================================================================== @@ -8885,48 +90,8 @@ index 0000000..17326bc +__modsign: $(modules) + @: + -+MODSECKEY = ./signing_key.priv -+MODPUBKEY = ./signing_key.x509 -+ -+ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) -+ifeq ($(KBUILD_SRC),) -+ # no O= is being used -+ SCRIPTS_DIR := scripts -+else -+ SCRIPTS_DIR := $(KBUILD_SRC)/scripts -+endif -+SIGN_MODULES := 1 -+else -+SIGN_MODULES := 0 -+endif -+ -+# only sign if it's an in-tree module -+ifneq ($(KBUILD_EXTMOD),) -+SIGN_MODULES := 0 -+endif -+ -+ifeq ($(SIGN_MODULES),1) -+ -+quiet_cmd_genkeyid = GENKEYID $@ -+ cmd_genkeyid = \ -+ perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid -+ -+%.signer %.keyid: % -+ $(call if_changed,genkeyid) -+ -+KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid +quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) -+ cmd_sign_ko = \ -+ sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) \ -+ $(2)/$(notdir $@) $(2)/$(notdir $@).signed && \ -+ mv $(2)/$(notdir $@).signed $(2)/$(notdir $@) && \ -+ rm -rf $(2)/$(notdir $@).{dig,sig} -+else -+KEYRING_DEP := -+quiet_cmd_sign_ko = NO SIGN [M] $@ -+ cmd_sign_ko = \ -+ true -+endif ++ cmd_sign_ko = $(mod_sign_cmd) $(2)/$(notdir $@) + +# Modules built outside the kernel source tree go into extra by default +INSTALL_MOD_DIR ?= extra @@ -8934,394 +99,13 @@ index 0000000..17326bc + +modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) + -+$(modules): $(KEYRING_DEP) ++$(modules): + $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) + +# Declare the contents of the .PHONY variable as phony. We keep that +# # information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) -diff --git a/scripts/sign-file b/scripts/sign-file -new file mode 100644 -index 0000000..1a472bb ---- /dev/null -+++ b/scripts/sign-file -@@ -0,0 +1,115 @@ -+#!/bin/sh -+# -+# Sign a module file using the given key. -+# -+# Format: sign-file -+# -+ -+scripts=`dirname $0` -+ -+CONFIG_MODULE_SIG_SHA512=y -+if [ -r .config ] -+then -+ source ./.config -+fi -+ -+key="$1" -+x509="$2" -+src="$3" -+dst="$4" -+ -+if [ ! -r "$key" ] -+then -+ echo "Can't read private key" >&2 -+ exit 2 -+fi -+ -+if [ ! -r "$x509" ] -+then -+ echo "Can't read X.509 certificate" >&2 -+ exit 2 -+fi -+if [ ! -r "$x509.signer" ] -+then -+ echo "Can't read Signer name" >&2 -+ exit 2; -+fi -+if [ ! -r "$x509.keyid" ] -+then -+ echo "Can't read Key identifier" >&2 -+ exit 2; -+fi -+ -+# -+# Signature parameters -+# -+algo=1 # Public-key crypto algorithm: RSA -+hash= # Digest algorithm -+id_type=1 # Identifier type: X.509 -+ -+# -+# Digest the data -+# -+dgst= -+if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] -+then -+ prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" -+ dgst=-sha1 -+ hash=2 -+elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] -+then -+ prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" -+ dgst=-sha224 -+ hash=7 -+elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] -+then -+ prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" -+ dgst=-sha256 -+ hash=4 -+elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] -+then -+ prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" -+ dgst=-sha384 -+ hash=5 -+elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] -+then -+ prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" -+ dgst=-sha512 -+ hash=6 -+else -+ echo "$0: Can't determine hash algorithm" >&2 -+ exit 2 -+fi -+ -+( -+perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? -+openssl dgst $dgst -binary $src || exit $? -+) >$src.dig || exit $? -+ -+# -+# Generate the binary signature, which will be just the integer that comprises -+# the signature with no metadata attached. -+# -+openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? -+signerlen=`stat -c %s $x509.signer` -+keyidlen=`stat -c %s $x509.keyid` -+siglen=`stat -c %s $src.sig` -+ -+# -+# Build the signed binary -+# -+( -+ cat $src || exit $? -+ echo '~Module signature appended~' || exit $? -+ cat $x509.signer $x509.keyid || exit $? -+ -+ # Preface each signature integer with a 2-byte BE length -+ perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -+ cat $src.sig || exit $? -+ -+ # Generate the information block -+ perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? -+) >$dst~ || exit $? -+ -+# Permit in-place signing -+mv $dst~ $dst || exit $? -- -1.7.11.4 - - -From 33c6737b352ec10a7e0d7b053fbb084c0b7a9d36 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 20:51:59 +0100 -Subject: [PATCH 26/26] MODSIGN: Extend the policy on signature check failure - -Extend the policy on handling various sorts of signature check failure such as -not having the requisite key available or being in FIPS mode. - -If the key specified is not known (ENOKEY) permit the module to be loaded in -non-enforcing mode, otherwise reject it. - -If in FIPS mode, any loading failure shall cause a panic. - -Also print a warning if we try and fail to find a module signing key: - - Request for unknown module key 'Magrathea: Glacier signing key: 5dd0839552bd6af498253f8af1e65da3472941c6' err -11 - -This contains the identity field and the key ID from the signature as well as -the error code. The error codes are the raw return from keyring_search() and -may be translated to -ENOKEY. - -Signed-off-by: David Howells ---- - kernel/Makefile | 2 +- - kernel/module.c | 9 ++++++++- - kernel/module_signing.c | 3 +++ - 3 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 63f8386..111a845 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -177,7 +177,7 @@ x509.genkey: - @echo >>x509.genkey "x509_extensions = myexts" - @echo >>x509.genkey - @echo >>x509.genkey "[ req_distinguished_name ]" -- @echo >>x509.genkey "O = Magarathea" -+ @echo >>x509.genkey "O = Magrathea" - @echo >>x509.genkey "CN = Glacier signing key" - @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" - @echo >>x509.genkey -diff --git a/kernel/module.c b/kernel/module.c -index ab69599..de16959 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include - #include "module-internal.h" - - #define CREATE_TRACE_POINTS -@@ -2470,7 +2471,13 @@ found_marker: - sig = p + markerlen; - /* Truncate module up to signature. */ - *len = p - mod; -- return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); -+ err = mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok); -+ if (err < 0 && fips_enabled) -+ panic("Module verification failed with error %d in FIPS mode\n", -+ err); -+ if (err == -ENOKEY && !sig_enforce) -+ err = 0; -+ return err; - } - #else /* !CONFIG_MODULE_SIG */ - static int module_sig_check(struct load_info *info, -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 83eb505..2beea56 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -159,6 +159,9 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - - key = keyring_search(make_key_ref(modsign_keyring, 1), - &key_type_asymmetric, id); -+ if (IS_ERR(key)) -+ pr_warn("Request for unknown module key '%s' err %ld\n", -+ id, PTR_ERR(key)); - kfree(id); - - if (IS_ERR(key)) { --- -1.7.11.4 - -The current choice of lifetime for the autogenerated X.509 of 100 years, -putting the validTo date in 2112, causes problems on 32-bit systems where a -32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. - -This can result in something like: - - Loading module verification certificates - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired - MODSIGN: Problem loading in-kernel X.509 certificate (-127) - -Or: - - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid - MODSIGN: Problem loading in-kernel X.509 certificate (-129) - -Instead of turning the dates into time_t values and comparing, turn the system -clock and the ASN.1 dates into tm structs and compare those piecemeal instead. - -Reported-by: Rusty Russell -Signed-off-by: David Howells ---- - - crypto/asymmetric_keys/x509_cert_parser.c | 25 ++++++++--------- - crypto/asymmetric_keys/x509_parser.h | 4 +-- - crypto/asymmetric_keys/x509_public_key.c | 42 ++++++++++++++++++++++++++--- - 3 files changed, 51 insertions(+), 20 deletions(-) - - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index 8fcac94..db07e8c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, - /* - * Record a certificate time. - */ --static int x509_note_time(time_t *_time, size_t hdrlen, -+static int x509_note_time(struct tm *tm, size_t hdrlen, - unsigned char tag, - const unsigned char *value, size_t vlen) - { -- unsigned YY, MM, DD, hh, mm, ss; - const unsigned char *p = value; - - #define dec2bin(X) ((X) - '0') -@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, - /* UTCTime: YYMMDDHHMMSSZ */ - if (vlen != 13) - goto unsupported_time; -- YY = DD2bin(p); -- if (YY > 50) -- YY += 1900; -+ tm->tm_year = DD2bin(p); -+ if (tm->tm_year >= 50) -+ tm->tm_year += 1900; - else -- YY += 2000; -+ tm->tm_year += 2000; - } else if (tag == ASN1_GENTIM) { - /* GenTime: YYYYMMDDHHMMSSZ */ - if (vlen != 15) - goto unsupported_time; -- YY = DD2bin(p) * 100 + DD2bin(p); -+ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); - } else { - goto unsupported_time; - } - -- MM = DD2bin(p); -- DD = DD2bin(p); -- hh = DD2bin(p); -- mm = DD2bin(p); -- ss = DD2bin(p); -+ tm->tm_year -= 1900; -+ tm->tm_mon = DD2bin(p) - 1; -+ tm->tm_mday = DD2bin(p); -+ tm->tm_hour = DD2bin(p); -+ tm->tm_min = DD2bin(p); -+ tm->tm_sec = DD2bin(p); - - if (*p != 'Z') - goto unsupported_time; - -- *_time = mktime(YY, MM, DD, hh, mm, ss); - return 0; - - unsupported_time: -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index 635053f..f86dc5f 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -18,8 +18,8 @@ struct x509_certificate { - char *subject; /* Name of certificate subject */ - char *fingerprint; /* Key fingerprint as hex */ - char *authority; /* Authority key fingerprint as hex */ -- time_t valid_from; -- time_t valid_to; -+ struct tm valid_from; -+ struct tm valid_to; - enum pkey_algo pkey_algo : 8; /* Public key algorithm */ - enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ - enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 716917c..5ab736d 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -106,7 +106,7 @@ error_no_sig: - static int x509_key_preparse(struct key_preparsed_payload *prep) - { - struct x509_certificate *cert; -- time_t now; -+ struct tm now; - size_t srlen, sulen; - char *desc = NULL; - int ret; -@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, -+ cert->valid_from.tm_mday, cert->valid_from.tm_hour, -+ cert->valid_from.tm_min, cert->valid_from.tm_sec); -+ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, -+ cert->valid_to.tm_mday, cert->valid_to.tm_hour, -+ cert->valid_to.tm_min, cert->valid_to.tm_sec); - pr_devel("Cert Signature: %s + %s\n", - pkey_algo[cert->sig_pkey_algo], - pkey_hash_algo[cert->sig_hash_algo]); -@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- now = CURRENT_TIME.tv_sec; -- if (now < cert->valid_from) { -+ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -+ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, -+ now.tm_hour, now.tm_min, now.tm_sec); -+ if (now.tm_year < cert->valid_from.tm_year || -+ (now.tm_year == cert->valid_from.tm_year && -+ (now.tm_mon < cert->valid_from.tm_mon || -+ (now.tm_mon == cert->valid_from.tm_mon && -+ (now.tm_mday < cert->valid_from.tm_mday || -+ (now.tm_mday == cert->valid_from.tm_mday && -+ (now.tm_hour < cert->valid_from.tm_hour || -+ (now.tm_hour == cert->valid_from.tm_hour && -+ (now.tm_min < cert->valid_from.tm_min || -+ (now.tm_min == cert->valid_from.tm_min && -+ (now.tm_sec < cert->valid_from.tm_sec -+ ))))))))))) { - pr_warn("Cert %s is not yet valid\n", cert->fingerprint); - ret = -EKEYREJECTED; - goto error_free_cert; - } -- if (now >= cert->valid_to) { -+ if (now.tm_year > cert->valid_to.tm_year || -+ (now.tm_year == cert->valid_to.tm_year && -+ (now.tm_mon > cert->valid_to.tm_mon || -+ (now.tm_mon == cert->valid_to.tm_mon && -+ (now.tm_mday > cert->valid_to.tm_mday || -+ (now.tm_mday == cert->valid_to.tm_mday && -+ (now.tm_hour > cert->valid_to.tm_hour || -+ (now.tm_hour == cert->valid_to.tm_hour && -+ (now.tm_min > cert->valid_to.tm_min || -+ (now.tm_min == cert->valid_to.tm_min && -+ (now.tm_sec > cert->valid_to.tm_sec -+ ))))))))))) { - pr_warn("Cert %s has expired\n", cert->fingerprint); - ret = -EKEYEXPIRED; - goto error_free_cert; +1.7.11.7 diff --git a/modsign-upstream-3.7.patch b/modsign-upstream-3.7.patch new file mode 100644 index 000000000..4ed27c8a5 --- /dev/null +++ b/modsign-upstream-3.7.patch @@ -0,0 +1,10963 @@ +From 9d501208ff48eb3ecc0d1ac8d897c38e99d18161 Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Wed, 26 Sep 2012 10:09:40 +0100 +Subject: [PATCH 01/37] module: signature checking hook + +We do a very simple search for a particular string appended to the module +(which is cache-hot and about to be SHA'd anyway). There's both a config +option and a boot parameter which control whether we accept or fail with +unsigned modules and modules that are signed with an unknown key. + +If module signing is enabled, the kernel will be tainted if a module is +loaded that is unsigned or has a signature for which we don't have the +key. + +(Useful feedback and tweaks by David Howells ) + +Signed-off-by: Rusty Russell +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + Documentation/kernel-parameters.txt | 6 +++ + include/linux/module.h | 8 ++++ + init/Kconfig | 14 ++++++ + kernel/Makefile | 1 + + kernel/module-internal.h | 13 ++++++ + kernel/module.c | 93 ++++++++++++++++++++++++++++++++++++- + kernel/module_signing.c | 23 +++++++++ + 7 files changed, 157 insertions(+), 1 deletion(-) + create mode 100644 kernel/module-internal.h + create mode 100644 kernel/module_signing.c + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index ad7e2e5..9b2b8d3 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + log everything. Information is printed at KERN_DEBUG + so loglevel=8 may also need to be specified. + ++ module.sig_enforce ++ [KNL] When CONFIG_MODULE_SIG is set, this means that ++ modules without (valid) signatures will fail to load. ++ Note that if CONFIG_MODULE_SIG_ENFORCE is set, that ++ is always true, so this option does nothing. ++ + mousedev.tap_time= + [MOUSE] Maximum time between finger touching and + leaving touchpad surface for touch to be considered +diff --git a/include/linux/module.h b/include/linux/module.h +index fbcafe2..7760c6d 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -21,6 +21,9 @@ + #include + #include + ++/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ ++#define MODULE_SIG_STRING "~Module signature appended~\n" ++ + /* Not Yet Implemented */ + #define MODULE_SUPPORTED_DEVICE(name) + +@@ -260,6 +263,11 @@ struct module + const unsigned long *unused_gpl_crcs; + #endif + ++#ifdef CONFIG_MODULE_SIG ++ /* Signature was verified. */ ++ bool sig_ok; ++#endif ++ + /* symbols that will be GPL-only in the near future. */ + const struct kernel_symbol *gpl_future_syms; + const unsigned long *gpl_future_crcs; +diff --git a/init/Kconfig b/init/Kconfig +index af6c7f8..7452e19 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL + the version). With this option, such a "srcversion" field + will be created for all modules. If unsure, say N. + ++config MODULE_SIG ++ bool "Module signature verification" ++ depends on MODULES ++ help ++ Check modules for valid signatures upon load: the signature ++ is simply appended to the module. For more information see ++ Documentation/module-signing.txt. ++ ++config MODULE_SIG_FORCE ++ bool "Require modules to be validly signed" ++ depends on MODULE_SIG ++ help ++ Reject unsigned modules or signed modules for which we don't have a ++ key. Without this, such modules will simply taint the kernel. + endif # MODULES + + config INIT_ALL_POSSIBLE +diff --git a/kernel/Makefile b/kernel/Makefile +index c0cc67a..08ba8a6 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +new file mode 100644 +index 0000000..033c17f +--- /dev/null ++++ b/kernel/module-internal.h +@@ -0,0 +1,13 @@ ++/* Module internals ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++extern int mod_verify_sig(const void *mod, unsigned long modlen, ++ const void *sig, unsigned long siglen); +diff --git a/kernel/module.c b/kernel/module.c +index 9ad9ee9..7efb415 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include "module-internal.h" + + #define CREATE_TRACE_POINTS + #include +@@ -102,6 +103,43 @@ static LIST_HEAD(modules); + struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ + #endif /* CONFIG_KGDB_KDB */ + ++#ifdef CONFIG_MODULE_SIG ++#ifdef CONFIG_MODULE_SIG_FORCE ++static bool sig_enforce = true; ++#else ++static bool sig_enforce = false; ++ ++static int param_set_bool_enable_only(const char *val, ++ const struct kernel_param *kp) ++{ ++ int err; ++ bool test; ++ struct kernel_param dummy_kp = *kp; ++ ++ dummy_kp.arg = &test; ++ ++ err = param_set_bool(val, &dummy_kp); ++ if (err) ++ return err; ++ ++ /* Don't let them unset it once it's set! */ ++ if (!test && sig_enforce) ++ return -EROFS; ++ ++ if (test) ++ sig_enforce = true; ++ return 0; ++} ++ ++static const struct kernel_param_ops param_ops_bool_enable_only = { ++ .set = param_set_bool_enable_only, ++ .get = param_get_bool, ++}; ++#define param_check_bool_enable_only param_check_bool ++ ++module_param(sig_enforce, bool_enable_only, 0644); ++#endif /* !CONFIG_MODULE_SIG_FORCE */ ++#endif /* CONFIG_MODULE_SIG */ + + /* Block module loading/unloading? */ + int modules_disabled = 0; +@@ -136,6 +174,7 @@ struct load_info { + unsigned long symoffs, stroffs; + struct _ddebug *debug; + unsigned int num_debug; ++ bool sig_ok; + struct { + unsigned int sym, str, mod, vers, info, pcpu; + } index; +@@ -2399,7 +2438,49 @@ static inline void kmemleak_load_module(const struct module *mod, + } + #endif + +-/* Sets info->hdr and info->len. */ ++#ifdef CONFIG_MODULE_SIG ++static int module_sig_check(struct load_info *info, ++ const void *mod, unsigned long *len) ++{ ++ int err = -ENOKEY; ++ const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; ++ const void *p = mod, *end = mod + *len; ++ ++ /* Poor man's memmem. */ ++ while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { ++ if (p + markerlen > end) ++ break; ++ ++ if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { ++ const void *sig = p + markerlen; ++ /* Truncate module up to signature. */ ++ *len = p - mod; ++ err = mod_verify_sig(mod, *len, sig, end - sig); ++ break; ++ } ++ p++; ++ } ++ ++ if (!err) { ++ info->sig_ok = true; ++ return 0; ++ } ++ ++ /* Not having a signature is only an error if we're strict. */ ++ if (err == -ENOKEY && !sig_enforce) ++ err = 0; ++ ++ return err; ++} ++#else /* !CONFIG_MODULE_SIG */ ++static int module_sig_check(struct load_info *info, ++ void *mod, unsigned long *len) ++{ ++ return 0; ++} ++#endif /* !CONFIG_MODULE_SIG */ ++ ++/* Sets info->hdr, info->len and info->sig_ok. */ + static int copy_and_check(struct load_info *info, + const void __user *umod, unsigned long len, + const char __user *uargs) +@@ -2419,6 +2500,10 @@ static int copy_and_check(struct load_info *info, + goto free_hdr; + } + ++ err = module_sig_check(info, hdr, &len); ++ if (err) ++ goto free_hdr; ++ + /* Sanity checks against insmoding binaries or wrong arch, + weird elf version */ + if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 +@@ -2890,6 +2975,12 @@ static struct module *load_module(void __user *umod, + goto free_copy; + } + ++#ifdef CONFIG_MODULE_SIG ++ mod->sig_ok = info.sig_ok; ++ if (!mod->sig_ok) ++ add_taint_module(mod, TAINT_FORCED_MODULE); ++#endif ++ + /* Now module is in final location, initialize linked lists, etc. */ + err = module_unload_init(mod); + if (err) +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +new file mode 100644 +index 0000000..499728a +--- /dev/null ++++ b/kernel/module_signing.c +@@ -0,0 +1,23 @@ ++/* Module signature checker ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include "module-internal.h" ++ ++/* ++ * Verify the signature on a module. ++ */ ++int mod_verify_sig(const void *mod, unsigned long modlen, ++ const void *sig, unsigned long siglen) ++{ ++ return -ENOKEY; ++} +-- +1.7.12.1 + + +From 82400c211d81ea36338fb8266b5c41710101a013 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 13:06:29 +0100 +Subject: [PATCH 02/37] KEYS: Add payload preparsing opportunity prior to key + instantiate or update + +Give the key type the opportunity to preparse the payload prior to the +instantiation and update routines being called. This is done with the +provision of two new key type operations: + + int (*preparse)(struct key_preparsed_payload *prep); + void (*free_preparse)(struct key_preparsed_payload *prep); + +If the first operation is present, then it is called before key creation (in +the add/update case) or before the key semaphore is taken (in the update and +instantiate cases). The second operation is called to clean up if the first +was called. + +preparse() is given the opportunity to fill in the following structure: + + struct key_preparsed_payload { + char *description; + void *type_data[2]; + void *payload; + const void *data; + size_t datalen; + size_t quotalen; + }; + +Before the preparser is called, the first three fields will have been cleared, +the payload pointer and size will be stored in data and datalen and the default +quota size from the key_type struct will be stored into quotalen. + +The preparser may parse the payload in any way it likes and may store data in +the type_data[] and payload fields for use by the instantiate() and update() +ops. + +The preparser may also propose a description for the key by attaching it as a +string to the description field. This can be used by passing a NULL or "" +description to the add_key() system call or the key_create_or_update() +function. This cannot work with request_key() as that required the description +to tell the upcall about the key to be created. + +This, for example permits keys that store PGP public keys to generate their own +name from the user ID and public key fingerprint in the key. + +The instantiate() and update() operations are then modified to look like this: + + int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + int (*update)(struct key *key, struct key_preparsed_payload *prep); + +and the new payload data is passed in *prep, whether or not it was preparsed. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + Documentation/security/keys.txt | 50 +++++++++++++- + fs/cifs/cifs_spnego.c | 6 +- + fs/cifs/cifsacl.c | 8 +-- + include/keys/user-type.h | 6 +- + include/linux/key-type.h | 35 +++++++++- + net/ceph/crypto.c | 9 +-- + net/dns_resolver/dns_key.c | 6 +- + net/rxrpc/ar-key.c | 40 +++++------ + security/keys/encrypted-keys/encrypted.c | 16 +++-- + security/keys/key.c | 114 ++++++++++++++++++++++--------- + security/keys/keyctl.c | 18 +++-- + security/keys/keyring.c | 6 +- + security/keys/request_key_auth.c | 8 +-- + security/keys/trusted.c | 16 +++-- + security/keys/user_defined.c | 14 ++-- + 15 files changed, 250 insertions(+), 102 deletions(-) + +diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt +index aa0dbd7..7d9ca92 100644 +--- a/Documentation/security/keys.txt ++++ b/Documentation/security/keys.txt +@@ -412,6 +412,10 @@ The main syscalls are: + to the keyring. In this case, an error will be generated if the process + does not have permission to write to the keyring. + ++ If the key type supports it, if the description is NULL or an empty ++ string, the key type will try and generate a description from the content ++ of the payload. ++ + The payload is optional, and the pointer can be NULL if not required by + the type. The payload is plen in size, and plen can be zero for an empty + payload. +@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: + it should return 0. + + +- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ (*) int (*preparse)(struct key_preparsed_payload *prep); ++ ++ This optional method permits the key type to attempt to parse payload ++ before a key is created (add key) or the key semaphore is taken (update or ++ instantiate key). The structure pointed to by prep looks like: ++ ++ struct key_preparsed_payload { ++ char *description; ++ void *type_data[2]; ++ void *payload; ++ const void *data; ++ size_t datalen; ++ size_t quotalen; ++ }; ++ ++ Before calling the method, the caller will fill in data and datalen with ++ the payload blob parameters; quotalen will be filled in with the default ++ quota size from the key type and the rest will be cleared. ++ ++ If a description can be proposed from the payload contents, that should be ++ attached as a string to the description field. This will be used for the ++ key description if the caller of add_key() passes NULL or "". ++ ++ The method can attach anything it likes to type_data[] and payload. These ++ are merely passed along to the instantiate() or update() operations. ++ ++ The method should return 0 if success ful or a negative error code ++ otherwise. ++ ++ ++ (*) void (*free_preparse)(struct key_preparsed_payload *prep); ++ ++ This method is only required if the preparse() method is provided, ++ otherwise it is unused. It cleans up anything attached to the ++ description, type_data and payload fields of the key_preparsed_payload ++ struct as filled in by the preparse() method. ++ ++ ++ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + This method is called to attach a payload to a key during construction. + The payload attached need not bear any relation to the data passed to this + function. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + If the amount of data attached to the key differs from the size in + keytype->def_datalen, then key_payload_reserve() should be called. + +@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: + If this type of key can be updated, then this method should be provided. + It is called to update a key's payload from the blob of data provided. + ++ The prep->data and prep->datalen fields will define the original payload ++ blob. If preparse() was supplied then other fields may be filled in also. ++ + key_payload_reserve() should be called if the data length might change + before any changes are actually made. Note that if this succeeds, the type + is committed to changing the key because it's already been altered, so all +diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c +index e622863..086f381 100644 +--- a/fs/cifs/cifs_spnego.c ++++ b/fs/cifs/cifs_spnego.c +@@ -31,18 +31,18 @@ + + /* create a new cifs key */ + static int +-cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + int ret; + + ret = -ENOMEM; +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + goto error; + + /* attach the data */ +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; + ret = 0; + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 05f4dc2..f3c60e2 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { + }; + + static int +-cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) ++cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + char *payload; + +- payload = kmalloc(datalen, GFP_KERNEL); ++ payload = kmalloc(prep->datalen, GFP_KERNEL); + if (!payload) + return -ENOMEM; + +- memcpy(payload, data, datalen); ++ memcpy(payload, prep->data, prep->datalen); + key->payload.data = payload; +- key->datalen = datalen; ++ key->datalen = prep->datalen; + return 0; + } + +diff --git a/include/keys/user-type.h b/include/keys/user-type.h +index bc9ec1d..5e452c8 100644 +--- a/include/keys/user-type.h ++++ b/include/keys/user-type.h +@@ -35,8 +35,10 @@ struct user_key_payload { + extern struct key_type key_type_user; + extern struct key_type key_type_logon; + +-extern int user_instantiate(struct key *key, const void *data, size_t datalen); +-extern int user_update(struct key *key, const void *data, size_t datalen); ++struct key_preparsed_payload; ++ ++extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); ++extern int user_update(struct key *key, struct key_preparsed_payload *prep); + extern int user_match(const struct key *key, const void *criterion); + extern void user_revoke(struct key *key); + extern void user_destroy(struct key *key); +diff --git a/include/linux/key-type.h b/include/linux/key-type.h +index f0c651c..518a53a 100644 +--- a/include/linux/key-type.h ++++ b/include/linux/key-type.h +@@ -26,6 +26,27 @@ struct key_construction { + struct key *authkey;/* authorisation for key being constructed */ + }; + ++/* ++ * Pre-parsed payload, used by key add, update and instantiate. ++ * ++ * This struct will be cleared and data and datalen will be set with the data ++ * and length parameters from the caller and quotalen will be set from ++ * def_datalen from the key type. Then if the preparse() op is provided by the ++ * key type, that will be called. Then the struct will be passed to the ++ * instantiate() or the update() op. ++ * ++ * If the preparse() op is given, the free_preparse() op will be called to ++ * clear the contents. ++ */ ++struct key_preparsed_payload { ++ char *description; /* Proposed key description (or NULL) */ ++ void *type_data[2]; /* Private key-type data */ ++ void *payload; /* Proposed payload */ ++ const void *data; /* Raw data */ ++ size_t datalen; /* Raw datalen */ ++ size_t quotalen; /* Quota length for proposed payload */ ++}; ++ + typedef int (*request_key_actor_t)(struct key_construction *key, + const char *op, void *aux); + +@@ -45,18 +66,28 @@ struct key_type { + /* vet a description */ + int (*vet_description)(const char *description); + ++ /* Preparse the data blob from userspace that is to be the payload, ++ * generating a proposed description and payload that will be handed to ++ * the instantiate() and update() ops. ++ */ ++ int (*preparse)(struct key_preparsed_payload *prep); ++ ++ /* Free a preparse data structure. ++ */ ++ void (*free_preparse)(struct key_preparsed_payload *prep); ++ + /* instantiate a key of this type + * - this method should call key_payload_reserve() to determine if the + * user's quota will hold the payload + */ +- int (*instantiate)(struct key *key, const void *data, size_t datalen); ++ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); + + /* update a key of this type (optional) + * - this method should call key_payload_reserve() to recalculate the + * quota consumption + * - the key must be locked against read when modifying + */ +- int (*update)(struct key *key, const void *data, size_t datalen); ++ int (*update)(struct key *key, struct key_preparsed_payload *prep); + + /* match a key against a description */ + int (*match)(const struct key *key, const void *desc); +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 9da7fdd..af14cb4 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, + } + } + +-int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) ++int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct ceph_crypto_key *ckey; ++ size_t datalen = prep->datalen; + int ret; + void *p; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto err; + + ret = key_payload_reserve(key, datalen); +@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) + goto err; + + /* TODO ceph_crypto_key_decode should really take const input */ +- p = (void *)data; +- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); ++ p = (void *)prep->data; ++ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); + if (ret < 0) + goto err_ckey; + +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index d9507dd..859ab8b 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; + * "ip1,ip2,...#foo=bar" + */ + static int +-dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) ++dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; + unsigned long derrno; + int ret; +- size_t result_len = 0; +- const char *data = _data, *end, *opt; ++ size_t datalen = prep->datalen, result_len = 0; ++ const char *data = prep->data, *end, *opt; + + kenter("%%%d,%s,'%*.*s',%zu", + key->serial, key->description, +diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c +index 8b1f9f4..106c5a6 100644 +--- a/net/rxrpc/ar-key.c ++++ b/net/rxrpc/ar-key.c +@@ -26,8 +26,8 @@ + #include "ar-internal.h" + + static int rxrpc_vet_description_s(const char *); +-static int rxrpc_instantiate(struct key *, const void *, size_t); +-static int rxrpc_instantiate_s(struct key *, const void *, size_t); ++static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); ++static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); + static void rxrpc_destroy(struct key *); + static void rxrpc_destroy_s(struct key *); + static void rxrpc_describe(const struct key *, struct seq_file *); +@@ -678,7 +678,7 @@ error: + * + * if no data is provided, then a no-security key is made + */ +-static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) ++static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + const struct rxrpc_key_data_v1 *v1; + struct rxrpc_key_token *token, **pp; +@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + u32 kver; + int ret; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + + /* handle a no-security key */ +- if (!data && datalen == 0) ++ if (!prep->data && prep->datalen == 0) + return 0; + + /* determine if the XDR payload format is being used */ +- if (datalen > 7 * 4) { +- ret = rxrpc_instantiate_xdr(key, data, datalen); ++ if (prep->datalen > 7 * 4) { ++ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); + if (ret != -EPROTO) + return ret; + } + + /* get the key interface version number */ + ret = -EINVAL; +- if (datalen <= 4 || !data) ++ if (prep->datalen <= 4 || !prep->data) + goto error; +- memcpy(&kver, data, sizeof(kver)); +- data += sizeof(kver); +- datalen -= sizeof(kver); ++ memcpy(&kver, prep->data, sizeof(kver)); ++ prep->data += sizeof(kver); ++ prep->datalen -= sizeof(kver); + + _debug("KEY I/F VERSION: %u", kver); + +@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) + + /* deal with a version 1 key */ + ret = -EINVAL; +- if (datalen < sizeof(*v1)) ++ if (prep->datalen < sizeof(*v1)) + goto error; + +- v1 = data; +- if (datalen != sizeof(*v1) + v1->ticket_length) ++ v1 = prep->data; ++ if (prep->datalen != sizeof(*v1) + v1->ticket_length) + goto error; + + _debug("SCIX: %u", v1->security_index); +@@ -784,17 +784,17 @@ error: + * instantiate a server secret key + * data should be a pointer to the 8-byte secret key + */ +-static int rxrpc_instantiate_s(struct key *key, const void *data, +- size_t datalen) ++static int rxrpc_instantiate_s(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct crypto_blkcipher *ci; + +- _enter("{%x},,%zu", key_serial(key), datalen); ++ _enter("{%x},,%zu", key_serial(key), prep->datalen); + +- if (datalen != 8) ++ if (prep->datalen != 8) + return -EINVAL; + +- memcpy(&key->type_data, data, 8); ++ memcpy(&key->type_data, prep->data, 8); + + ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(ci)) { +@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, + return PTR_ERR(ci); + } + +- if (crypto_blkcipher_setkey(ci, data, 8) < 0) ++ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) + BUG(); + + key->payload.data = ci; +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 2d1bb8a..9e1e005 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int encrypted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = NULL; + char *datablob = NULL; +@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, + char *master_desc = NULL; + char *decrypted_datalen = NULL; + char *hex_encoded_iv = NULL; ++ size_t datalen = prep->datalen; + int ret; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; + datablob[datalen] = 0; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + ret = datablob_parse(datablob, &format, &master_desc, + &decrypted_datalen, &hex_encoded_iv); + if (ret < 0) +@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) + * + * On success, return 0. Otherwise return errno. + */ +-static int encrypted_update(struct key *key, const void *data, size_t datalen) ++static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct encrypted_key_payload *epayload = key->payload.data; + struct encrypted_key_payload *new_epayload; + char *buf; + char *new_master_desc = NULL; + const char *format = NULL; ++ size_t datalen = prep->datalen; + int ret = 0; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + buf = kmalloc(datalen + 1, GFP_KERNEL); +@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) + return -ENOMEM; + + buf[datalen] = 0; +- memcpy(buf, data, datalen); ++ memcpy(buf, prep->data, datalen); + ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); + if (ret < 0) + goto out; +diff --git a/security/keys/key.c b/security/keys/key.c +index 50d96d4..1d039af 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); + * key_construction_mutex. + */ + static int __key_instantiate_and_link(struct key *key, +- const void *data, +- size_t datalen, ++ struct key_preparsed_payload *prep, + struct key *keyring, + struct key *authkey, + unsigned long *_prealloc) +@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, + /* can't instantiate twice */ + if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { + /* instantiate the key */ +- ret = key->type->instantiate(key, data, datalen); ++ ret = key->type->instantiate(key, prep); + + if (ret == 0) { + /* mark the key as being instantiated */ +@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, + struct key *keyring, + struct key *authkey) + { ++ struct key_preparsed_payload prep; + unsigned long prealloc; + int ret; + ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = data; ++ prep.datalen = datalen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; ++ } ++ + if (keyring) { + ret = __key_link_begin(keyring, key->type, key->description, + &prealloc); + if (ret < 0) +- return ret; ++ goto error_free_preparse; + } + +- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, ++ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, + &prealloc); + + if (keyring) + __key_link_end(keyring, key->type, prealloc); + ++error_free_preparse: ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + +@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) + * if we get an error. + */ + static inline key_ref_t __key_update(key_ref_t key_ref, +- const void *payload, size_t plen) ++ struct key_preparsed_payload *prep) + { + struct key *key = key_ref_to_ptr(key_ref); + int ret; +@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, + + down_write(&key->sem); + +- ret = key->type->update(key, payload, plen); ++ ret = key->type->update(key, prep); + if (ret == 0) + /* updating a negative key instantiates it */ + clear_bit(KEY_FLAG_NEGATIVE, &key->flags); +@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + unsigned long flags) + { + unsigned long prealloc; ++ struct key_preparsed_payload prep; + const struct cred *cred = current_cred(); + struct key_type *ktype; + struct key *keyring, *key = NULL; +@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + } + + key_ref = ERR_PTR(-EINVAL); +- if (!ktype->match || !ktype->instantiate) +- goto error_2; ++ if (!ktype->match || !ktype->instantiate || ++ (!description && !ktype->preparse)) ++ goto error_put_type; + + keyring = key_ref_to_ptr(keyring_ref); + +@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + + key_ref = ERR_PTR(-ENOTDIR); + if (keyring->type != &key_type_keyring) +- goto error_2; ++ goto error_put_type; ++ ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = ktype->def_datalen; ++ if (ktype->preparse) { ++ ret = ktype->preparse(&prep); ++ if (ret < 0) { ++ key_ref = ERR_PTR(ret); ++ goto error_put_type; ++ } ++ if (!description) ++ description = prep.description; ++ key_ref = ERR_PTR(-EINVAL); ++ if (!description) ++ goto error_free_prep; ++ } + + ret = __key_link_begin(keyring, ktype, description, &prealloc); +- if (ret < 0) +- goto error_2; ++ if (ret < 0) { ++ key_ref = ERR_PTR(ret); ++ goto error_free_prep; ++ } + + /* if we're going to allocate a new key, we're going to have + * to modify the keyring */ + ret = key_permission(keyring_ref, KEY_WRITE); + if (ret < 0) { + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + /* if it's possible to update this type of key, search for an existing +@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + perm, flags); + if (IS_ERR(key)) { + key_ref = ERR_CAST(key); +- goto error_3; ++ goto error_link_end; + } + + /* instantiate it and link it into the target keyring */ +- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, +- &prealloc); ++ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); + if (ret < 0) { + key_put(key); + key_ref = ERR_PTR(ret); +- goto error_3; ++ goto error_link_end; + } + + key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); + +- error_3: ++error_link_end: + __key_link_end(keyring, ktype, prealloc); +- error_2: ++error_free_prep: ++ if (ktype->preparse) ++ ktype->free_preparse(&prep); ++error_put_type: + key_type_put(ktype); +- error: ++error: + return key_ref; + + found_matching_key: +@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + * - we can drop the locks first as we have the key pinned + */ + __key_link_end(keyring, ktype, prealloc); +- key_type_put(ktype); + +- key_ref = __key_update(key_ref, payload, plen); +- goto error; ++ key_ref = __key_update(key_ref, &prep); ++ goto error_free_prep; + } + EXPORT_SYMBOL(key_create_or_update); + +@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); + */ + int key_update(key_ref_t key_ref, const void *payload, size_t plen) + { ++ struct key_preparsed_payload prep; + struct key *key = key_ref_to_ptr(key_ref); + int ret; + +@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) + + /* attempt to update it if supported */ + ret = -EOPNOTSUPP; +- if (key->type->update) { +- down_write(&key->sem); +- +- ret = key->type->update(key, payload, plen); +- if (ret == 0) +- /* updating a negative key instantiates it */ +- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ if (!key->type->update) ++ goto error; + +- up_write(&key->sem); ++ memset(&prep, 0, sizeof(prep)); ++ prep.data = payload; ++ prep.datalen = plen; ++ prep.quotalen = key->type->def_datalen; ++ if (key->type->preparse) { ++ ret = key->type->preparse(&prep); ++ if (ret < 0) ++ goto error; + } + +- error: ++ down_write(&key->sem); ++ ++ ret = key->type->update(key, &prep); ++ if (ret == 0) ++ /* updating a negative key instantiates it */ ++ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); ++ ++ up_write(&key->sem); ++ ++ if (key->type->preparse) ++ key->type->free_preparse(&prep); ++error: + return ret; + } + EXPORT_SYMBOL(key_update); +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 3364fbf..505d40b 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, + * Extract the description of a new key from userspace and either add it as a + * new key to the specified keyring or update a matching key in that keyring. + * ++ * If the description is NULL or an empty string, the key type is asked to ++ * generate one from the payload. ++ * + * The keyring must be writable so that we can attach the key to it. + * + * If successful, the new key's serial number is returned, otherwise an error +@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, + if (ret < 0) + goto error; + +- description = strndup_user(_description, PAGE_SIZE); +- if (IS_ERR(description)) { +- ret = PTR_ERR(description); +- goto error; ++ description = NULL; ++ if (_description) { ++ description = strndup_user(_description, PAGE_SIZE); ++ if (IS_ERR(description)) { ++ ret = PTR_ERR(description); ++ goto error; ++ } ++ if (!*description) { ++ kfree(description); ++ description = NULL; ++ } + } + + /* pull the payload in if one was supplied */ +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 81e7852..f04d8cf 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) + * operations. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen); ++ struct key_preparsed_payload *prep); + static int keyring_match(const struct key *keyring, const void *criterion); + static void keyring_revoke(struct key *keyring); + static void keyring_destroy(struct key *keyring); +@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) + * Returns 0 on success, -EINVAL if given any data. + */ + static int keyring_instantiate(struct key *keyring, +- const void *data, size_t datalen) ++ struct key_preparsed_payload *prep) + { + int ret; + + ret = -EINVAL; +- if (datalen == 0) { ++ if (prep->datalen == 0) { + /* make the keyring available by name if it has one */ + keyring_publish_name(keyring); + ret = 0; +diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c +index 60d4e3f..85730d5 100644 +--- a/security/keys/request_key_auth.c ++++ b/security/keys/request_key_auth.c +@@ -19,7 +19,8 @@ + #include + #include "internal.h" + +-static int request_key_auth_instantiate(struct key *, const void *, size_t); ++static int request_key_auth_instantiate(struct key *, ++ struct key_preparsed_payload *); + static void request_key_auth_describe(const struct key *, struct seq_file *); + static void request_key_auth_revoke(struct key *); + static void request_key_auth_destroy(struct key *); +@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { + * Instantiate a request-key authorisation key. + */ + static int request_key_auth_instantiate(struct key *key, +- const void *data, +- size_t datalen) ++ struct key_preparsed_payload *prep) + { +- key->payload.data = (struct request_key_auth *) data; ++ key->payload.data = (struct request_key_auth *)prep->data; + return 0; + } + +diff --git a/security/keys/trusted.c b/security/keys/trusted.c +index 2d5d041..42036c7 100644 +--- a/security/keys/trusted.c ++++ b/security/keys/trusted.c +@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) + * + * On success, return 0. Otherwise return errno. + */ +-static int trusted_instantiate(struct key *key, const void *data, +- size_t datalen) ++static int trusted_instantiate(struct key *key, ++ struct key_preparsed_payload *prep) + { + struct trusted_key_payload *payload = NULL; + struct trusted_key_options *options = NULL; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + int key_cmd; + +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + + options = trusted_options_alloc(); +@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) + /* + * trusted_update - reseal an existing key with new PCR values + */ +-static int trusted_update(struct key *key, const void *data, size_t datalen) ++static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + { + struct trusted_key_payload *p = key->payload.data; + struct trusted_key_payload *new_p; + struct trusted_key_options *new_o; ++ size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + + if (!p->migratable) + return -EPERM; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); +@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) + goto out; + } + +- memcpy(datablob, data, datalen); ++ memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + ret = datablob_parse(datablob, new_p, new_o); + if (ret != Opt_update) { +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index c7660a2..55dc889 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); + /* + * instantiate a user defined key + */ +-int user_instantiate(struct key *key, const void *data, size_t datalen) ++int user_instantiate(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + ret = key_payload_reserve(key, datalen); +@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) + + /* attach the data */ + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + rcu_assign_keypointer(key, upayload); + ret = 0; + +@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); + * update a user defined key + * - the key's semaphore is write-locked + */ +-int user_update(struct key *key, const void *data, size_t datalen) ++int user_update(struct key *key, struct key_preparsed_payload *prep) + { + struct user_key_payload *upayload, *zap; ++ size_t datalen = prep->datalen; + int ret; + + ret = -EINVAL; +- if (datalen <= 0 || datalen > 32767 || !data) ++ if (datalen <= 0 || datalen > 32767 || !prep->data) + goto error; + + /* construct a replacement payload */ +@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) + goto error; + + upayload->datalen = datalen; +- memcpy(upayload->data, data, datalen); ++ memcpy(upayload->data, prep->data, datalen); + + /* check the quota and attach the new data */ + zap = upayload; +-- +1.7.12.1 + + +From 162ce9c1b0f28d36598975f8931f216245b7e778 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 13:09:33 +0100 +Subject: [PATCH 03/37] MPILIB: Provide count_leading/trailing_zeros() based + on arch functions + +Provide count_leading/trailing_zeros() macros based on extant arch bit scanning +functions rather than reimplementing from scratch in MPILIB. + +Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). + +Also move the definition to asm-generic as other people may be interested in +using it. + +Signed-off-by: David Howells +Cc: David S. Miller +Cc: Dmitry Kasatkin +Cc: Arnd Bergmann +Signed-off-by: Rusty Russell +--- + include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ + lib/mpi/longlong.h | 138 +------------------------------ + lib/mpi/mpi-bit.c | 2 +- + lib/mpi/mpi-pow.c | 4 +- + 4 files changed, 62 insertions(+), 139 deletions(-) + create mode 100644 include/asm-generic/bitops/count_zeros.h + +diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h +new file mode 100644 +index 0000000..97520d2 +--- /dev/null ++++ b/include/asm-generic/bitops/count_zeros.h +@@ -0,0 +1,57 @@ ++/* Count leading and trailing zeros functions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ ++#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ ++ ++#include ++ ++/** ++ * count_leading_zeros - Count the number of zeros from the MSB back ++ * @x: The value ++ * ++ * Count the number of leading zeros from the MSB going towards the LSB in @x. ++ * ++ * If the MSB of @x is set, the result is 0. ++ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. ++ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. ++ */ ++static inline int count_leading_zeros(unsigned long x) ++{ ++ if (sizeof(x) == 4) ++ return BITS_PER_LONG - fls(x); ++ else ++ return BITS_PER_LONG - fls64(x); ++} ++ ++#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG ++ ++/** ++ * count_trailing_zeros - Count the number of zeros from the LSB forwards ++ * @x: The value ++ * ++ * Count the number of trailing zeros from the LSB going towards the MSB in @x. ++ * ++ * If the LSB of @x is set, the result is 0. ++ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. ++ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. ++ */ ++static inline int count_trailing_zeros(unsigned long x) ++{ ++#define COUNT_TRAILING_ZEROS_0 (-1) ++ ++ if (sizeof(x) == 4) ++ return ffs(x); ++ else ++ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; ++} ++ ++#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ +diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h +index 29f9862..678ce4f 100644 +--- a/lib/mpi/longlong.h ++++ b/lib/mpi/longlong.h +@@ -19,6 +19,8 @@ + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ + ++#include ++ + /* You have to define the following before including this file: + * + * UWtype -- An unsigned type, default type for operations (typically a "word") +@@ -146,12 +148,6 @@ do { \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +- +-#define count_leading_zeros(count, x) \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))) +-#define COUNT_LEADING_ZEROS_0 32 + #endif /* __a29k__ */ + + #if defined(__alpha) && W_TYPE_SIZE == 64 +@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +- __asm__ ("bsch/1 %1,%0" \ +- : "=g" (count) \ +- : "g" ((USItype)(x)), \ +- "0" ((USItype)0)) + #endif + + /*************************************** +@@ -354,27 +345,6 @@ do { USItype __r; \ + } while (0) + extern USItype __udiv_qrnnd(); + #endif /* LONGLONG_STANDALONE */ +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __tmp; \ +- __asm__ ( \ +- "ldi 1,%0\n" \ +- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ +- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ +- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ +- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ +- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ +- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ +- "extru %1,30,1,%1 ; Extract bit 1.\n" \ +- "sub %0,%1,%0 ; Subtract it. " \ +- : "=r" (count), "=r" (__tmp) : "1" (x)); \ +-} while (0) + #endif /* hppa */ + + /*************************************** +@@ -457,15 +427,6 @@ do { \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("bsrl %1,%0" \ +- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define count_trailing_zeros(count, x) \ +- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) + #ifndef UMUL_TIME + #define UMUL_TIME 40 + #endif +@@ -536,15 +497,6 @@ do { \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("scanbit %1,%0" \ +- : "=r" (__cbtmp) \ +- : "r" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ + #if defined(__i960mx) /* what is the proper symbol to test??? */ + #define rshift_rhlc(r, h, l, c) \ + do { \ +@@ -603,11 +555,6 @@ do { \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +-#define count_leading_zeros(count, x) \ +- __asm__ ("bfffo %1{%b2:%b2},%0" \ +- : "=d" ((USItype)(count)) \ +- : "od" ((USItype)(x)), "n" (0)) +-#define COUNT_LEADING_ZEROS_0 32 + #else /* not mc68020 */ + #define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ +@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +-#define count_leading_zeros(count, x) \ +-do { \ +- USItype __cbtmp; \ +- __asm__ ("ff1 %0,%1" \ +- : "=r" (__cbtmp) \ +- : "r" ((USItype)(x))); \ +- (count) = __cbtmp ^ 31; \ +-} while (0) +-#define COUNT_LEADING_ZEROS_0 63 /* sic */ + #if defined(__m88110__) + #define umul_ppmm(wh, wl, u, v) \ + do { \ +@@ -779,12 +717,6 @@ do { \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +-#define count_trailing_zeros(count, x) \ +-do { \ +- __asm__("ffsd %2,%0" \ +- : "=r"((USItype) (count)) \ +- : "0"((USItype) 0), "r"((USItype) (x))); \ +- } while (0) + #endif /* __ns32000__ */ + + /*************************************** +@@ -855,11 +787,6 @@ do { \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +-#define count_leading_zeros(count, x) \ +- __asm__ ("{cntlz|cntlzw} %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))) +-#define COUNT_LEADING_ZEROS_0 32 + #if defined(_ARCH_PPC) + #define umul_ppmm(ph, pl, m0, m1) \ + do { \ +@@ -1001,19 +928,6 @@ do { \ + } while (0) + #define UMUL_TIME 20 + #define UDIV_TIME 200 +-#define count_leading_zeros(count, x) \ +-do { \ +- if ((x) >= 0x10000) \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x) >> 16)); \ +- else { \ +- __asm__ ("clz %0,%1" \ +- : "=r" ((USItype)(count)) \ +- : "r" ((USItype)(x))); \ +- (count) += 16; \ +- } \ +-} while (0) + #endif /* RT/ROMP */ + + /*************************************** +@@ -1142,13 +1056,6 @@ do { \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) + #define UDIV_TIME 37 +-#define count_leading_zeros(count, x) \ +- __asm__ ("scan %1,0,%0" \ +- : "=r" ((USItype)(x)) \ +- : "r" ((USItype)(count))) +-/* Early sparclites return 63 for an argument of 0, but they warn that future +- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 +- undefined. */ + #endif /* __sparclite__ */ + #endif /* __sparc_v8__ */ + /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +@@ -1454,47 +1361,6 @@ do { \ + #define udiv_qrnnd __udiv_qrnnd_c + #endif + +-#undef count_leading_zeros +-#if !defined(count_leading_zeros) +- extern +-#ifdef __STDC__ +- const +-#endif +- unsigned char __clz_tab[]; +-#define count_leading_zeros(count, x) \ +-do { \ +- UWtype __xr = (x); \ +- UWtype __a; \ +- \ +- if (W_TYPE_SIZE <= 32) { \ +- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ +- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ +- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ +- } \ +- else { \ +- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ +- if (((__xr >> __a) & 0xff) != 0) \ +- break; \ +- } \ +- \ +- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ +-} while (0) +- /* This version gives a well-defined value for zero. */ +-#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +-#endif +- +-#if !defined(count_trailing_zeros) +-/* Define count_trailing_zeros using count_leading_zeros. The latter might be +- defined in asm, but if it is not, the C version above is good enough. */ +-#define count_trailing_zeros(count, x) \ +-do { \ +- UWtype __ctz_x = (x); \ +- UWtype __ctz_c; \ +- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ +- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ +-} while (0) +-#endif +- + #ifndef UDIV_NEEDS_NORMALIZATION + #define UDIV_NEEDS_NORMALIZATION 0 + #endif +diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c +index 5687248..503537e 100644 +--- a/lib/mpi/mpi-bit.c ++++ b/lib/mpi/mpi-bit.c +@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) + if (a->nlimbs) { + mpi_limb_t alimb = a->d[a->nlimbs - 1]; + if (alimb) +- count_leading_zeros(n, alimb); ++ n = count_leading_zeros(alimb); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; +diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c +index 67f3e79..5464c87 100644 +--- a/lib/mpi/mpi-pow.c ++++ b/lib/mpi/mpi-pow.c +@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + mp = mp_marker = mpi_alloc_limb_space(msize); + if (!mp) + goto enomem; +- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); ++ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); + if (mod_shift_cnt) + mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); + else +@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + + i = esize - 1; + e = ep[i]; +- count_leading_zeros(c, e); ++ c = count_leading_zeros(e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MPI_LIMB - 1 - c; + +-- +1.7.12.1 + + +From ef184bcab1e58dafae2f02ae30824365bec1d27a Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:21 +0100 +Subject: [PATCH 04/37] KEYS: Document asymmetric key type + +In-source documentation for the asymmetric key type. This will be located in: + + Documentation/crypto/asymmetric-keys.txt + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++ + 1 file changed, 312 insertions(+) + create mode 100644 Documentation/crypto/asymmetric-keys.txt + +diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt +new file mode 100644 +index 0000000..b767590 +--- /dev/null ++++ b/Documentation/crypto/asymmetric-keys.txt +@@ -0,0 +1,312 @@ ++ ============================================= ++ ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE ++ ============================================= ++ ++Contents: ++ ++ - Overview. ++ - Key identification. ++ - Accessing asymmetric keys. ++ - Signature verification. ++ - Asymmetric key subtypes. ++ - Instantiation data parsers. ++ ++ ++======== ++OVERVIEW ++======== ++ ++The "asymmetric" key type is designed to be a container for the keys used in ++public-key cryptography, without imposing any particular restrictions on the ++form or mechanism of the cryptography or form of the key. ++ ++The asymmetric key is given a subtype that defines what sort of data is ++associated with the key and provides operations to describe and destroy it. ++However, no requirement is made that the key data actually be stored in the ++key. ++ ++A completely in-kernel key retention and operation subtype can be defined, but ++it would also be possible to provide access to cryptographic hardware (such as ++a TPM) that might be used to both retain the relevant key and perform ++operations using that key. In such a case, the asymmetric key would then ++merely be an interface to the TPM driver. ++ ++Also provided is the concept of a data parser. Data parsers are responsible ++for extracting information from the blobs of data passed to the instantiation ++function. The first data parser that recognises the blob gets to set the ++subtype of the key and define the operations that can be done on that key. ++ ++A data parser may interpret the data blob as containing the bits representing a ++key, or it may interpret it as a reference to a key held somewhere else in the ++system (for example, a TPM). ++ ++ ++================== ++KEY IDENTIFICATION ++================== ++ ++If a key is added with an empty name, the instantiation data parsers are given ++the opportunity to pre-parse a key and to determine the description the key ++should be given from the content of the key. ++ ++This can then be used to refer to the key, either by complete match or by ++partial match. The key type may also use other criteria to refer to a key. ++ ++The asymmetric key type's match function can then perform a wider range of ++comparisons than just the straightforward comparison of the description with ++the criterion string: ++ ++ (1) If the criterion string is of the form "id:" then the match ++ function will examine a key's fingerprint to see if the hex digits given ++ after the "id:" match the tail. For instance: ++ ++ keyctl search @s asymmetric id:5acc2142 ++ ++ will match a key with fingerprint: ++ ++ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 ++ ++ (2) If the criterion string is of the form ":" then the ++ match will match the ID as in (1), but with the added restriction that ++ only keys of the specified subtype (e.g. tpm) will be matched. For ++ instance: ++ ++ keyctl search @s asymmetric tpm:5acc2142 ++ ++Looking in /proc/keys, the last 8 hex digits of the key fingerprint are ++displayed, along with the subtype: ++ ++ 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] ++ ++ ++========================= ++ACCESSING ASYMMETRIC KEYS ++========================= ++ ++For general access to asymmetric keys from within the kernel, the following ++inclusion is required: ++ ++ #include ++ ++This gives access to functions for dealing with asymmetric / public keys. ++Three enums are defined there for representing public-key cryptography ++algorithms: ++ ++ enum pkey_algo ++ ++digest algorithms used by those: ++ ++ enum pkey_hash_algo ++ ++and key identifier representations: ++ ++ enum pkey_id_type ++ ++Note that the key type representation types are required because key ++identifiers from different standards aren't necessarily compatible. For ++instance, PGP generates key identifiers by hashing the key data plus some ++PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. ++ ++The operations defined upon a key are: ++ ++ (1) Signature verification. ++ ++Other operations are possible (such as encryption) with the same key data ++required for verification, but not currently supported, and others ++(eg. decryption and signature generation) require extra key data. ++ ++ ++SIGNATURE VERIFICATION ++---------------------- ++ ++An operation is provided to perform cryptographic signature verification, using ++an asymmetric key to provide or to provide access to the public key. ++ ++ int verify_signature(const struct key *key, ++ const struct public_key_signature *sig); ++ ++The caller must have already obtained the key from some source and can then use ++it to check the signature. The caller must have parsed the signature and ++transferred the relevant bits to the structure pointed to by sig. ++ ++ struct public_key_signature { ++ u8 *digest; ++ u8 digest_size; ++ enum pkey_hash_algo pkey_hash_algo : 8; ++ u8 nr_mpi; ++ union { ++ MPI mpi[2]; ++ ... ++ }; ++ }; ++ ++The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that ++make up the actual signature must be stored in sig->mpi[] and the count of MPIs ++placed in sig->nr_mpi. ++ ++In addition, the data must have been digested by the caller and the resulting ++hash must be pointed to by sig->digest and the size of the hash be placed in ++sig->digest_size. ++ ++The function will return 0 upon success or -EKEYREJECTED if the signature ++doesn't match. ++ ++The function may also return -ENOTSUPP if an unsupported public-key algorithm ++or public-key/hash algorithm combination is specified or the key doesn't ++support the operation; -EBADMSG or -ERANGE if some of the parameters have weird ++data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned ++if the key argument is the wrong type or is incompletely set up. ++ ++ ++======================= ++ASYMMETRIC KEY SUBTYPES ++======================= ++ ++Asymmetric keys have a subtype that defines the set of operations that can be ++performed on that key and that determines what data is attached as the key ++payload. The payload format is entirely at the whim of the subtype. ++ ++The subtype is selected by the key data parser and the parser must initialise ++the data required for it. The asymmetric key retains a reference on the ++subtype module. ++ ++The subtype definition structure can be found in: ++ ++ #include ++ ++and looks like the following: ++ ++ struct asymmetric_key_subtype { ++ struct module *owner; ++ const char *name; ++ ++ void (*describe)(const struct key *key, struct seq_file *m); ++ void (*destroy)(void *payload); ++ int (*verify_signature)(const struct key *key, ++ const struct public_key_signature *sig); ++ }; ++ ++Asymmetric keys point to this with their type_data[0] member. ++ ++The owner and name fields should be set to the owning module and the name of ++the subtype. Currently, the name is only used for print statements. ++ ++There are a number of operations defined by the subtype: ++ ++ (1) describe(). ++ ++ Mandatory. This allows the subtype to display something in /proc/keys ++ against the key. For instance the name of the public key algorithm type ++ could be displayed. The key type will display the tail of the key ++ identity string after this. ++ ++ (2) destroy(). ++ ++ Mandatory. This should free the memory associated with the key. The ++ asymmetric key will look after freeing the fingerprint and releasing the ++ reference on the subtype module. ++ ++ (3) verify_signature(). ++ ++ Optional. These are the entry points for the key usage operations. ++ Currently there is only the one defined. If not set, the caller will be ++ given -ENOTSUPP. The subtype may do anything it likes to implement an ++ operation, including offloading to hardware. ++ ++ ++========================== ++INSTANTIATION DATA PARSERS ++========================== ++ ++The asymmetric key type doesn't generally want to store or to deal with a raw ++blob of data that holds the key data. It would have to parse it and error ++check it each time it wanted to use it. Further, the contents of the blob may ++have various checks that can be performed on it (eg. self-signatures, validity ++dates) and may contain useful data about the key (identifiers, capabilities). ++ ++Also, the blob may represent a pointer to some hardware containing the key ++rather than the key itself. ++ ++Examples of blob formats for which parsers could be implemented include: ++ ++ - OpenPGP packet stream [RFC 4880]. ++ - X.509 ASN.1 stream. ++ - Pointer to TPM key. ++ - Pointer to UEFI key. ++ ++During key instantiation each parser in the list is tried until one doesn't ++return -EBADMSG. ++ ++The parser definition structure can be found in: ++ ++ #include ++ ++and looks like the following: ++ ++ struct asymmetric_key_parser { ++ struct module *owner; ++ const char *name; ++ ++ int (*parse)(struct key_preparsed_payload *prep); ++ }; ++ ++The owner and name fields should be set to the owning module and the name of ++the parser. ++ ++There is currently only a single operation defined by the parser, and it is ++mandatory: ++ ++ (1) parse(). ++ ++ This is called to preparse the key from the key creation and update paths. ++ In particular, it is called during the key creation _before_ a key is ++ allocated, and as such, is permitted to provide the key's description in ++ the case that the caller declines to do so. ++ ++ The caller passes a pointer to the following struct with all of the fields ++ cleared, except for data, datalen and quotalen [see ++ Documentation/security/keys.txt]. ++ ++ struct key_preparsed_payload { ++ char *description; ++ void *type_data[2]; ++ void *payload; ++ const void *data; ++ size_t datalen; ++ size_t quotalen; ++ }; ++ ++ The instantiation data is in a blob pointed to by data and is datalen in ++ size. The parse() function is not permitted to change these two values at ++ all, and shouldn't change any of the other values _unless_ they are ++ recognise the blob format and will not return -EBADMSG to indicate it is ++ not theirs. ++ ++ If the parser is happy with the blob, it should propose a description for ++ the key and attach it to ->description, ->type_data[0] should be set to ++ point to the subtype to be used, ->payload should be set to point to the ++ initialised data for that subtype, ->type_data[1] should point to a hex ++ fingerprint and quotalen should be updated to indicate how much quota this ++ key should account for. ++ ++ When clearing up, the data attached to ->type_data[1] and ->description ++ will be kfree()'d and the data attached to ->payload will be passed to the ++ subtype's ->destroy() method to be disposed of. A module reference for ++ the subtype pointed to by ->type_data[0] will be put. ++ ++ ++ If the data format is not recognised, -EBADMSG should be returned. If it ++ is recognised, but the key cannot for some reason be set up, some other ++ negative error code should be returned. On success, 0 should be returned. ++ ++ The key's fingerprint string may be partially matched upon. For a ++ public-key algorithm such as RSA and DSA this will likely be a printable ++ hex version of the key's fingerprint. ++ ++Functions are provided to register and unregister parsers: ++ ++ int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); ++ void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); ++ ++Parsers may not have the same name. The names are otherwise only used for ++displaying in debugging messages. +-- +1.7.12.1 + + +From 0e450d75d1067b6f45f1f6b58a530a5d95144373 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:21 +0100 +Subject: [PATCH 05/37] KEYS: Implement asymmetric key type + +Create a key type that can be used to represent an asymmetric key type for use +in appropriate cryptographic operations, such as encryption, decryption, +signature generation and signature verification. + +The key type is "asymmetric" and can provide access to a variety of +cryptographic algorithms. + +Possibly, this would be better as "public_key" - but that has the disadvantage +that "public key" is an overloaded term. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/Kconfig | 1 + + crypto/Makefile | 1 + + crypto/asymmetric_keys/Kconfig | 13 +++ + crypto/asymmetric_keys/Makefile | 7 ++ + crypto/asymmetric_keys/asymmetric_keys.h | 15 +++ + crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++ + include/keys/asymmetric-subtype.h | 55 +++++++++++ + include/keys/asymmetric-type.h | 25 +++++ + 8 files changed, 273 insertions(+) + create mode 100644 crypto/asymmetric_keys/Kconfig + create mode 100644 crypto/asymmetric_keys/Makefile + create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h + create mode 100644 crypto/asymmetric_keys/asymmetric_type.c + create mode 100644 include/keys/asymmetric-subtype.h + create mode 100644 include/keys/asymmetric-type.h + +diff --git a/crypto/Kconfig b/crypto/Kconfig +index a323805..1ca0b24 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER + key cipher algorithms. + + source "drivers/crypto/Kconfig" ++source crypto/asymmetric_keys/Kconfig + + endif # if CRYPTO +diff --git a/crypto/Makefile b/crypto/Makefile +index 30f33d6..ced472e 100644 +--- a/crypto/Makefile ++++ b/crypto/Makefile +@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o + # + obj-$(CONFIG_XOR_BLOCKS) += xor.o + obj-$(CONFIG_ASYNC_CORE) += async_tx/ ++obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +new file mode 100644 +index 0000000..cad29b3 +--- /dev/null ++++ b/crypto/asymmetric_keys/Kconfig +@@ -0,0 +1,13 @@ ++menuconfig ASYMMETRIC_KEY_TYPE ++ tristate "Asymmetric (public-key cryptographic) key type" ++ depends on KEYS ++ help ++ This option provides support for a key type that holds the data for ++ the asymmetric keys used for public key cryptographic operations such ++ as encryption, decryption, signature generation and signature ++ verification. ++ ++if ASYMMETRIC_KEY_TYPE ++ ++ ++endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +new file mode 100644 +index 0000000..b725bcc +--- /dev/null ++++ b/crypto/asymmetric_keys/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for asymmetric cryptographic keys ++# ++ ++obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o ++ ++asymmetric_keys-y := asymmetric_type.o +diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h +new file mode 100644 +index 0000000..515b634 +--- /dev/null ++++ b/crypto/asymmetric_keys/asymmetric_keys.h +@@ -0,0 +1,15 @@ ++/* Internal definitions for asymmetric key type ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++static inline const char *asymmetric_key_id(const struct key *key) ++{ ++ return key->type_data.p[1]; ++} +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +new file mode 100644 +index 0000000..bfb0424 +--- /dev/null ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -0,0 +1,156 @@ ++/* Asymmetric public-key cryptography key type ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++ ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Match asymmetric keys on (part of) their name ++ * We have some shorthand methods for matching keys. We allow: ++ * ++ * "" - request a key by description ++ * "id:" - request a key matching the ID ++ * ":" - request a key of a subtype ++ */ ++static int asymmetric_key_match(const struct key *key, const void *description) ++{ ++ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ const char *spec = description; ++ const char *id, *kid; ++ ptrdiff_t speclen; ++ size_t idlen, kidlen; ++ ++ if (!subtype || !spec || !*spec) ++ return 0; ++ ++ /* See if the full key description matches as is */ ++ if (key->description && strcmp(key->description, description) == 0) ++ return 1; ++ ++ /* All tests from here on break the criterion description into a ++ * specifier, a colon and then an identifier. ++ */ ++ id = strchr(spec, ':'); ++ if (!id) ++ return 0; ++ ++ speclen = id - spec; ++ id++; ++ ++ /* Anything after here requires a partial match on the ID string */ ++ kid = asymmetric_key_id(key); ++ if (!kid) ++ return 0; ++ ++ idlen = strlen(id); ++ kidlen = strlen(kid); ++ if (idlen > kidlen) ++ return 0; ++ ++ kid += kidlen - idlen; ++ if (strcasecmp(id, kid) != 0) ++ return 0; ++ ++ if (speclen == 2 && ++ memcmp(spec, "id", 2) == 0) ++ return 1; ++ ++ if (speclen == subtype->name_len && ++ memcmp(spec, subtype->name, speclen) == 0) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * Describe the asymmetric key ++ */ ++static void asymmetric_key_describe(const struct key *key, struct seq_file *m) ++{ ++ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ const char *kid = asymmetric_key_id(key); ++ size_t n; ++ ++ seq_puts(m, key->description); ++ ++ if (subtype) { ++ seq_puts(m, ": "); ++ subtype->describe(key, m); ++ ++ if (kid) { ++ seq_putc(m, ' '); ++ n = strlen(kid); ++ if (n <= 8) ++ seq_puts(m, kid); ++ else ++ seq_puts(m, kid + n - 8); ++ } ++ ++ seq_puts(m, " ["); ++ /* put something here to indicate the key's capabilities */ ++ seq_putc(m, ']'); ++ } ++} ++ ++/* ++ * Instantiate a asymmetric_key defined key. The key was preparsed, so we just ++ * have to transfer the data here. ++ */ ++static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) ++{ ++ return -EOPNOTSUPP; ++} ++ ++/* ++ * dispose of the data dangling from the corpse of a asymmetric key ++ */ ++static void asymmetric_key_destroy(struct key *key) ++{ ++ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ if (subtype) { ++ subtype->destroy(key->payload.data); ++ module_put(subtype->owner); ++ key->type_data.p[0] = NULL; ++ } ++ kfree(key->type_data.p[1]); ++ key->type_data.p[1] = NULL; ++} ++ ++struct key_type key_type_asymmetric = { ++ .name = "asymmetric", ++ .instantiate = asymmetric_key_instantiate, ++ .match = asymmetric_key_match, ++ .destroy = asymmetric_key_destroy, ++ .describe = asymmetric_key_describe, ++}; ++EXPORT_SYMBOL_GPL(key_type_asymmetric); ++ ++/* ++ * Module stuff ++ */ ++static int __init asymmetric_key_init(void) ++{ ++ return register_key_type(&key_type_asymmetric); ++} ++ ++static void __exit asymmetric_key_cleanup(void) ++{ ++ unregister_key_type(&key_type_asymmetric); ++} ++ ++module_init(asymmetric_key_init); ++module_exit(asymmetric_key_cleanup); +diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h +new file mode 100644 +index 0000000..4b840e8 +--- /dev/null ++++ b/include/keys/asymmetric-subtype.h +@@ -0,0 +1,55 @@ ++/* Asymmetric public-key cryptography key subtype ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H ++#define _KEYS_ASYMMETRIC_SUBTYPE_H ++ ++#include ++#include ++ ++struct public_key_signature; ++ ++/* ++ * Keys of this type declare a subtype that indicates the handlers and ++ * capabilities. ++ */ ++struct asymmetric_key_subtype { ++ struct module *owner; ++ const char *name; ++ unsigned short name_len; /* length of name */ ++ ++ /* Describe a key of this subtype for /proc/keys */ ++ void (*describe)(const struct key *key, struct seq_file *m); ++ ++ /* Destroy a key of this subtype */ ++ void (*destroy)(void *payload); ++ ++ /* Verify the signature on a key of this subtype (optional) */ ++ int (*verify_signature)(const struct key *key, ++ const struct public_key_signature *sig); ++}; ++ ++/** ++ * asymmetric_key_subtype - Get the subtype from an asymmetric key ++ * @key: The key of interest. ++ * ++ * Retrieves and returns the subtype pointer of the asymmetric key from the ++ * type-specific data attached to the key. ++ */ ++static inline ++struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) ++{ ++ return key->type_data.p[0]; ++} ++ ++#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ +diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h +new file mode 100644 +index 0000000..7dd4734 +--- /dev/null ++++ b/include/keys/asymmetric-type.h +@@ -0,0 +1,25 @@ ++/* Asymmetric Public-key cryptography key type interface ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_TYPE_H ++#define _KEYS_ASYMMETRIC_TYPE_H ++ ++#include ++ ++extern struct key_type key_type_asymmetric; ++ ++/* ++ * The payload is at the discretion of the subtype. ++ */ ++ ++#endif /* _KEYS_ASYMMETRIC_TYPE_H */ +-- +1.7.12.1 + + +From 6ec62201b26995d57fbd457469314bfc5653f2a0 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 13 Sep 2012 15:17:32 +0100 +Subject: [PATCH 06/37] KEYS: Asymmetric key pluggable data parsers + +The instantiation data passed to the asymmetric key type are expected to be +formatted in some way, and there are several possible standard ways to format +the data. + +The two obvious standards are OpenPGP keys and X.509 certificates. The latter +is especially useful when dealing with UEFI, and the former might be useful +when dealing with, say, eCryptfs. + +Further, it might be desirable to provide formatted blobs that indicate +hardware is to be accessed to retrieve the keys or that the keys live +unretrievably in a hardware store, but that the keys can be used by means of +the hardware. + +From userspace, the keys can be loaded using the keyctl command, for example, +an X.509 binary certificate: + + keyctl padd asymmetric foo @s +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++- + include/keys/asymmetric-parser.h | 37 ++++++++++ + 2 files changed, 156 insertions(+), 1 deletion(-) + create mode 100644 include/keys/asymmetric-parser.h + +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +index bfb0424..cf80765 100644 +--- a/crypto/asymmetric_keys/asymmetric_type.c ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -11,6 +11,7 @@ + * 2 of the Licence, or (at your option) any later version. + */ + #include ++#include + #include + #include + #include +@@ -18,6 +19,9 @@ + + MODULE_LICENSE("GPL"); + ++static LIST_HEAD(asymmetric_key_parsers); ++static DECLARE_RWSEM(asymmetric_key_parsers_sem); ++ + /* + * Match asymmetric keys on (part of) their name + * We have some shorthand methods for matching keys. We allow: +@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) + } + + /* ++ * Preparse a asymmetric payload to get format the contents appropriately for the ++ * internal payload to cut down on the number of scans of the data performed. ++ * ++ * We also generate a proposed description from the contents of the key that ++ * can be used to name the key if the user doesn't want to provide one. ++ */ ++static int asymmetric_key_preparse(struct key_preparsed_payload *prep) ++{ ++ struct asymmetric_key_parser *parser; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (prep->datalen == 0) ++ return -EINVAL; ++ ++ down_read(&asymmetric_key_parsers_sem); ++ ++ ret = -EBADMSG; ++ list_for_each_entry(parser, &asymmetric_key_parsers, link) { ++ pr_debug("Trying parser '%s'\n", parser->name); ++ ++ ret = parser->parse(prep); ++ if (ret != -EBADMSG) { ++ pr_debug("Parser recognised the format (ret %d)\n", ++ ret); ++ break; ++ } ++ } ++ ++ up_read(&asymmetric_key_parsers_sem); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++ ++/* ++ * Clean up the preparse data ++ */ ++static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) ++{ ++ struct asymmetric_key_subtype *subtype = prep->type_data[0]; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (subtype) { ++ subtype->destroy(prep->payload); ++ module_put(subtype->owner); ++ } ++ kfree(prep->type_data[1]); ++ kfree(prep->description); ++} ++ ++/* + * Instantiate a asymmetric_key defined key. The key was preparsed, so we just + * have to transfer the data here. + */ + static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + { +- return -EOPNOTSUPP; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ ret = key_payload_reserve(key, prep->quotalen); ++ if (ret == 0) { ++ key->type_data.p[0] = prep->type_data[0]; ++ key->type_data.p[1] = prep->type_data[1]; ++ key->payload.data = prep->payload; ++ prep->type_data[0] = NULL; ++ prep->type_data[1] = NULL; ++ prep->payload = NULL; ++ } ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; + } + + /* +@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) + + struct key_type key_type_asymmetric = { + .name = "asymmetric", ++ .preparse = asymmetric_key_preparse, ++ .free_preparse = asymmetric_key_free_preparse, + .instantiate = asymmetric_key_instantiate, + .match = asymmetric_key_match, + .destroy = asymmetric_key_destroy, +@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { + }; + EXPORT_SYMBOL_GPL(key_type_asymmetric); + ++/** ++ * register_asymmetric_key_parser - Register a asymmetric key blob parser ++ * @parser: The parser to register ++ */ ++int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) ++{ ++ struct asymmetric_key_parser *cursor; ++ int ret; ++ ++ down_write(&asymmetric_key_parsers_sem); ++ ++ list_for_each_entry(cursor, &asymmetric_key_parsers, link) { ++ if (strcmp(cursor->name, parser->name) == 0) { ++ pr_err("Asymmetric key parser '%s' already registered\n", ++ parser->name); ++ ret = -EEXIST; ++ goto out; ++ } ++ } ++ ++ list_add_tail(&parser->link, &asymmetric_key_parsers); ++ ++ pr_notice("Asymmetric key parser '%s' registered\n", parser->name); ++ ret = 0; ++ ++out: ++ up_write(&asymmetric_key_parsers_sem); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); ++ ++/** ++ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser ++ * @parser: The parser to unregister ++ */ ++void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) ++{ ++ down_write(&asymmetric_key_parsers_sem); ++ list_del(&parser->link); ++ up_write(&asymmetric_key_parsers_sem); ++ ++ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); ++} ++EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); ++ + /* + * Module stuff + */ +diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h +new file mode 100644 +index 0000000..09b3b48 +--- /dev/null ++++ b/include/keys/asymmetric-parser.h +@@ -0,0 +1,37 @@ ++/* Asymmetric public-key cryptography data parser ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_ASYMMETRIC_PARSER_H ++#define _KEYS_ASYMMETRIC_PARSER_H ++ ++/* ++ * Key data parser. Called during key instantiation. ++ */ ++struct asymmetric_key_parser { ++ struct list_head link; ++ struct module *owner; ++ const char *name; ++ ++ /* Attempt to parse a key from the data blob passed to add_key() or ++ * keyctl_instantiate(). Should also generate a proposed description ++ * that the caller can optionally use for the key. ++ * ++ * Return EBADMSG if not recognised. ++ */ ++ int (*parse)(struct key_preparsed_payload *prep); ++}; ++ ++extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); ++extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); ++ ++#endif /* _KEYS_ASYMMETRIC_PARSER_H */ +-- +1.7.12.1 + + +From 390ad626607322c6e4da8a2e6d2a4094e78b919a Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:24:55 +0100 +Subject: [PATCH 07/37] KEYS: Asymmetric public-key algorithm crypto key + subtype + +Add a subtype for supporting asymmetric public-key encryption algorithms such +as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/Kconfig | 8 +++ + crypto/asymmetric_keys/Makefile | 2 + + crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/public_key.h | 28 ++++++++++ + include/crypto/public_key.h | 104 ++++++++++++++++++++++++++++++++++ + 5 files changed, 250 insertions(+) + create mode 100644 crypto/asymmetric_keys/public_key.c + create mode 100644 crypto/asymmetric_keys/public_key.h + create mode 100644 include/crypto/public_key.h + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index cad29b3..bbfccaa 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE + + if ASYMMETRIC_KEY_TYPE + ++config ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ tristate "Asymmetric public-key crypto algorithm subtype" ++ select MPILIB ++ help ++ This option provides support for asymmetric public key type handling. ++ If signature generation and/or verification are to be used, ++ appropriate hash algorithms (such as SHA-1) must be available. ++ ENOPKG will be reported if the requisite algorithm is unavailable. + + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index b725bcc..5ed46ee 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -5,3 +5,5 @@ + obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + + asymmetric_keys-y := asymmetric_type.o ++ ++obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +new file mode 100644 +index 0000000..cb2e291 +--- /dev/null ++++ b/crypto/asymmetric_keys/public_key.c +@@ -0,0 +1,108 @@ ++/* In-software asymmetric public-key crypto subtype ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PKEY: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include "public_key.h" ++ ++MODULE_LICENSE("GPL"); ++ ++const char *const pkey_algo[PKEY_ALGO__LAST] = { ++ [PKEY_ALGO_DSA] = "DSA", ++ [PKEY_ALGO_RSA] = "RSA", ++}; ++EXPORT_SYMBOL_GPL(pkey_algo); ++ ++const char *const pkey_hash_algo[PKEY_HASH__LAST] = { ++ [PKEY_HASH_MD4] = "md4", ++ [PKEY_HASH_MD5] = "md5", ++ [PKEY_HASH_SHA1] = "sha1", ++ [PKEY_HASH_RIPE_MD_160] = "rmd160", ++ [PKEY_HASH_SHA256] = "sha256", ++ [PKEY_HASH_SHA384] = "sha384", ++ [PKEY_HASH_SHA512] = "sha512", ++ [PKEY_HASH_SHA224] = "sha224", ++}; ++EXPORT_SYMBOL_GPL(pkey_hash_algo); ++ ++const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { ++ [PKEY_ID_PGP] = "PGP", ++ [PKEY_ID_X509] = "X509", ++}; ++EXPORT_SYMBOL_GPL(pkey_id_type); ++ ++/* ++ * Provide a part of a description of the key for /proc/keys. ++ */ ++static void public_key_describe(const struct key *asymmetric_key, ++ struct seq_file *m) ++{ ++ struct public_key *key = asymmetric_key->payload.data; ++ ++ if (key) ++ seq_printf(m, "%s.%s", ++ pkey_id_type[key->id_type], key->algo->name); ++} ++ ++/* ++ * Destroy a public key algorithm key. ++ */ ++void public_key_destroy(void *payload) ++{ ++ struct public_key *key = payload; ++ int i; ++ ++ if (key) { ++ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) ++ mpi_free(key->mpi[i]); ++ kfree(key); ++ } ++} ++EXPORT_SYMBOL_GPL(public_key_destroy); ++ ++/* ++ * Verify a signature using a public key. ++ */ ++static int public_key_verify_signature(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct public_key *pk = key->payload.data; ++ ++ if (!pk->algo->verify_signature) ++ return -ENOTSUPP; ++ ++ if (sig->nr_mpi != pk->algo->n_sig_mpi) { ++ pr_debug("Signature has %u MPI not %u\n", ++ sig->nr_mpi, pk->algo->n_sig_mpi); ++ return -EINVAL; ++ } ++ ++ return pk->algo->verify_signature(pk, sig); ++} ++ ++/* ++ * Public key algorithm asymmetric key subtype ++ */ ++struct asymmetric_key_subtype public_key_subtype = { ++ .owner = THIS_MODULE, ++ .name = "public_key", ++ .describe = public_key_describe, ++ .destroy = public_key_destroy, ++ .verify_signature = public_key_verify_signature, ++}; ++EXPORT_SYMBOL_GPL(public_key_subtype); +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +new file mode 100644 +index 0000000..1f86aad +--- /dev/null ++++ b/crypto/asymmetric_keys/public_key.h +@@ -0,0 +1,28 @@ ++/* Public key algorithm internals ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++ ++extern struct asymmetric_key_subtype public_key_subtype; ++ ++/* ++ * Public key algorithm definition. ++ */ ++struct public_key_algorithm { ++ const char *name; ++ u8 n_pub_mpi; /* Number of MPIs in public key */ ++ u8 n_sec_mpi; /* Number of MPIs in secret key */ ++ u8 n_sig_mpi; /* Number of MPIs in a signature */ ++ int (*verify_signature)(const struct public_key *key, ++ const struct public_key_signature *sig); ++}; +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +new file mode 100644 +index 0000000..4b8b6c1 +--- /dev/null ++++ b/include/crypto/public_key.h +@@ -0,0 +1,104 @@ ++/* Asymmetric public-key algorithm definitions ++ * ++ * See Documentation/crypto/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_PUBLIC_KEY_H ++#define _LINUX_PUBLIC_KEY_H ++ ++#include ++ ++enum pkey_algo { ++ PKEY_ALGO_DSA, ++ PKEY_ALGO_RSA, ++ PKEY_ALGO__LAST ++}; ++ ++extern const char *const pkey_algo[PKEY_ALGO__LAST]; ++ ++enum pkey_hash_algo { ++ PKEY_HASH_MD4, ++ PKEY_HASH_MD5, ++ PKEY_HASH_SHA1, ++ PKEY_HASH_RIPE_MD_160, ++ PKEY_HASH_SHA256, ++ PKEY_HASH_SHA384, ++ PKEY_HASH_SHA512, ++ PKEY_HASH_SHA224, ++ PKEY_HASH__LAST ++}; ++ ++extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; ++ ++enum pkey_id_type { ++ PKEY_ID_PGP, /* OpenPGP generated key ID */ ++ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ ++ PKEY_ID_TYPE__LAST ++}; ++ ++extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; ++ ++/* ++ * Cryptographic data for the public-key subtype of the asymmetric key type. ++ * ++ * Note that this may include private part of the key as well as the public ++ * part. ++ */ ++struct public_key { ++ const struct public_key_algorithm *algo; ++ u8 capabilities; ++#define PKEY_CAN_ENCRYPT 0x01 ++#define PKEY_CAN_DECRYPT 0x02 ++#define PKEY_CAN_SIGN 0x04 ++#define PKEY_CAN_VERIFY 0x08 ++ enum pkey_id_type id_type : 8; ++ union { ++ MPI mpi[5]; ++ struct { ++ MPI p; /* DSA prime */ ++ MPI q; /* DSA group order */ ++ MPI g; /* DSA group generator */ ++ MPI y; /* DSA public-key value = g^x mod p */ ++ MPI x; /* DSA secret exponent (if present) */ ++ } dsa; ++ struct { ++ MPI n; /* RSA public modulus */ ++ MPI e; /* RSA public encryption exponent */ ++ MPI d; /* RSA secret encryption exponent (if present) */ ++ MPI p; /* RSA secret prime (if present) */ ++ MPI q; /* RSA secret prime (if present) */ ++ } rsa; ++ }; ++}; ++ ++extern void public_key_destroy(void *payload); ++ ++/* ++ * Public key cryptography signature data ++ */ ++struct public_key_signature { ++ u8 *digest; ++ u8 digest_size; /* Number of bytes in digest */ ++ u8 nr_mpi; /* Occupancy of mpi[] */ ++ enum pkey_hash_algo pkey_hash_algo : 8; ++ union { ++ MPI mpi[2]; ++ struct { ++ MPI s; /* m^d mod n */ ++ } rsa; ++ struct { ++ MPI r; ++ MPI s; ++ } dsa; ++ }; ++}; ++ ++#endif /* _LINUX_PUBLIC_KEY_H */ +-- +1.7.12.1 + + +From 13d9a26663043faaa37dbe6c2f214ceef5f00b05 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:04 +0100 +Subject: [PATCH 08/37] KEYS: Provide signature verification with an + asymmetric key + +Provide signature verification using an asymmetric-type key to indicate the +public key to be used. + +The API is a single function that can be found in crypto/public_key.h: + + int verify_signature(const struct key *key, + const struct public_key_signature *sig) + +The first argument is the appropriate key to be used and the second argument +is the parsed signature data: + + struct public_key_signature { + u8 *digest; + u16 digest_size; + enum pkey_hash_algo pkey_hash_algo : 8; + union { + MPI mpi[2]; + struct { + MPI s; /* m^d mod n */ + } rsa; + struct { + MPI r; + MPI s; + } dsa; + }; + }; + +This should be filled in prior to calling the function. The hash algorithm +should already have been called and the hash finalised and the output should +be in a buffer pointed to by the 'digest' member. + +Any extra data to be added to the hash by the hash format (eg. PGP) should +have been added by the caller prior to finalising the hash. + +It is assumed that the signature is made up of a number of MPI values. If an +algorithm becomes available for which this is not the case, the above structure +will have to change. + +It is also assumed that it will have been checked that the signature algorithm +matches the key algorithm. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/Makefile | 2 +- + crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++ + include/crypto/public_key.h | 4 ++++ + 3 files changed, 54 insertions(+), 1 deletion(-) + create mode 100644 crypto/asymmetric_keys/signature.c + +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 5ed46ee..8dcdf0c 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -4,6 +4,6 @@ + + obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + +-asymmetric_keys-y := asymmetric_type.o ++asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c +new file mode 100644 +index 0000000..50b3f88 +--- /dev/null ++++ b/crypto/asymmetric_keys/signature.c +@@ -0,0 +1,49 @@ ++/* Signature verification with an asymmetric key ++ * ++ * See Documentation/security/asymmetric-keys.txt ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++ ++/** ++ * verify_signature - Initiate the use of an asymmetric key to verify a signature ++ * @key: The asymmetric key to verify against ++ * @sig: The signature to check ++ * ++ * Returns 0 if successful or else an error. ++ */ ++int verify_signature(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct asymmetric_key_subtype *subtype; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ if (key->type != &key_type_asymmetric) ++ return -EINVAL; ++ subtype = asymmetric_key_subtype(key); ++ if (!subtype || ++ !key->payload.data) ++ return -EINVAL; ++ if (!subtype->verify_signature) ++ return -ENOTSUPP; ++ ++ ret = subtype->verify_signature(key, sig); ++ ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(verify_signature); +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 4b8b6c1..f5b0224 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -101,4 +101,8 @@ struct public_key_signature { + }; + }; + ++struct key; ++extern int verify_signature(const struct key *key, ++ const struct public_key_signature *sig); ++ + #endif /* _LINUX_PUBLIC_KEY_H */ +-- +1.7.12.1 + + +From 3d379de76f21782c611b7d409d7374b82bc90220 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:22 +0100 +Subject: [PATCH 09/37] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA + signature verification + +Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by +RSA signature verification as per RFC3447 section 5.2.2 step 1. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + lib/mpi/Makefile | 1 + + lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 71 insertions(+) + create mode 100644 lib/mpi/mpi-cmp.c + +diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile +index 45ca90a..019a68c 100644 +--- a/lib/mpi/Makefile ++++ b/lib/mpi/Makefile +@@ -14,6 +14,7 @@ mpi-y = \ + generic_mpih-add1.o \ + mpicoder.o \ + mpi-bit.o \ ++ mpi-cmp.o \ + mpih-cmp.o \ + mpih-div.o \ + mpih-mul.o \ +diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c +new file mode 100644 +index 0000000..1871e7b +--- /dev/null ++++ b/lib/mpi/mpi-cmp.c +@@ -0,0 +1,70 @@ ++/* mpi-cmp.c - MPI functions ++ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. ++ * ++ * This file is part of GnuPG. ++ * ++ * GnuPG is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * GnuPG 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ */ ++ ++#include "mpi-internal.h" ++ ++int mpi_cmp_ui(MPI u, unsigned long v) ++{ ++ mpi_limb_t limb = v; ++ ++ mpi_normalize(u); ++ if (!u->nlimbs && !limb) ++ return 0; ++ if (u->sign) ++ return -1; ++ if (u->nlimbs > 1) ++ return 1; ++ ++ if (u->d[0] == limb) ++ return 0; ++ else if (u->d[0] > limb) ++ return 1; ++ else ++ return -1; ++} ++EXPORT_SYMBOL_GPL(mpi_cmp_ui); ++ ++int mpi_cmp(MPI u, MPI v) ++{ ++ mpi_size_t usize, vsize; ++ int cmp; ++ ++ mpi_normalize(u); ++ mpi_normalize(v); ++ usize = u->nlimbs; ++ vsize = v->nlimbs; ++ if (!u->sign && v->sign) ++ return 1; ++ if (u->sign && !v->sign) ++ return -1; ++ if (usize != vsize && !u->sign && !v->sign) ++ return usize - vsize; ++ if (usize != vsize && u->sign && v->sign) ++ return vsize + usize; ++ if (!usize) ++ return 0; ++ cmp = mpihelp_cmp(u->d, v->d, usize); ++ if (!cmp) ++ return 0; ++ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) ++ return 1; ++ return -1; ++} ++EXPORT_SYMBOL_GPL(mpi_cmp); +-- +1.7.12.1 + + +From b872c7db2ce34b5f051d1c38216843a1f796aa86 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:25:40 +0100 +Subject: [PATCH 10/37] RSA: Implement signature verification algorithm + [PKCS#1 / RFC3447] + +Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only +the signature verification algorithm is supported. This uses the asymmetric +public key subtype to hold its key data. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/Kconfig | 7 + + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/public_key.h | 2 + + crypto/asymmetric_keys/rsa.c | 269 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 279 insertions(+) + create mode 100644 crypto/asymmetric_keys/rsa.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index bbfccaa..561759d 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE + appropriate hash algorithms (such as SHA-1) must be available. + ENOPKG will be reported if the requisite algorithm is unavailable. + ++config PUBLIC_KEY_ALGO_RSA ++ tristate "RSA public-key algorithm" ++ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select MPILIB_EXTRA ++ help ++ This option enables support for the RSA algorithm (PKCS#1, RFC3447). ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 8dcdf0c..7c92691 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o + asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o ++obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +index 1f86aad..5e5e356 100644 +--- a/crypto/asymmetric_keys/public_key.h ++++ b/crypto/asymmetric_keys/public_key.h +@@ -26,3 +26,5 @@ struct public_key_algorithm { + int (*verify_signature)(const struct public_key *key, + const struct public_key_signature *sig); + }; ++ ++extern const struct public_key_algorithm RSA_public_key_algorithm; +diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c +new file mode 100644 +index 0000000..9b31ee2 +--- /dev/null ++++ b/crypto/asymmetric_keys/rsa.c +@@ -0,0 +1,269 @@ ++/* RSA asymmetric public-key algorithm [RFC3447] ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "RSA: "fmt ++#include ++#include ++#include ++#include "public_key.h" ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("RSA Public Key Algorithm"); ++ ++#define kenter(FMT, ...) \ ++ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) ++#define kleave(FMT, ...) \ ++ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) ++ ++/* ++ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. ++ */ ++static const u8 RSA_digest_info_MD5[] = { ++ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, ++ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ ++ 0x05, 0x00, 0x04, 0x10 ++}; ++ ++static const u8 RSA_digest_info_SHA1[] = { ++ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, ++ 0x2B, 0x0E, 0x03, 0x02, 0x1A, ++ 0x05, 0x00, 0x04, 0x14 ++}; ++ ++static const u8 RSA_digest_info_RIPE_MD_160[] = { ++ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, ++ 0x2B, 0x24, 0x03, 0x02, 0x01, ++ 0x05, 0x00, 0x04, 0x14 ++}; ++ ++static const u8 RSA_digest_info_SHA224[] = { ++ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, ++ 0x05, 0x00, 0x04, 0x1C ++}; ++ ++static const u8 RSA_digest_info_SHA256[] = { ++ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, ++ 0x05, 0x00, 0x04, 0x20 ++}; ++ ++static const u8 RSA_digest_info_SHA384[] = { ++ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, ++ 0x05, 0x00, 0x04, 0x30 ++}; ++ ++static const u8 RSA_digest_info_SHA512[] = { ++ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, ++ 0x05, 0x00, 0x04, 0x40 ++}; ++ ++static const struct { ++ const u8 *data; ++ size_t size; ++} RSA_ASN1_templates[PKEY_HASH__LAST] = { ++#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } ++ [PKEY_HASH_MD5] = _(MD5), ++ [PKEY_HASH_SHA1] = _(SHA1), ++ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), ++ [PKEY_HASH_SHA256] = _(SHA256), ++ [PKEY_HASH_SHA384] = _(SHA384), ++ [PKEY_HASH_SHA512] = _(SHA512), ++ [PKEY_HASH_SHA224] = _(SHA224), ++#undef _ ++}; ++ ++/* ++ * RSAVP1() function [RFC3447 sec 5.2.2] ++ */ ++static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) ++{ ++ MPI m; ++ int ret; ++ ++ /* (1) Validate 0 <= s < n */ ++ if (mpi_cmp_ui(s, 0) < 0) { ++ kleave(" = -EBADMSG [s < 0]"); ++ return -EBADMSG; ++ } ++ if (mpi_cmp(s, key->rsa.n) >= 0) { ++ kleave(" = -EBADMSG [s >= n]"); ++ return -EBADMSG; ++ } ++ ++ m = mpi_alloc(0); ++ if (!m) ++ return -ENOMEM; ++ ++ /* (2) m = s^e mod n */ ++ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); ++ if (ret < 0) { ++ mpi_free(m); ++ return ret; ++ } ++ ++ *_m = m; ++ return 0; ++} ++ ++/* ++ * Integer to Octet String conversion [RFC3447 sec 4.1] ++ */ ++static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) ++{ ++ unsigned X_size, x_size; ++ int X_sign; ++ u8 *X; ++ ++ /* Make sure the string is the right length. The number should begin ++ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero ++ * bits not being reported by MPI. ++ */ ++ x_size = mpi_get_nbits(x); ++ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); ++ if (x_size != xLen * 8 - 15) ++ return -ERANGE; ++ ++ X = mpi_get_buffer(x, &X_size, &X_sign); ++ if (!X) ++ return -ENOMEM; ++ if (X_sign < 0) { ++ kfree(X); ++ return -EBADMSG; ++ } ++ if (X_size != xLen - 1) { ++ kfree(X); ++ return -EBADMSG; ++ } ++ ++ *_X = X; ++ return 0; ++} ++ ++/* ++ * Perform the RSA signature verification. ++ * @H: Value of hash of data and metadata ++ * @EM: The computed signature value ++ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) ++ * @hash_size: The size of H ++ * @asn1_template: The DigestInfo ASN.1 template ++ * @asn1_size: Size of asm1_template[] ++ */ ++static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, ++ const u8 *asn1_template, size_t asn1_size) ++{ ++ unsigned PS_end, T_offset, i; ++ ++ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); ++ ++ if (k < 2 + 1 + asn1_size + hash_size) ++ return -EBADMSG; ++ ++ /* Decode the EMSA-PKCS1-v1_5 */ ++ if (EM[1] != 0x01) { ++ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); ++ return -EBADMSG; ++ } ++ ++ T_offset = k - (asn1_size + hash_size); ++ PS_end = T_offset - 1; ++ if (EM[PS_end] != 0x00) { ++ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); ++ return -EBADMSG; ++ } ++ ++ for (i = 2; i < PS_end; i++) { ++ if (EM[i] != 0xff) { ++ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); ++ return -EBADMSG; ++ } ++ } ++ ++ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { ++ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); ++ return -EBADMSG; ++ } ++ ++ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { ++ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); ++ return -EKEYREJECTED; ++ } ++ ++ kleave(" = 0"); ++ return 0; ++} ++ ++/* ++ * Perform the verification step [RFC3447 sec 8.2.2]. ++ */ ++static int RSA_verify_signature(const struct public_key *key, ++ const struct public_key_signature *sig) ++{ ++ size_t tsize; ++ int ret; ++ ++ /* Variables as per RFC3447 sec 8.2.2 */ ++ const u8 *H = sig->digest; ++ u8 *EM = NULL; ++ MPI m = NULL; ++ size_t k; ++ ++ kenter(""); ++ ++ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) ++ return -ENOTSUPP; ++ ++ /* (1) Check the signature size against the public key modulus size */ ++ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; ++ ++ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; ++ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); ++ if (tsize != k) { ++ ret = -EBADMSG; ++ goto error; ++ } ++ ++ /* (2b) Apply the RSAVP1 verification primitive to the public key */ ++ ret = RSAVP1(key, sig->rsa.s, &m); ++ if (ret < 0) ++ goto error; ++ ++ /* (2c) Convert the message representative (m) to an encoded message ++ * (EM) of length k octets. ++ * ++ * NOTE! The leading zero byte is suppressed by MPI, so we pass a ++ * pointer to the _preceding_ byte to RSA_verify()! ++ */ ++ ret = RSA_I2OSP(m, k, &EM); ++ if (ret < 0) ++ goto error; ++ ++ ret = RSA_verify(H, EM - 1, k, sig->digest_size, ++ RSA_ASN1_templates[sig->pkey_hash_algo].data, ++ RSA_ASN1_templates[sig->pkey_hash_algo].size); ++ ++error: ++ kfree(EM); ++ mpi_free(m); ++ kleave(" = %d", ret); ++ return ret; ++} ++ ++const struct public_key_algorithm RSA_public_key_algorithm = { ++ .name = "RSA", ++ .n_pub_mpi = 2, ++ .n_sec_mpi = 3, ++ .n_sig_mpi = 1, ++ .verify_signature = RSA_verify_signature, ++}; ++EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); +-- +1.7.12.1 + + +From 362af238a35e095094b3f5a228cf2c0f60c10cd9 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:28:05 +0100 +Subject: [PATCH 11/37] RSA: Fix signature verification for shorter signatures + +gpg can produce a signature file where length of signature is less than the +modulus size because the amount of space an MPI takes up is kept as low as +possible by discarding leading zeros. This regularly happens for several +modules during the build. + +Fix it by relaxing check in RSA verification code. + +Thanks to Tomas Mraz and Miloslav Trmac for help. + +Signed-off-by: Milan Broz +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/rsa.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c +index 9b31ee2..4a6a069 100644 +--- a/crypto/asymmetric_keys/rsa.c ++++ b/crypto/asymmetric_keys/rsa.c +@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key, + return -ENOTSUPP; + + /* (1) Check the signature size against the public key modulus size */ +- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; ++ k = mpi_get_nbits(key->rsa.n); ++ tsize = mpi_get_nbits(sig->rsa.s); + +- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; ++ /* According to RFC 4880 sec 3.2, length of MPI is computed starting ++ * from most significant bit. So the RFC 3447 sec 8.2.2 size check ++ * must be relaxed to conform with shorter signatures - so we fail here ++ * only if signature length is longer than modulus size. ++ */ + pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); +- if (tsize != k) { ++ if (k < tsize) { + ret = -EBADMSG; + goto error; + } + ++ /* Round up and convert to octets */ ++ k = (k + 7) / 8; ++ + /* (2b) Apply the RSAVP1 verification primitive to the public key */ + ret = RSAVP1(key, sig->rsa.s, &m); + if (ret < 0) +-- +1.7.12.1 + + +From 81451f08c7db892e06144cf3bc89746e68269624 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:30:46 +0100 +Subject: [PATCH 12/37] X.509: Implement simple static OID registry + +Implement a simple static OID registry that allows the mapping of an encoded +OID to an enum value for ease of use. + +The OID registry index enum appears in the: + + linux/oid_registry.h + +header file. A script generates the registry from lines in the header file +that look like: + + OID_foo,/*1.2.3.4*/ + +The actual OID is taken to be represented by the numbers with interpolated +dots in the comment. + +All other lines in the header are ignored. + +The registry is queries by calling: + + OID look_up_oid(const void *data, size_t datasize); + +This returns a number from the registry enum representing the OID if found or +OID__NR if not. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + include/linux/oid_registry.h | 90 +++++++++++++++++++ + lib/.gitignore | 2 +- + lib/Kconfig | 5 ++ + lib/Makefile | 16 ++++ + lib/build_OID_registry | 209 +++++++++++++++++++++++++++++++++++++++++++ + lib/oid_registry.c | 89 ++++++++++++++++++ + 6 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 include/linux/oid_registry.h + create mode 100755 lib/build_OID_registry + create mode 100644 lib/oid_registry.c + +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +new file mode 100644 +index 0000000..5928546 +--- /dev/null ++++ b/include/linux/oid_registry.h +@@ -0,0 +1,90 @@ ++/* ASN.1 Object identifier (OID) registry ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_OID_REGISTRY_H ++#define _LINUX_OID_REGISTRY_H ++ ++#include ++ ++/* ++ * OIDs are turned into these values if possible, or OID__NR if not held here. ++ * ++ * NOTE! Do not mess with the format of each line as this is read by ++ * build_OID_registry.pl to generate the data for look_up_OID(). ++ */ ++enum OID { ++ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ ++ OID_id_dsa, /* 1.2.840.10040.4.1 */ ++ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ ++ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ ++ ++ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ ++ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ ++ OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ ++ OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ ++ OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ ++ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ ++ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ ++ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ ++ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ ++ OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ ++ /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ ++ OID_data, /* 1.2.840.113549.1.7.1 */ ++ OID_signed_data, /* 1.2.840.113549.1.7.2 */ ++ /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ ++ OID_email_address, /* 1.2.840.113549.1.9.1 */ ++ OID_content_type, /* 1.2.840.113549.1.9.3 */ ++ OID_messageDigest, /* 1.2.840.113549.1.9.4 */ ++ OID_signingTime, /* 1.2.840.113549.1.9.5 */ ++ OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ ++ OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ ++ ++ /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ ++ OID_md2, /* 1.2.840.113549.2.2 */ ++ OID_md4, /* 1.2.840.113549.2.4 */ ++ OID_md5, /* 1.2.840.113549.2.5 */ ++ ++ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ ++ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ ++ OID_sha1, /* 1.3.14.3.2.26 */ ++ ++ /* Distinguished Name attribute IDs [RFC 2256] */ ++ OID_commonName, /* 2.5.4.3 */ ++ OID_surname, /* 2.5.4.4 */ ++ OID_countryName, /* 2.5.4.6 */ ++ OID_locality, /* 2.5.4.7 */ ++ OID_stateOrProvinceName, /* 2.5.4.8 */ ++ OID_organizationName, /* 2.5.4.10 */ ++ OID_organizationUnitName, /* 2.5.4.11 */ ++ OID_title, /* 2.5.4.12 */ ++ OID_description, /* 2.5.4.13 */ ++ OID_name, /* 2.5.4.41 */ ++ OID_givenName, /* 2.5.4.42 */ ++ OID_initials, /* 2.5.4.43 */ ++ OID_generationalQualifier, /* 2.5.4.44 */ ++ ++ /* Certificate extension IDs */ ++ OID_subjectKeyIdentifier, /* 2.5.29.14 */ ++ OID_keyUsage, /* 2.5.29.15 */ ++ OID_subjectAltName, /* 2.5.29.17 */ ++ OID_issuerAltName, /* 2.5.29.18 */ ++ OID_basicConstraints, /* 2.5.29.19 */ ++ OID_crlDistributionPoints, /* 2.5.29.31 */ ++ OID_certPolicies, /* 2.5.29.32 */ ++ OID_authorityKeyIdentifier, /* 2.5.29.35 */ ++ OID_extKeyUsage, /* 2.5.29.37 */ ++ ++ OID__NR ++}; ++ ++extern enum OID look_up_OID(const void *data, size_t datasize); ++ ++#endif /* _LINUX_OID_REGISTRY_H */ +diff --git a/lib/.gitignore b/lib/.gitignore +index 3bef1ea..09aae85 100644 +--- a/lib/.gitignore ++++ b/lib/.gitignore +@@ -3,4 +3,4 @@ + # + gen_crc32table + crc32table.h +- ++oid_registry_data.c +diff --git a/lib/Kconfig b/lib/Kconfig +index bb94c1b..4b31a46 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -396,4 +396,9 @@ config SIGNATURE + config LIBFDT + bool + ++config OID_REGISTRY ++ tristate ++ help ++ Enable fast lookup object identifier registry. ++ + endmenu +diff --git a/lib/Makefile b/lib/Makefile +index 42d283e..b042896 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN $@ + + $(obj)/crc32table.h: $(obj)/gen_crc32table + $(call cmd,crc32) ++ ++# ++# Build a fast OID lookip registry from include/linux/oid_registry.h ++# ++obj-$(CONFIG_OID_REGISTRY) += oid_registry.o ++ ++$(obj)/oid_registry.c: $(obj)/oid_registry_data.c ++ ++$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ ++ $(src)/build_OID_registry ++ $(call cmd,build_OID_registry) ++ ++quiet_cmd_build_OID_registry = GEN $@ ++ cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ ++ ++clean-files += oid_registry_data.c +diff --git a/lib/build_OID_registry b/lib/build_OID_registry +new file mode 100755 +index 0000000..dfbdaab +--- /dev/null ++++ b/lib/build_OID_registry +@@ -0,0 +1,209 @@ ++#!/usr/bin/perl -w ++# ++# Build a static ASN.1 Object Identified (OID) registry ++# ++# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++# Written by David Howells (dhowells@redhat.com) ++# ++# This program is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public Licence ++# as published by the Free Software Foundation; either version ++# 2 of the Licence, or (at your option) any later version. ++# ++ ++use strict; ++ ++my @names = (); ++my @oids = (); ++ ++if ($#ARGV != 1) { ++ print STDERR "Format: ", $0, " \n"; ++ exit(2); ++} ++ ++# ++# Open the file to read from ++# ++open IN_FILE, "<$ARGV[0]" || die; ++while () { ++ chomp; ++ if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { ++ push @names, $1; ++ push @oids, $2; ++ } ++} ++close IN_FILE || die; ++ ++# ++# Open the files to write into ++# ++open C_FILE, ">$ARGV[1]" or die; ++print C_FILE "/*\n"; ++print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; ++print C_FILE " */\n"; ++ ++# ++# Split the data up into separate lists and also determine the lengths of the ++# encoded data arrays. ++# ++my @indices = (); ++my @lengths = (); ++my $total_length = 0; ++ ++print "Compiling ", $#names + 1, " OIDs\n"; ++ ++for (my $i = 0; $i <= $#names; $i++) { ++ my $name = $names[$i]; ++ my $oid = $oids[$i]; ++ ++ my @components = split(/[.]/, $oid); ++ ++ # Determine the encoded length of this OID ++ my $size = $#components; ++ for (my $loop = 2; $loop <= $#components; $loop++) { ++ my $c = $components[$loop]; ++ ++ # We will base128 encode the number ++ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); ++ $tmp = int($tmp / 7); ++ $size += $tmp; ++ } ++ push @lengths, $size; ++ push @indices, $total_length; ++ $total_length += $size; ++} ++ ++# ++# Emit the look-up-by-OID index table ++# ++print C_FILE "\n"; ++if ($total_length <= 255) { ++ print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; ++} else { ++ print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; ++} ++for (my $i = 0; $i <= $#names; $i++) { ++ print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" ++} ++print C_FILE "\t[OID__NR] = ", $total_length, "\n"; ++print C_FILE "};\n"; ++ ++# ++# Encode the OIDs ++# ++my @encoded_oids = (); ++ ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = (); ++ ++ my @components = split(/[.]/, $oids[$i]); ++ ++ push @octets, $components[0] * 40 + $components[1]; ++ ++ for (my $loop = 2; $loop <= $#components; $loop++) { ++ my $c = $components[$loop]; ++ ++ # Base128 encode the number ++ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); ++ $tmp = int($tmp / 7); ++ ++ for (; $tmp > 0; $tmp--) { ++ push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; ++ } ++ push @octets, $c & 0x7f; ++ } ++ ++ push @encoded_oids, \@octets; ++} ++ ++# ++# Create a hash value for each OID ++# ++my @hash_values = (); ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$i]}; ++ ++ my $hash = $#octets; ++ foreach (@octets) { ++ $hash += $_ * 33; ++ } ++ ++ $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); ++ ++ push @hash_values, $hash & 0xff; ++} ++ ++# ++# Emit the OID data ++# ++print C_FILE "\n"; ++print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$i]}; ++ print C_FILE "\t"; ++ print C_FILE $_, ", " foreach (@octets); ++ print C_FILE "\t// ", $names[$i]; ++ print C_FILE "\n"; ++} ++print C_FILE "};\n"; ++ ++# ++# Build the search index table (ordered by length then hash then content) ++# ++my @index_table = ( 0 .. $#names ); ++ ++@index_table = sort { ++ my @octets_a = @{$encoded_oids[$a]}; ++ my @octets_b = @{$encoded_oids[$b]}; ++ ++ return $hash_values[$a] <=> $hash_values[$b] ++ if ($hash_values[$a] != $hash_values[$b]); ++ return $#octets_a <=> $#octets_b ++ if ($#octets_a != $#octets_b); ++ for (my $i = $#octets_a; $i >= 0; $i--) { ++ return $octets_a[$i] <=> $octets_b[$i] ++ if ($octets_a[$i] != $octets_b[$i]); ++ } ++ return 0; ++ ++} @index_table; ++ ++# ++# Emit the search index and hash value table ++# ++print C_FILE "\n"; ++print C_FILE "static const struct {\n"; ++print C_FILE "\tunsigned char hash;\n"; ++if ($#names <= 255) { ++ print C_FILE "\tenum OID oid : 8;\n"; ++} else { ++ print C_FILE "\tenum OID oid : 16;\n"; ++} ++print C_FILE "} oid_search_table[OID__NR] = {\n"; ++for (my $i = 0; $i <= $#names; $i++) { ++ my @octets = @{$encoded_oids[$index_table[$i]]}; ++ printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", ++ $i, ++ $hash_values[$index_table[$i]], ++ $names[$index_table[$i]]); ++ printf C_FILE "%02x", $_ foreach (@octets); ++ print C_FILE "\n"; ++} ++print C_FILE "};\n"; ++ ++# ++# Emit the OID debugging name table ++# ++#print C_FILE "\n"; ++#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; ++# ++#for (my $i = 0; $i <= $#names; $i++) { ++# print C_FILE "\t\"", $names[$i], "\",\n" ++#} ++#print C_FILE "\t\"Unknown-OID\"\n"; ++#print C_FILE "};\n"; ++ ++# ++# Polish off ++# ++close C_FILE or die; +diff --git a/lib/oid_registry.c b/lib/oid_registry.c +new file mode 100644 +index 0000000..33cfd17 +--- /dev/null ++++ b/lib/oid_registry.c +@@ -0,0 +1,89 @@ ++/* ASN.1 Object identifier (OID) registry ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include "oid_registry_data.c" ++ ++/** ++ * look_up_OID - Find an OID registration for the specified data ++ * @data: Binary representation of the OID ++ * @datasize: Size of the binary representation ++ */ ++enum OID look_up_OID(const void *data, size_t datasize) ++{ ++ const unsigned char *octets = data; ++ enum OID oid; ++ unsigned char xhash; ++ unsigned i, j, k, hash; ++ size_t len; ++ ++ /* Hash the OID data */ ++ hash = datasize - 1; ++ ++ for (i = 0; i < datasize; i++) ++ hash += octets[i] * 33; ++ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; ++ hash &= 0xff; ++ ++ /* Binary search the OID registry. OIDs are stored in ascending order ++ * of hash value then ascending order of size and then in ascending ++ * order of reverse value. ++ */ ++ i = 0; ++ k = OID__NR; ++ while (i < k) { ++ j = (i + k) / 2; ++ ++ xhash = oid_search_table[j].hash; ++ if (xhash > hash) { ++ k = j; ++ continue; ++ } ++ if (xhash < hash) { ++ i = j + 1; ++ continue; ++ } ++ ++ oid = oid_search_table[j].oid; ++ len = oid_index[oid + 1] - oid_index[oid]; ++ if (len > datasize) { ++ k = j; ++ continue; ++ } ++ if (len < datasize) { ++ i = j + 1; ++ continue; ++ } ++ ++ /* Variation is most likely to be at the tail end of the ++ * OID, so do the comparison in reverse. ++ */ ++ while (len > 0) { ++ unsigned char a = oid_data[oid_index[oid] + --len]; ++ unsigned char b = octets[len]; ++ if (a > b) { ++ k = j; ++ goto next; ++ } ++ if (a < b) { ++ i = j + 1; ++ goto next; ++ } ++ } ++ return oid; ++ next: ++ ; ++ } ++ ++ return OID__NR; ++} ++EXPORT_SYMBOL_GPL(look_up_OID); +-- +1.7.12.1 + + +From 3e1b30d7c67fd5419d4f6eb5d10b557dda4bc4fd Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:30:51 +0100 +Subject: [PATCH 13/37] X.509: Add utility functions to render OIDs as strings + +Add a pair of utility functions to render OIDs as strings. The first takes an +encoded OID and turns it into a "a.b.c.d" form string: + + int sprint_oid(const void *data, size_t datasize, + char *buffer, size_t bufsize); + +The second takes an OID enum index and calls the first on the data held +therein: + + int sprint_OID(enum OID oid, char *buffer, size_t bufsize); + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + include/linux/oid_registry.h | 2 ++ + lib/oid_registry.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 83 insertions(+) + +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +index 5928546..6926db7 100644 +--- a/include/linux/oid_registry.h ++++ b/include/linux/oid_registry.h +@@ -86,5 +86,7 @@ enum OID { + }; + + extern enum OID look_up_OID(const void *data, size_t datasize); ++extern int sprint_oid(const void *, size_t, char *, size_t); ++extern int sprint_OID(enum OID, char *, size_t); + + #endif /* _LINUX_OID_REGISTRY_H */ +diff --git a/lib/oid_registry.c b/lib/oid_registry.c +index 33cfd17..d8de11f 100644 +--- a/lib/oid_registry.c ++++ b/lib/oid_registry.c +@@ -11,6 +11,9 @@ + + #include + #include ++#include ++#include ++#include + #include "oid_registry_data.c" + + /** +@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize) + return OID__NR; + } + EXPORT_SYMBOL_GPL(look_up_OID); ++ ++/* ++ * sprint_OID - Print an Object Identifier into a buffer ++ * @data: The encoded OID to print ++ * @datasize: The size of the encoded OID ++ * @buffer: The buffer to render into ++ * @bufsize: The size of the buffer ++ * ++ * The OID is rendered into the buffer in "a.b.c.d" format and the number of ++ * bytes is returned. -EBADMSG is returned if the data could not be intepreted ++ * and -ENOBUFS if the buffer was too small. ++ */ ++int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) ++{ ++ const unsigned char *v = data, *end = v + datasize; ++ unsigned long num; ++ unsigned char n; ++ size_t ret; ++ int count; ++ ++ if (v >= end) ++ return -EBADMSG; ++ ++ n = *v++; ++ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); ++ buffer += count; ++ bufsize -= count; ++ if (bufsize == 0) ++ return -ENOBUFS; ++ ++ while (v < end) { ++ num = 0; ++ n = *v++; ++ if (!(n & 0x80)) { ++ num = n; ++ } else { ++ num = n & 0x7f; ++ do { ++ if (v >= end) ++ return -EBADMSG; ++ n = *v++; ++ num <<= 7; ++ num |= n & 0x7f; ++ } while (n & 0x80); ++ } ++ ret += count = snprintf(buffer, bufsize, ".%lu", num); ++ buffer += count; ++ bufsize -= count; ++ if (bufsize == 0) ++ return -ENOBUFS; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sprint_oid); ++ ++/** ++ * sprint_OID - Print an Object Identifier into a buffer ++ * @oid: The OID to print ++ * @buffer: The buffer to render into ++ * @bufsize: The size of the buffer ++ * ++ * The OID is rendered into the buffer in "a.b.c.d" format and the number of ++ * bytes is returned. ++ */ ++int sprint_OID(enum OID oid, char *buffer, size_t bufsize) ++{ ++ int ret; ++ ++ BUG_ON(oid >= OID__NR); ++ ++ ret = sprint_oid(oid_data + oid_index[oid], ++ oid_index[oid + 1] - oid_index[oid], ++ buffer, bufsize); ++ BUG_ON(ret == -EBADMSG); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sprint_OID); +-- +1.7.12.1 + + +From 978cd19071f71ae6a0e622bb2521f88ea633a326 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 21 Sep 2012 23:31:13 +0100 +Subject: [PATCH 14/37] X.509: Add simple ASN.1 grammar compiler + +Add a simple ASN.1 grammar compiler. This produces a bytecode output that can +be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it +is trying to parse. + +Action functions can be specified in the grammar by interpolating: + + ({ foo }) + +after a type, for example: + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING ({ do_key_data }) + } + +The decoder is expected to call these after matching this type and parsing the +contents if it is a constructed type. + +The grammar compiler does not currently support the SET type (though it does +support SET OF) as I can't see a good way of tracking which members have been +encountered yet without using up extra stack space. + +Currently, the grammar compiler will fail if more than 256 bytes of bytecode +would be produced or more than 256 actions have been specified as it uses +8-bit jump values and action indices to keep space usage down. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + include/linux/asn1.h | 67 ++ + include/linux/asn1_ber_bytecode.h | 87 +++ + init/Kconfig | 8 + + scripts/.gitignore | 1 + + scripts/Makefile | 2 + + scripts/Makefile.build | 11 + + scripts/asn1_compiler.c | 1545 +++++++++++++++++++++++++++++++++++++ + 7 files changed, 1721 insertions(+) + create mode 100644 include/linux/asn1.h + create mode 100644 include/linux/asn1_ber_bytecode.h + create mode 100644 scripts/asn1_compiler.c + +diff --git a/include/linux/asn1.h b/include/linux/asn1.h +new file mode 100644 +index 0000000..5c3f4e4 +--- /dev/null ++++ b/include/linux/asn1.h +@@ -0,0 +1,67 @@ ++/* ASN.1 BER/DER/CER encoding definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_H ++#define _LINUX_ASN1_H ++ ++/* Class */ ++enum asn1_class { ++ ASN1_UNIV = 0, /* Universal */ ++ ASN1_APPL = 1, /* Application */ ++ ASN1_CONT = 2, /* Context */ ++ ASN1_PRIV = 3 /* Private */ ++}; ++#define ASN1_CLASS_BITS 0xc0 ++ ++ ++enum asn1_method { ++ ASN1_PRIM = 0, /* Primitive */ ++ ASN1_CONS = 1 /* Constructed */ ++}; ++#define ASN1_CONS_BIT 0x20 ++ ++/* Tag */ ++enum asn1_tag { ++ ASN1_EOC = 0, /* End Of Contents or N/A */ ++ ASN1_BOOL = 1, /* Boolean */ ++ ASN1_INT = 2, /* Integer */ ++ ASN1_BTS = 3, /* Bit String */ ++ ASN1_OTS = 4, /* Octet String */ ++ ASN1_NULL = 5, /* Null */ ++ ASN1_OID = 6, /* Object Identifier */ ++ ASN1_ODE = 7, /* Object Description */ ++ ASN1_EXT = 8, /* External */ ++ ASN1_REAL = 9, /* Real float */ ++ ASN1_ENUM = 10, /* Enumerated */ ++ ASN1_EPDV = 11, /* Embedded PDV */ ++ ASN1_UTF8STR = 12, /* UTF8 String */ ++ ASN1_RELOID = 13, /* Relative OID */ ++ /* 14 - Reserved */ ++ /* 15 - Reserved */ ++ ASN1_SEQ = 16, /* Sequence and Sequence of */ ++ ASN1_SET = 17, /* Set and Set of */ ++ ASN1_NUMSTR = 18, /* Numerical String */ ++ ASN1_PRNSTR = 19, /* Printable String */ ++ ASN1_TEXSTR = 20, /* T61 String / Teletext String */ ++ ASN1_VIDSTR = 21, /* Videotex String */ ++ ASN1_IA5STR = 22, /* IA5 String */ ++ ASN1_UNITIM = 23, /* Universal Time */ ++ ASN1_GENTIM = 24, /* General Time */ ++ ASN1_GRASTR = 25, /* Graphic String */ ++ ASN1_VISSTR = 26, /* Visible String */ ++ ASN1_GENSTR = 27, /* General String */ ++ ASN1_UNISTR = 28, /* Universal String */ ++ ASN1_CHRSTR = 29, /* Character String */ ++ ASN1_BMPSTR = 30, /* BMP String */ ++ ASN1_LONG_TAG = 31 /* Long form tag */ ++}; ++ ++#endif /* _LINUX_ASN1_H */ +diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h +new file mode 100644 +index 0000000..945d44a +--- /dev/null ++++ b/include/linux/asn1_ber_bytecode.h +@@ -0,0 +1,87 @@ ++/* ASN.1 BER/DER/CER parsing state machine internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_BER_BYTECODE_H ++#define _LINUX_ASN1_BER_BYTECODE_H ++ ++#ifdef __KERNEL__ ++#include ++#endif ++#include ++ ++typedef int (*asn1_action_t)(void *context, ++ size_t hdrlen, /* In case of ANY type */ ++ unsigned char tag, /* In case of ANY type */ ++ const void *value, size_t vlen); ++ ++struct asn1_decoder { ++ const unsigned char *machine; ++ size_t machlen; ++ const asn1_action_t *actions; ++}; ++ ++enum asn1_opcode { ++ /* The tag-matching ops come first and the odd-numbered slots ++ * are for OR_SKIP ops. ++ */ ++#define ASN1_OP_MATCH__SKIP 0x01 ++#define ASN1_OP_MATCH__ACT 0x02 ++#define ASN1_OP_MATCH__JUMP 0x04 ++#define ASN1_OP_MATCH__ANY 0x08 ++#define ASN1_OP_MATCH__COND 0x10 ++ ++ ASN1_OP_MATCH = 0x00, ++ ASN1_OP_MATCH_OR_SKIP = 0x01, ++ ASN1_OP_MATCH_ACT = 0x02, ++ ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, ++ ASN1_OP_MATCH_JUMP = 0x04, ++ ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, ++ ASN1_OP_MATCH_ANY = 0x08, ++ ASN1_OP_MATCH_ANY_ACT = 0x0a, ++ /* Everything before here matches unconditionally */ ++ ++ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, ++ ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, ++ ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, ++ ASN1_OP_COND_MATCH_ANY = 0x18, ++ ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, ++ ++ /* Everything before here will want a tag from the data */ ++#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT ++ ++ /* These are here to help fill up space */ ++ ASN1_OP_COND_FAIL = 0x1b, ++ ASN1_OP_COMPLETE = 0x1c, ++ ASN1_OP_ACT = 0x1d, ++ ASN1_OP_RETURN = 0x1e, ++ ++ /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ ++ ASN1_OP_END_SEQ = 0x20, ++ ASN1_OP_END_SET = 0x21, ++ ASN1_OP_END_SEQ_OF = 0x22, ++ ASN1_OP_END_SET_OF = 0x23, ++ ASN1_OP_END_SEQ_ACT = 0x24, ++ ASN1_OP_END_SET_ACT = 0x25, ++ ASN1_OP_END_SEQ_OF_ACT = 0x26, ++ ASN1_OP_END_SET_OF_ACT = 0x27, ++#define ASN1_OP_END__SET 0x01 ++#define ASN1_OP_END__OF 0x02 ++#define ASN1_OP_END__ACT 0x04 ++ ++ ASN1_OP__NR ++}; ++ ++#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) ++#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) ++#define _jump_target(N) (N) ++#define _action(N) (N) ++ ++#endif /* _LINUX_ASN1_BER_BYTECODE_H */ +diff --git a/init/Kconfig b/init/Kconfig +index 7452e19..fa8ccad 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1626,4 +1626,12 @@ config PADATA + depends on SMP + bool + ++config ASN1 ++ tristate ++ help ++ Build a simple ASN.1 grammar compiler that produces a bytecode output ++ that can be interpreted by the ASN.1 stream decoder and used to ++ inform it as to what tags are to be expected in a stream and what ++ functions to call on what tags. ++ + source "kernel/Kconfig.locks" +diff --git a/scripts/.gitignore b/scripts/.gitignore +index 65f362d..fb070fa 100644 +--- a/scripts/.gitignore ++++ b/scripts/.gitignore +@@ -10,3 +10,4 @@ ihex2fw + recordmcount + docproc + sortextable ++asn1_compiler +diff --git a/scripts/Makefile b/scripts/Makefile +index a55b006..01e7adb 100644 +--- a/scripts/Makefile ++++ b/scripts/Makefile +@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash + hostprogs-$(CONFIG_IKCONFIG) += bin2c + hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount + hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable ++hostprogs-$(CONFIG_ASN1) += asn1_compiler + + HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include ++HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include + + always := $(hostprogs-y) $(hostprogs-m) + +diff --git a/scripts/Makefile.build b/scripts/Makefile.build +index ff1720d..0e801c3 100644 +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ + $(obj)/%.lds: $(src)/%.lds.S FORCE + $(call if_changed_dep,cpp_lds_S) + ++# ASN.1 grammar ++# --------------------------------------------------------------------------- ++quiet_cmd_asn1_compiler = ASN.1 $@ ++ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ ++ $(subst .h,.c,$@) $(subst .c,.h,$@) ++ ++.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h ++ ++$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler ++ $(call cmd,asn1_compiler) ++ + # Build the compiled-in targets + # --------------------------------------------------------------------------- + +diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c +new file mode 100644 +index 0000000..db0e5cd +--- /dev/null ++++ b/scripts/asn1_compiler.c +@@ -0,0 +1,1545 @@ ++/* Simplified ASN.1 notation parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum token_type { ++ DIRECTIVE_ABSENT, ++ DIRECTIVE_ALL, ++ DIRECTIVE_ANY, ++ DIRECTIVE_APPLICATION, ++ DIRECTIVE_AUTOMATIC, ++ DIRECTIVE_BEGIN, ++ DIRECTIVE_BIT, ++ DIRECTIVE_BMPString, ++ DIRECTIVE_BOOLEAN, ++ DIRECTIVE_BY, ++ DIRECTIVE_CHARACTER, ++ DIRECTIVE_CHOICE, ++ DIRECTIVE_CLASS, ++ DIRECTIVE_COMPONENT, ++ DIRECTIVE_COMPONENTS, ++ DIRECTIVE_CONSTRAINED, ++ DIRECTIVE_CONTAINING, ++ DIRECTIVE_DEFAULT, ++ DIRECTIVE_DEFINED, ++ DIRECTIVE_DEFINITIONS, ++ DIRECTIVE_EMBEDDED, ++ DIRECTIVE_ENCODED, ++ DIRECTIVE_ENCODING_CONTROL, ++ DIRECTIVE_END, ++ DIRECTIVE_ENUMERATED, ++ DIRECTIVE_EXCEPT, ++ DIRECTIVE_EXPLICIT, ++ DIRECTIVE_EXPORTS, ++ DIRECTIVE_EXTENSIBILITY, ++ DIRECTIVE_EXTERNAL, ++ DIRECTIVE_FALSE, ++ DIRECTIVE_FROM, ++ DIRECTIVE_GeneralString, ++ DIRECTIVE_GeneralizedTime, ++ DIRECTIVE_GraphicString, ++ DIRECTIVE_IA5String, ++ DIRECTIVE_IDENTIFIER, ++ DIRECTIVE_IMPLICIT, ++ DIRECTIVE_IMPLIED, ++ DIRECTIVE_IMPORTS, ++ DIRECTIVE_INCLUDES, ++ DIRECTIVE_INSTANCE, ++ DIRECTIVE_INSTRUCTIONS, ++ DIRECTIVE_INTEGER, ++ DIRECTIVE_INTERSECTION, ++ DIRECTIVE_ISO646String, ++ DIRECTIVE_MAX, ++ DIRECTIVE_MIN, ++ DIRECTIVE_MINUS_INFINITY, ++ DIRECTIVE_NULL, ++ DIRECTIVE_NumericString, ++ DIRECTIVE_OBJECT, ++ DIRECTIVE_OCTET, ++ DIRECTIVE_OF, ++ DIRECTIVE_OPTIONAL, ++ DIRECTIVE_ObjectDescriptor, ++ DIRECTIVE_PATTERN, ++ DIRECTIVE_PDV, ++ DIRECTIVE_PLUS_INFINITY, ++ DIRECTIVE_PRESENT, ++ DIRECTIVE_PRIVATE, ++ DIRECTIVE_PrintableString, ++ DIRECTIVE_REAL, ++ DIRECTIVE_RELATIVE_OID, ++ DIRECTIVE_SEQUENCE, ++ DIRECTIVE_SET, ++ DIRECTIVE_SIZE, ++ DIRECTIVE_STRING, ++ DIRECTIVE_SYNTAX, ++ DIRECTIVE_T61String, ++ DIRECTIVE_TAGS, ++ DIRECTIVE_TRUE, ++ DIRECTIVE_TeletexString, ++ DIRECTIVE_UNION, ++ DIRECTIVE_UNIQUE, ++ DIRECTIVE_UNIVERSAL, ++ DIRECTIVE_UTCTime, ++ DIRECTIVE_UTF8String, ++ DIRECTIVE_UniversalString, ++ DIRECTIVE_VideotexString, ++ DIRECTIVE_VisibleString, ++ DIRECTIVE_WITH, ++ NR__DIRECTIVES, ++ TOKEN_ASSIGNMENT = NR__DIRECTIVES, ++ TOKEN_OPEN_CURLY, ++ TOKEN_CLOSE_CURLY, ++ TOKEN_OPEN_SQUARE, ++ TOKEN_CLOSE_SQUARE, ++ TOKEN_OPEN_ACTION, ++ TOKEN_CLOSE_ACTION, ++ TOKEN_COMMA, ++ TOKEN_NUMBER, ++ TOKEN_TYPE_NAME, ++ TOKEN_ELEMENT_NAME, ++ NR__TOKENS ++}; ++ ++static const unsigned char token_to_tag[NR__TOKENS] = { ++ /* EOC goes first */ ++ [DIRECTIVE_BOOLEAN] = ASN1_BOOL, ++ [DIRECTIVE_INTEGER] = ASN1_INT, ++ [DIRECTIVE_BIT] = ASN1_BTS, ++ [DIRECTIVE_OCTET] = ASN1_OTS, ++ [DIRECTIVE_NULL] = ASN1_NULL, ++ [DIRECTIVE_OBJECT] = ASN1_OID, ++ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, ++ [DIRECTIVE_EXTERNAL] = ASN1_EXT, ++ [DIRECTIVE_REAL] = ASN1_REAL, ++ [DIRECTIVE_ENUMERATED] = ASN1_ENUM, ++ [DIRECTIVE_EMBEDDED] = 0, ++ [DIRECTIVE_UTF8String] = ASN1_UTF8STR, ++ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, ++ /* 14 */ ++ /* 15 */ ++ [DIRECTIVE_SEQUENCE] = ASN1_SEQ, ++ [DIRECTIVE_SET] = ASN1_SET, ++ [DIRECTIVE_NumericString] = ASN1_NUMSTR, ++ [DIRECTIVE_PrintableString] = ASN1_PRNSTR, ++ [DIRECTIVE_T61String] = ASN1_TEXSTR, ++ [DIRECTIVE_TeletexString] = ASN1_TEXSTR, ++ [DIRECTIVE_VideotexString] = ASN1_VIDSTR, ++ [DIRECTIVE_IA5String] = ASN1_IA5STR, ++ [DIRECTIVE_UTCTime] = ASN1_UNITIM, ++ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, ++ [DIRECTIVE_GraphicString] = ASN1_GRASTR, ++ [DIRECTIVE_VisibleString] = ASN1_VISSTR, ++ [DIRECTIVE_GeneralString] = ASN1_GENSTR, ++ [DIRECTIVE_UniversalString] = ASN1_UNITIM, ++ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, ++ [DIRECTIVE_BMPString] = ASN1_BMPSTR, ++}; ++ ++static const char asn1_classes[4][5] = { ++ [ASN1_UNIV] = "UNIV", ++ [ASN1_APPL] = "APPL", ++ [ASN1_CONT] = "CONT", ++ [ASN1_PRIV] = "PRIV" ++}; ++ ++static const char asn1_methods[2][5] = { ++ [ASN1_UNIV] = "PRIM", ++ [ASN1_APPL] = "CONS" ++}; ++ ++static const char *const asn1_universal_tags[32] = { ++ "EOC", ++ "BOOL", ++ "INT", ++ "BTS", ++ "OTS", ++ "NULL", ++ "OID", ++ "ODE", ++ "EXT", ++ "REAL", ++ "ENUM", ++ "EPDV", ++ "UTF8STR", ++ "RELOID", ++ NULL, /* 14 */ ++ NULL, /* 15 */ ++ "SEQ", ++ "SET", ++ "NUMSTR", ++ "PRNSTR", ++ "TEXSTR", ++ "VIDSTR", ++ "IA5STR", ++ "UNITIM", ++ "GENTIM", ++ "GRASTR", ++ "VISSTR", ++ "GENSTR", ++ "UNISTR", ++ "CHRSTR", ++ "BMPSTR", ++ NULL /* 31 */ ++}; ++ ++static const char *filename; ++static const char *grammar_name; ++static const char *outputname; ++static const char *headername; ++ ++static const char *const directives[NR__DIRECTIVES] = { ++#define _(X) [DIRECTIVE_##X] = #X ++ _(ABSENT), ++ _(ALL), ++ _(ANY), ++ _(APPLICATION), ++ _(AUTOMATIC), ++ _(BEGIN), ++ _(BIT), ++ _(BMPString), ++ _(BOOLEAN), ++ _(BY), ++ _(CHARACTER), ++ _(CHOICE), ++ _(CLASS), ++ _(COMPONENT), ++ _(COMPONENTS), ++ _(CONSTRAINED), ++ _(CONTAINING), ++ _(DEFAULT), ++ _(DEFINED), ++ _(DEFINITIONS), ++ _(EMBEDDED), ++ _(ENCODED), ++ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", ++ _(END), ++ _(ENUMERATED), ++ _(EXCEPT), ++ _(EXPLICIT), ++ _(EXPORTS), ++ _(EXTENSIBILITY), ++ _(EXTERNAL), ++ _(FALSE), ++ _(FROM), ++ _(GeneralString), ++ _(GeneralizedTime), ++ _(GraphicString), ++ _(IA5String), ++ _(IDENTIFIER), ++ _(IMPLICIT), ++ _(IMPLIED), ++ _(IMPORTS), ++ _(INCLUDES), ++ _(INSTANCE), ++ _(INSTRUCTIONS), ++ _(INTEGER), ++ _(INTERSECTION), ++ _(ISO646String), ++ _(MAX), ++ _(MIN), ++ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", ++ [DIRECTIVE_NULL] = "NULL", ++ _(NumericString), ++ _(OBJECT), ++ _(OCTET), ++ _(OF), ++ _(OPTIONAL), ++ _(ObjectDescriptor), ++ _(PATTERN), ++ _(PDV), ++ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", ++ _(PRESENT), ++ _(PRIVATE), ++ _(PrintableString), ++ _(REAL), ++ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", ++ _(SEQUENCE), ++ _(SET), ++ _(SIZE), ++ _(STRING), ++ _(SYNTAX), ++ _(T61String), ++ _(TAGS), ++ _(TRUE), ++ _(TeletexString), ++ _(UNION), ++ _(UNIQUE), ++ _(UNIVERSAL), ++ _(UTCTime), ++ _(UTF8String), ++ _(UniversalString), ++ _(VideotexString), ++ _(VisibleString), ++ _(WITH) ++}; ++ ++struct action { ++ struct action *next; ++ unsigned char index; ++ char name[]; ++}; ++ ++static struct action *action_list; ++static unsigned nr_actions; ++ ++struct token { ++ unsigned short line; ++ enum token_type token_type : 8; ++ unsigned char size; ++ struct action *action; ++ const char *value; ++ struct type *type; ++}; ++ ++static struct token *token_list; ++static unsigned nr_tokens; ++ ++static int directive_compare(const void *_key, const void *_pdir) ++{ ++ const struct token *token = _key; ++ const char *const *pdir = _pdir, *dir = *pdir; ++ size_t dlen, clen; ++ int val; ++ ++ dlen = strlen(dir); ++ clen = (dlen < token->size) ? dlen : token->size; ++ ++ //printf("cmp(%*.*s,%s) = ", ++ // (int)token->size, (int)token->size, token->value, ++ // dir); ++ ++ val = memcmp(token->value, dir, clen); ++ if (val != 0) { ++ //printf("%d [cmp]\n", val); ++ return val; ++ } ++ ++ if (dlen == token->size) { ++ //printf("0\n"); ++ return 0; ++ } ++ //printf("%d\n", (int)dlen - (int)token->size); ++ return dlen - token->size; /* shorter -> negative */ ++} ++ ++/* ++ * Tokenise an ASN.1 grammar ++ */ ++static void tokenise(char *buffer, char *end) ++{ ++ struct token *tokens; ++ char *line, *nl, *p, *q; ++ unsigned tix, lineno; ++ ++ /* Assume we're going to have half as many tokens as we have ++ * characters ++ */ ++ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); ++ if (!tokens) { ++ perror(NULL); ++ exit(1); ++ } ++ tix = 0; ++ ++ lineno = 0; ++ while (buffer < end) { ++ /* First of all, break out a line */ ++ lineno++; ++ line = buffer; ++ nl = memchr(line, '\n', end - buffer); ++ if (!nl) { ++ buffer = nl = end; ++ } else { ++ buffer = nl + 1; ++ *nl = '\0'; ++ } ++ ++ /* Remove "--" comments */ ++ p = line; ++ next_comment: ++ while ((p = memchr(p, '-', nl - p))) { ++ if (p[1] == '-') { ++ /* Found a comment; see if there's a terminator */ ++ q = p + 2; ++ while ((q = memchr(q, '-', nl - q))) { ++ if (q[1] == '-') { ++ /* There is - excise the comment */ ++ q += 2; ++ memmove(p, q, nl - q); ++ goto next_comment; ++ } ++ q++; ++ } ++ *p = '\0'; ++ nl = p; ++ break; ++ } else { ++ p++; ++ } ++ } ++ ++ p = line; ++ while (p < nl) { ++ /* Skip white space */ ++ while (p < nl && isspace(*p)) ++ *(p++) = 0; ++ if (p >= nl) ++ break; ++ ++ tokens[tix].line = lineno; ++ tokens[tix].value = p; ++ ++ /* Handle string tokens */ ++ if (isalpha(*p)) { ++ const char **dir; ++ ++ /* Can be a directive, type name or element ++ * name. Find the end of the name. ++ */ ++ q = p + 1; ++ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) ++ q++; ++ tokens[tix].size = q - p; ++ p = q; ++ ++ /* If it begins with a lowercase letter then ++ * it's an element name ++ */ ++ if (islower(tokens[tix].value[0])) { ++ tokens[tix++].token_type = TOKEN_ELEMENT_NAME; ++ continue; ++ } ++ ++ /* Otherwise we need to search the directive ++ * table ++ */ ++ dir = bsearch(&tokens[tix], directives, ++ sizeof(directives) / sizeof(directives[1]), ++ sizeof(directives[1]), ++ directive_compare); ++ if (dir) { ++ tokens[tix++].token_type = dir - directives; ++ continue; ++ } ++ ++ tokens[tix++].token_type = TOKEN_TYPE_NAME; ++ continue; ++ } ++ ++ /* Handle numbers */ ++ if (isdigit(*p)) { ++ /* Find the end of the number */ ++ q = p + 1; ++ while (q < nl && (isdigit(*q))) ++ q++; ++ tokens[tix].size = q - p; ++ p = q; ++ tokens[tix++].token_type = TOKEN_NUMBER; ++ continue; ++ } ++ ++ if (nl - p >= 3) { ++ if (memcmp(p, "::=", 3) == 0) { ++ p += 3; ++ tokens[tix].size = 3; ++ tokens[tix++].token_type = TOKEN_ASSIGNMENT; ++ continue; ++ } ++ } ++ ++ if (nl - p >= 2) { ++ if (memcmp(p, "({", 2) == 0) { ++ p += 2; ++ tokens[tix].size = 2; ++ tokens[tix++].token_type = TOKEN_OPEN_ACTION; ++ continue; ++ } ++ if (memcmp(p, "})", 2) == 0) { ++ p += 2; ++ tokens[tix].size = 2; ++ tokens[tix++].token_type = TOKEN_CLOSE_ACTION; ++ continue; ++ } ++ } ++ ++ if (nl - p >= 1) { ++ tokens[tix].size = 1; ++ switch (*p) { ++ case '{': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_OPEN_CURLY; ++ continue; ++ case '}': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_CLOSE_CURLY; ++ continue; ++ case '[': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_OPEN_SQUARE; ++ continue; ++ case ']': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; ++ continue; ++ case ',': ++ p += 1; ++ tokens[tix++].token_type = TOKEN_COMMA; ++ continue; ++ default: ++ break; ++ } ++ } ++ ++ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", ++ filename, lineno, *p); ++ exit(1); ++ } ++ } ++ ++ nr_tokens = tix; ++ printf("Extracted %u tokens\n", nr_tokens); ++ ++#if 0 ++ { ++ int n; ++ for (n = 0; n < nr_tokens; n++) ++ printf("Token %3u: '%*.*s'\n", ++ n, ++ (int)token_list[n].size, (int)token_list[n].size, ++ token_list[n].value); ++ } ++#endif ++} ++ ++static void build_type_list(void); ++static void parse(void); ++static void render(FILE *out, FILE *hdr); ++ ++/* ++ * ++ */ ++int main(int argc, char **argv) ++{ ++ struct stat st; ++ ssize_t readlen; ++ FILE *out, *hdr; ++ char *buffer, *p; ++ int fd; ++ ++ if (argc != 4) { ++ fprintf(stderr, "Format: %s \n", ++ argv[0]); ++ exit(2); ++ } ++ ++ filename = argv[1]; ++ outputname = argv[2]; ++ headername = argv[3]; ++ ++ fd = open(filename, O_RDONLY); ++ if (fd < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (fstat(fd, &st) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (!(buffer = malloc(st.st_size + 1))) { ++ perror(NULL); ++ exit(1); ++ } ++ ++ if ((readlen = read(fd, buffer, st.st_size)) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (close(fd) < 0) { ++ perror(filename); ++ exit(1); ++ } ++ ++ if (readlen != st.st_size) { ++ fprintf(stderr, "%s: Short read\n", filename); ++ exit(1); ++ } ++ ++ p = strrchr(argv[1], '/'); ++ p = p ? p + 1 : argv[1]; ++ grammar_name = strdup(p); ++ if (!p) { ++ perror(NULL); ++ exit(1); ++ } ++ p = strchr(grammar_name, '.'); ++ if (p) ++ *p = '\0'; ++ ++ buffer[readlen] = 0; ++ tokenise(buffer, buffer + readlen); ++ build_type_list(); ++ parse(); ++ ++ out = fopen(outputname, "w"); ++ if (!out) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ hdr = fopen(headername, "w"); ++ if (!out) { ++ perror(headername); ++ exit(1); ++ } ++ ++ render(out, hdr); ++ ++ if (fclose(out) < 0) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ if (fclose(hdr) < 0) { ++ perror(headername); ++ exit(1); ++ } ++ ++ return 0; ++} ++ ++enum compound { ++ NOT_COMPOUND, ++ SET, ++ SET_OF, ++ SEQUENCE, ++ SEQUENCE_OF, ++ CHOICE, ++ ANY, ++ TYPE_REF, ++ TAG_OVERRIDE ++}; ++ ++struct element { ++ struct type *type_def; ++ struct token *name; ++ struct token *type; ++ struct action *action; ++ struct element *children; ++ struct element *next; ++ struct element *render_next; ++ struct element *list_next; ++ uint8_t n_elements; ++ enum compound compound : 8; ++ enum asn1_class class : 8; ++ enum asn1_method method : 8; ++ uint8_t tag; ++ unsigned entry_index; ++ unsigned flags; ++#define ELEMENT_IMPLICIT 0x0001 ++#define ELEMENT_EXPLICIT 0x0002 ++#define ELEMENT_MARKED 0x0004 ++#define ELEMENT_RENDERED 0x0008 ++#define ELEMENT_SKIPPABLE 0x0010 ++#define ELEMENT_CONDITIONAL 0x0020 ++}; ++ ++struct type { ++ struct token *name; ++ struct token *def; ++ struct element *element; ++ unsigned ref_count; ++ unsigned flags; ++#define TYPE_STOP_MARKER 0x0001 ++#define TYPE_BEGIN 0x0002 ++}; ++ ++static struct type *type_list; ++static struct type **type_index; ++static unsigned nr_types; ++ ++static int type_index_compare(const void *_a, const void *_b) ++{ ++ const struct type *const *a = _a, *const *b = _b; ++ ++ if ((*a)->name->size != (*b)->name->size) ++ return (*a)->name->size - (*b)->name->size; ++ else ++ return memcmp((*a)->name->value, (*b)->name->value, ++ (*a)->name->size); ++} ++ ++static int type_finder(const void *_key, const void *_ti) ++{ ++ const struct token *token = _key; ++ const struct type *const *ti = _ti; ++ const struct type *type = *ti; ++ ++ if (token->size != type->name->size) ++ return token->size - type->name->size; ++ else ++ return memcmp(token->value, type->name->value, ++ token->size); ++} ++ ++/* ++ * Build up a list of types and a sorted index to that list. ++ */ ++static void build_type_list(void) ++{ ++ struct type *types; ++ unsigned nr, t, n; ++ ++ nr = 0; ++ for (n = 0; n < nr_tokens - 1; n++) ++ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && ++ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) ++ nr++; ++ ++ if (nr == 0) { ++ fprintf(stderr, "%s: No defined types\n", filename); ++ exit(1); ++ } ++ ++ nr_types = nr; ++ types = type_list = calloc(nr + 1, sizeof(type_list[0])); ++ if (!type_list) { ++ perror(NULL); ++ exit(1); ++ } ++ type_index = calloc(nr, sizeof(type_index[0])); ++ if (!type_index) { ++ perror(NULL); ++ exit(1); ++ } ++ ++ t = 0; ++ types[t].flags |= TYPE_BEGIN; ++ for (n = 0; n < nr_tokens - 1; n++) { ++ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && ++ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { ++ types[t].name = &token_list[n]; ++ type_index[t] = &types[t]; ++ t++; ++ } ++ } ++ types[t].name = &token_list[n + 1]; ++ types[t].flags |= TYPE_STOP_MARKER; ++ ++ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); ++ ++ printf("Extracted %u types\n", nr_types); ++#if 0 ++ for (n = 0; n < nr_types; n++) { ++ struct type *type = type_index[n]; ++ printf("- %*.*s\n", ++ (int)type->name->size, ++ (int)type->name->size, ++ type->name->value); ++ } ++#endif ++} ++ ++static struct element *parse_type(struct token **_cursor, struct token *stop, ++ struct token *name); ++ ++/* ++ * Parse the token stream ++ */ ++static void parse(void) ++{ ++ struct token *cursor; ++ struct type *type; ++ ++ /* Parse one type definition statement at a time */ ++ type = type_list; ++ do { ++ cursor = type->name; ++ ++ if (cursor[0].token_type != TOKEN_TYPE_NAME || ++ cursor[1].token_type != TOKEN_ASSIGNMENT) ++ abort(); ++ cursor += 2; ++ ++ type->element = parse_type(&cursor, type[1].name, NULL); ++ type->element->type_def = type; ++ ++ if (cursor != type[1].name) { ++ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ } while (type++, !(type->flags & TYPE_STOP_MARKER)); ++ ++ printf("Extracted %u actions\n", nr_actions); ++} ++ ++static struct element *element_list; ++ ++static struct element *alloc_elem(struct token *type) ++{ ++ struct element *e = calloc(1, sizeof(*e)); ++ if (!e) { ++ perror(NULL); ++ exit(1); ++ } ++ e->list_next = element_list; ++ element_list = e; ++ return e; ++} ++ ++static struct element *parse_compound(struct token **_cursor, struct token *end, ++ int alternates); ++ ++/* ++ * Parse one type definition statement ++ */ ++static struct element *parse_type(struct token **_cursor, struct token *end, ++ struct token *name) ++{ ++ struct element *top, *element; ++ struct action *action, **ppaction; ++ struct token *cursor = *_cursor; ++ struct type **ref; ++ char *p; ++ int labelled = 0, implicit = 0; ++ ++ top = element = alloc_elem(cursor); ++ element->class = ASN1_UNIV; ++ element->method = ASN1_PRIM; ++ element->tag = token_to_tag[cursor->token_type]; ++ element->name = name; ++ ++ /* Extract the tag value if one given */ ++ if (cursor->token_type == TOKEN_OPEN_SQUARE) { ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ switch (cursor->token_type) { ++ case DIRECTIVE_UNIVERSAL: ++ element->class = ASN1_UNIV; ++ cursor++; ++ break; ++ case DIRECTIVE_APPLICATION: ++ element->class = ASN1_APPL; ++ cursor++; ++ break; ++ case TOKEN_NUMBER: ++ element->class = ASN1_CONT; ++ break; ++ case DIRECTIVE_PRIVATE: ++ element->class = ASN1_PRIV; ++ cursor++; ++ break; ++ default: ++ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_NUMBER) { ++ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ element->tag &= ~0x1f; ++ element->tag |= strtoul(cursor->value, &p, 10); ++ if (p - cursor->value != cursor->size) ++ abort(); ++ cursor++; ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_CLOSE_SQUARE) { ++ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ labelled = 1; ++ } ++ ++ /* Handle implicit and explicit markers */ ++ if (cursor->token_type == DIRECTIVE_IMPLICIT) { ++ element->flags |= ELEMENT_IMPLICIT; ++ implicit = 1; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { ++ element->flags |= ELEMENT_EXPLICIT; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ if (labelled) { ++ if (!implicit) ++ element->method |= ASN1_CONS; ++ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; ++ element->children = alloc_elem(cursor); ++ element = element->children; ++ element->class = ASN1_UNIV; ++ element->method = ASN1_PRIM; ++ element->tag = token_to_tag[cursor->token_type]; ++ element->name = name; ++ } ++ ++ /* Extract the type we're expecting here */ ++ element->type = cursor; ++ switch (cursor->token_type) { ++ case DIRECTIVE_ANY: ++ element->compound = ANY; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_NULL: ++ case DIRECTIVE_BOOLEAN: ++ case DIRECTIVE_ENUMERATED: ++ case DIRECTIVE_INTEGER: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_EXTERNAL: ++ element->method = ASN1_CONS; ++ ++ case DIRECTIVE_BMPString: ++ case DIRECTIVE_GeneralString: ++ case DIRECTIVE_GraphicString: ++ case DIRECTIVE_IA5String: ++ case DIRECTIVE_ISO646String: ++ case DIRECTIVE_NumericString: ++ case DIRECTIVE_PrintableString: ++ case DIRECTIVE_T61String: ++ case DIRECTIVE_TeletexString: ++ case DIRECTIVE_UniversalString: ++ case DIRECTIVE_UTF8String: ++ case DIRECTIVE_VideotexString: ++ case DIRECTIVE_VisibleString: ++ case DIRECTIVE_ObjectDescriptor: ++ case DIRECTIVE_GeneralizedTime: ++ case DIRECTIVE_UTCTime: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_BIT: ++ case DIRECTIVE_OCTET: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != DIRECTIVE_STRING) ++ goto parse_error; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_OBJECT: ++ element->compound = NOT_COMPOUND; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != DIRECTIVE_IDENTIFIER) ++ goto parse_error; ++ cursor++; ++ break; ++ ++ case TOKEN_TYPE_NAME: ++ element->compound = TYPE_REF; ++ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), ++ type_finder); ++ if (!ref) { ++ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor->type = *ref; ++ (*ref)->ref_count++; ++ cursor++; ++ break; ++ ++ case DIRECTIVE_CHOICE: ++ element->compound = CHOICE; ++ cursor++; ++ element->children = parse_compound(&cursor, end, 1); ++ break; ++ ++ case DIRECTIVE_SEQUENCE: ++ element->compound = SEQUENCE; ++ element->method = ASN1_CONS; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type == DIRECTIVE_OF) { ++ element->compound = SEQUENCE_OF; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ element->children = parse_type(&cursor, end, NULL); ++ } else { ++ element->children = parse_compound(&cursor, end, 0); ++ } ++ break; ++ ++ case DIRECTIVE_SET: ++ element->compound = SET; ++ element->method = ASN1_CONS; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type == DIRECTIVE_OF) { ++ element->compound = SET_OF; ++ cursor++; ++ if (cursor >= end) ++ goto parse_error; ++ element->children = parse_type(&cursor, end, NULL); ++ } else { ++ element->children = parse_compound(&cursor, end, 1); ++ } ++ break; ++ ++ default: ++ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ /* Handle elements that are optional */ ++ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || ++ cursor->token_type == DIRECTIVE_DEFAULT) ++ ) { ++ cursor++; ++ top->flags |= ELEMENT_SKIPPABLE; ++ } ++ ++ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_ELEMENT_NAME) { ++ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ ++ action = malloc(sizeof(struct action) + cursor->size + 1); ++ if (!action) { ++ perror(NULL); ++ exit(1); ++ } ++ action->index = 0; ++ memcpy(action->name, cursor->value, cursor->size); ++ action->name[cursor->size] = 0; ++ ++ for (ppaction = &action_list; ++ *ppaction; ++ ppaction = &(*ppaction)->next ++ ) { ++ int cmp = strcmp(action->name, (*ppaction)->name); ++ if (cmp == 0) { ++ free(action); ++ action = *ppaction; ++ goto found; ++ } ++ if (cmp < 0) { ++ action->next = *ppaction; ++ *ppaction = action; ++ nr_actions++; ++ goto found; ++ } ++ } ++ action->next = NULL; ++ *ppaction = action; ++ nr_actions++; ++ found: ++ ++ element->action = action; ++ cursor->action = action; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_CLOSE_ACTION) { ++ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ } ++ ++ *_cursor = cursor; ++ return top; ++ ++parse_error: ++ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ ++overrun_error: ++ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); ++ exit(1); ++} ++ ++/* ++ * Parse a compound type list ++ */ ++static struct element *parse_compound(struct token **_cursor, struct token *end, ++ int alternates) ++{ ++ struct element *children, **child_p = &children, *element; ++ struct token *cursor = *_cursor, *name; ++ ++ if (cursor->token_type != TOKEN_OPEN_CURLY) { ++ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ ++ if (cursor->token_type == TOKEN_OPEN_CURLY) { ++ fprintf(stderr, "%s:%d: Empty compound\n", ++ filename, cursor->line); ++ exit(1); ++ } ++ ++ for (;;) { ++ name = NULL; ++ if (cursor->token_type == TOKEN_ELEMENT_NAME) { ++ name = cursor; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ element = parse_type(&cursor, end, name); ++ if (alternates) ++ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; ++ ++ *child_p = element; ++ child_p = &element->next; ++ ++ if (cursor >= end) ++ goto overrun_error; ++ if (cursor->token_type != TOKEN_COMMA) ++ break; ++ cursor++; ++ if (cursor >= end) ++ goto overrun_error; ++ } ++ ++ children->flags &= ~ELEMENT_CONDITIONAL; ++ ++ if (cursor->token_type != TOKEN_CLOSE_CURLY) { ++ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", ++ filename, cursor->line, ++ (int)cursor->size, (int)cursor->size, cursor->value); ++ exit(1); ++ } ++ cursor++; ++ ++ *_cursor = cursor; ++ return children; ++ ++overrun_error: ++ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); ++ exit(1); ++} ++ ++static void render_element(FILE *out, struct element *e, struct element *tag); ++static void render_out_of_line_list(FILE *out); ++ ++static int nr_entries; ++static int render_depth = 1; ++static struct element *render_list, **render_list_p = &render_list; ++ ++__attribute__((format(printf, 2, 3))) ++static void render_opcode(FILE *out, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (out) { ++ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); ++ va_start(va, fmt); ++ vfprintf(out, fmt, va); ++ va_end(va); ++ } ++ nr_entries++; ++} ++ ++__attribute__((format(printf, 2, 3))) ++static void render_more(FILE *out, const char *fmt, ...) ++{ ++ va_list va; ++ ++ if (out) { ++ va_start(va, fmt); ++ vfprintf(out, fmt, va); ++ va_end(va); ++ } ++} ++ ++/* ++ * Render the grammar into a state machine definition. ++ */ ++static void render(FILE *out, FILE *hdr) ++{ ++ struct element *e; ++ struct action *action; ++ struct type *root; ++ int index; ++ ++ fprintf(hdr, "/*\n"); ++ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); ++ fprintf(hdr, " *\n"); ++ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); ++ fprintf(hdr, " */\n"); ++ fprintf(hdr, "#include \n"); ++ fprintf(hdr, "\n"); ++ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); ++ if (ferror(hdr)) { ++ perror(headername); ++ exit(1); ++ } ++ ++ fprintf(out, "/*\n"); ++ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); ++ fprintf(out, " *\n"); ++ fprintf(out, " * ASN.1 parser for %s\n", grammar_name); ++ fprintf(out, " */\n"); ++ fprintf(out, "#include \n"); ++ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); ++ fprintf(out, "\n"); ++ if (ferror(out)) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ /* Tabulate the action functions we might have to call */ ++ fprintf(hdr, "\n"); ++ index = 0; ++ for (action = action_list; action; action = action->next) { ++ action->index = index++; ++ fprintf(hdr, ++ "extern int %s(void *, size_t, unsigned char," ++ " const void *, size_t);\n", ++ action->name); ++ } ++ fprintf(hdr, "\n"); ++ ++ fprintf(out, "enum %s_actions {\n", grammar_name); ++ for (action = action_list; action; action = action->next) ++ fprintf(out, "\tACT_%s = %u,\n", ++ action->name, action->index); ++ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); ++ fprintf(out, "};\n"); ++ ++ fprintf(out, "\n"); ++ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", ++ grammar_name, grammar_name); ++ for (action = action_list; action; action = action->next) ++ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); ++ fprintf(out, "};\n"); ++ ++ if (ferror(out)) { ++ perror(outputname); ++ exit(1); ++ } ++ ++ /* We do two passes - the first one calculates all the offsets */ ++ printf("Pass 1\n"); ++ nr_entries = 0; ++ root = &type_list[0]; ++ render_element(NULL, root->element, NULL); ++ render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); ++ render_out_of_line_list(NULL); ++ ++ for (e = element_list; e; e = e->list_next) ++ e->flags &= ~ELEMENT_RENDERED; ++ ++ /* And then we actually render */ ++ printf("Pass 2\n"); ++ fprintf(out, "\n"); ++ fprintf(out, "static const unsigned char %s_machine[] = {\n", ++ grammar_name); ++ ++ nr_entries = 0; ++ root = &type_list[0]; ++ render_element(out, root->element, NULL); ++ render_opcode(out, "ASN1_OP_COMPLETE,\n"); ++ render_out_of_line_list(out); ++ ++ fprintf(out, "};\n"); ++ ++ fprintf(out, "\n"); ++ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); ++ fprintf(out, "\t.machine = %s_machine,\n", grammar_name); ++ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); ++ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); ++ fprintf(out, "};\n"); ++} ++ ++/* ++ * Render the out-of-line elements ++ */ ++static void render_out_of_line_list(FILE *out) ++{ ++ struct element *e, *ce; ++ const char *act; ++ int entry; ++ ++ while ((e = render_list)) { ++ render_list = e->render_next; ++ if (!render_list) ++ render_list_p = &render_list; ++ ++ render_more(out, "\n"); ++ e->entry_index = entry = nr_entries; ++ render_depth++; ++ for (ce = e->children; ce; ce = ce->next) ++ render_element(out, ce, NULL); ++ render_depth--; ++ ++ act = e->action ? "_ACT" : ""; ++ switch (e->compound) { ++ case SEQUENCE: ++ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); ++ break; ++ case SEQUENCE_OF: ++ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ break; ++ case SET: ++ render_opcode(out, "ASN1_OP_END_SET%s,\n", act); ++ break; ++ case SET_OF: ++ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ break; ++ } ++ if (e->action) ++ render_opcode(out, "_action(ACT_%s),\n", ++ e->action->name); ++ render_opcode(out, "ASN1_OP_RETURN,\n"); ++ } ++} ++ ++/* ++ * Render an element. ++ */ ++static void render_element(FILE *out, struct element *e, struct element *tag) ++{ ++ struct element *ec; ++ const char *cond, *act; ++ int entry, skippable = 0, outofline = 0; ++ ++ if (e->flags & ELEMENT_SKIPPABLE || ++ (tag && tag->flags & ELEMENT_SKIPPABLE)) ++ skippable = 1; ++ ++ if ((e->type_def && e->type_def->ref_count > 1) || ++ skippable) ++ outofline = 1; ++ ++ if (e->type_def && out) { ++ render_more(out, "\t// %*.*s\n", ++ (int)e->type_def->name->size, (int)e->type_def->name->size, ++ e->type_def->name->value); ++ } ++ ++ /* Render the operation */ ++ cond = (e->flags & ELEMENT_CONDITIONAL || ++ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; ++ act = e->action ? "_ACT" : ""; ++ switch (e->compound) { ++ case ANY: ++ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); ++ if (e->name) ++ render_more(out, "\t\t// %*.*s", ++ (int)e->name->size, (int)e->name->size, ++ e->name->value); ++ render_more(out, "\n"); ++ goto dont_render_tag; ++ ++ case TAG_OVERRIDE: ++ render_element(out, e->children, e); ++ return; ++ ++ case SEQUENCE: ++ case SEQUENCE_OF: ++ case SET: ++ case SET_OF: ++ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", ++ cond, ++ outofline ? "_JUMP" : "", ++ skippable ? "_OR_SKIP" : ""); ++ break; ++ ++ case CHOICE: ++ goto dont_render_tag; ++ ++ case TYPE_REF: ++ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) ++ goto dont_render_tag; ++ default: ++ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", ++ cond, act, ++ skippable ? "_OR_SKIP" : ""); ++ break; ++ } ++ ++ if (e->name) ++ render_more(out, "\t\t// %*.*s", ++ (int)e->name->size, (int)e->name->size, ++ e->name->value); ++ render_more(out, "\n"); ++ ++ /* Render the tag */ ++ if (!tag) ++ tag = e; ++ if (tag->class == ASN1_UNIV && ++ tag->tag != 14 && ++ tag->tag != 15 && ++ tag->tag != 31) ++ render_opcode(out, "_tag(%s, %s, %s),\n", ++ asn1_classes[tag->class], ++ asn1_methods[tag->method | e->method], ++ asn1_universal_tags[tag->tag]); ++ else ++ render_opcode(out, "_tagn(%s, %s, %2u),\n", ++ asn1_classes[tag->class], ++ asn1_methods[tag->method | e->method], ++ tag->tag); ++ tag = NULL; ++dont_render_tag: ++ ++ /* Deal with compound types */ ++ switch (e->compound) { ++ case TYPE_REF: ++ render_element(out, e->type->type->element, tag); ++ if (e->action) ++ render_opcode(out, "ASN1_OP_ACT,\n"); ++ break; ++ ++ case SEQUENCE: ++ if (outofline) { ++ /* Render out-of-line for multiple use or ++ * skipability */ ++ render_opcode(out, "_jump_target(%u),", e->entry_index); ++ if (e->type_def && e->type_def->name) ++ render_more(out, "\t\t// --> %*.*s", ++ (int)e->type_def->name->size, ++ (int)e->type_def->name->size, ++ e->type_def->name->value); ++ render_more(out, "\n"); ++ if (!(e->flags & ELEMENT_RENDERED)) { ++ e->flags |= ELEMENT_RENDERED; ++ *render_list_p = e; ++ render_list_p = &e->render_next; ++ } ++ return; ++ } else { ++ /* Render inline for single use */ ++ render_depth++; ++ for (ec = e->children; ec; ec = ec->next) ++ render_element(out, ec, NULL); ++ render_depth--; ++ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); ++ } ++ break; ++ ++ case SEQUENCE_OF: ++ case SET_OF: ++ if (outofline) { ++ /* Render out-of-line for multiple use or ++ * skipability */ ++ render_opcode(out, "_jump_target(%u),", e->entry_index); ++ if (e->type_def && e->type_def->name) ++ render_more(out, "\t\t// --> %*.*s", ++ (int)e->type_def->name->size, ++ (int)e->type_def->name->size, ++ e->type_def->name->value); ++ render_more(out, "\n"); ++ if (!(e->flags & ELEMENT_RENDERED)) { ++ e->flags |= ELEMENT_RENDERED; ++ *render_list_p = e; ++ render_list_p = &e->render_next; ++ } ++ return; ++ } else { ++ /* Render inline for single use */ ++ entry = nr_entries; ++ render_depth++; ++ render_element(out, e->children, NULL); ++ render_depth--; ++ if (e->compound == SEQUENCE_OF) ++ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); ++ else ++ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); ++ render_opcode(out, "_jump_target(%u),\n", entry); ++ } ++ break; ++ ++ case SET: ++ /* I can't think of a nice way to do SET support without having ++ * a stack of bitmasks to make sure no element is repeated. ++ * The bitmask has also to be checked that no non-optional ++ * elements are left out whilst not preventing optional ++ * elements from being left out. ++ */ ++ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); ++ exit(1); ++ ++ case CHOICE: ++ for (ec = e->children; ec; ec = ec->next) ++ render_element(out, ec, NULL); ++ if (!skippable) ++ render_opcode(out, "ASN1_OP_COND_FAIL,\n"); ++ if (e->action) ++ render_opcode(out, "ASN1_OP_ACT,\n"); ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (e->action) ++ render_opcode(out, "_action(ACT_%s),\n", e->action->name); ++} +-- +1.7.12.1 + + +From 650c728e4b8d58d72b19973e97c3c765178e81b8 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:16 +0100 +Subject: [PATCH 15/37] X.509: Add an ASN.1 decoder + +Add an ASN.1 BER/DER/CER decoder. This uses the bytecode from the ASN.1 +compiler in the previous patch to inform it as to what to expect to find in the +encoded byte stream. The output from the compiler also tells it what functions +to call on what tags, thus allowing the caller to retrieve information. + +The decoder is called as follows: + + int asn1_decoder(const struct asn1_decoder *decoder, + void *context, + const unsigned char *data, + size_t datalen); + +The decoder argument points to the bytecode from the ASN.1 compiler. context +is the caller's context and is passed to the action functions. data and +datalen define the byte stream to be decoded. + +Note that the decoder is currently limited to datalen being less than 64K. +This reduces the amount of stack space used by the decoder because ASN.1 is a +nested construct. Similarly, the decoder is limited to a maximum of 10 levels +of constructed data outside of a leaf node also in an effort to keep stack +usage down. + +These restrictions can be raised if necessary. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + include/linux/asn1_decoder.h | 24 +++ + lib/Makefile | 2 + + lib/asn1_decoder.c | 477 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 503 insertions(+) + create mode 100644 include/linux/asn1_decoder.h + create mode 100644 lib/asn1_decoder.c + +diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h +new file mode 100644 +index 0000000..fa2ff5b +--- /dev/null ++++ b/include/linux/asn1_decoder.h +@@ -0,0 +1,24 @@ ++/* ASN.1 decoder ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_ASN1_DECODER_H ++#define _LINUX_ASN1_DECODER_H ++ ++#include ++ ++struct asn1_decoder; ++ ++extern int asn1_ber_decoder(const struct asn1_decoder *decoder, ++ void *context, ++ const unsigned char *data, ++ size_t datalen); ++ ++#endif /* _LINUX_ASN1_DECODER_H */ +diff --git a/lib/Makefile b/lib/Makefile +index b042896..ca856b6 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \ + $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) + lib-$(CONFIG_LIBFDT) += $(libfdt_files) + ++obj-$(CONFIG_ASN1) += asn1_decoder.o ++ + hostprogs-y := gen_crc32table + clean-files := crc32table.h + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +new file mode 100644 +index 0000000..2e4196d +--- /dev/null ++++ b/lib/asn1_decoder.c +@@ -0,0 +1,477 @@ ++/* Decoder for ASN.1 BER/DER/CER encoded bytestream ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { ++ /* OPC TAG JMP ACT */ ++ [ASN1_OP_MATCH] = 1 + 1, ++ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, ++ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_MATCH_ANY] = 1, ++ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, ++ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, ++ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, ++ [ASN1_OP_COND_MATCH_ANY] = 1, ++ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, ++ [ASN1_OP_COND_FAIL] = 1, ++ [ASN1_OP_COMPLETE] = 1, ++ [ASN1_OP_ACT] = 1 + 1, ++ [ASN1_OP_RETURN] = 1, ++ [ASN1_OP_END_SEQ] = 1, ++ [ASN1_OP_END_SEQ_OF] = 1 + 1, ++ [ASN1_OP_END_SET] = 1, ++ [ASN1_OP_END_SET_OF] = 1 + 1, ++ [ASN1_OP_END_SEQ_ACT] = 1 + 1, ++ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, ++ [ASN1_OP_END_SET_ACT] = 1 + 1, ++ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, ++}; ++ ++/* ++ * Find the length of an indefinite length object ++ */ ++static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, ++ const char **_errmsg, size_t *_err_dp) ++{ ++ unsigned char tag, tmp; ++ size_t dp = 0, len, n; ++ int indef_level = 1; ++ ++next_tag: ++ if (unlikely(datalen - dp < 2)) { ++ if (datalen == dp) ++ goto missing_eoc; ++ goto data_overrun_error; ++ } ++ ++ /* Extract a tag from the data */ ++ tag = data[dp++]; ++ if (tag == 0) { ++ /* It appears to be an EOC. */ ++ if (data[dp++] != 0) ++ goto invalid_eoc; ++ if (--indef_level <= 0) ++ return dp; ++ goto next_tag; ++ } ++ ++ if (unlikely((tag & 0x1f) == 0x1f)) { ++ do { ++ if (unlikely(datalen - dp < 2)) ++ goto data_overrun_error; ++ tmp = data[dp++]; ++ } while (tmp & 0x80); ++ } ++ ++ /* Extract the length */ ++ len = data[dp++]; ++ if (len < 0x7f) { ++ dp += len; ++ goto next_tag; ++ } ++ ++ if (unlikely(len == 0x80)) { ++ /* Indefinite length */ ++ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) ++ goto indefinite_len_primitive; ++ indef_level++; ++ goto next_tag; ++ } ++ ++ n = len - 0x80; ++ if (unlikely(n > sizeof(size_t) - 1)) ++ goto length_too_long; ++ if (unlikely(n > datalen - dp)) ++ goto data_overrun_error; ++ for (len = 0; n > 0; n--) { ++ len <<= 8; ++ len |= data[dp++]; ++ } ++ dp += len; ++ goto next_tag; ++ ++length_too_long: ++ *_errmsg = "Unsupported length"; ++ goto error; ++indefinite_len_primitive: ++ *_errmsg = "Indefinite len primitive not permitted"; ++ goto error; ++invalid_eoc: ++ *_errmsg = "Invalid length EOC"; ++ goto error; ++data_overrun_error: ++ *_errmsg = "Data overrun error"; ++ goto error; ++missing_eoc: ++ *_errmsg = "Missing EOC in indefinite len cons"; ++error: ++ *_err_dp = dp; ++ return -1; ++} ++ ++/** ++ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern ++ * @decoder: The decoder definition (produced by asn1_compiler) ++ * @context: The caller's context (to be passed to the action functions) ++ * @data: The encoded data ++ * @datasize: The size of the encoded data ++ * ++ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern ++ * produced by asn1_compiler. Action functions are called on marked tags to ++ * allow the caller to retrieve significant data. ++ * ++ * LIMITATIONS: ++ * ++ * To keep down the amount of stack used by this function, the following limits ++ * have been imposed: ++ * ++ * (1) This won't handle datalen > 65535 without increasing the size of the ++ * cons stack elements and length_too_long checking. ++ * ++ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf ++ * constructed types exceeds this, the decode will fail. ++ * ++ * (3) The SET type (not the SET OF type) isn't really supported as tracking ++ * what members of the set have been seen is a pain. ++ */ ++int asn1_ber_decoder(const struct asn1_decoder *decoder, ++ void *context, ++ const unsigned char *data, ++ size_t datalen) ++{ ++ const unsigned char *machine = decoder->machine; ++ const asn1_action_t *actions = decoder->actions; ++ size_t machlen = decoder->machlen; ++ enum asn1_opcode op; ++ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; ++ const char *errmsg; ++ size_t pc = 0, dp = 0, tdp = 0, len = 0; ++ int ret; ++ ++ unsigned char flags = 0; ++#define FLAG_INDEFINITE_LENGTH 0x01 ++#define FLAG_MATCHED 0x02 ++#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag ++ * - ie. whether or not we are going to parse ++ * a compound type. ++ */ ++ ++#define NR_CONS_STACK 10 ++ unsigned short cons_dp_stack[NR_CONS_STACK]; ++ unsigned short cons_datalen_stack[NR_CONS_STACK]; ++ unsigned char cons_hdrlen_stack[NR_CONS_STACK]; ++#define NR_JUMP_STACK 10 ++ unsigned char jump_stack[NR_JUMP_STACK]; ++ ++ if (datalen > 65535) ++ return -EMSGSIZE; ++ ++next_op: ++ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", ++ pc, machlen, dp, datalen, csp, jsp); ++ if (unlikely(pc >= machlen)) ++ goto machine_overrun_error; ++ op = machine[pc]; ++ if (unlikely(pc + asn1_op_lengths[op] > machlen)) ++ goto machine_overrun_error; ++ ++ /* If this command is meant to match a tag, then do that before ++ * evaluating the command. ++ */ ++ if (op <= ASN1_OP__MATCHES_TAG) { ++ unsigned char tmp; ++ ++ /* Skip conditional matches if possible */ ++ if ((op & ASN1_OP_MATCH__COND && ++ flags & FLAG_MATCHED) || ++ dp == datalen) { ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ } ++ ++ flags = 0; ++ hdr = 2; ++ ++ /* Extract a tag from the data */ ++ if (unlikely(dp >= datalen - 1)) ++ goto data_overrun_error; ++ tag = data[dp++]; ++ if (unlikely((tag & 0x1f) == 0x1f)) ++ goto long_tag_not_supported; ++ ++ if (op & ASN1_OP_MATCH__ANY) { ++ pr_debug("- any %02x\n", tag); ++ } else { ++ /* Extract the tag from the machine ++ * - Either CONS or PRIM are permitted in the data if ++ * CONS is not set in the op stream, otherwise CONS ++ * is mandatory. ++ */ ++ optag = machine[pc + 1]; ++ flags |= optag & FLAG_CONS; ++ ++ /* Determine whether the tag matched */ ++ tmp = optag ^ tag; ++ tmp &= ~(optag & ASN1_CONS_BIT); ++ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); ++ if (tmp != 0) { ++ /* All odd-numbered tags are MATCH_OR_SKIP. */ ++ if (op & ASN1_OP_MATCH__SKIP) { ++ pc += asn1_op_lengths[op]; ++ dp--; ++ goto next_op; ++ } ++ goto tag_mismatch; ++ } ++ } ++ flags |= FLAG_MATCHED; ++ ++ len = data[dp++]; ++ if (len > 0x7f) { ++ if (unlikely(len == 0x80)) { ++ /* Indefinite length */ ++ if (unlikely(!(tag & ASN1_CONS_BIT))) ++ goto indefinite_len_primitive; ++ flags |= FLAG_INDEFINITE_LENGTH; ++ if (unlikely(2 > datalen - dp)) ++ goto data_overrun_error; ++ } else { ++ int n = len - 0x80; ++ if (unlikely(n > 2)) ++ goto length_too_long; ++ if (unlikely(dp >= datalen - n)) ++ goto data_overrun_error; ++ hdr += n; ++ for (len = 0; n > 0; n--) { ++ len <<= 8; ++ len |= data[dp++]; ++ } ++ if (unlikely(len > datalen - dp)) ++ goto data_overrun_error; ++ } ++ } ++ ++ if (flags & FLAG_CONS) { ++ /* For expected compound forms, we stack the positions ++ * of the start and end of the data. ++ */ ++ if (unlikely(csp >= NR_CONS_STACK)) ++ goto cons_stack_overflow; ++ cons_dp_stack[csp] = dp; ++ cons_hdrlen_stack[csp] = hdr; ++ if (!(flags & FLAG_INDEFINITE_LENGTH)) { ++ cons_datalen_stack[csp] = datalen; ++ datalen = dp + len; ++ } else { ++ cons_datalen_stack[csp] = 0; ++ } ++ csp++; ++ } ++ ++ pr_debug("- TAG: %02x %zu%s\n", ++ tag, len, flags & FLAG_CONS ? " CONS" : ""); ++ tdp = dp; ++ } ++ ++ /* Decide how to handle the operation */ ++ switch (op) { ++ case ASN1_OP_MATCH_ANY_ACT: ++ case ASN1_OP_COND_MATCH_ANY_ACT: ++ ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); ++ if (ret < 0) ++ return ret; ++ goto skip_data; ++ ++ case ASN1_OP_MATCH_ACT: ++ case ASN1_OP_MATCH_ACT_OR_SKIP: ++ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: ++ ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); ++ if (ret < 0) ++ return ret; ++ goto skip_data; ++ ++ case ASN1_OP_MATCH: ++ case ASN1_OP_MATCH_OR_SKIP: ++ case ASN1_OP_MATCH_ANY: ++ case ASN1_OP_COND_MATCH_OR_SKIP: ++ case ASN1_OP_COND_MATCH_ANY: ++ skip_data: ++ if (!(flags & FLAG_CONS)) { ++ if (flags & FLAG_INDEFINITE_LENGTH) { ++ len = asn1_find_indefinite_length( ++ data + dp, datalen - dp, &errmsg, &dp); ++ if (len < 0) ++ goto error; ++ } ++ pr_debug("- LEAF: %zu\n", len); ++ dp += len; ++ } ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_MATCH_JUMP: ++ case ASN1_OP_MATCH_JUMP_OR_SKIP: ++ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: ++ pr_debug("- MATCH_JUMP\n"); ++ if (unlikely(jsp == NR_JUMP_STACK)) ++ goto jump_stack_overflow; ++ jump_stack[jsp++] = pc + asn1_op_lengths[op]; ++ pc = machine[pc + 2]; ++ goto next_op; ++ ++ case ASN1_OP_COND_FAIL: ++ if (unlikely(!(flags & FLAG_MATCHED))) ++ goto tag_mismatch; ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_COMPLETE: ++ if (unlikely(jsp != 0 || csp != 0)) { ++ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", ++ jsp, csp); ++ return -EBADMSG; ++ } ++ return 0; ++ ++ case ASN1_OP_END_SET: ++ case ASN1_OP_END_SET_ACT: ++ if (unlikely(!(flags & FLAG_MATCHED))) ++ goto tag_mismatch; ++ case ASN1_OP_END_SEQ: ++ case ASN1_OP_END_SET_OF: ++ case ASN1_OP_END_SEQ_OF: ++ case ASN1_OP_END_SEQ_ACT: ++ case ASN1_OP_END_SET_OF_ACT: ++ case ASN1_OP_END_SEQ_OF_ACT: ++ if (unlikely(csp <= 0)) ++ goto cons_stack_underflow; ++ csp--; ++ tdp = cons_dp_stack[csp]; ++ hdr = cons_hdrlen_stack[csp]; ++ len = datalen; ++ datalen = cons_datalen_stack[csp]; ++ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", ++ tdp, dp, len, datalen); ++ if (datalen == 0) { ++ /* Indefinite length - check for the EOC. */ ++ datalen = len; ++ if (unlikely(datalen - dp < 2)) ++ goto data_overrun_error; ++ if (data[dp++] != 0) { ++ if (op & ASN1_OP_END__OF) { ++ dp--; ++ csp++; ++ pc = machine[pc + 1]; ++ pr_debug("- continue\n"); ++ goto next_op; ++ } ++ goto missing_eoc; ++ } ++ if (data[dp++] != 0) ++ goto invalid_eoc; ++ len = dp - tdp - 2; ++ } else { ++ if (dp < len && (op & ASN1_OP_END__OF)) { ++ datalen = len; ++ csp++; ++ pc = machine[pc + 1]; ++ pr_debug("- continue\n"); ++ goto next_op; ++ } ++ if (dp != len) ++ goto cons_length_error; ++ len -= tdp; ++ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); ++ } ++ ++ if (op & ASN1_OP_END__ACT) { ++ unsigned char act; ++ if (op & ASN1_OP_END__OF) ++ act = machine[pc + 2]; ++ else ++ act = machine[pc + 1]; ++ ret = actions[act](context, hdr, 0, data + tdp, len); ++ } ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_ACT: ++ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); ++ pc += asn1_op_lengths[op]; ++ goto next_op; ++ ++ case ASN1_OP_RETURN: ++ if (unlikely(jsp <= 0)) ++ goto jump_stack_underflow; ++ pc = jump_stack[--jsp]; ++ goto next_op; ++ ++ default: ++ break; ++ } ++ ++ /* Shouldn't reach here */ ++ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); ++ return -EBADMSG; ++ ++data_overrun_error: ++ errmsg = "Data overrun error"; ++ goto error; ++machine_overrun_error: ++ errmsg = "Machine overrun error"; ++ goto error; ++jump_stack_underflow: ++ errmsg = "Jump stack underflow"; ++ goto error; ++jump_stack_overflow: ++ errmsg = "Jump stack overflow"; ++ goto error; ++cons_stack_underflow: ++ errmsg = "Cons stack underflow"; ++ goto error; ++cons_stack_overflow: ++ errmsg = "Cons stack overflow"; ++ goto error; ++cons_length_error: ++ errmsg = "Cons length error"; ++ goto error; ++missing_eoc: ++ errmsg = "Missing EOC in indefinite len cons"; ++ goto error; ++invalid_eoc: ++ errmsg = "Invalid length EOC"; ++ goto error; ++length_too_long: ++ errmsg = "Unsupported length"; ++ goto error; ++indefinite_len_primitive: ++ errmsg = "Indefinite len primitive not permitted"; ++ goto error; ++tag_mismatch: ++ errmsg = "Unexpected tag"; ++ goto error; ++long_tag_not_supported: ++ errmsg = "Long tag not supported"; ++error: ++ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", ++ errmsg, pc, dp, optag, tag, len); ++ return -EBADMSG; ++} ++EXPORT_SYMBOL_GPL(asn1_ber_decoder); +-- +1.7.12.1 + + +From 686b0b5e3549b711c0bcc405d833697ff5e2344d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:27 +0100 +Subject: [PATCH 16/37] MPILIB: Provide a function to read raw data into an + MPI + +Provide a function to read raw data of a predetermined size into an MPI rather +than expecting the size to be encoded within the data. The data is assumed to +represent an unsigned integer, and the resulting MPI will be positive. + +The function looks like this: + + MPI mpi_read_raw_data(const void *, size_t); + +This is useful for reading ASN.1 integer primitives where the length is encoded +in the ASN.1 metadata. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + include/linux/mpi.h | 1 + + lib/mpi/mpicoder.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+) + +diff --git a/include/linux/mpi.h b/include/linux/mpi.h +index d02cca6..5af1b81 100644 +--- a/include/linux/mpi.h ++++ b/include/linux/mpi.h +@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); + + /*-- mpicoder.c --*/ + MPI do_encode_md(const void *sha_buffer, unsigned nbits); ++MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); + MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); + int mpi_fromstr(MPI val, const char *str); + u32 mpi_get_keyid(MPI a, u32 *keyid); +diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c +index f0fa659..3962b7f 100644 +--- a/lib/mpi/mpicoder.c ++++ b/lib/mpi/mpicoder.c +@@ -18,10 +18,65 @@ + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + ++#include ++#include + #include "mpi-internal.h" + + #define MAX_EXTERN_MPI_BITS 16384 + ++/** ++ * mpi_read_raw_data - Read a raw byte stream as a positive integer ++ * @xbuffer: The data to read ++ * @nbytes: The amount of data to read ++ */ ++MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) ++{ ++ const uint8_t *buffer = xbuffer; ++ int i, j; ++ unsigned nbits, nlimbs; ++ mpi_limb_t a; ++ MPI val = NULL; ++ ++ while (nbytes >= 0 && buffer[0] == 0) { ++ buffer++; ++ nbytes--; ++ } ++ ++ nbits = nbytes * 8; ++ if (nbits > MAX_EXTERN_MPI_BITS) { ++ pr_info("MPI: mpi too large (%u bits)\n", nbits); ++ return NULL; ++ } ++ if (nbytes > 0) ++ nbits -= count_leading_zeros(buffer[0]); ++ else ++ nbits = 0; ++ ++ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; ++ val = mpi_alloc(nlimbs); ++ if (!val) ++ return NULL; ++ val->nbits = nbits; ++ val->sign = 0; ++ val->nlimbs = nlimbs; ++ ++ if (nbytes > 0) { ++ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; ++ i %= BYTES_PER_MPI_LIMB; ++ for (j = nlimbs; j > 0; j--) { ++ a = 0; ++ for (; i < BYTES_PER_MPI_LIMB; i++) { ++ a <<= 8; ++ a |= *buffer++; ++ } ++ i = 0; ++ val->d[j - 1] = a; ++ } ++ } ++ return val; ++} ++EXPORT_SYMBOL_GPL(mpi_read_raw_data); ++ + MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) + { + const uint8_t *buffer = xbuffer; +-- +1.7.12.1 + + +From c6ca1b7770b65d0639fb84a7afead457ff22c8d4 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Mon, 24 Sep 2012 17:11:48 +0100 +Subject: [PATCH 17/37] X.509: Add a crypto key parser for binary (DER) X.509 + certificates + +Add a crypto key parser for binary (DER) encoded X.509 certificates. The +certificate is parsed and, if possible, the signature is verified. + +An X.509 key can be added like this: + + # keyctl padd crypto bar @s +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/.gitignore | 1 + + crypto/asymmetric_keys/Kconfig | 10 + + crypto/asymmetric_keys/Makefile | 17 + + crypto/asymmetric_keys/x509.asn1 | 60 ++++ + crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/x509_parser.h | 36 +++ + crypto/asymmetric_keys/x509_public_key.c | 207 +++++++++++++ + crypto/asymmetric_keys/x509_rsakey.asn1 | 4 + + 8 files changed, 832 insertions(+) + create mode 100644 crypto/asymmetric_keys/.gitignore + create mode 100644 crypto/asymmetric_keys/x509.asn1 + create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c + create mode 100644 crypto/asymmetric_keys/x509_parser.h + create mode 100644 crypto/asymmetric_keys/x509_public_key.c + create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 + +diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore +new file mode 100644 +index 0000000..ee32837 +--- /dev/null ++++ b/crypto/asymmetric_keys/.gitignore +@@ -0,0 +1 @@ ++*-asn1.[ch] +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 561759d..6d2c2ea 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA + help + This option enables support for the RSA algorithm (PKCS#1, RFC3447). + ++config X509_CERTIFICATE_PARSER ++ tristate "X.509 certificate parser" ++ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select ASN1 ++ select OID_REGISTRY ++ help ++ This option procides support for parsing X.509 format blobs for key ++ data and provides the ability to instantiate a crypto key from a ++ public key packet found inside the certificate. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 7c92691..0727204 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++ ++# ++# X.509 Certificate handling ++# ++obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o ++x509_key_parser-y := \ ++ x509-asn1.o \ ++ x509_rsakey-asn1.o \ ++ x509_cert_parser.o \ ++ x509_public_key.o ++ ++$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h ++$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h ++$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h ++ ++clean-files += x509-asn1.c x509-asn1.h ++clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h +diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 +new file mode 100644 +index 0000000..bf32b3d +--- /dev/null ++++ b/crypto/asymmetric_keys/x509.asn1 +@@ -0,0 +1,60 @@ ++Certificate ::= SEQUENCE { ++ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), ++ signatureAlgorithm AlgorithmIdentifier, ++ signature BIT STRING ({ x509_note_signature }) ++ } ++ ++TBSCertificate ::= SEQUENCE { ++ version [ 0 ] Version DEFAULT, ++ serialNumber CertificateSerialNumber, ++ signature AlgorithmIdentifier ({ x509_note_pkey_algo }), ++ issuer Name ({ x509_note_issuer }), ++ validity Validity, ++ subject Name ({ x509_note_subject }), ++ subjectPublicKeyInfo SubjectPublicKeyInfo, ++ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, ++ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, ++ extensions [ 3 ] Extensions OPTIONAL ++ } ++ ++Version ::= INTEGER ++CertificateSerialNumber ::= INTEGER ++ ++AlgorithmIdentifier ::= SEQUENCE { ++ algorithm OBJECT IDENTIFIER ({ x509_note_OID }), ++ parameters ANY OPTIONAL ++} ++ ++Name ::= SEQUENCE OF RelativeDistinguishedName ++ ++RelativeDistinguishedName ::= SET OF AttributeValueAssertion ++ ++AttributeValueAssertion ::= SEQUENCE { ++ attributeType OBJECT IDENTIFIER ({ x509_note_OID }), ++ attributeValue ANY ({ x509_extract_name_segment }) ++ } ++ ++Validity ::= SEQUENCE { ++ notBefore Time ({ x509_note_not_before }), ++ notAfter Time ({ x509_note_not_after }) ++ } ++ ++Time ::= CHOICE { ++ utcTime UTCTime, ++ generalTime GeneralizedTime ++ } ++ ++SubjectPublicKeyInfo ::= SEQUENCE { ++ algorithm AlgorithmIdentifier, ++ subjectPublicKey BIT STRING ({ x509_extract_key_data }) ++ } ++ ++UniqueIdentifier ::= BIT STRING ++ ++Extensions ::= SEQUENCE OF Extension ++ ++Extension ::= SEQUENCE { ++ extnid OBJECT IDENTIFIER ({ x509_note_OID }), ++ critical BOOLEAN DEFAULT, ++ extnValue OCTET STRING ({ x509_process_extension }) ++ } +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +new file mode 100644 +index 0000000..8fcac94 +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -0,0 +1,497 @@ ++/* X.509 certificate parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "X.509: "fmt ++#include ++#include ++#include ++#include ++#include "public_key.h" ++#include "x509_parser.h" ++#include "x509-asn1.h" ++#include "x509_rsakey-asn1.h" ++ ++struct x509_parse_context { ++ struct x509_certificate *cert; /* Certificate being constructed */ ++ unsigned long data; /* Start of data */ ++ const void *cert_start; /* Start of cert content */ ++ const void *key; /* Key data */ ++ size_t key_size; /* Size of key data */ ++ enum OID last_oid; /* Last OID encountered */ ++ enum OID algo_oid; /* Algorithm OID */ ++ unsigned char nr_mpi; /* Number of MPIs stored */ ++ u8 o_size; /* Size of organizationName (O) */ ++ u8 cn_size; /* Size of commonName (CN) */ ++ u8 email_size; /* Size of emailAddress */ ++ u16 o_offset; /* Offset of organizationName (O) */ ++ u16 cn_offset; /* Offset of commonName (CN) */ ++ u16 email_offset; /* Offset of emailAddress */ ++}; ++ ++/* ++ * Free an X.509 certificate ++ */ ++void x509_free_certificate(struct x509_certificate *cert) ++{ ++ if (cert) { ++ public_key_destroy(cert->pub); ++ kfree(cert->issuer); ++ kfree(cert->subject); ++ kfree(cert->fingerprint); ++ kfree(cert->authority); ++ kfree(cert); ++ } ++} ++ ++/* ++ * Parse an X.509 certificate ++ */ ++struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) ++{ ++ struct x509_certificate *cert; ++ struct x509_parse_context *ctx; ++ long ret; ++ ++ ret = -ENOMEM; ++ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); ++ if (!cert) ++ goto error_no_cert; ++ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); ++ if (!cert->pub) ++ goto error_no_ctx; ++ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); ++ if (!ctx) ++ goto error_no_ctx; ++ ++ ctx->cert = cert; ++ ctx->data = (unsigned long)data; ++ ++ /* Attempt to decode the certificate */ ++ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); ++ if (ret < 0) ++ goto error_decode; ++ ++ /* Decode the public key */ ++ ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, ++ ctx->key, ctx->key_size); ++ if (ret < 0) ++ goto error_decode; ++ ++ kfree(ctx); ++ return cert; ++ ++error_decode: ++ kfree(ctx); ++error_no_ctx: ++ x509_free_certificate(cert); ++error_no_cert: ++ return ERR_PTR(ret); ++} ++ ++/* ++ * Note an OID when we find one for later processing when we know how ++ * to interpret it. ++ */ ++int x509_note_OID(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ ctx->last_oid = look_up_OID(value, vlen); ++ if (ctx->last_oid == OID__NR) { ++ char buffer[50]; ++ sprint_oid(value, vlen, buffer, sizeof(buffer)); ++ pr_debug("Unknown OID: [%zu] %s\n", ++ (unsigned long)value - ctx->data, buffer); ++ } ++ return 0; ++} ++ ++/* ++ * Save the position of the TBS data so that we can check the signature over it ++ * later. ++ */ ++int x509_note_tbs_certificate(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", ++ hdrlen, tag, (unsigned long)value - ctx->data, vlen); ++ ++ ctx->cert->tbs = value - hdrlen; ++ ctx->cert->tbs_size = vlen + hdrlen; ++ return 0; ++} ++ ++/* ++ * Record the public key algorithm ++ */ ++int x509_note_pkey_algo(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("PubKey Algo: %u\n", ctx->last_oid); ++ ++ switch (ctx->last_oid) { ++ case OID_md2WithRSAEncryption: ++ case OID_md3WithRSAEncryption: ++ default: ++ return -ENOPKG; /* Unsupported combination */ ++ ++ case OID_md4WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_MD5; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha1WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha256WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha384WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha512WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ ++ case OID_sha224WithRSAEncryption: ++ ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; ++ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ break; ++ } ++ ++ ctx->algo_oid = ctx->last_oid; ++ return 0; ++} ++ ++/* ++ * Note the whereabouts and type of the signature. ++ */ ++int x509_note_signature(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); ++ ++ if (ctx->last_oid != ctx->algo_oid) { ++ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", ++ ctx->algo_oid, ctx->last_oid); ++ return -EINVAL; ++ } ++ ++ ctx->cert->sig = value; ++ ctx->cert->sig_size = vlen; ++ return 0; ++} ++ ++/* ++ * Note some of the name segments from which we'll fabricate a name. ++ */ ++int x509_extract_name_segment(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ switch (ctx->last_oid) { ++ case OID_commonName: ++ ctx->cn_size = vlen; ++ ctx->cn_offset = (unsigned long)value - ctx->data; ++ break; ++ case OID_organizationName: ++ ctx->o_size = vlen; ++ ctx->o_offset = (unsigned long)value - ctx->data; ++ break; ++ case OID_email_address: ++ ctx->email_size = vlen; ++ ctx->email_offset = (unsigned long)value - ctx->data; ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Fabricate and save the issuer and subject names ++ */ ++static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, ++ unsigned char tag, ++ char **_name, size_t vlen) ++{ ++ const void *name, *data = (const void *)ctx->data; ++ size_t namesize; ++ char *buffer; ++ ++ if (*_name) ++ return -EINVAL; ++ ++ /* Empty name string if no material */ ++ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { ++ buffer = kmalloc(1, GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ buffer[0] = 0; ++ goto done; ++ } ++ ++ if (ctx->cn_size && ctx->o_size) { ++ /* Consider combining O and CN, but use only the CN if it is ++ * prefixed by the O, or a significant portion thereof. ++ */ ++ namesize = ctx->cn_size; ++ name = data + ctx->cn_offset; ++ if (ctx->cn_size >= ctx->o_size && ++ memcmp(data + ctx->cn_offset, data + ctx->o_offset, ++ ctx->o_size) == 0) ++ goto single_component; ++ if (ctx->cn_size >= 7 && ++ ctx->o_size >= 7 && ++ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) ++ goto single_component; ++ ++ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, ++ GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ ++ memcpy(buffer, ++ data + ctx->o_offset, ctx->o_size); ++ buffer[ctx->o_size + 0] = ':'; ++ buffer[ctx->o_size + 1] = ' '; ++ memcpy(buffer + ctx->o_size + 2, ++ data + ctx->cn_offset, ctx->cn_size); ++ buffer[ctx->o_size + 2 + ctx->cn_size] = 0; ++ goto done; ++ ++ } else if (ctx->cn_size) { ++ namesize = ctx->cn_size; ++ name = data + ctx->cn_offset; ++ } else if (ctx->o_size) { ++ namesize = ctx->o_size; ++ name = data + ctx->o_offset; ++ } else { ++ namesize = ctx->email_size; ++ name = data + ctx->email_offset; ++ } ++ ++single_component: ++ buffer = kmalloc(namesize + 1, GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ memcpy(buffer, name, namesize); ++ buffer[namesize] = 0; ++ ++done: ++ *_name = buffer; ++ ctx->cn_size = 0; ++ ctx->o_size = 0; ++ ctx->email_size = 0; ++ return 0; ++} ++ ++int x509_note_issuer(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); ++} ++ ++int x509_note_subject(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); ++} ++ ++/* ++ * Extract the data for the public key algorithm ++ */ ++int x509_extract_key_data(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ++ if (ctx->last_oid != OID_rsaEncryption) ++ return -ENOPKG; ++ ++ /* There seems to be an extraneous 0 byte on the front of the data */ ++ ctx->cert->pkey_algo = PKEY_ALGO_RSA; ++ ctx->key = value + 1; ++ ctx->key_size = vlen - 1; ++ return 0; ++} ++ ++/* ++ * Extract a RSA public key value ++ */ ++int rsa_extract_mpi(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ MPI mpi; ++ ++ if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { ++ pr_err("Too many public key MPIs in certificate\n"); ++ return -EBADMSG; ++ } ++ ++ mpi = mpi_read_raw_data(value, vlen); ++ if (!mpi) ++ return -ENOMEM; ++ ++ ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; ++ return 0; ++} ++ ++/* ++ * Process certificate extensions that are used to qualify the certificate. ++ */ ++int x509_process_extension(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ const unsigned char *v = value; ++ char *f; ++ int i; ++ ++ pr_debug("Extension: %u\n", ctx->last_oid); ++ ++ if (ctx->last_oid == OID_subjectKeyIdentifier) { ++ /* Get hold of the key fingerprint */ ++ if (vlen < 3) ++ return -EBADMSG; ++ if (v[0] != ASN1_OTS || v[1] != vlen - 2) ++ return -EBADMSG; ++ v += 2; ++ vlen -= 2; ++ ++ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); ++ if (!f) ++ return -ENOMEM; ++ for (i = 0; i < vlen; i++) ++ sprintf(f + i * 2, "%02x", v[i]); ++ pr_debug("fingerprint %s\n", f); ++ ctx->cert->fingerprint = f; ++ return 0; ++ } ++ ++ if (ctx->last_oid == OID_authorityKeyIdentifier) { ++ /* Get hold of the CA key fingerprint */ ++ if (vlen < 5) ++ return -EBADMSG; ++ if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || ++ v[1] != vlen - 2 || ++ v[2] != (ASN1_CONT << 6) || ++ v[3] != vlen - 4) ++ return -EBADMSG; ++ v += 4; ++ vlen -= 4; ++ ++ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); ++ if (!f) ++ return -ENOMEM; ++ for (i = 0; i < vlen; i++) ++ sprintf(f + i * 2, "%02x", v[i]); ++ pr_debug("authority %s\n", f); ++ ctx->cert->authority = f; ++ return 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Record a certificate time. ++ */ ++static int x509_note_time(time_t *_time, size_t hdrlen, ++ unsigned char tag, ++ const unsigned char *value, size_t vlen) ++{ ++ unsigned YY, MM, DD, hh, mm, ss; ++ const unsigned char *p = value; ++ ++#define dec2bin(X) ((X) - '0') ++#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) ++ ++ if (tag == ASN1_UNITIM) { ++ /* UTCTime: YYMMDDHHMMSSZ */ ++ if (vlen != 13) ++ goto unsupported_time; ++ YY = DD2bin(p); ++ if (YY > 50) ++ YY += 1900; ++ else ++ YY += 2000; ++ } else if (tag == ASN1_GENTIM) { ++ /* GenTime: YYYYMMDDHHMMSSZ */ ++ if (vlen != 15) ++ goto unsupported_time; ++ YY = DD2bin(p) * 100 + DD2bin(p); ++ } else { ++ goto unsupported_time; ++ } ++ ++ MM = DD2bin(p); ++ DD = DD2bin(p); ++ hh = DD2bin(p); ++ mm = DD2bin(p); ++ ss = DD2bin(p); ++ ++ if (*p != 'Z') ++ goto unsupported_time; ++ ++ *_time = mktime(YY, MM, DD, hh, mm, ss); ++ return 0; ++ ++unsupported_time: ++ pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", ++ tag, (int)vlen, (int)vlen, value); ++ return -EBADMSG; ++} ++ ++int x509_note_not_before(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); ++} ++ ++int x509_note_not_after(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); ++} +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +new file mode 100644 +index 0000000..635053f +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -0,0 +1,36 @@ ++/* X.509 certificate parser internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++ ++struct x509_certificate { ++ struct x509_certificate *next; ++ struct public_key *pub; /* Public key details */ ++ char *issuer; /* Name of certificate issuer */ ++ char *subject; /* Name of certificate subject */ ++ char *fingerprint; /* Key fingerprint as hex */ ++ char *authority; /* Authority key fingerprint as hex */ ++ time_t valid_from; ++ time_t valid_to; ++ enum pkey_algo pkey_algo : 8; /* Public key algorithm */ ++ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ ++ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ ++ const void *tbs; /* Signed data */ ++ size_t tbs_size; /* Size of signed data */ ++ const void *sig; /* Signature data */ ++ size_t sig_size; /* Size of sigature */ ++}; ++ ++/* ++ * x509_cert_parser.c ++ */ ++extern void x509_free_certificate(struct x509_certificate *cert); ++extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +new file mode 100644 +index 0000000..716917c +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -0,0 +1,207 @@ ++/* Instantiate a public key crypto key from an X.509 Certificate ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "X.509: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++#include "public_key.h" ++#include "x509_parser.h" ++ ++static const ++struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { ++ [PKEY_ALGO_DSA] = NULL, ++#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ ++ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) ++ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, ++#endif ++}; ++ ++/* ++ * Check the signature on a certificate using the provided public key ++ */ ++static int x509_check_signature(const struct public_key *pub, ++ const struct x509_certificate *cert) ++{ ++ struct public_key_signature *sig; ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ ++ /* We allocate the hash operational data storage on the end of our ++ * context data. ++ */ ++ ret = -ENOMEM; ++ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); ++ if (!sig) ++ goto error_no_sig; ++ ++ sig->pkey_hash_algo = cert->sig_hash_algo; ++ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; ++ sig->digest_size = digest_size; ++ ++ desc = (void *)sig + sizeof(*sig); ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ++ ret = -ENOMEM; ++ sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); ++ if (!sig->rsa.s) ++ goto error; ++ ++ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); ++ if (ret < 0) ++ goto error_mpi; ++ ++ ret = pub->algo->verify_signature(pub, sig); ++ ++ pr_debug("Cert Verification: %d\n", ret); ++ ++error_mpi: ++ mpi_free(sig->rsa.s); ++error: ++ kfree(sig); ++error_no_sig: ++ crypto_free_shash(tfm); ++ ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++ ++/* ++ * Attempt to parse a data blob for a key as an X509 certificate. ++ */ ++static int x509_key_preparse(struct key_preparsed_payload *prep) ++{ ++ struct x509_certificate *cert; ++ time_t now; ++ size_t srlen, sulen; ++ char *desc = NULL; ++ int ret; ++ ++ cert = x509_cert_parse(prep->data, prep->datalen); ++ if (IS_ERR(cert)) ++ return PTR_ERR(cert); ++ ++ pr_devel("Cert Issuer: %s\n", cert->issuer); ++ pr_devel("Cert Subject: %s\n", cert->subject); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); ++ pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); ++ pr_devel("Cert Signature: %s + %s\n", ++ pkey_algo[cert->sig_pkey_algo], ++ pkey_hash_algo[cert->sig_hash_algo]); ++ ++ if (!cert->fingerprint || !cert->authority) { ++ pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", ++ cert->subject); ++ ret = -EKEYREJECTED; ++ goto error_free_cert; ++ } ++ ++ now = CURRENT_TIME.tv_sec; ++ if (now < cert->valid_from) { ++ pr_warn("Cert %s is not yet valid\n", cert->fingerprint); ++ ret = -EKEYREJECTED; ++ goto error_free_cert; ++ } ++ if (now >= cert->valid_to) { ++ pr_warn("Cert %s has expired\n", cert->fingerprint); ++ ret = -EKEYEXPIRED; ++ goto error_free_cert; ++ } ++ ++ cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; ++ cert->pub->id_type = PKEY_ID_X509; ++ ++ /* Check the signature on the key */ ++ if (strcmp(cert->fingerprint, cert->authority) == 0) { ++ ret = x509_check_signature(cert->pub, cert); ++ if (ret < 0) ++ goto error_free_cert; ++ } ++ ++ /* Propose a description */ ++ sulen = strlen(cert->subject); ++ srlen = strlen(cert->fingerprint); ++ ret = -ENOMEM; ++ desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); ++ if (!desc) ++ goto error_free_cert; ++ memcpy(desc, cert->subject, sulen); ++ desc[sulen] = ':'; ++ desc[sulen + 1] = ' '; ++ memcpy(desc + sulen + 2, cert->fingerprint, srlen); ++ desc[sulen + 2 + srlen] = 0; ++ ++ /* We're pinning the module by being linked against it */ ++ __module_get(public_key_subtype.owner); ++ prep->type_data[0] = &public_key_subtype; ++ prep->type_data[1] = cert->fingerprint; ++ prep->payload = cert->pub; ++ prep->description = desc; ++ prep->quotalen = 100; ++ ++ /* We've finished with the certificate */ ++ cert->pub = NULL; ++ cert->fingerprint = NULL; ++ desc = NULL; ++ ret = 0; ++ ++error_free_cert: ++ x509_free_certificate(cert); ++ return ret; ++} ++ ++static struct asymmetric_key_parser x509_key_parser = { ++ .owner = THIS_MODULE, ++ .name = "x509", ++ .parse = x509_key_preparse, ++}; ++ ++/* ++ * Module stuff ++ */ ++static int __init x509_key_init(void) ++{ ++ return register_asymmetric_key_parser(&x509_key_parser); ++} ++ ++static void __exit x509_key_exit(void) ++{ ++ unregister_asymmetric_key_parser(&x509_key_parser); ++} ++ ++module_init(x509_key_init); ++module_exit(x509_key_exit); +diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 +new file mode 100644 +index 0000000..4ec7cc6 +--- /dev/null ++++ b/crypto/asymmetric_keys/x509_rsakey.asn1 +@@ -0,0 +1,4 @@ ++RSAPublicKey ::= SEQUENCE { ++ modulus INTEGER ({ rsa_extract_mpi }), -- n ++ publicExponent INTEGER ({ rsa_extract_mpi }) -- e ++ } +-- +1.7.12.1 + + +From a4c3000ab42b11536ffc8eb9c1d03a746b424bda Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:09:50 +0100 +Subject: [PATCH 18/37] MODSIGN: Add FIPS policy + +If we're in FIPS mode, we should panic if we fail to verify the signature on a +module or we're asked to load an unsigned module in signature enforcing mode. +Possibly FIPS mode should automatically enable enforcing mode. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + kernel/module.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/module.c b/kernel/module.c +index 7efb415..3e8b1a7 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include "module-internal.h" + + #define CREATE_TRACE_POINTS +@@ -2467,6 +2468,9 @@ static int module_sig_check(struct load_info *info, + } + + /* Not having a signature is only an error if we're strict. */ ++ if (err < 0 && fips_enabled) ++ panic("Module verification failed with error %d in FIPS mode\n", ++ err); + if (err == -ENOKEY && !sig_enforce) + err = 0; + +-- +1.7.12.1 + + +From 86342ab6db2c5b10b08bd9d1064b1779070c2a82 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:09:50 +0100 +Subject: [PATCH 19/37] MODSIGN: Provide gitignore and make clean rules for + extra files + +Provide gitignore and make clean rules for extra files to hide and clean up the +extra files produced by module signing stuff once it is added. Also add a +clean up rule for the module content extractor program used to extract the data +to be signed. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + .gitignore | 14 ++++++++++++++ + Makefile | 1 + + 2 files changed, 15 insertions(+) + +diff --git a/.gitignore b/.gitignore +index 57af07c..0f2f40f 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -14,6 +14,10 @@ + *.o.* + *.a + *.s ++*.ko.unsigned ++*.ko.stripped ++*.ko.stripped.dig ++*.ko.stripped.sig + *.ko + *.so + *.so.dbg +@@ -84,3 +88,13 @@ GTAGS + *.orig + *~ + \#*# ++ ++# ++# Leavings from module signing ++# ++extra_certificates ++signing_key.priv ++signing_key.x509 ++signing_key.x509.keyid ++signing_key.x509.signer ++x509.genkey +diff --git a/Makefile b/Makefile +index 6cdadf4..b4f9eb5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ ++ -o -name '*.ko.*' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ +-- +1.7.12.1 + + +From c631aa86c295b87aa09188d9313cccf41e5db23f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:09:50 +0100 +Subject: [PATCH 20/37] MODSIGN: Provide Kconfig options + +Provide kernel configuration options for module signing. + +The following configuration options are added: + + CONFIG_MODULE_SIG_SHA1 + CONFIG_MODULE_SIG_SHA224 + CONFIG_MODULE_SIG_SHA256 + CONFIG_MODULE_SIG_SHA384 + CONFIG_MODULE_SIG_SHA512 + +These select the cryptographic hash used to digest the data prior to signing. +Additionally, the crypto module selected will be built into the kernel as it +won't be possible to load it as a module without incurring a circular +dependency when the kernel tries to check its signature. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/init/Kconfig b/init/Kconfig +index fa8ccad..00d4579 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1593,12 +1593,50 @@ config MODULE_SIG + is simply appended to the module. For more information see + Documentation/module-signing.txt. + ++ !!!WARNING!!! If you enable this option, you MUST make sure that the ++ module DOES NOT get stripped after being signed. This includes the ++ debuginfo strip done by some packagers (such as rpmbuild) and ++ inclusion into an initramfs that wants the module size reduced. ++ + config MODULE_SIG_FORCE + bool "Require modules to be validly signed" + depends on MODULE_SIG + help + Reject unsigned modules or signed modules for which we don't have a + key. Without this, such modules will simply taint the kernel. ++ ++choice ++ prompt "Which hash algorithm should modules be signed with?" ++ depends on MODULE_SIG ++ help ++ This determines which sort of hashing algorithm will be used during ++ signature generation. This algorithm _must_ be built into the kernel ++ directly so that signature verification can take place. It is not ++ possible to load a signed module containing the algorithm to check ++ the signature on that module. ++ ++config MODULE_SIG_SHA1 ++ bool "Sign modules with SHA-1" ++ select CRYPTO_SHA1 ++ ++config MODULE_SIG_SHA224 ++ bool "Sign modules with SHA-224" ++ select CRYPTO_SHA256 ++ ++config MODULE_SIG_SHA256 ++ bool "Sign modules with SHA-256" ++ select CRYPTO_SHA256 ++ ++config MODULE_SIG_SHA384 ++ bool "Sign modules with SHA-384" ++ select CRYPTO_SHA512 ++ ++config MODULE_SIG_SHA512 ++ bool "Sign modules with SHA-512" ++ select CRYPTO_SHA512 ++ ++endchoice ++ + endif # MODULES + + config INIT_ALL_POSSIBLE +-- +1.7.12.1 + + +From 84d1788d1ea47ecfe2d30d0c2081055d7e89441d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:09:51 +0100 +Subject: [PATCH 21/37] MODSIGN: Automatically generate module signing keys if + missing + +Automatically generate keys for module signing if they're absent so that +allyesconfig doesn't break. The builder should consider generating their own +key and certificate, however, so that the keys are appropriately named. + +The private key for the module signer should be placed in signing_key.priv +(unencrypted!) and the public key in an X.509 certificate as signing_key.x509. + +If a transient key is desired for signing the modules, a config file for +'openssl req' can be placed in x509.genkey, looking something like the +following: + + [ req ] + default_bits = 4096 + distinguished_name = req_distinguished_name + prompt = no + x509_extensions = myexts + + [ req_distinguished_name ] + O = Magarathea + CN = Glacier signing key + emailAddress = slartibartfast@magrathea.h2g2 + + [ myexts ] + basicConstraints=critical,CA:FALSE + keyUsage=digitalSignature + subjectKeyIdentifier=hash + authorityKeyIdentifier=hash + +The build process will use this to configure: + + openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ + -x509 -config x509.genkey \ + -outform DER -out signing_key.x509 \ + -keyout signing_key.priv + +to generate the key. + +Note that it is required that the X.509 certificate have a subjectKeyIdentifier +and an authorityKeyIdentifier. Without those, the certificate will be +rejected. These can be used to check the validity of a certificate. + +Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey, +whether or not they were generated automatically. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 08ba8a6..58c6f11 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ + targets += timeconst.h + $(obj)/timeconst.h: $(src)/timeconst.pl FORCE + $(call if_changed,timeconst) ++ ++ifeq ($(CONFIG_MODULE_SIG),y) ++ ++############################################################################### ++# ++# If module signing is requested, say by allyesconfig, but a key has not been ++# supplied, then one will need to be generated to make sure the build does not ++# fail and that the kernel may be used afterwards. ++# ++############################################################################### ++signing_key.priv signing_key.x509: x509.genkey ++ @echo "###" ++ @echo "### Now generating an X.509 key pair to be used for signing modules." ++ @echo "###" ++ @echo "### If this takes a long time, you might wish to run rngd in the" ++ @echo "### background to keep the supply of entropy topped up. It" ++ @echo "### needs to be run as root, and should use a hardware random" ++ @echo "### number generator if one is available, eg:" ++ @echo "###" ++ @echo "### rngd -r /dev/hwrandom" ++ @echo "###" ++ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ ++ -x509 -config x509.genkey \ ++ -outform DER -out signing_key.x509 \ ++ -keyout signing_key.priv ++ @echo "###" ++ @echo "### Key pair generated." ++ @echo "###" ++ ++x509.genkey: ++ @echo Generating X.509 key generation config ++ @echo >x509.genkey "[ req ]" ++ @echo >>x509.genkey "default_bits = 4096" ++ @echo >>x509.genkey "distinguished_name = req_distinguished_name" ++ @echo >>x509.genkey "prompt = no" ++ @echo >>x509.genkey "x509_extensions = myexts" ++ @echo >>x509.genkey ++ @echo >>x509.genkey "[ req_distinguished_name ]" ++ @echo >>x509.genkey "O = Magrathea" ++ @echo >>x509.genkey "CN = Glacier signing key" ++ @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" ++ @echo >>x509.genkey ++ @echo >>x509.genkey "[ myexts ]" ++ @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" ++ @echo >>x509.genkey "keyUsage=digitalSignature" ++ @echo >>x509.genkey "subjectKeyIdentifier=hash" ++ @echo >>x509.genkey "authorityKeyIdentifier=keyid" ++endif ++CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey +-- +1.7.12.1 + + +From 51da59e56f0666efe97c376830dffefdfcecd21f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:09:51 +0100 +Subject: [PATCH 22/37] MODSIGN: Provide module signing public keys to the + kernel + +Include a PGP keyring containing the public keys required to perform module +verification in the kernel image during build and create a special keyring +during boot which is then populated with keys of crypto type holding the public +keys found in the PGP keyring. + +These can be seen by root: + +[root@andromeda ~]# cat /proc/keys +07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] +15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 +... + +It is probably worth permitting root to invalidate these keys, resulting in +their removal and preventing further modules from being loaded with that key. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + kernel/Makefile | 11 ++++- + kernel/modsign_pubkey.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ + kernel/module-internal.h | 2 + + 3 files changed, 124 insertions(+), 2 deletions(-) + create mode 100644 kernel/modsign_pubkey.c + +diff --git a/kernel/Makefile b/kernel/Makefile +index 58c6f11..111a845 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,7 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o +-obj-$(CONFIG_MODULE_SIG) += module_signing.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE + $(call if_changed,timeconst) + + ifeq ($(CONFIG_MODULE_SIG),y) ++# ++# Pull the signing certificate and any extra certificates into the kernel ++# ++extra_certificates: ++ touch $@ ++ ++kernel/modsign_pubkey.o: signing_key.x509 extra_certificates + + ############################################################################### + # +@@ -180,4 +187,4 @@ x509.genkey: + @echo >>x509.genkey "subjectKeyIdentifier=hash" + @echo >>x509.genkey "authorityKeyIdentifier=keyid" + endif +-CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey ++CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +new file mode 100644 +index 0000000..4646eb2 +--- /dev/null ++++ b/kernel/modsign_pubkey.c +@@ -0,0 +1,113 @@ ++/* Public keys for module signature verification ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++struct key *modsign_keyring; ++ ++extern __initdata const u8 modsign_certificate_list[]; ++extern __initdata const u8 modsign_certificate_list_end[]; ++asm(".section .init.data,\"aw\"\n" ++ "modsign_certificate_list:\n" ++ ".incbin \"signing_key.x509\"\n" ++ ".incbin \"extra_certificates\"\n" ++ "modsign_certificate_list_end:" ++ ); ++ ++/* ++ * We need to make sure ccache doesn't cache the .o file as it doesn't notice ++ * if modsign.pub changes. ++ */ ++static __initdata const char annoy_ccache[] = __TIME__ "foo"; ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int module_verify_init(void) ++{ ++ pr_notice("Initialise module verification\n"); ++ ++ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", ++ KUIDT_INIT(0), KGIDT_INIT(0), ++ current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_keyring)) ++ panic("Can't allocate module signing keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module signing keyring\n"); ++ ++ return 0; ++} ++ ++/* ++ * Must be initialised before we try and load the keys into the keyring. ++ */ ++device_initcall(module_verify_init); ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int load_module_signing_keys(void) ++{ ++ key_ref_t key; ++ const u8 *p, *end; ++ size_t plen; ++ ++ pr_notice("Loading module verification certificates\n"); ++ ++ end = modsign_certificate_list_end; ++ p = modsign_certificate_list; ++ while (p < end) { ++ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more ++ * than 256 bytes in size. ++ */ ++ if (end - p < 4) ++ goto dodgy_cert; ++ if (p[0] != 0x30 && ++ p[1] != 0x82) ++ goto dodgy_cert; ++ plen = (p[2] << 8) | p[3]; ++ plen += 4; ++ if (plen > end - p) ++ goto dodgy_cert; ++ ++ key = key_create_or_update(make_key_ref(modsign_keyring, 1), ++ "asymmetric", ++ NULL, ++ p, ++ plen, ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(key)) ++ pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("MODSIGN: Loaded cert '%s'\n", ++ key_ref_to_ptr(key)->description); ++ p += plen; ++ } ++ ++ return 0; ++ ++dodgy_cert: ++ pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); ++ return 0; ++} ++late_initcall(load_module_signing_keys); +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 033c17f..6114a13 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -9,5 +9,7 @@ + * 2 of the Licence, or (at your option) any later version. + */ + ++extern struct key *modsign_keyring; ++ + extern int mod_verify_sig(const void *mod, unsigned long modlen, + const void *sig, unsigned long siglen); +-- +1.7.12.1 + + +From 81a8def438b252dac4aa9c7eda39ad517bfe51ac Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:11:03 +0100 +Subject: [PATCH 23/37] MODSIGN: Implement module signature checking + +Check the signature on the module against the keys compiled into the kernel or +available in a hardware key store. + +Currently, only RSA keys are supported - though that's easy enough to change, +and the signature is expected to contain raw components (so not a PGP or +PKCS#7 formatted blob). + +The signature blob is expected to consist of the following pieces in order: + + (1) The binary identifier for the key. This is expected to match the + SubjectKeyIdentifier from an X.509 certificate. Only X.509 type + identifiers are currently supported. + + (2) The signature data, consisting of a series of MPIs in which each is in + the format of a 2-byte BE word sizes followed by the content data. + + (3) A 12 byte information block of the form: + + struct module_signature { + enum pkey_algo algo : 8; + enum pkey_hash_algo hash : 8; + enum pkey_id_type id_type : 8; + u8 __pad; + __be32 id_length; + __be32 sig_length; + }; + + The three enums are defined in crypto/public_key.h. + + 'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA). + + 'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1, + etc.). + + 'id_type' contains the public-key identifier type (0->PGP, 1->X.509). + + '__pad' should be 0. + + 'id_length' should contain in the binary identifier length in BE form. + + 'sig_length' should contain in the signature data length in BE form. + + The lengths are in BE order rather than CPU order to make dealing with + cross-compilation easier. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell (minor Kconfig fix) +--- + init/Kconfig | 8 ++ + kernel/module_signing.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 229 insertions(+), 1 deletion(-) + +diff --git a/init/Kconfig b/init/Kconfig +index 00d4579..abc6e63 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL + config MODULE_SIG + bool "Module signature verification" + depends on MODULES ++ select KEYS ++ select CRYPTO ++ select ASYMMETRIC_KEY_TYPE ++ select ASYMMETRIC_PUBLIC_KEY_SUBTYPE ++ select PUBLIC_KEY_ALGO_RSA ++ select ASN1 ++ select OID_REGISTRY ++ select X509_CERTIFICATE_PARSER + help + Check modules for valid signatures upon load: the signature + is simply appended to the module. For more information see +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 499728a..6b09f69 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -11,13 +11,233 @@ + + #include + #include ++#include ++#include ++#include + #include "module-internal.h" + + /* ++ * Module signature information block. ++ * ++ * The constituents of the signature section are, in order: ++ * ++ * - Signer's name ++ * - Key identifier ++ * - Signature data ++ * - Information block ++ */ ++struct module_signature { ++ enum pkey_algo algo : 8; /* Public-key crypto algorithm */ ++ enum pkey_hash_algo hash : 8; /* Digest algorithm */ ++ enum pkey_id_type id_type : 8; /* Key identifier type */ ++ u8 signer_len; /* Length of signer's name */ ++ u8 key_id_len; /* Length of key identifier */ ++ u8 __pad[3]; ++ __be32 sig_len; /* Length of signature data */ ++}; ++ ++/* ++ * Digest the module contents. ++ */ ++static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, ++ const void *mod, ++ unsigned long modlen) ++{ ++ struct public_key_signature *pks; ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ int ret; ++ ++ pr_devel("==>%s()\n", __func__); ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ ++ /* We allocate the hash operational data storage on the end of our ++ * context data and the digest output buffer on the end of that. ++ */ ++ ret = -ENOMEM; ++ pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); ++ if (!pks) ++ goto error_no_pks; ++ ++ pks->pkey_hash_algo = hash; ++ pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; ++ pks->digest_size = digest_size; ++ ++ desc = (void *)pks + sizeof(*pks); ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ++ ret = crypto_shash_finup(desc, mod, modlen, pks->digest); ++ if (ret < 0) ++ goto error; ++ ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = ok\n", __func__); ++ return pks; ++ ++error: ++ kfree(pks); ++error_no_pks: ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ERR_PTR(ret); ++} ++ ++/* ++ * Extract an MPI array from the signature data. This represents the actual ++ * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the ++ * size of the MPI in bytes. ++ * ++ * RSA signatures only have one MPI, so currently we only read one. ++ */ ++static int mod_extract_mpi_array(struct public_key_signature *pks, ++ const void *data, size_t len) ++{ ++ size_t nbytes; ++ MPI mpi; ++ ++ if (len < 3) ++ return -EBADMSG; ++ nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; ++ data += 2; ++ len -= 2; ++ if (len != nbytes) ++ return -EBADMSG; ++ ++ mpi = mpi_read_raw_data(data, nbytes); ++ if (!mpi) ++ return -ENOMEM; ++ pks->mpi[0] = mpi; ++ pks->nr_mpi = 1; ++ return 0; ++} ++ ++/* ++ * Request an asymmetric key. ++ */ ++static struct key *request_asymmetric_key(const char *signer, size_t signer_len, ++ const u8 *key_id, size_t key_id_len) ++{ ++ key_ref_t key; ++ size_t i; ++ char *id, *q; ++ ++ pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); ++ ++ /* Construct an identifier. */ ++ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); ++ if (!id) ++ return ERR_PTR(-ENOKEY); ++ ++ memcpy(id, signer, signer_len); ++ ++ q = id + signer_len; ++ *q++ = ':'; ++ *q++ = ' '; ++ for (i = 0; i < key_id_len; i++) { ++ *q++ = hex_asc[*key_id >> 4]; ++ *q++ = hex_asc[*key_id++ & 0x0f]; ++ } ++ ++ *q = 0; ++ ++ pr_debug("Look up: \"%s\"\n", id); ++ ++ key = keyring_search(make_key_ref(modsign_keyring, 1), ++ &key_type_asymmetric, id); ++ if (IS_ERR(key)) ++ pr_warn("Request for unknown module key '%s' err %ld\n", ++ id, PTR_ERR(key)); ++ kfree(id); ++ ++ if (IS_ERR(key)) { ++ switch (PTR_ERR(key)) { ++ /* Hide some search errors */ ++ case -EACCES: ++ case -ENOTDIR: ++ case -EAGAIN: ++ return ERR_PTR(-ENOKEY); ++ default: ++ return ERR_CAST(key); ++ } ++ } ++ ++ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); ++ return key_ref_to_ptr(key); ++} ++ ++/* + * Verify the signature on a module. + */ + int mod_verify_sig(const void *mod, unsigned long modlen, + const void *sig, unsigned long siglen) + { +- return -ENOKEY; ++ struct public_key_signature *pks; ++ struct module_signature ms; ++ struct key *key; ++ size_t sig_len; ++ int ret; ++ ++ pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); ++ ++ if (siglen <= sizeof(ms)) ++ return -EBADMSG; ++ ++ memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); ++ siglen -= sizeof(ms); ++ ++ sig_len = be32_to_cpu(ms.sig_len); ++ if (sig_len >= siglen || ++ siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) ++ return -EBADMSG; ++ ++ /* For the moment, only support RSA and X.509 identifiers */ ++ if (ms.algo != PKEY_ALGO_RSA || ++ ms.id_type != PKEY_ID_X509) ++ return -ENOPKG; ++ ++ if (ms.hash >= PKEY_HASH__LAST || ++ !pkey_hash_algo[ms.hash]) ++ return -ENOPKG; ++ ++ key = request_asymmetric_key(sig, ms.signer_len, ++ sig + ms.signer_len, ms.key_id_len); ++ if (IS_ERR(key)) ++ return PTR_ERR(key); ++ ++ pks = mod_make_digest(ms.hash, mod, modlen); ++ if (IS_ERR(pks)) { ++ ret = PTR_ERR(pks); ++ goto error_put_key; ++ } ++ ++ ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, ++ sig_len); ++ if (ret < 0) ++ goto error_free_pks; ++ ++ ret = verify_signature(key, pks); ++ pr_devel("verify_signature() = %d\n", ret); ++ ++error_free_pks: ++ mpi_free(pks->rsa.s); ++ kfree(pks); ++error_put_key: ++ key_put(key); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; + } +-- +1.7.12.1 + + +From 952f5922dd45a25f7896843df02aec2250c41f42 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:11:06 +0100 +Subject: [PATCH 24/37] MODSIGN: Provide a script for generating a key ID from + an X.509 cert + +Provide a script to parse an X.509 certificate and certain pieces of +information from it in order to generate a key identifier to be included within +a module signature. + +The script takes the Subject Name and extracts (if present) the +organizationName (O), the commonName (CN) and the emailAddress and fabricates +the signer's name from them: + + (1) If both O and CN exist, then the name will be "O: CN", unless: + + (a) CN is prefixed by O, in which case only CN is used. + + (b) CN and O share at least the first 7 characters, in which case only CN + is used. + + (2) Otherwise, CN is used if present. + + (3) Otherwise, O is used if present. + + (4) Otherwise the emailAddress is used, if present. + + (5) Otherwise a blank name is used. + +The script emits a binary encoded identifier in the following form: + + - 2 BE bytes indicating the length of the signer's name. + + - 2 BE bytes indicating the length of the subject key identifier. + + - The characters of the signer's name. + + - The bytes of the subject key identifier. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 268 insertions(+) + create mode 100755 scripts/x509keyid + +diff --git a/scripts/x509keyid b/scripts/x509keyid +new file mode 100755 +index 0000000..c8e91a4 +--- /dev/null ++++ b/scripts/x509keyid +@@ -0,0 +1,268 @@ ++#!/usr/bin/perl -w ++# ++# Generate an identifier from an X.509 certificate that can be placed in a ++# module signature to indentify the key to use. ++# ++# Format: ++# ++# ./scripts/x509keyid ++# ++# We read the DER-encoded X509 certificate and parse it to extract the Subject ++# name and Subject Key Identifier. The provide the data we need to build the ++# certificate identifier. ++# ++# The signer's name part of the identifier is fabricated from the commonName, ++# the organizationName or the emailAddress components of the X.509 subject ++# name and written to the second named file. ++# ++# The subject key ID to select which of that signer's certificates we're ++# intending to use to sign the module is written to the third named file. ++# ++use strict; ++ ++my $raw_data; ++ ++die "Need three filenames\n" if ($#ARGV != 2); ++ ++my $src = $ARGV[0]; ++ ++open(FD, "<$src") || die $src; ++binmode FD; ++my @st = stat(FD); ++die $src if (!@st); ++read(FD, $raw_data, $st[7]) || die $src; ++close(FD); ++ ++my $UNIV = 0 << 6; ++my $APPL = 1 << 6; ++my $CONT = 2 << 6; ++my $PRIV = 3 << 6; ++ ++my $CONS = 0x20; ++ ++my $BOOLEAN = 0x01; ++my $INTEGER = 0x02; ++my $BIT_STRING = 0x03; ++my $OCTET_STRING = 0x04; ++my $NULL = 0x05; ++my $OBJ_ID = 0x06; ++my $UTF8String = 0x0c; ++my $SEQUENCE = 0x10; ++my $SET = 0x11; ++my $UTCTime = 0x17; ++my $GeneralizedTime = 0x18; ++ ++my %OIDs = ( ++ pack("CCC", 85, 4, 3) => "commonName", ++ pack("CCC", 85, 4, 6) => "countryName", ++ pack("CCC", 85, 4, 10) => "organizationName", ++ pack("CCC", 85, 4, 11) => "organizationUnitName", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", ++ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", ++ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", ++ pack("CCC", 85, 29, 19) => "basicConstraints" ++); ++ ++############################################################################### ++# ++# Extract an ASN.1 element from a string and return information about it. ++# ++############################################################################### ++sub asn1_extract($$@) ++{ ++ my ($cursor, $expected_tag, $optional) = @_; ++ ++ return [ -1 ] ++ if ($cursor->[1] == 0 && $optional); ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" ++ if ($cursor->[1] < 2); ++ ++ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ ++ if ($expected_tag != -1 && $tag != $expected_tag) { ++ return [ -1 ] ++ if ($optional); ++ die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, ++ " not ", $expected_tag, ")\n"; ++ } ++ ++ $cursor->[0] += 2; ++ $cursor->[1] -= 2; ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" ++ if (($tag & 0x1f) == 0x1f); ++ die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" ++ if ($len == 0x80); ++ ++ if ($len > 0x80) { ++ my $l = $len - 0x80; ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" ++ if ($cursor->[1] < $l); ++ ++ if ($l == 0x1) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); ++ } elsif ($l = 0x2) { ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ } elsif ($l = 0x3) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); ++ } elsif ($l = 0x4) { ++ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); ++ } else { ++ die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; ++ } ++ ++ $cursor->[0] += $l; ++ $cursor->[1] -= $l; ++ } ++ ++ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" ++ if ($cursor->[1] < $len); ++ ++ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; ++ $cursor->[0] += $len; ++ $cursor->[1] -= $len; ++ ++ return $ret; ++} ++ ++############################################################################### ++# ++# Retrieve the data referred to by a cursor ++# ++############################################################################### ++sub asn1_retrieve($) ++{ ++ my ($cursor) = @_; ++ my ($offset, $len, $data) = @$cursor; ++ return substr($$data, $offset, $len); ++} ++ ++############################################################################### ++# ++# Roughly parse the X.509 certificate ++# ++############################################################################### ++my $cursor = [ 0, length($raw_data), \$raw_data ]; ++ ++my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); ++my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); ++my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); ++my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); ++my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); ++my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); ++my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); ++ ++my $subject_key_id = (); ++my $authority_key_id = (); ++ ++# ++# Parse the extension list ++# ++if ($extension_list->[0] != -1) { ++ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); ++ ++ while ($extensions->[1]->[1] > 0) { ++ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); ++ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); ++ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); ++ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); ++ ++ my $raw_oid = asn1_retrieve($x_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $x_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($x_val->[1]); ++ ++ if ($x_type eq "subjectKeyIdentifier") { ++ my $vcursor = [ 0, length($raw_value), \$raw_value ]; ++ ++ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); ++ } ++ } ++} ++ ++############################################################################### ++# ++# Determine what we're going to use as the signer's name. In order of ++# preference, take one of: commonName, organizationName or emailAddress. ++# ++############################################################################### ++my $org = ""; ++my $cn = ""; ++my $email = ""; ++ ++while ($subject->[1]->[1] > 0) { ++ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); ++ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); ++ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); ++ my $n_val = asn1_extract($attr->[1], -1); ++ ++ my $raw_oid = asn1_retrieve($n_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $n_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($n_val->[1]); ++ ++ if ($n_type eq "organizationName") { ++ $org = $raw_value; ++ } elsif ($n_type eq "commonName") { ++ $cn = $raw_value; ++ } elsif ($n_type eq "emailAddress") { ++ $email = $raw_value; ++ } ++} ++ ++my $id_name = $email; ++ ++if ($org && $cn) { ++ # Don't use the organizationName if the commonName repeats it ++ if (length($org) <= length($cn) && ++ substr($cn, 0, length($org)) eq $org) { ++ $id_name = $cn; ++ goto got_id_name; ++ } ++ ++ # Or a signifcant chunk of it ++ if (length($org) >= 7 && ++ length($cn) >= 7 && ++ substr($cn, 0, 7) eq substr($org, 0, 7)) { ++ $id_name = $cn; ++ goto got_id_name; ++ } ++ ++ $id_name = $org . ": " . $cn; ++} elsif ($org) { ++ $id_name = $org; ++} elsif ($cn) { ++ $id_name = $cn; ++} ++ ++got_id_name: ++ ++############################################################################### ++# ++# Output the signer's name and the key identifier that we're going to include ++# in module signatures. ++# ++############################################################################### ++die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" ++ if (!$subject_key_id); ++ ++my $id_key_id = asn1_retrieve($subject_key_id->[1]); ++ ++open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; ++print OUTFD $id_name; ++close OUTFD || die $ARGV[1]; ++ ++open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; ++print OUTFD $id_key_id; ++close OUTFD || die $ARGV[2]; +-- +1.7.12.1 + + +From 52a1f2ba9612d689f1a5ed6c1a03bd784f34bf1c Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Sep 2012 10:11:06 +0100 +Subject: [PATCH 25/37] MODSIGN: Sign modules during the build process + +If CONFIG_MODULE_SIG is set, then this patch will cause all modules files to +to have signatures added. The following steps will occur: + + (1) The module will be linked to foo.ko.unsigned instead of foo.ko + + (2) The module will be stripped using both "strip -x -g" and "eu-strip" to + ensure minimal size for inclusion in an initramfs. + + (3) The signature will be generated on the stripped module. + + (4) The signature will be appended to the module, along with some information + about the signature and a magic string that indicates the presence of the + signature. + +Step (3) requires private and public keys to be available. By default these +are expected to be found in files: + + signing_key.priv + signing_key.x509 + +in the base directory of the build. The first is the private key in PEM form +and the second is the X.509 certificate in DER form as can be generated from +openssl: + + openssl req \ + -new -x509 -outform PEM -out signing_key.x509 \ + -keyout signing_key.priv -nodes \ + -subj "/CN=H2G2/O=Magrathea/CN=Slartibartfast" + +If the secret key is not found then signing will be skipped and the unsigned +module from (1) will just be copied to foo.ko. + +If signing occurs, lines like the following will be seen: + + LD [M] fs/foo/foo.ko.unsigned + STRIP [M] fs/foo/foo.ko.stripped + SIGN [M] fs/foo/foo.ko + +will appear in the build log. If the signature step will be skipped and the +following will be seen: + + LD [M] fs/foo/foo.ko.unsigned + STRIP [M] fs/foo/foo.ko.stripped + NO SIGN [M] fs/foo/foo.ko + +NOTE! After the signature step, the signed module _must_not_ be passed through +strip. The unstripped, unsigned module is still available at the name on the +LD [M] line. This restriction may affect packaging tools (such as rpmbuild) +and initramfs composition tools. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + scripts/Makefile.modpost | 77 ++++++++++++++++++++++++++++++- + scripts/sign-file | 115 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 191 insertions(+), 1 deletion(-) + create mode 100644 scripts/sign-file + +diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost +index 08dce14..2a4d1a1 100644 +--- a/scripts/Makefile.modpost ++++ b/scripts/Makefile.modpost +@@ -14,7 +14,8 @@ + # 3) create one .mod.c file pr. module + # 4) create one Module.symvers file with CRC for all exported symbols + # 5) compile all .mod.c files +-# 6) final link of the module to a file ++# 6) final link of the module to a (or ) file ++# 7) signs the modules to a file + + # Step 3 is used to place certain information in the module's ELF + # section, including information such as: +@@ -32,6 +33,8 @@ + # Step 4 is solely used to allow module versioning in external modules, + # where the CRC of each module is retrieved from the Module.symvers file. + ++# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. ++ + # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined + # symbols in the final module linking stage + # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. +@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE + targets += $(modules:.ko=.mod.o) + + # Step 6), final link of the modules ++ifneq ($(CONFIG_MODULE_SIG),y) + quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ +@@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE + $(call if_changed,ld_ko_o) + + targets += $(modules) ++else ++quiet_cmd_ld_ko_unsigned_o = LD [M] $@ ++ cmd_ld_ko_unsigned_o = \ ++ $(LD) -r $(LDFLAGS) \ ++ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ ++ -o $@ $(filter-out FORCE,$^) \ ++ $(if $(AFTER_LINK),; $(AFTER_LINK)) ++ ++$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE ++ $(call if_changed,ld_ko_unsigned_o) ++ ++targets += $(modules:.ko=.ko.unsigned) ++ ++# Step 7), sign the modules ++MODSECKEY = ./signing_key.priv ++MODPUBKEY = ./signing_key.x509 ++ ++ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) ++ifeq ($(KBUILD_SRC),) ++ # no O= is being used ++ SCRIPTS_DIR := scripts ++else ++ SCRIPTS_DIR := $(KBUILD_SRC)/scripts ++endif ++SIGN_MODULES := 1 ++else ++SIGN_MODULES := 0 ++endif ++ ++# only sign if it's an in-tree module ++ifneq ($(KBUILD_EXTMOD),) ++SIGN_MODULES := 0 ++endif + ++# We strip the module as best we can - note that using both strip and eu-strip ++# results in a smaller module than using either alone. ++EU_STRIP = $(shell which eu-strip || echo true) ++ ++quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ ++ cmd_sign_ko_stripped_ko_unsigned = \ ++ cp $< $@ && \ ++ strip -x -g $@ && \ ++ $(EU_STRIP) $@ ++ ++ifeq ($(SIGN_MODULES),1) ++ ++quiet_cmd_genkeyid = GENKEYID $@ ++ cmd_genkeyid = \ ++ perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid ++ ++%.signer %.keyid: % ++ $(call if_changed,genkeyid) ++ ++KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid ++quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ ++ cmd_sign_ko_ko_stripped = \ ++ sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ ++else ++KEYRING_DEP := ++quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ ++ cmd_sign_ko_ko_unsigned = \ ++ cp $< $@ ++endif ++ ++$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE ++ $(call if_changed,sign_ko_ko_stripped) ++ ++$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE ++ $(call if_changed,sign_ko_stripped_ko_unsigned) ++ ++targets += $(modules) ++endif + + # Add FORCE to the prequisites of a target to force it to be always rebuilt. + # --------------------------------------------------------------------------- +diff --git a/scripts/sign-file b/scripts/sign-file +new file mode 100644 +index 0000000..e58e34e +--- /dev/null ++++ b/scripts/sign-file +@@ -0,0 +1,115 @@ ++#!/bin/sh ++# ++# Sign a module file using the given key. ++# ++# Format: sign-file ++# ++ ++scripts=`dirname $0` ++ ++CONFIG_MODULE_SIG_SHA512=y ++if [ -r .config ] ++then ++ . ./.config ++fi ++ ++key="$1" ++x509="$2" ++src="$3" ++dst="$4" ++ ++if [ ! -r "$key" ] ++then ++ echo "Can't read private key" >&2 ++ exit 2 ++fi ++ ++if [ ! -r "$x509" ] ++then ++ echo "Can't read X.509 certificate" >&2 ++ exit 2 ++fi ++if [ ! -r "$x509.signer" ] ++then ++ echo "Can't read Signer name" >&2 ++ exit 2; ++fi ++if [ ! -r "$x509.keyid" ] ++then ++ echo "Can't read Key identifier" >&2 ++ exit 2; ++fi ++ ++# ++# Signature parameters ++# ++algo=1 # Public-key crypto algorithm: RSA ++hash= # Digest algorithm ++id_type=1 # Identifier type: X.509 ++ ++# ++# Digest the data ++# ++dgst= ++if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] ++then ++ prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" ++ dgst=-sha1 ++ hash=2 ++elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] ++then ++ prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" ++ dgst=-sha224 ++ hash=7 ++elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] ++then ++ prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" ++ dgst=-sha256 ++ hash=4 ++elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] ++then ++ prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" ++ dgst=-sha384 ++ hash=5 ++elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] ++then ++ prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" ++ dgst=-sha512 ++ hash=6 ++else ++ echo "$0: Can't determine hash algorithm" >&2 ++ exit 2 ++fi ++ ++( ++perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? ++openssl dgst $dgst -binary $src || exit $? ++) >$src.dig || exit $? ++ ++# ++# Generate the binary signature, which will be just the integer that comprises ++# the signature with no metadata attached. ++# ++openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? ++signerlen=`stat -c %s $x509.signer` ++keyidlen=`stat -c %s $x509.keyid` ++siglen=`stat -c %s $src.sig` ++ ++# ++# Build the signed binary ++# ++( ++ cat $src || exit $? ++ echo '~Module signature appended~' || exit $? ++ cat $x509.signer $x509.keyid || exit $? ++ ++ # Preface each signature integer with a 2-byte BE length ++ perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? ++ cat $src.sig || exit $? ++ ++ # Generate the information block ++ perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? ++) >$dst~ || exit $? ++ ++# Permit in-place signing ++mv $dst~ $dst || exit $? +-- +1.7.12.1 + + +From 1e9ce85a6c40e2c0ba6c589605ceb565b1c83784 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 28 Sep 2012 11:16:57 +0100 +Subject: [PATCH 26/37] MODSIGN: Use the same digest for the autogen key sig + as for the module sig + +Use the same digest type for the autogenerated key signature as for the module +signature so that the hash algorithm is guaranteed to be present in the kernel. + +Without this, the X.509 certificate loader may reject the X.509 certificate so +generated because it was self-signed and the signature will be checked against +itself - but this won't work if the digest algorithm must be loaded as a +module. + +The symptom is that the key fails to load with the following message emitted +into the kernel log: + + MODSIGN: Problem loading in-kernel X.509 certificate (-65) + +the error in brackets being -ENOPKG. What you should see is something like: + + MODSIGN: Loaded cert 'Magarathea: Glacier signing key: 9588321144239a119d3406d4c4cf1fbae1836fa0' + +Note that this doesn't apply to certificates that are not self-signed as we +don't check those currently as they require the parent CA certificate to be +available. + +Reported-by: Rusty Russell +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + kernel/Makefile | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 111a845..a799029 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -149,6 +149,26 @@ kernel/modsign_pubkey.o: signing_key.x509 extra_certificates + # fail and that the kernel may be used afterwards. + # + ############################################################################### ++sign_key_with_hash := ++ifeq ($(CONFIG_MODULE_SIG_SHA1),y) ++sign_key_with_hash := -sha1 ++endif ++ifeq ($(CONFIG_MODULE_SIG_SHA224),y) ++sign_key_with_hash := -sha224 ++endif ++ifeq ($(CONFIG_MODULE_SIG_SHA256),y) ++sign_key_with_hash := -sha256 ++endif ++ifeq ($(CONFIG_MODULE_SIG_SHA384),y) ++sign_key_with_hash := -sha384 ++endif ++ifeq ($(CONFIG_MODULE_SIG_SHA512),y) ++sign_key_with_hash := -sha512 ++endif ++ifeq ($(sign_key_with_hash),) ++$(error Could not determine digest type to use from kernel config) ++endif ++ + signing_key.priv signing_key.x509: x509.genkey + @echo "###" + @echo "### Now generating an X.509 key pair to be used for signing modules." +@@ -160,7 +180,7 @@ signing_key.priv signing_key.x509: x509.genkey + @echo "###" + @echo "### rngd -r /dev/hwrandom" + @echo "###" +- openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ ++ openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \ + -x509 -config x509.genkey \ + -outform DER -out signing_key.x509 \ + -keyout signing_key.priv +-- +1.7.12.1 + + +From 4c13d777ecee93ae75dae3184473003acff05a53 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 28 Sep 2012 11:16:57 +0100 +Subject: [PATCH 27/37] MODSIGN: Use utf8 strings in signer's name in + autogenerated X.509 certs + +Place an indication that the certificate should use utf8 strings into the +x509.genkey template generated by kernel/Makefile. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + kernel/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/Makefile b/kernel/Makefile +index a799029..e951adf 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -194,6 +194,7 @@ x509.genkey: + @echo >>x509.genkey "default_bits = 4096" + @echo >>x509.genkey "distinguished_name = req_distinguished_name" + @echo >>x509.genkey "prompt = no" ++ @echo >>x509.genkey "string_mask = utf8only" + @echo >>x509.genkey "x509_extensions = myexts" + @echo >>x509.genkey + @echo >>x509.genkey "[ req_distinguished_name ]" +-- +1.7.12.1 + + +From 836513a2dd15675d4ad5fefa585d1b866bec4995 Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Tue, 2 Oct 2012 14:35:24 +0930 +Subject: [PATCH 28/37] MODSIGN: Make mrproper should remove generated files. + +It doesn't, because the clean targets don't include kernel/Makefile, and +because two files were missing from the list. + +Signed-off-by: Rusty Russell +--- + Makefile | 5 ++++- + kernel/Makefile | 1 - + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index b4f9eb5..e4292ea 100644 +--- a/Makefile ++++ b/Makefile +@@ -995,7 +995,10 @@ MRPROPER_DIRS += include/config usr/include include/generated \ + arch/*/include/generated + MRPROPER_FILES += .config .config.old .version .old_version \ + include/linux/version.h \ +- Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS ++ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ ++ signing_key.priv signing_key.x509 x509.genkey \ ++ extra_certificates signing_key.x509.keyid \ ++ signing_key.x509.signer + + # clean - Delete most, but leave enough to build external modules + # +diff --git a/kernel/Makefile b/kernel/Makefile +index e951adf..d3611c8 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -208,4 +208,3 @@ x509.genkey: + @echo >>x509.genkey "subjectKeyIdentifier=hash" + @echo >>x509.genkey "authorityKeyIdentifier=keyid" + endif +-CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates +-- +1.7.12.1 + + +From 855c92bdf2fb006e4190650b809a6216579395d5 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 2 Oct 2012 14:36:16 +0100 +Subject: [PATCH 29/37] MODSIGN: Fix 32-bit overflow in X.509 certificate + validity date checking + +The current choice of lifetime for the autogenerated X.509 of 100 years, +putting the validTo date in 2112, causes problems on 32-bit systems where a +32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. + +This can result in something like: + + Loading module verification certificates + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired + MODSIGN: Problem loading in-kernel X.509 certificate (-127) + +Or: + + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid + MODSIGN: Problem loading in-kernel X.509 certificate (-129) + +Instead of turning the dates into time_t values and comparing, turn the system +clock and the ASN.1 dates into tm structs and compare those piecemeal instead. + +Reported-by: Rusty Russell +Signed-off-by: David Howells +Acked-by: Josh Boyer +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/x509_cert_parser.c | 25 +++++++++--------- + crypto/asymmetric_keys/x509_parser.h | 4 +-- + crypto/asymmetric_keys/x509_public_key.c | 42 +++++++++++++++++++++++++++---- + 3 files changed, 51 insertions(+), 20 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 8fcac94..db07e8c 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, + /* + * Record a certificate time. + */ +-static int x509_note_time(time_t *_time, size_t hdrlen, ++static int x509_note_time(struct tm *tm, size_t hdrlen, + unsigned char tag, + const unsigned char *value, size_t vlen) + { +- unsigned YY, MM, DD, hh, mm, ss; + const unsigned char *p = value; + + #define dec2bin(X) ((X) - '0') +@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, + /* UTCTime: YYMMDDHHMMSSZ */ + if (vlen != 13) + goto unsupported_time; +- YY = DD2bin(p); +- if (YY > 50) +- YY += 1900; ++ tm->tm_year = DD2bin(p); ++ if (tm->tm_year >= 50) ++ tm->tm_year += 1900; + else +- YY += 2000; ++ tm->tm_year += 2000; + } else if (tag == ASN1_GENTIM) { + /* GenTime: YYYYMMDDHHMMSSZ */ + if (vlen != 15) + goto unsupported_time; +- YY = DD2bin(p) * 100 + DD2bin(p); ++ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); + } else { + goto unsupported_time; + } + +- MM = DD2bin(p); +- DD = DD2bin(p); +- hh = DD2bin(p); +- mm = DD2bin(p); +- ss = DD2bin(p); ++ tm->tm_year -= 1900; ++ tm->tm_mon = DD2bin(p) - 1; ++ tm->tm_mday = DD2bin(p); ++ tm->tm_hour = DD2bin(p); ++ tm->tm_min = DD2bin(p); ++ tm->tm_sec = DD2bin(p); + + if (*p != 'Z') + goto unsupported_time; + +- *_time = mktime(YY, MM, DD, hh, mm, ss); + return 0; + + unsupported_time: +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 635053f..f86dc5f 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -18,8 +18,8 @@ struct x509_certificate { + char *subject; /* Name of certificate subject */ + char *fingerprint; /* Key fingerprint as hex */ + char *authority; /* Authority key fingerprint as hex */ +- time_t valid_from; +- time_t valid_to; ++ struct tm valid_from; ++ struct tm valid_to; + enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 716917c..5ab736d 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -106,7 +106,7 @@ error_no_sig: + static int x509_key_preparse(struct key_preparsed_payload *prep) + { + struct x509_certificate *cert; +- time_t now; ++ struct tm now; + size_t srlen, sulen; + char *desc = NULL; + int ret; +@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); + pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); +- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); ++ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, ++ cert->valid_from.tm_mday, cert->valid_from.tm_hour, ++ cert->valid_from.tm_min, cert->valid_from.tm_sec); ++ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, ++ cert->valid_to.tm_mday, cert->valid_to.tm_hour, ++ cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", + pkey_algo[cert->sig_pkey_algo], + pkey_hash_algo[cert->sig_hash_algo]); +@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- now = CURRENT_TIME.tv_sec; +- if (now < cert->valid_from) { ++ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); ++ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, ++ now.tm_hour, now.tm_min, now.tm_sec); ++ if (now.tm_year < cert->valid_from.tm_year || ++ (now.tm_year == cert->valid_from.tm_year && ++ (now.tm_mon < cert->valid_from.tm_mon || ++ (now.tm_mon == cert->valid_from.tm_mon && ++ (now.tm_mday < cert->valid_from.tm_mday || ++ (now.tm_mday == cert->valid_from.tm_mday && ++ (now.tm_hour < cert->valid_from.tm_hour || ++ (now.tm_hour == cert->valid_from.tm_hour && ++ (now.tm_min < cert->valid_from.tm_min || ++ (now.tm_min == cert->valid_from.tm_min && ++ (now.tm_sec < cert->valid_from.tm_sec ++ ))))))))))) { + pr_warn("Cert %s is not yet valid\n", cert->fingerprint); + ret = -EKEYREJECTED; + goto error_free_cert; + } +- if (now >= cert->valid_to) { ++ if (now.tm_year > cert->valid_to.tm_year || ++ (now.tm_year == cert->valid_to.tm_year && ++ (now.tm_mon > cert->valid_to.tm_mon || ++ (now.tm_mon == cert->valid_to.tm_mon && ++ (now.tm_mday > cert->valid_to.tm_mday || ++ (now.tm_mday == cert->valid_to.tm_mday && ++ (now.tm_hour > cert->valid_to.tm_hour || ++ (now.tm_hour == cert->valid_to.tm_hour && ++ (now.tm_min > cert->valid_to.tm_min || ++ (now.tm_min == cert->valid_to.tm_min && ++ (now.tm_sec > cert->valid_to.tm_sec ++ ))))))))))) { + pr_warn("Cert %s has expired\n", cert->fingerprint); + ret = -EKEYEXPIRED; + goto error_free_cert; +-- +1.7.12.1 + + +From f69bc56c32645bcc0b1a9ee88be662e8246398b4 Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Wed, 3 Oct 2012 16:04:46 -0700 +Subject: [PATCH 30/37] asymmetric keys: fix printk format warning + +Fix printk format warning in x509_cert_parser.c: + +crypto/asymmetric_keys/x509_cert_parser.c: In function 'x509_note_OID': +crypto/asymmetric_keys/x509_cert_parser.c:113:3: warning: format '%zu' expects type 'size_t', but argument 2 has type 'long unsigned int' + +Builds cleanly on i386 and x86_64. + +Signed-off-by: Randy Dunlap +Cc: David Howells +Cc: Herbert Xu +Cc: linux-crypto@vger.kernel.org +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/x509_cert_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index db07e8c..7fabc4c 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -110,7 +110,7 @@ int x509_note_OID(void *context, size_t hdrlen, + if (ctx->last_oid == OID__NR) { + char buffer[50]; + sprint_oid(value, vlen, buffer, sizeof(buffer)); +- pr_debug("Unknown OID: [%zu] %s\n", ++ pr_debug("Unknown OID: [%lu] %s\n", + (unsigned long)value - ctx->data, buffer); + } + return 0; +-- +1.7.12.1 + + +From 81338d71c284b7d001004e4a03abfce2d2144087 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 4 Oct 2012 14:21:23 +0100 +Subject: [PATCH 31/37] X.509: Convert some printk calls to pr_devel + +Some debugging printk() calls should've been converted to pr_devel() calls. +Do that now. + +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + crypto/asymmetric_keys/x509_public_key.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 5ab736d..06007f0 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -118,11 +118,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); + pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); +- printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, + cert->valid_from.tm_mday, cert->valid_from.tm_hour, + cert->valid_from.tm_min, cert->valid_from.tm_sec); +- printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, + cert->valid_to.tm_mday, cert->valid_to.tm_hour, + cert->valid_to.tm_min, cert->valid_to.tm_sec); +@@ -138,7 +138,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + } + + time_to_tm(CURRENT_TIME.tv_sec, 0, &now); +- printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec); + if (now.tm_year < cert->valid_from.tm_year || +-- +1.7.12.1 + + +From 1054ea17fe1bf8f2087197c453626153d4649ac5 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 4 Oct 2012 14:21:23 +0100 +Subject: [PATCH 32/37] X.509: Fix indefinite length element skip error + handling + +asn1_find_indefinite_length() returns an error indicator of -1, which the +caller asn1_ber_decoder() places in a size_t (which is usually unsigned) and +then checks to see whether it is less than 0 (which it can't be). This can +lead to the following warning: + + lib/asn1_decoder.c:320 asn1_ber_decoder() + warn: unsigned 'len' is never less than zero. + +Instead, asn1_find_indefinite_length() update the caller's idea of the data +cursor and length separately from returning the error code. + +Reported-by: Dan Carpenter +Signed-off-by: David Howells +Signed-off-by: Rusty Russell +--- + lib/asn1_decoder.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +index 2e4196d..de2c8b5 100644 +--- a/lib/asn1_decoder.c ++++ b/lib/asn1_decoder.c +@@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { + + /* + * Find the length of an indefinite length object ++ * @data: The data buffer ++ * @datalen: The end of the innermost containing element in the buffer ++ * @_dp: The data parse cursor (updated before returning) ++ * @_len: Where to return the size of the element. ++ * @_errmsg: Where to return a pointer to an error message on error + */ + static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, +- const char **_errmsg, size_t *_err_dp) ++ size_t *_dp, size_t *_len, ++ const char **_errmsg) + { + unsigned char tag, tmp; +- size_t dp = 0, len, n; ++ size_t dp = *_dp, len, n; + int indef_level = 1; + + next_tag: +@@ -67,8 +73,11 @@ next_tag: + /* It appears to be an EOC. */ + if (data[dp++] != 0) + goto invalid_eoc; +- if (--indef_level <= 0) +- return dp; ++ if (--indef_level <= 0) { ++ *_len = dp - *_dp; ++ *_dp = dp; ++ return 0; ++ } + goto next_tag; + } + +@@ -122,7 +131,7 @@ data_overrun_error: + missing_eoc: + *_errmsg = "Missing EOC in indefinite len cons"; + error: +- *_err_dp = dp; ++ *_dp = dp; + return -1; + } + +@@ -315,13 +324,14 @@ next_op: + skip_data: + if (!(flags & FLAG_CONS)) { + if (flags & FLAG_INDEFINITE_LENGTH) { +- len = asn1_find_indefinite_length( +- data + dp, datalen - dp, &errmsg, &dp); +- if (len < 0) ++ ret = asn1_find_indefinite_length( ++ data, datalen, &dp, &len, &errmsg); ++ if (ret < 0) + goto error; ++ } else { ++ dp += len; + } + pr_debug("- LEAF: %zu\n", len); +- dp += len; + } + pc += asn1_op_lengths[op]; + goto next_op; +-- +1.7.12.1 + + +From 4ae37452e7450971072481b98f6e1c29e5165c1e Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Fri, 19 Oct 2012 11:53:15 +1030 +Subject: [PATCH 33/37] kbuild: sign the modules at install time + +Linus deleted the old code and put signing on the install command, +I fixed it to extract the keyid and signer-name within sign-file +and cleaned up that script now it always signs in-place. + +Some enthusiast should convert sign-key to perl and pull +x509keyid into it. + +Signed-off-by: Rusty Russell +Signed-off-by: Linus Torvalds +--- + Makefile | 11 +++++++ + scripts/Makefile.modinst | 2 +- + scripts/Makefile.modpost | 77 +----------------------------------------------- + scripts/sign-file | 44 +++++++++++---------------- + scripts/x509keyid | 16 +++++----- + 5 files changed, 39 insertions(+), 111 deletions(-) + +diff --git a/Makefile b/Makefile +index e4292ea..1cc5de4 100644 +--- a/Makefile ++++ b/Makefile +@@ -714,6 +714,17 @@ endif # INSTALL_MOD_STRIP + export mod_strip_cmd + + ++ifeq ($(CONFIG_MODULE_SIG),y) ++MODSECKEY = ./signing_key.priv ++MODPUBKEY = ./signing_key.x509 ++export MODPUBKEY ++mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid ++else ++mod_sign_cmd = true ++endif ++export mod_sign_cmd ++ ++ + ifeq ($(KBUILD_EXTMOD),) + core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ + +diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst +index efa5d94..38367bd 100644 +--- a/scripts/Makefile.modinst ++++ b/scripts/Makefile.modinst +@@ -17,7 +17,7 @@ __modinst: $(modules) + @: + + quiet_cmd_modules_install = INSTALL $@ +- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ++ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) + + # Modules built outside the kernel source tree go into extra by default + INSTALL_MOD_DIR ?= extra +diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost +index 2a4d1a1..08dce14 100644 +--- a/scripts/Makefile.modpost ++++ b/scripts/Makefile.modpost +@@ -14,8 +14,7 @@ + # 3) create one .mod.c file pr. module + # 4) create one Module.symvers file with CRC for all exported symbols + # 5) compile all .mod.c files +-# 6) final link of the module to a (or ) file +-# 7) signs the modules to a file ++# 6) final link of the module to a file + + # Step 3 is used to place certain information in the module's ELF + # section, including information such as: +@@ -33,8 +32,6 @@ + # Step 4 is solely used to allow module versioning in external modules, + # where the CRC of each module is retrieved from the Module.symvers file. + +-# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. +- + # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined + # symbols in the final module linking stage + # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. +@@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE + targets += $(modules:.ko=.mod.o) + + # Step 6), final link of the modules +-ifneq ($(CONFIG_MODULE_SIG),y) + quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ +@@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE + $(call if_changed,ld_ko_o) + + targets += $(modules) +-else +-quiet_cmd_ld_ko_unsigned_o = LD [M] $@ +- cmd_ld_ko_unsigned_o = \ +- $(LD) -r $(LDFLAGS) \ +- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ +- -o $@ $(filter-out FORCE,$^) \ +- $(if $(AFTER_LINK),; $(AFTER_LINK)) +- +-$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE +- $(call if_changed,ld_ko_unsigned_o) +- +-targets += $(modules:.ko=.ko.unsigned) +- +-# Step 7), sign the modules +-MODSECKEY = ./signing_key.priv +-MODPUBKEY = ./signing_key.x509 +- +-ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) +-ifeq ($(KBUILD_SRC),) +- # no O= is being used +- SCRIPTS_DIR := scripts +-else +- SCRIPTS_DIR := $(KBUILD_SRC)/scripts +-endif +-SIGN_MODULES := 1 +-else +-SIGN_MODULES := 0 +-endif +- +-# only sign if it's an in-tree module +-ifneq ($(KBUILD_EXTMOD),) +-SIGN_MODULES := 0 +-endif + +-# We strip the module as best we can - note that using both strip and eu-strip +-# results in a smaller module than using either alone. +-EU_STRIP = $(shell which eu-strip || echo true) +- +-quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ +- cmd_sign_ko_stripped_ko_unsigned = \ +- cp $< $@ && \ +- strip -x -g $@ && \ +- $(EU_STRIP) $@ +- +-ifeq ($(SIGN_MODULES),1) +- +-quiet_cmd_genkeyid = GENKEYID $@ +- cmd_genkeyid = \ +- perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid +- +-%.signer %.keyid: % +- $(call if_changed,genkeyid) +- +-KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid +-quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ +- cmd_sign_ko_ko_stripped = \ +- sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ +-else +-KEYRING_DEP := +-quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ +- cmd_sign_ko_ko_unsigned = \ +- cp $< $@ +-endif +- +-$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE +- $(call if_changed,sign_ko_ko_stripped) +- +-$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE +- $(call if_changed,sign_ko_stripped_ko_unsigned) +- +-targets += $(modules) +-endif + + # Add FORCE to the prequisites of a target to force it to be always rebuilt. + # --------------------------------------------------------------------------- +diff --git a/scripts/sign-file b/scripts/sign-file +index e58e34e..095a953 100644 +--- a/scripts/sign-file ++++ b/scripts/sign-file +@@ -1,8 +1,8 @@ +-#!/bin/sh ++#!/bin/bash + # + # Sign a module file using the given key. + # +-# Format: sign-file ++# Format: sign-file + # + + scripts=`dirname $0` +@@ -15,8 +15,8 @@ fi + + key="$1" + x509="$2" +-src="$3" +-dst="$4" ++keyid_script="$3" ++mod="$4" + + if [ ! -r "$key" ] + then +@@ -29,16 +29,6 @@ then + echo "Can't read X.509 certificate" >&2 + exit 2 + fi +-if [ ! -r "$x509.signer" ] +-then +- echo "Can't read Signer name" >&2 +- exit 2; +-fi +-if [ ! -r "$x509.keyid" ] +-then +- echo "Can't read Key identifier" >&2 +- exit 2; +-fi + + # + # Signature parameters +@@ -83,33 +73,35 @@ fi + + ( + perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? +-openssl dgst $dgst -binary $src || exit $? +-) >$src.dig || exit $? ++openssl dgst $dgst -binary $mod || exit $? ++) >$mod.dig || exit $? + + # + # Generate the binary signature, which will be just the integer that comprises + # the signature with no metadata attached. + # +-openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? +-signerlen=`stat -c %s $x509.signer` +-keyidlen=`stat -c %s $x509.keyid` +-siglen=`stat -c %s $src.sig` ++openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? ++ ++SIGNER="`perl $keyid_script $x509 signer-name`" ++KEYID="`perl $keyid_script $x509 keyid`" ++keyidlen=${#KEYID} ++siglen=${#SIGNER} + + # + # Build the signed binary + # + ( +- cat $src || exit $? ++ cat $mod || exit $? + echo '~Module signature appended~' || exit $? +- cat $x509.signer $x509.keyid || exit $? ++ echo -n "$SIGNER" || exit $? ++ echo -n "$KEYID" || exit $? + + # Preface each signature integer with a 2-byte BE length + perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? +- cat $src.sig || exit $? ++ cat $mod.sig || exit $? + + # Generate the information block + perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? +-) >$dst~ || exit $? ++) >$mod~ || exit $? + +-# Permit in-place signing +-mv $dst~ $dst || exit $? ++mv $mod~ $mod || exit $? +diff --git a/scripts/x509keyid b/scripts/x509keyid +index c8e91a4..4241ec6 100755 +--- a/scripts/x509keyid ++++ b/scripts/x509keyid +@@ -22,7 +22,7 @@ use strict; + + my $raw_data; + +-die "Need three filenames\n" if ($#ARGV != 2); ++die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); + + my $src = $ARGV[0]; + +@@ -259,10 +259,10 @@ die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" + + my $id_key_id = asn1_retrieve($subject_key_id->[1]); + +-open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; +-print OUTFD $id_name; +-close OUTFD || die $ARGV[1]; +- +-open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; +-print OUTFD $id_key_id; +-close OUTFD || die $ARGV[2]; ++if ($ARGV[1] eq "signer-name") { ++ print $id_name; ++} elsif ($ARGV[1] eq "keyid") { ++ print $id_key_id; ++} else { ++ die "Unknown arg"; ++} +-- +1.7.12.1 + + +From 4aa23562520f07f4f27edb5c289bc289438005a0 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 19 Oct 2012 12:43:19 -0700 +Subject: [PATCH 34/37] kbuild: Fix module signature generation + +Rusty had clearly not actually tested his module signing changes that I +(trustingly) applied as commit e2a666d52b48 ("kbuild: sign the modules +at install time"). That commit had multiple bugs: + + - using "${#VARIABLE}" to get the number of characters in a shell + variable may look clever, but it's locale-dependent: it returns the + number of *characters*, not bytes. And we do need bytes. + + So don't use "${#..}" expansion, do the stupid "wc -c" thing instead + (where "c" stands for "bytes", not "characters", despite the letter. + + - Rusty had confused "siglen" and "signerlen", and his conversion + didn't set "signerlen" at all, and incorrectly set "siglen" to the + size of the signer, not the size of the signature. + +End result: the modified sign-file script did create something that +superficially *looked* like a signature, but didn't actually work at +all, and would fail the signature check. Oops. + +Tssk, tssk, Rusty. + +But Rusty was definitely right that this whole thing should be rewritten +in perl by somebody who has the perl-fu to do so. That is not me, +though - I'm just doing an emergency fix for the shell script. + +Cc: Rusty Russell +Signed-off-by: Linus Torvalds +--- + scripts/sign-file | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/scripts/sign-file b/scripts/sign-file +index 095a953..d014abd 100644 +--- a/scripts/sign-file ++++ b/scripts/sign-file +@@ -81,11 +81,12 @@ openssl dgst $dgst -binary $mod || exit $? + # the signature with no metadata attached. + # + openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? ++siglen=`stat -c %s $mod.sig` + + SIGNER="`perl $keyid_script $x509 signer-name`" + KEYID="`perl $keyid_script $x509 keyid`" +-keyidlen=${#KEYID} +-siglen=${#SIGNER} ++keyidlen=$(echo -n "$KEYID" | wc -c) ++signerlen=$(echo -n "$SIGNER" | wc -c) + + # + # Build the signed binary +-- +1.7.12.1 + + +From f51b71db2cae9539acaa4d64a9e708d7aac1f879 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 19 Oct 2012 23:56:37 +0100 +Subject: [PATCH 35/37] MODSIGN: perlify sign-file and merge in x509keyid + +Turn sign-file into perl and merge in x509keyid. The latter doesn't +need to be a separate script as it doesn't actually need to work out the +SHA1 sum of the X.509 certificate itself, since it can get that from the +X.509 certificate. + +Signed-off-by: David Howells +Signed-off-by: Linus Torvalds +--- + Makefile | 2 +- + scripts/sign-file | 477 +++++++++++++++++++++++++++++++++++++++++++++--------- + scripts/x509keyid | 268 ------------------------------ + 3 files changed, 400 insertions(+), 347 deletions(-) + mode change 100644 => 100755 scripts/sign-file + delete mode 100755 scripts/x509keyid + +diff --git a/Makefile b/Makefile +index 1cc5de4..f4f9cdb 100644 +--- a/Makefile ++++ b/Makefile +@@ -718,7 +718,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) + MODSECKEY = ./signing_key.priv + MODPUBKEY = ./signing_key.x509 + export MODPUBKEY +-mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid ++mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) + else + mod_sign_cmd = true + endif +diff --git a/scripts/sign-file b/scripts/sign-file +old mode 100644 +new mode 100755 +index d014abd..d37d130 +--- a/scripts/sign-file ++++ b/scripts/sign-file +@@ -1,108 +1,429 @@ +-#!/bin/bash ++#!/usr/bin/perl -w + # + # Sign a module file using the given key. + # +-# Format: sign-file ++# Format: + # ++# ./scripts/sign-file [-v] [] ++# ++# ++use strict; ++use FileHandle; ++use IPC::Open2; ++ ++my $verbose = 0; ++if ($#ARGV >= 0 && $ARGV[0] eq "-v") { ++ $verbose = 1; ++ shift; ++} ++ ++die "Format: ./scripts/sign-file [-v] []\n" ++ if ($#ARGV != 2 && $#ARGV != 3); ++ ++my $private_key = $ARGV[0]; ++my $x509 = $ARGV[1]; ++my $module = $ARGV[2]; ++my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; ++ ++die "Can't read private key\n" unless (-r $private_key); ++die "Can't read X.509 certificate\n" unless (-r $x509); ++die "Can't read module\n" unless (-r $module); ++ ++# ++# Read the kernel configuration ++# ++my %config = ( ++ CONFIG_MODULE_SIG_SHA512 => 1 ++ ); ++ ++if (-r ".config") { ++ open(FD, "<.config") || die ".config"; ++ while () { ++ if ($_ =~ /^(CONFIG_.*)=[ym]/) { ++ $config{$1} = 1; ++ } ++ } ++ close(FD); ++} + +-scripts=`dirname $0` ++# ++# Function to read the contents of a file into a variable. ++# ++sub read_file($) ++{ ++ my ($file) = @_; ++ my $contents; ++ my $len; ++ ++ open(FD, "<$file") || die $file; ++ binmode FD; ++ my @st = stat(FD); ++ die $file if (!@st); ++ $len = read(FD, $contents, $st[7]) || die $file; ++ close(FD) || die $file; ++ die "$file: Wanted length ", $st[7], ", got ", $len, "\n" ++ if ($len != $st[7]); ++ return $contents; ++} ++ ++############################################################################### ++# ++# First of all, we have to parse the X.509 certificate to find certain details ++# about it. ++# ++# We read the DER-encoded X509 certificate and parse it to extract the Subject ++# name and Subject Key Identifier. Theis provides the data we need to build ++# the certificate identifier. ++# ++# The signer's name part of the identifier is fabricated from the commonName, ++# the organizationName or the emailAddress components of the X.509 subject ++# name. ++# ++# The subject key ID is used to select which of that signer's certificates ++# we're intending to use to sign the module. ++# ++############################################################################### ++my $x509_certificate = read_file($x509); + +-CONFIG_MODULE_SIG_SHA512=y +-if [ -r .config ] +-then +- . ./.config +-fi ++my $UNIV = 0 << 6; ++my $APPL = 1 << 6; ++my $CONT = 2 << 6; ++my $PRIV = 3 << 6; + +-key="$1" +-x509="$2" +-keyid_script="$3" +-mod="$4" ++my $CONS = 0x20; + +-if [ ! -r "$key" ] +-then +- echo "Can't read private key" >&2 +- exit 2 +-fi ++my $BOOLEAN = 0x01; ++my $INTEGER = 0x02; ++my $BIT_STRING = 0x03; ++my $OCTET_STRING = 0x04; ++my $NULL = 0x05; ++my $OBJ_ID = 0x06; ++my $UTF8String = 0x0c; ++my $SEQUENCE = 0x10; ++my $SET = 0x11; ++my $UTCTime = 0x17; ++my $GeneralizedTime = 0x18; + +-if [ ! -r "$x509" ] +-then +- echo "Can't read X.509 certificate" >&2 +- exit 2 +-fi ++my %OIDs = ( ++ pack("CCC", 85, 4, 3) => "commonName", ++ pack("CCC", 85, 4, 6) => "countryName", ++ pack("CCC", 85, 4, 10) => "organizationName", ++ pack("CCC", 85, 4, 11) => "organizationUnitName", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", ++ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", ++ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", ++ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", ++ pack("CCC", 85, 29, 19) => "basicConstraints" ++); ++ ++############################################################################### ++# ++# Extract an ASN.1 element from a string and return information about it. ++# ++############################################################################### ++sub asn1_extract($$@) ++{ ++ my ($cursor, $expected_tag, $optional) = @_; ++ ++ return [ -1 ] ++ if ($cursor->[1] == 0 && $optional); ++ ++ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" ++ if ($cursor->[1] < 2); ++ ++ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ ++ if ($expected_tag != -1 && $tag != $expected_tag) { ++ return [ -1 ] ++ if ($optional); ++ die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, ++ " not ", $expected_tag, ")\n"; ++ } ++ ++ $cursor->[0] += 2; ++ $cursor->[1] -= 2; ++ ++ die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" ++ if (($tag & 0x1f) == 0x1f); ++ die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" ++ if ($len == 0x80); ++ ++ if ($len > 0x80) { ++ my $l = $len - 0x80; ++ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" ++ if ($cursor->[1] < $l); ++ ++ if ($l == 0x1) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); ++ } elsif ($l = 0x2) { ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); ++ } elsif ($l = 0x3) { ++ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; ++ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); ++ } elsif ($l = 0x4) { ++ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); ++ } else { ++ die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; ++ } ++ ++ $cursor->[0] += $l; ++ $cursor->[1] -= $l; ++ } ++ ++ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" ++ if ($cursor->[1] < $len); ++ ++ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; ++ $cursor->[0] += $len; ++ $cursor->[1] -= $len; ++ ++ return $ret; ++} ++ ++############################################################################### ++# ++# Retrieve the data referred to by a cursor ++# ++############################################################################### ++sub asn1_retrieve($) ++{ ++ my ($cursor) = @_; ++ my ($offset, $len, $data) = @$cursor; ++ return substr($$data, $offset, $len); ++} ++ ++############################################################################### ++# ++# Roughly parse the X.509 certificate ++# ++############################################################################### ++my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; ++ ++my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); ++my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); ++my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); ++my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); ++my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); ++my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); ++my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); ++my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); ++ ++my $subject_key_id = (); ++my $authority_key_id = (); ++ ++# ++# Parse the extension list ++# ++if ($extension_list->[0] != -1) { ++ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); ++ ++ while ($extensions->[1]->[1] > 0) { ++ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); ++ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); ++ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); ++ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); ++ ++ my $raw_oid = asn1_retrieve($x_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $x_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($x_val->[1]); ++ ++ if ($x_type eq "subjectKeyIdentifier") { ++ my $vcursor = [ 0, length($raw_value), \$raw_value ]; ++ ++ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); ++ } ++ } ++} ++ ++############################################################################### ++# ++# Determine what we're going to use as the signer's name. In order of ++# preference, take one of: commonName, organizationName or emailAddress. ++# ++############################################################################### ++my $org = ""; ++my $cn = ""; ++my $email = ""; ++ ++while ($subject->[1]->[1] > 0) { ++ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); ++ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); ++ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); ++ my $n_val = asn1_extract($attr->[1], -1); ++ ++ my $raw_oid = asn1_retrieve($n_oid->[1]); ++ next if (!exists($OIDs{$raw_oid})); ++ my $n_type = $OIDs{$raw_oid}; ++ ++ my $raw_value = asn1_retrieve($n_val->[1]); ++ ++ if ($n_type eq "organizationName") { ++ $org = $raw_value; ++ } elsif ($n_type eq "commonName") { ++ $cn = $raw_value; ++ } elsif ($n_type eq "emailAddress") { ++ $email = $raw_value; ++ } ++} ++ ++my $signers_name = $email; ++ ++if ($org && $cn) { ++ # Don't use the organizationName if the commonName repeats it ++ if (length($org) <= length($cn) && ++ substr($cn, 0, length($org)) eq $org) { ++ $signers_name = $cn; ++ goto got_id_name; ++ } ++ ++ # Or a signifcant chunk of it ++ if (length($org) >= 7 && ++ length($cn) >= 7 && ++ substr($cn, 0, 7) eq substr($org, 0, 7)) { ++ $signers_name = $cn; ++ goto got_id_name; ++ } ++ ++ $signers_name = $org . ": " . $cn; ++} elsif ($org) { ++ $signers_name = $org; ++} elsif ($cn) { ++ $signers_name = $cn; ++} ++ ++got_id_name: ++ ++die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" ++ if (!$subject_key_id); ++ ++my $key_identifier = asn1_retrieve($subject_key_id->[1]); ++ ++############################################################################### ++# ++# Create and attach the module signature ++# ++############################################################################### + + # + # Signature parameters + # +-algo=1 # Public-key crypto algorithm: RSA +-hash= # Digest algorithm +-id_type=1 # Identifier type: X.509 ++my $algo = 1; # Public-key crypto algorithm: RSA ++my $hash = 0; # Digest algorithm ++my $id_type = 1; # Identifier type: X.509 + + # + # Digest the data + # +-dgst= +-if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] +-then +- prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" +- dgst=-sha1 +- hash=2 +-elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] +-then +- prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" +- dgst=-sha224 +- hash=7 +-elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] +-then +- prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" +- dgst=-sha256 +- hash=4 +-elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] +-then +- prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" +- dgst=-sha384 +- hash=5 +-elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] +-then +- prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" +- dgst=-sha512 +- hash=6 +-else +- echo "$0: Can't determine hash algorithm" >&2 +- exit 2 +-fi +- +-( +-perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? +-openssl dgst $dgst -binary $mod || exit $? +-) >$mod.dig || exit $? ++my ($dgst, $prologue) = (); ++if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) { ++ $prologue = pack("C*", ++ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, ++ 0x2B, 0x0E, 0x03, 0x02, 0x1A, ++ 0x05, 0x00, 0x04, 0x14); ++ $dgst = "-sha1"; ++ $hash = 2; ++} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) { ++ $prologue = pack("C*", ++ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, ++ 0x05, 0x00, 0x04, 0x1C); ++ $dgst = "-sha224"; ++ $hash = 7; ++} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) { ++ $prologue = pack("C*", ++ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, ++ 0x05, 0x00, 0x04, 0x20); ++ $dgst = "-sha256"; ++ $hash = 4; ++} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) { ++ $prologue = pack("C*", ++ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, ++ 0x05, 0x00, 0x04, 0x30); ++ $dgst = "-sha384"; ++ $hash = 5; ++} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) { ++ $prologue = pack("C*", ++ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, ++ 0x05, 0x00, 0x04, 0x40); ++ $dgst = "-sha512"; ++ $hash = 6; ++} else { ++ die "Can't determine hash algorithm"; ++} ++ ++# ++# Generate the digest and read from openssl's stdout ++# ++my $digest; ++$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst"; + + # + # Generate the binary signature, which will be just the integer that comprises + # the signature with no metadata attached. + # +-openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? +-siglen=`stat -c %s $mod.sig` ++my $pid; ++$pid = open2(*read_from, *write_to, ++ "openssl rsautl -sign -inkey $private_key -keyform PEM") || ++ die "openssl rsautl"; ++binmode write_to; ++print write_to $prologue . $digest || die "pipe to openssl rsautl"; ++close(write_to) || die "pipe to openssl rsautl"; ++ ++binmode read_from; ++my $signature; ++read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; ++close(read_from) || die "pipe from openssl rsautl"; ++$signature = pack("n", length($signature)) . $signature, + +-SIGNER="`perl $keyid_script $x509 signer-name`" +-KEYID="`perl $keyid_script $x509 keyid`" +-keyidlen=$(echo -n "$KEYID" | wc -c) +-signerlen=$(echo -n "$SIGNER" | wc -c) ++waitpid($pid, 0) || die; ++die "openssl rsautl died: $?" if ($? >> 8); + + # + # Build the signed binary + # +-( +- cat $mod || exit $? +- echo '~Module signature appended~' || exit $? +- echo -n "$SIGNER" || exit $? +- echo -n "$KEYID" || exit $? ++my $unsigned_module = read_file($module); ++ ++my $magic_number = "~Module signature appended~\n"; ++ ++my $info = pack("CCCCCxxxN", ++ $algo, $hash, $id_type, ++ length($signers_name), ++ length($key_identifier), ++ length($signature)); + +- # Preface each signature integer with a 2-byte BE length +- perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? +- cat $mod.sig || exit $? ++if ($verbose) { ++ print "Size of unsigned module: ", length($unsigned_module), "\n"; ++ print "Size of magic number : ", length($magic_number), "\n"; ++ print "Size of signer's name : ", length($signers_name), "\n"; ++ print "Size of key identifier : ", length($key_identifier), "\n"; ++ print "Size of signature : ", length($signature), "\n"; ++ print "Size of informaton : ", length($info), "\n"; ++ print "Signer's name : '", $signers_name, "'\n"; ++ print "Digest : $dgst\n"; ++} + +- # Generate the information block +- perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? +-) >$mod~ || exit $? ++open(FD, ">$dest") || die $dest; ++binmode FD; ++print FD ++ $unsigned_module, ++ $magic_number, ++ $signers_name, ++ $key_identifier, ++ $signature, ++ $info ++ ; ++close FD || die $dest; + +-mv $mod~ $mod || exit $? ++if ($#ARGV != 3) { ++ rename($dest, $module) || die $module; ++} +diff --git a/scripts/x509keyid b/scripts/x509keyid +deleted file mode 100755 +index 4241ec6..0000000 +--- a/scripts/x509keyid ++++ /dev/null +@@ -1,268 +0,0 @@ +-#!/usr/bin/perl -w +-# +-# Generate an identifier from an X.509 certificate that can be placed in a +-# module signature to indentify the key to use. +-# +-# Format: +-# +-# ./scripts/x509keyid +-# +-# We read the DER-encoded X509 certificate and parse it to extract the Subject +-# name and Subject Key Identifier. The provide the data we need to build the +-# certificate identifier. +-# +-# The signer's name part of the identifier is fabricated from the commonName, +-# the organizationName or the emailAddress components of the X.509 subject +-# name and written to the second named file. +-# +-# The subject key ID to select which of that signer's certificates we're +-# intending to use to sign the module is written to the third named file. +-# +-use strict; +- +-my $raw_data; +- +-die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); +- +-my $src = $ARGV[0]; +- +-open(FD, "<$src") || die $src; +-binmode FD; +-my @st = stat(FD); +-die $src if (!@st); +-read(FD, $raw_data, $st[7]) || die $src; +-close(FD); +- +-my $UNIV = 0 << 6; +-my $APPL = 1 << 6; +-my $CONT = 2 << 6; +-my $PRIV = 3 << 6; +- +-my $CONS = 0x20; +- +-my $BOOLEAN = 0x01; +-my $INTEGER = 0x02; +-my $BIT_STRING = 0x03; +-my $OCTET_STRING = 0x04; +-my $NULL = 0x05; +-my $OBJ_ID = 0x06; +-my $UTF8String = 0x0c; +-my $SEQUENCE = 0x10; +-my $SET = 0x11; +-my $UTCTime = 0x17; +-my $GeneralizedTime = 0x18; +- +-my %OIDs = ( +- pack("CCC", 85, 4, 3) => "commonName", +- pack("CCC", 85, 4, 6) => "countryName", +- pack("CCC", 85, 4, 10) => "organizationName", +- pack("CCC", 85, 4, 11) => "organizationUnitName", +- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", +- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", +- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", +- pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", +- pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", +- pack("CCC", 85, 29, 19) => "basicConstraints" +-); +- +-############################################################################### +-# +-# Extract an ASN.1 element from a string and return information about it. +-# +-############################################################################### +-sub asn1_extract($$@) +-{ +- my ($cursor, $expected_tag, $optional) = @_; +- +- return [ -1 ] +- if ($cursor->[1] == 0 && $optional); +- +- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" +- if ($cursor->[1] < 2); +- +- my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); +- +- if ($expected_tag != -1 && $tag != $expected_tag) { +- return [ -1 ] +- if ($optional); +- die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, +- " not ", $expected_tag, ")\n"; +- } +- +- $cursor->[0] += 2; +- $cursor->[1] -= 2; +- +- die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" +- if (($tag & 0x1f) == 0x1f); +- die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" +- if ($len == 0x80); +- +- if ($len > 0x80) { +- my $l = $len - 0x80; +- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" +- if ($cursor->[1] < $l); +- +- if ($l == 0x1) { +- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); +- } elsif ($l = 0x2) { +- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); +- } elsif ($l = 0x3) { +- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; +- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); +- } elsif ($l = 0x4) { +- $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); +- } else { +- die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; +- } +- +- $cursor->[0] += $l; +- $cursor->[1] -= $l; +- } +- +- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" +- if ($cursor->[1] < $len); +- +- my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; +- $cursor->[0] += $len; +- $cursor->[1] -= $len; +- +- return $ret; +-} +- +-############################################################################### +-# +-# Retrieve the data referred to by a cursor +-# +-############################################################################### +-sub asn1_retrieve($) +-{ +- my ($cursor) = @_; +- my ($offset, $len, $data) = @$cursor; +- return substr($$data, $offset, $len); +-} +- +-############################################################################### +-# +-# Roughly parse the X.509 certificate +-# +-############################################################################### +-my $cursor = [ 0, length($raw_data), \$raw_data ]; +- +-my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); +-my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); +-my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); +-my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); +-my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +-my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +-my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +-my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +-my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +-my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); +-my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); +-my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); +- +-my $subject_key_id = (); +-my $authority_key_id = (); +- +-# +-# Parse the extension list +-# +-if ($extension_list->[0] != -1) { +- my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); +- +- while ($extensions->[1]->[1] > 0) { +- my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); +- my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); +- my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); +- my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); +- +- my $raw_oid = asn1_retrieve($x_oid->[1]); +- next if (!exists($OIDs{$raw_oid})); +- my $x_type = $OIDs{$raw_oid}; +- +- my $raw_value = asn1_retrieve($x_val->[1]); +- +- if ($x_type eq "subjectKeyIdentifier") { +- my $vcursor = [ 0, length($raw_value), \$raw_value ]; +- +- $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); +- } +- } +-} +- +-############################################################################### +-# +-# Determine what we're going to use as the signer's name. In order of +-# preference, take one of: commonName, organizationName or emailAddress. +-# +-############################################################################### +-my $org = ""; +-my $cn = ""; +-my $email = ""; +- +-while ($subject->[1]->[1] > 0) { +- my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); +- my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); +- my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); +- my $n_val = asn1_extract($attr->[1], -1); +- +- my $raw_oid = asn1_retrieve($n_oid->[1]); +- next if (!exists($OIDs{$raw_oid})); +- my $n_type = $OIDs{$raw_oid}; +- +- my $raw_value = asn1_retrieve($n_val->[1]); +- +- if ($n_type eq "organizationName") { +- $org = $raw_value; +- } elsif ($n_type eq "commonName") { +- $cn = $raw_value; +- } elsif ($n_type eq "emailAddress") { +- $email = $raw_value; +- } +-} +- +-my $id_name = $email; +- +-if ($org && $cn) { +- # Don't use the organizationName if the commonName repeats it +- if (length($org) <= length($cn) && +- substr($cn, 0, length($org)) eq $org) { +- $id_name = $cn; +- goto got_id_name; +- } +- +- # Or a signifcant chunk of it +- if (length($org) >= 7 && +- length($cn) >= 7 && +- substr($cn, 0, 7) eq substr($org, 0, 7)) { +- $id_name = $cn; +- goto got_id_name; +- } +- +- $id_name = $org . ": " . $cn; +-} elsif ($org) { +- $id_name = $org; +-} elsif ($cn) { +- $id_name = $cn; +-} +- +-got_id_name: +- +-############################################################################### +-# +-# Output the signer's name and the key identifier that we're going to include +-# in module signatures. +-# +-############################################################################### +-die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" +- if (!$subject_key_id); +- +-my $id_key_id = asn1_retrieve($subject_key_id->[1]); +- +-if ($ARGV[1] eq "signer-name") { +- print $id_name; +-} elsif ($ARGV[1] eq "keyid") { +- print $id_key_id; +-} else { +- die "Unknown arg"; +-} +-- +1.7.12.1 + + +From 02c76d9df8ff5387b9131799750895475f87c351 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 19 Oct 2012 23:56:45 +0100 +Subject: [PATCH 36/37] MODSIGN: Cleanup .gitignore + +The module build process no longer creates intermediate files for module +signing, so remove them from .gitignore. + +Signed-off-by: David Howells +Signed-off-by: Linus Torvalds +--- + .gitignore | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/.gitignore b/.gitignore +index 0f2f40f..92bd0e4 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -14,10 +14,6 @@ + *.o.* + *.a + *.s +-*.ko.unsigned +-*.ko.stripped +-*.ko.stripped.dig +-*.ko.stripped.sig + *.ko + *.so + *.so.dbg +@@ -95,6 +91,4 @@ GTAGS + extra_certificates + signing_key.priv + signing_key.x509 +-signing_key.x509.keyid +-signing_key.x509.signer + x509.genkey +-- +1.7.12.1 + + +From fd08dfdc1a0022b48b7a5d4599cb4d46bf099882 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Sat, 20 Oct 2012 01:19:29 +0100 +Subject: [PATCH 37/37] MODSIGN: Move the magic string to the end of a module + and eliminate the search + +Emit the magic string that indicates a module has a signature after the +signature data instead of before it. This allows module_sig_check() to +be made simpler and faster by the elimination of the search for the +magic string. Instead we just need to do a single memcmp(). + +This works because at the end of the signature data there is the +fixed-length signature information block. This block then falls +immediately prior to the magic number. + +From the contents of the information block, it is trivial to calculate +the size of the signature data and thus the size of the actual module +data. + +Signed-off-by: David Howells +Signed-off-by: Linus Torvalds +--- + kernel/module-internal.h | 3 +-- + kernel/module.c | 26 +++++++++----------------- + kernel/module_signing.c | 24 +++++++++++++++--------- + scripts/sign-file | 6 +++--- + 4 files changed, 28 insertions(+), 31 deletions(-) + +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 6114a13..24f9247 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -11,5 +11,4 @@ + + extern struct key *modsign_keyring; + +-extern int mod_verify_sig(const void *mod, unsigned long modlen, +- const void *sig, unsigned long siglen); ++extern int mod_verify_sig(const void *mod, unsigned long *_modlen); +diff --git a/kernel/module.c b/kernel/module.c +index 3e8b1a7..0cfcccc 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2441,25 +2441,17 @@ static inline void kmemleak_load_module(const struct module *mod, + + #ifdef CONFIG_MODULE_SIG + static int module_sig_check(struct load_info *info, +- const void *mod, unsigned long *len) ++ const void *mod, unsigned long *_len) + { + int err = -ENOKEY; +- const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; +- const void *p = mod, *end = mod + *len; +- +- /* Poor man's memmem. */ +- while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { +- if (p + markerlen > end) +- break; +- +- if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { +- const void *sig = p + markerlen; +- /* Truncate module up to signature. */ +- *len = p - mod; +- err = mod_verify_sig(mod, *len, sig, end - sig); +- break; +- } +- p++; ++ unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; ++ unsigned long len = *_len; ++ ++ if (len > markerlen && ++ memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { ++ /* We truncate the module to discard the signature */ ++ *_len -= markerlen; ++ err = mod_verify_sig(mod, _len); + } + + if (!err) { +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 6b09f69..d492a23 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + /* + * Verify the signature on a module. + */ +-int mod_verify_sig(const void *mod, unsigned long modlen, +- const void *sig, unsigned long siglen) ++int mod_verify_sig(const void *mod, unsigned long *_modlen) + { + struct public_key_signature *pks; + struct module_signature ms; + struct key *key; +- size_t sig_len; ++ const void *sig; ++ size_t modlen = *_modlen, sig_len; + int ret; + +- pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); ++ pr_devel("==>%s(,%lu)\n", __func__, modlen); + +- if (siglen <= sizeof(ms)) ++ if (modlen <= sizeof(ms)) + return -EBADMSG; + +- memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); +- siglen -= sizeof(ms); ++ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); ++ modlen -= sizeof(ms); + + sig_len = be32_to_cpu(ms.sig_len); +- if (sig_len >= siglen || +- siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) ++ if (sig_len >= modlen) + return -EBADMSG; ++ modlen -= sig_len; ++ if ((size_t)ms.signer_len + ms.key_id_len >= modlen) ++ return -EBADMSG; ++ modlen -= (size_t)ms.signer_len + ms.key_id_len; ++ ++ *_modlen = modlen; ++ sig = mod + modlen; + + /* For the moment, only support RSA and X.509 identifiers */ + if (ms.algo != PKEY_ALGO_RSA || +diff --git a/scripts/sign-file b/scripts/sign-file +index d37d130..87ca59d 100755 +--- a/scripts/sign-file ++++ b/scripts/sign-file +@@ -403,11 +403,11 @@ my $info = pack("CCCCCxxxN", + + if ($verbose) { + print "Size of unsigned module: ", length($unsigned_module), "\n"; +- print "Size of magic number : ", length($magic_number), "\n"; + print "Size of signer's name : ", length($signers_name), "\n"; + print "Size of key identifier : ", length($key_identifier), "\n"; + print "Size of signature : ", length($signature), "\n"; + print "Size of informaton : ", length($info), "\n"; ++ print "Size of magic number : ", length($magic_number), "\n"; + print "Signer's name : '", $signers_name, "'\n"; + print "Digest : $dgst\n"; + } +@@ -416,11 +416,11 @@ open(FD, ">$dest") || die $dest; + binmode FD; + print FD + $unsigned_module, +- $magic_number, + $signers_name, + $key_identifier, + $signature, +- $info ++ $info, ++ $magic_number + ; + close FD || die $dest; + +-- +1.7.12.1 + diff --git a/secure-boot-20120924.patch b/secure-boot-20121026.patch similarity index 52% rename from secure-boot-20120924.patch rename to secure-boot-20121026.patch index 54825efe6..b0bddd943 100644 --- a/secure-boot-20120924.patch +++ b/secure-boot-20121026.patch @@ -711,3 +711,694 @@ index de16959..7d4c50a 100644 -- 1.7.11.4 +From 945f3829d0d376c5e0c790b57c4fa9e875d602d3 Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:30:54 -0400 +Subject: [PATCH 1/2] Add EFI signature data types, such as are used for + containing hashes, keys and certificates for + cryptographic verification. + +Signed-off-by: David Howells +--- + include/linux/efi.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 8670eb1..836c797 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + ++#define EFI_CERT_SHA256_GUID \ ++ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) ++ ++#define EFI_CERT_X509_GUID \ ++ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +@@ -447,6 +453,20 @@ typedef struct { + + #define EFI_INVALID_TABLE_ADDR (~0UL) + ++typedef struct { ++ efi_guid_t signature_owner; ++ u8 signature_data[]; ++} efi_signature_data_t; ++ ++typedef struct { ++ efi_guid_t signature_type; ++ u32 signature_list_size; ++ u32 signature_header_size; ++ u32 signature_size; ++ u8 signature_header[]; ++ /* efi_signature_data_t signatures[][] */ ++} efi_signature_list_t; ++ + /* + * All runtime access to EFI goes through this structure: + */ +-- +1.7.12.1 + + +From 5934634101936bc4ee4636df7269e00c4979911c Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:36:28 -0400 +Subject: [PATCH 2/2] Add an EFI signature blob parser and key loader. X.509 + certificates are loaded into the specified keyring as + asymmetric type keys. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 7 +++ + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/efi_parser.c | 107 ++++++++++++++++++++++++++++++++++++ + include/linux/efi.h | 4 ++ + 4 files changed, 119 insertions(+) + create mode 100644 crypto/asymmetric_keys/efi_parser.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 6d2c2ea..eb53fc3 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -35,4 +35,11 @@ config X509_CERTIFICATE_PARSER + data and provides the ability to instantiate a crypto key from a + public key packet found inside the certificate. + ++config EFI_SIGNATURE_LIST_PARSER ++ bool "EFI signature list parser" ++ select X509_CERTIFICATE_PARSER ++ help ++ This option provides support for parsing EFI signature lists for ++ X.509 certificates and turning them into keys. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 0727204..cd8388e 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o + + # + # X.509 Certificate handling +diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c +new file mode 100644 +index 0000000..59b859a +--- /dev/null ++++ b/crypto/asymmetric_keys/efi_parser.c +@@ -0,0 +1,107 @@ ++/* EFI signature/key/certificate list parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "EFI: "fmt ++#include ++#include ++#include ++#include ++#include ++ ++static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; ++ ++/** ++ * parse_efi_signature_list - Parse an EFI signature list for certificates ++ * @data: The data blob to parse ++ * @size: The size of the data blob ++ * @keyring: The keyring to add extracted keys to ++ */ ++int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) ++{ ++ unsigned offs = 0; ++ size_t lsize, esize, hsize, elsize; ++ ++ pr_devel("-->%s(,%zu)\n", __func__, size); ++ ++ while (size > 0) { ++ efi_signature_list_t list; ++ const efi_signature_data_t *elem; ++ key_ref_t key; ++ ++ if (size < sizeof(list)) ++ return -EBADMSG; ++ ++ memcpy(&list, data, sizeof(list)); ++ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", ++ offs, ++ list.signature_type.b, list.signature_list_size, ++ list.signature_header_size, list.signature_size); ++ ++ lsize = list.signature_list_size; ++ hsize = list.signature_header_size; ++ esize = list.signature_size; ++ elsize = lsize - sizeof(list) - hsize; ++ ++ if (lsize > size) { ++ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", ++ __func__, offs); ++ return -EBADMSG; ++ } ++ if (lsize < sizeof(list) || ++ lsize - sizeof(list) < hsize || ++ esize < sizeof(*elem) || ++ elsize < esize || ++ elsize % esize != 0) { ++ pr_devel("- bad size combo @%x\n", offs); ++ continue; ++ } ++ ++ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { ++ data += lsize; ++ size -= lsize; ++ offs += lsize; ++ continue; ++ } ++ ++ data += sizeof(list) + hsize; ++ size -= sizeof(list) + hsize; ++ offs += sizeof(list) + hsize; ++ ++ for (; elsize > 0; elsize -= esize) { ++ elem = data; ++ ++ pr_devel("ELEM[%04x]\n", offs); ++ ++ key = key_create_or_update( ++ make_key_ref(keyring, 1), ++ "asymmetric", ++ NULL, ++ &elem->signature_data, ++ esize - sizeof(*elem), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ ++ if (IS_ERR(key)) ++ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("Loaded cert '%s'\n", ++ key_ref_to_ptr(key)->description); ++ ++ data += esize; ++ size -= esize; ++ offs += esize; ++ } ++ } ++ ++ return 0; ++} +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 836c797..9cc3250 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -536,6 +536,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); + extern void efi_reserve_boot_services(void); + extern struct efi_memory_map memmap; + ++struct key; ++extern int __init parse_efi_signature_list(const void *data, size_t size, ++ struct key *keyring); ++ + /** + * efi_range_is_wc - check the WC bit on an address range + * @start: starting kvirt address +-- +1.7.12.1 + +From 84d11d541cc039e8561d06deab5f9b700f12f246 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:29:49 -0400 +Subject: [PATCH 1/3] EFI: Add in-kernel variable to determine if Secure Boot + is enabled + +There are a few cases where in-kernel functions may need to know if +Secure Boot is enabled. The added capability check cannot be used as the +kernel can't drop it's own capabilites, so we add a global variable +similar to efi_enabled so they can determine if Secure Boot is enabled. + +Signed-off-by: Josh Boyer +--- + arch/x86/kernel/setup.c | 4 +++- + arch/x86/platform/efi/efi.c | 2 ++ + include/linux/efi.h | 3 +++ + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 51f6970..d5b9548 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -961,8 +961,10 @@ void __init setup_arch(char **cmdline_p) + + io_delay_init(); + +- if (boot_params.secure_boot) ++ if (boot_params.secure_boot) { + secureboot_enable(); ++ secure_boot_enabled = 1; ++ } + + /* + * Parse the ACPI tables for possible boot-time SMP configuration. +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index aded2a9..e57320b 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -54,6 +54,8 @@ + int efi_enabled; + EXPORT_SYMBOL(efi_enabled); + ++int secure_boot_enabled; ++ + struct efi __read_mostly efi = { + .mps = EFI_INVALID_TABLE_ADDR, + .acpi = EFI_INVALID_TABLE_ADDR, +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 9cc3250..ff72468 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -573,11 +573,14 @@ extern int __init efi_setup_pcdp_console(char *); + # ifdef CONFIG_X86 + extern int efi_enabled; + extern bool efi_64bit; ++ extern int secure_boot_enabled; + # else + # define efi_enabled 1 ++# define secure_boot_enabled 0 + # endif + #else + # define efi_enabled 0 ++# define secure_boot_enabled 0 + #endif + + /* +-- +1.7.12.1 + + +From 2a5f33b264daffd717b509bc5ac3cdc060b5573e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:36:24 -0400 +Subject: [PATCH 2/3] MODSIGN: Add module certificate blacklist keyring + +This adds an additional keyring that is used to store certificates that +are blacklisted. This keyring is searched first when loading signed modules +and if the module's certificate is found, it will refuse to load. This is +useful in cases where third party certificates are used for module signing. + +Signed-off-by: Josh Boyer +--- + init/Kconfig | 8 ++++++++ + kernel/modsign_pubkey.c | 17 +++++++++++++++++ + kernel/module-internal.h | 3 +++ + kernel/module_signing.c | 14 +++++++++++++- + 4 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/init/Kconfig b/init/Kconfig +index 6fdd6e3..7a9bf00 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE + Reject unsigned modules or signed modules for which we don't have a + key. Without this, such modules will simply taint the kernel. + ++config MODULE_SIG_BLACKLIST ++ bool "Support for blacklisting module signature certificates" ++ depends on MODULE_SIG ++ help ++ This adds support for keeping a blacklist of certificates that ++ should not pass module signature verification. If a module is ++ signed with something in this keyring, the load will be rejected. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +index 4646eb2..6d70783 100644 +--- a/kernel/modsign_pubkey.c ++++ b/kernel/modsign_pubkey.c +@@ -17,6 +17,9 @@ + #include "module-internal.h" + + struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++struct key *modsign_blacklist; ++#endif + + extern __initdata const u8 modsign_certificate_list[]; + extern __initdata const u8 modsign_certificate_list_end[]; +@@ -52,6 +55,20 @@ static __init int module_verify_init(void) + if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) + panic("Can't instantiate module signing keyring\n"); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", ++ KUIDT_INIT(0), KGIDT_INIT(0), ++ current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_blacklist)) ++ panic("Can't allocate module signing blacklist keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module signing blacklist keyring\n"); ++#endif ++ + return 0; + } + +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 24f9247..51a8380 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -10,5 +10,8 @@ + */ + + extern struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++extern struct key *modsign_blacklist; ++#endif + + extern int mod_verify_sig(const void *mod, unsigned long *_modlen); +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index ea1b1df..602aa24 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, + static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + const u8 *key_id, size_t key_id_len) + { +- key_ref_t key; ++ key_ref_t key, blacklist; + size_t i; + char *id, *q; + +@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ blacklist = keyring_search(make_key_ref(modsign_blacklist, 1), ++ &key_type_asymmetric, id); ++ if (!IS_ERR(blacklist)) { ++ /* module is signed with a cert in the blacklist. reject */ ++ pr_err("Module key '%s' is in blacklist\n", id); ++ key_ref_put(blacklist); ++ kfree(id); ++ return ERR_PTR(-EKEYREJECTED); ++ } ++#endif ++ + key = keyring_search(make_key_ref(modsign_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) +-- +1.7.12.1 + + + +From ddd5e2e1b775fb19aeec7fb842e707fc35347bc0 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:42:16 -0400 +Subject: [PATCH] MODSIGN: Import certificates from UEFI Secure Boot + +Secure Boot stores a list of allowed certificates in the 'db' variable. +This imports those certificates into the module signing keyring. This +allows for a third party signing certificate to be used in conjunction +with signed modules. By importing the public certificate into the 'db' +variable, a user can allow a module signed with that certificate to +load. + +In the opposite case, Secure Boot maintains a list of disallowed +certificates in the 'dbx' variable. We load those certificates into +the newly introduced module blacklist keyring and forbid any module +signed with those from loading. + +Signed-off-by: Josh Boyer +--- + include/linux/efi.h | 3 ++ + init/Kconfig | 9 ++++++ + kernel/Makefile | 3 ++ + kernel/modsign_uefi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 99 insertions(+) + create mode 100644 kernel/modsign_uefi.c + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index ff72468..509755e 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -318,6 +318,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_CERT_X509_GUID \ + EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) + ++#define EFI_IMAGE_SECURITY_DATABASE_GUID \ ++ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +diff --git a/init/Kconfig b/init/Kconfig +index 7a9bf00..9c4c529 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST + should not pass module signature verification. If a module is + signed with something in this keyring, the load will be rejected. + ++config MODULE_SIG_UEFI ++ bool "Allow modules signed with certs stored in UEFI" ++ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI ++ select EFI_SIGNATURE_LIST_PARSER ++ help ++ This will import certificates stored in UEFI and allow modules ++ signed with those to be loaded. It will also disallow loading ++ of modules stored in the UEFI dbx variable. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/Makefile b/kernel/Makefile +index 0dfeca4..ff1468f 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o ++obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o + + $(obj)/configs.o: $(obj)/config_data.h + ++$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar ++ + # config_data.h contains the same information as ikconfig.h but gzipped. + # Info from config_data can be extracted from /proc/config* + targets += config_data.gz +diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c +new file mode 100644 +index 0000000..049669d +--- /dev/null ++++ b/kernel/modsign_uefi.c +@@ -0,0 +1,84 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) ++{ ++ efi_status_t status; ++ unsigned long lsize = 4; ++ unsigned long tmpdb[4]; ++ void *db = NULL; ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); ++ if (status != EFI_BUFFER_TOO_SMALL) { ++ pr_err("Couldn't get size: 0x%lx\n", status); ++ return NULL; ++ } ++ ++ db = kmalloc(lsize, GFP_KERNEL); ++ if (!db) { ++ pr_err("Couldn't allocate memory for uefi cert list\n"); ++ goto out; ++ } ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, db); ++ if (status != EFI_SUCCESS) { ++ kfree(db); ++ db = NULL; ++ pr_err("Error reading db var: 0x%lx\n", status); ++ } ++out: ++ *size = lsize; ++ return db; ++} ++ ++/* ++ * * Load the certs contained in the UEFI databases ++ * */ ++static int __init load_uefi_certs(void) ++{ ++ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; ++ void *db = NULL, *dbx = NULL; ++ unsigned long dbsize = 0, dbxsize = 0; ++ int rc = 0; ++ ++ /* Check if SB is enabled and just return if not */ ++ if (!secure_boot_enabled) ++ return 0; ++ ++ db = get_cert_list(L"db", &secure_var, &dbsize); ++ if (!db) { ++ pr_err("Couldn't get db list\n"); ++ rc = -1; ++ goto err; ++ } ++ ++ /* Get dbx. It might not exist, so it isn't an error if we can't ++ * get it. ++ */ ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); ++ if (!dbx) { ++ pr_err("Couldn't get dbx list\n"); ++ } ++ ++ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse db signatures: %d\n", rc); ++ ++ if (dbx) { ++ rc = parse_efi_signature_list(dbx, dbxsize, ++ modsign_blacklist); ++ if (rc) ++ pr_err("Couldn't parse dbx signatures: %d\n", rc); ++ } ++ ++err: ++ kfree(db); ++ kfree(dbx); ++ return rc; ++} ++late_initcall(load_uefi_certs); +-- +1.7.12.1 + + +From 924e09f1b267c407ca037171bc6f8f90b09265d6 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 14:02:09 -0400 +Subject: [PATCH] hibernate: Disable in a Secure Boot environment + +There is currently no way to verify the resume image when returning +from hibernate. This might compromise the secure boot trust model, +so until we can work with signed hibernate images we disable it in +a Secure Boot environment. + +Signed-off-by: Josh Boyer +--- + kernel/power/hibernate.c | 14 +++++++++++++- + kernel/power/main.c | 4 +++- + kernel/power/user.c | 3 +++ + 3 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index b26f5f1..f04343b 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -632,6 +632,10 @@ int hibernate(void) + { + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ return -EPERM; ++ } ++ + lock_system_sleep(); + /* The snapshot device should not be opened while we're running */ + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +@@ -723,7 +727,7 @@ static int software_resume(void) + /* + * If the user said "noresume".. bail out early. + */ +- if (noresume) ++ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) + return 0; + + /* +@@ -889,6 +893,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, + int i; + char *start = buf; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ buf += sprintf(buf, "[%s]\n", "disabled"); ++ return buf-start; ++ } ++ + for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { + if (!hibernation_modes[i]) + continue; +@@ -923,6 +932,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, + char *p; + int mode = HIBERNATION_INVALID; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + p = memchr(buf, '\n', n); + len = p ? p - buf : n; + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index f458238..72580c1 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -301,7 +301,9 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + } + #endif + #ifdef CONFIG_HIBERNATION +- s += sprintf(s, "%s\n", "disk"); ++ if (capable(CAP_COMPROMISE_KERNEL)) { ++ s += sprintf(s, "%s\n", "disk"); ++ } + #else + if (s != buf) + /* convert the last space to a newline */ +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 4ed81e7..b11a0f4 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) + struct snapshot_data *data; + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + lock_system_sleep(); + + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +-- +1.7.12.1 + From 4f94f043d0e44d9c8af1841736b946e9fff13f3d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 5 Nov 2012 14:24:27 +0000 Subject: [PATCH 091/492] Fix efifb handling on MBP8,3 --- ...hecks-if-the-bootloader-knows-what-i.patch | 69 +++++++++++++++++++ ...e-the-EFI-framebuffer-size-instead-o.patch | 43 ++++++++++++ kernel.spec | 9 +++ 3 files changed, 121 insertions(+) create mode 100644 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch create mode 100644 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch diff --git a/0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch b/0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch new file mode 100644 index 000000000..efd0fa24c --- /dev/null +++ b/0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch @@ -0,0 +1,69 @@ +From f462ed939de67c20528bc08f11d2fc4f2d59c0d5 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Fri, 27 Jul 2012 12:58:53 -0400 +Subject: [PATCH 1/2] efifb: Skip DMI checks if the bootloader knows what it's + doing + +The majority of the DMI checks in efifb are for cases where the bootloader +has provided invalid information. However, on some machines the overrides +may do more harm than good due to configuration differences between machines +with the same machine identifier. It turns out that it's possible for the +bootloader to get the correct information on GOP-based systems, but we +can't guarantee that the kernel's being booted with one that's been updated +to do so. Add support for a capabilities flag that can be set by the +bootloader, and skip the DMI checks in that case. Additionally, set this +flag in the UEFI stub code. + +Signed-off-by: Matthew Garrett +Acked-by: Peter Jones +Signed-off-by: Matt Fleming +--- + arch/x86/boot/compressed/eboot.c | 2 ++ + drivers/video/efifb.c | 4 +++- + include/linux/screen_info.h | 2 ++ + 3 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index d5e4044..bbd83b9 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -379,6 +379,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, + si->rsvd_pos = 0; + } + ++ si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; ++ + free_handle: + efi_call_phys1(sys_table->boottime->free_pool, gop_handle); + return status; +diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c +index b4a632a..932abaa 100644 +--- a/drivers/video/efifb.c ++++ b/drivers/video/efifb.c +@@ -553,7 +553,9 @@ static int __init efifb_init(void) + int ret; + char *option = NULL; + +- dmi_check_system(dmi_system_table); ++ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || ++ !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) ++ dmi_check_system(dmi_system_table); + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + return -ENODEV; +diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h +index 899fbb4..fb3c5a8 100644 +--- a/include/linux/screen_info.h ++++ b/include/linux/screen_info.h +@@ -68,6 +68,8 @@ struct screen_info { + + #define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */ + ++#define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) ++ + #ifdef __KERNEL__ + extern struct screen_info screen_info; + +-- +1.7.12.1 + diff --git a/0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch b/0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch new file mode 100644 index 000000000..c7298d5e2 --- /dev/null +++ b/0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -0,0 +1,43 @@ +From e9b10953edbccd3744e039ffc060ab2692f17856 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Fri, 27 Jul 2012 17:20:49 -0400 +Subject: [PATCH 2/2] x86, EFI: Calculate the EFI framebuffer size instead of + trusting the firmware + +Seth Forshee reported that his system was reporting that the EFI framebuffer +stretched from 0x90010000-0xb0010000 despite the GPU's BAR only covering +0x90000000-0x9ffffff. It's safer to calculate this value from the pixel +stride and screen height (values we already depend on) rather than face +potential problems with resource allocation later on. + +Signed-off-by: Matthew Garrett +Tested-by: Seth Forshee +Signed-off-by: Matt Fleming +--- + arch/x86/boot/compressed/eboot.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index bbd83b9..c760e07 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -331,7 +331,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, + si->lfb_width = width; + si->lfb_height = height; + si->lfb_base = fb_base; +- si->lfb_size = fb_size; + si->pages = 1; + + if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { +@@ -379,6 +378,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, + si->rsvd_pos = 0; + } + ++ si->lfb_size = si->lfb_linelength * si->lfb_height; ++ + si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; + + free_handle: +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index 55ff8d5f4..8ceb2a57c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -732,6 +732,9 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19001: i82975x-edac-fix.patch +Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch +Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch + # ARM Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch @@ -1485,6 +1488,9 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch i82975x-edac-fix.patch +ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch +ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch + #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -2372,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 05 2012 David Woodhouse - 3.6.5-3 +- Fix EFI framebuffer handling + * Wed Oct 31 2012 Josh Boyer - 3.6.5-2 - Update modsign to what is currently in 3.7-rc2 - Update secure boot support for UEFI cert importing. From fd50c1cf708988da5d572d93fbc609995265ee8f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Nov 2012 08:19:48 -0500 Subject: [PATCH 092/492] Linux v3.6.6 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8ceb2a57c..ffe7d0972 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2378,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 05 2012 Josh Boyer - 3.6.6-1 +- Linux v3.6.6 + * Mon Nov 05 2012 David Woodhouse - 3.6.5-3 - Fix EFI framebuffer handling diff --git a/sources b/sources index 3800ac99f..d3c14f4b8 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -6ad8ceebb9b5c1bf69a0c07ef7cc81f2 patch-3.6.5.xz +11d6d8749d4612a77f43f0531c0f2824 patch-3.6.6.xz From 7002a8cc0b3ddc8c9bcfb0dce8d6e33c41fb72e0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Nov 2012 09:51:22 -0500 Subject: [PATCH 093/492] Fix build break without CONFIG_EFI set (reported by Peter W. Bowey) --- kernel.spec | 9 ++++--- ...121026.patch => secure-boot-20121105.patch | 26 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) rename secure-boot-20121026.patch => secure-boot-20121105.patch (98%) diff --git a/kernel.spec b/kernel.spec index ffe7d0972..ca8951994 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -687,7 +687,7 @@ Patch900: modsign-upstream-3.7.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20121026.patch +Patch1000: secure-boot-20121105.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -1444,7 +1444,7 @@ ApplyPatch modsign-upstream-3.7.patch ApplyPatch modsign-post-KS-jwb.patch # secure boot -ApplyPatch secure-boot-20121026.patch +ApplyPatch secure-boot-20121105.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -2378,7 +2378,8 @@ fi # ||----w | # || || %changelog -* Mon Nov 05 2012 Josh Boyer - 3.6.6-1 +* Mon Nov 05 2012 Josh Boyer - 3.6.6-2 +- Fix build break without CONFIG_EFI set (reported by Peter W. Bowey) - Linux v3.6.6 * Mon Nov 05 2012 David Woodhouse - 3.6.5-3 diff --git a/secure-boot-20121026.patch b/secure-boot-20121105.patch similarity index 98% rename from secure-boot-20121026.patch rename to secure-boot-20121105.patch index b0bddd943..67a08201d 100644 --- a/secure-boot-20121026.patch +++ b/secure-boot-20121105.patch @@ -940,11 +940,12 @@ index 836c797..9cc3250 100644 -- 1.7.12.1 -From 84d11d541cc039e8561d06deab5f9b700f12f246 Mon Sep 17 00:00:00 2001 + +From a06f449cee6152ce8f0a051593fceb82d26e4f16 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:29:49 -0400 -Subject: [PATCH 1/3] EFI: Add in-kernel variable to determine if Secure Boot - is enabled +Subject: [PATCH] EFI: Add in-kernel variable to determine if Secure Boot is + enabled There are a few cases where in-kernel functions may need to know if Secure Boot is enabled. The added capability check cannot be used as the @@ -953,32 +954,34 @@ similar to efi_enabled so they can determine if Secure Boot is enabled. Signed-off-by: Josh Boyer --- - arch/x86/kernel/setup.c | 4 +++- + arch/x86/kernel/setup.c | 6 +++++- arch/x86/platform/efi/efi.c | 2 ++ include/linux/efi.h | 3 +++ - 3 files changed, 8 insertions(+), 1 deletion(-) + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 51f6970..d5b9548 100644 +index b4f4666..db74940 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -961,8 +961,10 @@ void __init setup_arch(char **cmdline_p) +@@ -961,8 +961,12 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); - if (boot_params.secure_boot) + if (boot_params.secure_boot) { secureboot_enable(); ++#ifdef CONFIG_EFI + secure_boot_enabled = 1; ++#endif + } /* * Parse the ACPI tables for possible boot-time SMP configuration. diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index aded2a9..e57320b 100644 +index 72d8899..882d794 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c -@@ -54,6 +54,8 @@ +@@ -53,6 +53,8 @@ int efi_enabled; EXPORT_SYMBOL(efi_enabled); @@ -988,10 +991,10 @@ index aded2a9..e57320b 100644 .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h -index 9cc3250..ff72468 100644 +index 54b5936..411997f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -573,11 +573,14 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -575,11 +575,14 @@ extern int __init efi_setup_pcdp_console(char *); # ifdef CONFIG_X86 extern int efi_enabled; extern bool efi_64bit; @@ -1009,7 +1012,6 @@ index 9cc3250..ff72468 100644 -- 1.7.12.1 - From 2a5f33b264daffd717b509bc5ac3cdc060b5573e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 From 0854ddfab8e7ccdf55638f8793ca277c11a1864c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Nov 2012 10:05:38 -0500 Subject: [PATCH 094/492] Backport efivarfs from efi/next for moktools --- efivarfs-3.6.patch | 1630 ++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 1635 insertions(+), 2 deletions(-) create mode 100644 efivarfs-3.6.patch diff --git a/efivarfs-3.6.patch b/efivarfs-3.6.patch new file mode 100644 index 000000000..de7b4434d --- /dev/null +++ b/efivarfs-3.6.patch @@ -0,0 +1,1630 @@ +From bc390c0e405a4fe896dfc54c8e6e737e41661e28 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 01/17] efi: Add support for a UEFI variable filesystem + +The existing EFI variables code only supports variables of up to 1024 +bytes. This limitation existed in version 0.99 of the EFI specification, +but was removed before any full releases. Since variables can now be +larger than a single page, sysfs isn't the best interface for this. So, +instead, let's add a filesystem. Variables can be read, written and +created, with the first 4 bytes of each variable representing its UEFI +attributes. The create() method doesn't actually commit to flash since +zero-length variables can't exist per-spec. + +Updates from Jeremy Kerr . + +Signed-off-by: Matthew Garrett +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 384 ++++++++++++++++++++++++++++++++++++++++++++- + include/linux/efi.h | 5 + + 2 files changed, 383 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d10c987..b605c48 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -80,6 +80,10 @@ + #include + #include + ++#include ++#include ++#include ++ + #include + + #define EFIVARS_VERSION "0.08" +@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 ++#define GUID_LEN 37 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -108,7 +113,6 @@ struct efi_variable { + __u32 Attributes; + } __attribute__((packed)); + +- + struct efivar_entry { + struct efivars *efivars; + struct efi_variable var; +@@ -122,6 +126,9 @@ struct efivar_attribute { + ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); + }; + ++static struct efivars __efivars; ++static struct efivar_operations ops; ++ + #define PSTORE_EFI_ATTRIBUTES \ + (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ +@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = { + .default_attrs = def_attrs, + }; + +-static struct pstore_info efi_pstore_info; +- + static inline void + efivar_unregister(struct efivar_entry *var) + { + kobject_put(&var->kobj); + } + ++static int efivarfs_file_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static ssize_t efivarfs_file_write(struct file *file, ++ const char __user *userbuf, size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars; ++ efi_status_t status; ++ void *data; ++ u32 attributes; ++ struct inode *inode = file->f_mapping->host; ++ int datasize = count - sizeof(attributes); ++ ++ if (count < sizeof(attributes)) ++ return -EINVAL; ++ ++ data = kmalloc(datasize, GFP_KERNEL); ++ ++ if (!data) ++ return -ENOMEM; ++ ++ efivars = var->efivars; ++ ++ if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (attributes & ~(EFI_VARIABLE_MASK)) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (validate_var(&var->var, data, datasize) == false) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ attributes, datasize, ++ data); ++ ++ switch (status) { ++ case EFI_SUCCESS: ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, count); ++ mutex_unlock(&inode->i_mutex); ++ break; ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ break; ++ } ++out: ++ kfree(data); ++ ++ return count; ++} ++ ++static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ unsigned long datasize = 0; ++ u32 attributes; ++ void *data; ++ ssize_t size; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, NULL); ++ ++ if (status != EFI_BUFFER_TOO_SMALL) ++ return 0; ++ ++ data = kmalloc(datasize + 4, GFP_KERNEL); ++ ++ if (!data) ++ return 0; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, ++ (data + 4)); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ memcpy(data, &attributes, 4); ++ size = simple_read_from_buffer(userbuf, count, ppos, ++ data, datasize + 4); ++ kfree(data); ++ ++ return size; ++} ++ ++static void efivarfs_evict_inode(struct inode *inode) ++{ ++ clear_inode(inode); ++} ++ ++static const struct super_operations efivarfs_ops = { ++ .statfs = simple_statfs, ++ .drop_inode = generic_delete_inode, ++ .evict_inode = efivarfs_evict_inode, ++ .show_options = generic_show_options, ++}; ++ ++static struct super_block *efivarfs_sb; ++ ++static const struct inode_operations efivarfs_dir_inode_operations; ++ ++static const struct file_operations efivarfs_file_operations = { ++ .open = efivarfs_file_open, ++ .read = efivarfs_file_read, ++ .write = efivarfs_file_write, ++ .llseek = no_llseek, ++}; ++ ++static struct inode *efivarfs_get_inode(struct super_block *sb, ++ const struct inode *dir, int mode, dev_t dev) ++{ ++ struct inode *inode = new_inode(sb); ++ ++ if (inode) { ++ inode->i_ino = get_next_ino(); ++ inode->i_uid = inode->i_gid = 0; ++ inode->i_mode = mode; ++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ inode->i_fop = &efivarfs_file_operations; ++ break; ++ case S_IFDIR: ++ inode->i_op = &efivarfs_dir_inode_operations; ++ inode->i_fop = &simple_dir_operations; ++ inc_nlink(inode); ++ break; ++ } ++ } ++ return inode; ++} ++ ++static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) ++{ ++ guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); ++ guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]); ++ guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]); ++ guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]); ++ guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]); ++ guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]); ++ guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]); ++ guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]); ++ guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]); ++ guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]); ++ guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]); ++ guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]); ++ guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]); ++ guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]); ++ guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]); ++ guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]); ++} ++ ++static int efivarfs_create(struct inode *dir, struct dentry *dentry, ++ umode_t mode, bool excl) ++{ ++ struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct efivars *efivars = &__efivars; ++ struct efivar_entry *var; ++ int namelen, i = 0, err = 0; ++ ++ if (dentry->d_name.len < 38) ++ return -EINVAL; ++ ++ if (!inode) ++ return -ENOSPC; ++ ++ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); ++ ++ if (!var) ++ return -ENOMEM; ++ ++ namelen = dentry->d_name.len - GUID_LEN; ++ ++ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, ++ &var->var.VendorGuid); ++ ++ for (i = 0; i < namelen; i++) ++ var->var.VariableName[i] = dentry->d_name.name[i]; ++ ++ var->var.VariableName[i] = '\0'; ++ ++ inode->i_private = var; ++ var->efivars = efivars; ++ var->kobj.kset = efivars->kset; ++ ++ err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", ++ dentry->d_name.name); ++ if (err) ++ goto out; ++ ++ kobject_uevent(&var->kobj, KOBJ_ADD); ++ spin_lock(&efivars->lock); ++ list_add(&var->list, &efivars->list); ++ spin_unlock(&efivars->lock); ++ d_instantiate(dentry, inode); ++ dget(dentry); ++out: ++ if (err) ++ kfree(var); ++ return err; ++} ++ ++static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ struct efivar_entry *var = dentry->d_inode->i_private; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ ++ spin_lock(&efivars->lock); ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ 0, 0, NULL); ++ ++ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(dir); ++ dput(dentry); ++ return 0; ++ } ++ ++ spin_unlock(&efivars->lock); ++ return -EINVAL; ++}; ++ ++int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct inode *inode = NULL; ++ struct dentry *root; ++ struct efivar_entry *entry, *n; ++ struct efivars *efivars = &__efivars; ++ int err; ++ ++ efivarfs_sb = sb; ++ ++ sb->s_maxbytes = MAX_LFS_FILESIZE; ++ sb->s_blocksize = PAGE_CACHE_SIZE; ++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_op = &efivarfs_ops; ++ sb->s_time_gran = 1; ++ ++ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); ++ if (!inode) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ inode->i_op = &efivarfs_dir_inode_operations; ++ ++ root = d_make_root(inode); ++ sb->s_root = root; ++ if (!root) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ list_for_each_entry_safe(entry, n, &efivars->list, list) { ++ struct inode *inode; ++ struct dentry *dentry, *root = efivarfs_sb->s_root; ++ char *name; ++ unsigned long size = 0; ++ int len, i; ++ ++ len = utf16_strlen(entry->var.VariableName); ++ ++ /* GUID plus trailing NULL */ ++ name = kmalloc(len + 38, GFP_ATOMIC); ++ ++ for (i = 0; i < len; i++) ++ name[i] = entry->var.VariableName[i] & 0xFF; ++ ++ name[len] = '-'; ++ ++ efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); ++ ++ name[len+GUID_LEN] = '\0'; ++ ++ inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, ++ S_IFREG | 0644, 0); ++ dentry = d_alloc_name(root, name); ++ ++ efivars->ops->get_variable(entry->var.VariableName, ++ &entry->var.VendorGuid, ++ &entry->var.Attributes, ++ &size, ++ NULL); ++ ++ mutex_lock(&inode->i_mutex); ++ inode->i_private = entry; ++ i_size_write(inode, size+4); ++ mutex_unlock(&inode->i_mutex); ++ d_add(dentry, inode); ++ } ++ ++ return 0; ++fail: ++ iput(inode); ++ return err; ++} ++ ++static struct dentry *efivarfs_mount(struct file_system_type *fs_type, ++ int flags, const char *dev_name, void *data) ++{ ++ return mount_single(fs_type, flags, data, efivarfs_fill_super); ++} ++ ++static void efivarfs_kill_sb(struct super_block *sb) ++{ ++ kill_litter_super(sb); ++ efivarfs_sb = NULL; ++} ++ ++static struct file_system_type efivarfs_type = { ++ .name = "efivarfs", ++ .mount = efivarfs_mount, ++ .kill_sb = efivarfs_kill_sb, ++}; ++ ++static const struct inode_operations efivarfs_dir_inode_operations = { ++ .lookup = simple_lookup, ++ .unlink = efivarfs_unlink, ++ .create = efivarfs_create, ++}; ++ ++static struct pstore_info efi_pstore_info; ++ + #ifdef CONFIG_PSTORE + + static int efi_pstore_open(struct pstore_info *psi) +@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars, + pstore_register(&efivars->efi_pstore_info); + } + ++ register_filesystem(&efivarfs_type); ++ + out: + kfree(variable_name); + +@@ -1205,9 +1580,6 @@ out: + } + EXPORT_SYMBOL_GPL(register_efivars); + +-static struct efivars __efivars; +-static struct efivar_operations ops; +- + /* + * For now we register the efi subsystem with the firmware subsystem + * and the vars subsystem with the efi subsystem. In the future, it +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 5782114..2f1db28 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -29,7 +29,12 @@ + #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) + #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) + + typedef unsigned long efi_status_t; + typedef u8 efi_bool_t; +-- +1.7.12.1 + + +From 47c7d712bac1ba86ae9d3f8bb5594d8d9ab57537 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 02/17] efi: Handle deletions and size changes in + efivarfs_write_file + +A write to an efivarfs file will not always result in a variable of +'count' size after the EFI SetVariable() call. We may have appended to +the existing data (ie, with the EFI_VARIABLE_APPEND_WRITE attribute), or +even have deleted the variable (with an authenticated variable update, +with a zero datasize). + +This change re-reads the updated variable from firmware, to check for +size changes and deletions. In the latter case, we need to drop the +dentry. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 49 ++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b605c48..d7658b4 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file, + u32 attributes; + struct inode *inode = file->f_mapping->host; + int datasize = count - sizeof(attributes); ++ unsigned long newdatasize; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file, + + switch (status) { + case EFI_SUCCESS: +- mutex_lock(&inode->i_mutex); +- i_size_write(inode, count); +- mutex_unlock(&inode->i_mutex); + break; + case EFI_INVALID_PARAMETER: + count = -EINVAL; +- break; ++ goto out; + case EFI_OUT_OF_RESOURCES: + count = -ENOSPC; +- break; ++ goto out; + case EFI_DEVICE_ERROR: + count = -EIO; +- break; ++ goto out; + case EFI_WRITE_PROTECTED: + count = -EROFS; +- break; ++ goto out; + case EFI_SECURITY_VIOLATION: + count = -EACCES; +- break; ++ goto out; + case EFI_NOT_FOUND: + count = -ENOENT; +- break; ++ goto out; + default: + count = -EINVAL; +- break; ++ goto out; + } ++ ++ /* ++ * Writing to the variable may have caused a change in size (which ++ * could either be an append or an overwrite), or the variable to be ++ * deleted. Perform a GetVariable() so we can tell what actually ++ * happened. ++ */ ++ newdatasize = 0; ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ NULL, &newdatasize, ++ NULL); ++ ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, newdatasize + sizeof(attributes)); ++ mutex_unlock(&inode->i_mutex); ++ ++ } else if (status == EFI_NOT_FOUND) { ++ spin_lock(&efivars->lock); ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(inode); ++ dput(file->f_dentry); ++ ++ } else { ++ pr_warn("efivarfs: inconsistent EFI variable implementation? " ++ "status = %lx\n", status); ++ } ++ + out: + kfree(data); + +-- +1.7.12.1 + + +From 48173c3d1e7014574d5b2517a471587775e4cb91 Mon Sep 17 00:00:00 2001 +From: "Lee, Chun-Yi" +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 03/17] efi: add efivars kobject to efi sysfs folder + +UEFI variable filesystem need a new mount point, so this patch add +efivars kobject to efi_kobj for create a /sys/firmware/efi/efivars +folder. + +Cc: Matthew Garrett +Cc: H. Peter Anvin +Signed-off-by: Lee, Chun-Yi +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 9 +++++++++ + include/linux/efi.h | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d7658b4..6793965 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -1527,6 +1527,7 @@ void unregister_efivars(struct efivars *efivars) + sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); + kfree(efivars->new_var); + kfree(efivars->del_var); ++ kobject_put(efivars->kobject); + kset_unregister(efivars->kset); + } + EXPORT_SYMBOL_GPL(unregister_efivars); +@@ -1558,6 +1559,14 @@ int register_efivars(struct efivars *efivars, + goto out; + } + ++ efivars->kobject = kobject_create_and_add("efivars", parent_kobj); ++ if (!efivars->kobject) { ++ pr_err("efivars: Subsystem registration failed.\n"); ++ error = -ENOMEM; ++ kset_unregister(efivars->kset); ++ goto out; ++ } ++ + /* + * Per EFI spec, the maximum storage allocated for both + * the variable name and variable data is 1024 bytes. +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 2f1db28..bff4b5e 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -659,6 +659,7 @@ struct efivars { + spinlock_t lock; + struct list_head list; + struct kset *kset; ++ struct kobject *kobject; + struct bin_attribute *new_var, *del_var; + const struct efivar_operations *ops; + struct efivar_entry *walk_entry; +-- +1.7.12.1 + + +From 8c209f22c606ba8c4fa939245efae9921fb1988a Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Thu, 4 Oct 2012 09:57:31 +0100 +Subject: [PATCH 04/17] efivarfs: Add documentation for the EFI variable + filesystem + +Signed-off-by: Matt Fleming +--- + Documentation/filesystems/00-INDEX | 2 ++ + Documentation/filesystems/efivarfs.txt | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 Documentation/filesystems/efivarfs.txt + +diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX +index 8c624a1..7b52ba7 100644 +--- a/Documentation/filesystems/00-INDEX ++++ b/Documentation/filesystems/00-INDEX +@@ -38,6 +38,8 @@ dnotify_test.c + - example program for dnotify + ecryptfs.txt + - docs on eCryptfs: stacked cryptographic filesystem for Linux. ++efivarfs.txt ++ - info for the efivarfs filesystem. + exofs.txt + - info, usage, mount options, design about EXOFS. + ext2.txt +diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt +new file mode 100644 +index 0000000..c477af0 +--- /dev/null ++++ b/Documentation/filesystems/efivarfs.txt +@@ -0,0 +1,16 @@ ++ ++efivarfs - a (U)EFI variable filesystem ++ ++The efivarfs filesystem was created to address the shortcomings of ++using entries in sysfs to maintain EFI variables. The old sysfs EFI ++variables code only supported variables of up to 1024 bytes. This ++limitation existed in version 0.99 of the EFI specification, but was ++removed before any full releases. Since variables can now be larger ++than a single page, sysfs isn't the best interface for this. ++ ++Variables can be created, deleted and modified with the efivarfs ++filesystem. ++ ++efivarfs is typically mounted like this, ++ ++ mount -t efivarfs none /sys/firmware/efi/efivars +-- +1.7.12.1 + + +From 5897a97e56e999e3fe1d5b9d018496f2656f33fb Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:17 +0100 +Subject: [PATCH 05/17] efivarfs: efivarfs_file_read ensure we free data in + error paths + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6793965..b7c9a32 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -766,7 +766,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + unsigned long datasize = 0; + u32 attributes; + void *data; +- ssize_t size; ++ ssize_t size = 0; + + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, +@@ -784,13 +784,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); +- + if (status != EFI_SUCCESS) +- return 0; ++ goto out_free; + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, + data, datasize + 4); ++out_free: + kfree(data); + + return size; +-- +1.7.12.1 + + +From e1f15611b82a3137949ec11b09a7c1230eec1b8e Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:18 +0100 +Subject: [PATCH 06/17] efivarfs: efivarfs_create() ensure we drop our + reference on inode on error + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b7c9a32..6e5f367 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -866,7 +866,7 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) + static int efivarfs_create(struct inode *dir, struct dentry *dentry, + umode_t mode, bool excl) + { +- struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct inode *inode; + struct efivars *efivars = &__efivars; + struct efivar_entry *var; + int namelen, i = 0, err = 0; +@@ -874,13 +874,15 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + if (dentry->d_name.len < 38) + return -EINVAL; + ++ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) + return -ENOSPC; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); +- +- if (!var) +- return -ENOMEM; ++ if (!var) { ++ err = -ENOMEM; ++ goto out; ++ } + + namelen = dentry->d_name.len - GUID_LEN; + +@@ -908,8 +910,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + d_instantiate(dentry, inode); + dget(dentry); + out: +- if (err) ++ if (err) { + kfree(var); ++ iput(inode); ++ } + return err; + } + +-- +1.7.12.1 + + +From da03533239fd31112b355b2e1c1b8aa168a27440 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:19 +0100 +Subject: [PATCH 07/17] efivarfs: efivarfs_fill_super() fix inode reference + counts + +When d_make_root() fails it will automatically drop the reference +on the root inode. We should not be doing so as well. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6e5f367..adfc486 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,7 +948,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; +- int err; + + efivarfs_sb = sb; + +@@ -960,18 +959,14 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_time_gran = 1; + + inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); +- if (!inode) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!inode) ++ return -ENOMEM; + inode->i_op = &efivarfs_dir_inode_operations; + + root = d_make_root(inode); + sb->s_root = root; +- if (!root) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!root) ++ return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { + struct inode *inode; +@@ -1012,9 +1007,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; +-fail: +- iput(inode); +- return err; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From 2e2b7d34a6b3b4534165d5cc22705b3c60e48f0a Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:20 +0100 +Subject: [PATCH 08/17] efivarfs: efivarfs_fill_super() ensure we free our + temporary name + +d_alloc_name() copies the passed name to new storage, once complete we +no longer need our name. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index adfc486..36b3dd6 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -992,6 +992,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); + dentry = d_alloc_name(root, name); ++ /* copied by the above to local storage in the dentry. */ ++ kfree(name); + + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, +-- +1.7.12.1 + + +From 247fd819a9fa1920ed7149bdbe13a16beb0ad44f Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:21 +0100 +Subject: [PATCH 09/17] efivarfs: efivarfs_fill_super() ensure we clean up + correctly on error + +Ensure we free both the name and inode on error when building the +individual variables. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 36b3dd6..216086d 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; ++ char *name; + + efivarfs_sb = sb; + +@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { +- struct inode *inode; + struct dentry *dentry, *root = efivarfs_sb->s_root; +- char *name; + unsigned long size = 0; + int len, i; + ++ inode = NULL; ++ + len = utf16_strlen(entry->var.VariableName); + + /* GUID plus trailing NULL */ + name = kmalloc(len + 38, GFP_ATOMIC); ++ if (!name) ++ goto fail; + + for (i = 0; i < len; i++) + name[i] = entry->var.VariableName[i] & 0xFF; +@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); ++ if (!inode) ++ goto fail_name; ++ + dentry = d_alloc_name(root, name); ++ if (!dentry) ++ goto fail_inode; ++ + /* copied by the above to local storage in the dentry. */ + kfree(name); + +@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; ++ ++fail_inode: ++ iput(inode); ++fail_name: ++ kfree(name); ++fail: ++ return -ENOMEM; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From 01eb8510eb659fd1471d92166bfd7a4d939b2b21 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Thu, 11 Oct 2012 21:19:11 +0800 +Subject: [PATCH 10/17] efivarfs: Implement exclusive access for + {get,set}_variable + +Currently, efivarfs does not enforce exclusion over the get_variable and +set_variable operations. Section 7.1 of UEFI requires us to only allow a +single processor to enter {get,set}_variable services at once. + +This change acquires the efivars->lock over calls to these operations +from the efivarfs paths. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 68 +++++++++++++++++++++++++++++----------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 216086d..d478c56 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -690,35 +690,45 @@ static ssize_t efivarfs_file_write(struct file *file, + goto out; + } + ++ /* ++ * The lock here protects the get_variable call, the conditional ++ * set_variable call, and removal of the variable from the efivars ++ * list (in the case of an authenticated delete). ++ */ ++ spin_lock(&efivars->lock); ++ + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, + attributes, datasize, + data); + +- switch (status) { +- case EFI_SUCCESS: +- break; +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- goto out; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- goto out; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- goto out; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- goto out; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- goto out; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- goto out; +- default: +- count = -EINVAL; +- goto out; ++ if (status != EFI_SUCCESS) { ++ spin_unlock(&efivars->lock); ++ kfree(data); ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ } ++ return count; + } + + /* +@@ -734,12 +744,12 @@ static ssize_t efivarfs_file_write(struct file *file, + NULL); + + if (status == EFI_BUFFER_TOO_SMALL) { ++ spin_unlock(&efivars->lock); + mutex_lock(&inode->i_mutex); + i_size_write(inode, newdatasize + sizeof(attributes)); + mutex_unlock(&inode->i_mutex); + + } else if (status == EFI_NOT_FOUND) { +- spin_lock(&efivars->lock); + list_del(&var->list); + spin_unlock(&efivars->lock); + efivar_unregister(var); +@@ -747,6 +757,7 @@ static ssize_t efivarfs_file_write(struct file *file, + dput(file->f_dentry); + + } else { ++ spin_unlock(&efivars->lock); + pr_warn("efivarfs: inconsistent EFI variable implementation? " + "status = %lx\n", status); + } +@@ -768,9 +779,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + void *data; + ssize_t size = 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, NULL); ++ spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) + return 0; +@@ -780,10 +793,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (!data) + return 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); ++ spin_unlock(&efivars->lock); ++ + if (status != EFI_SUCCESS) + goto out_free; + +@@ -1004,11 +1020,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + /* copied by the above to local storage in the dentry. */ + kfree(name); + ++ spin_lock(&efivars->lock); + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, + &entry->var.Attributes, + &size, + NULL); ++ spin_unlock(&efivars->lock); + + mutex_lock(&inode->i_mutex); + inode->i_private = entry; +-- +1.7.12.1 + + +From 871a36dd8509c2833d02930d6f166a65f85c4f92 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Fri, 19 Oct 2012 15:16:45 +0800 +Subject: [PATCH 11/17] efi: Clarify GUID length calculations + +At present, the handling of GUIDs in efivar file names isn't consistent. +We use GUID_LEN in some places, and 38 in others (GUID_LEN plus +separator), and implicitly use the presence of the trailing NUL. + +This change removes the trailing NUL from GUID_LEN, so that we're +explicitly adding it when required. We also replace magic numbers +with GUID_LEN, and clarify the comments where appropriate. + +We also fix the allocation size in efivar_create_sysfs_entry, where +we're allocating one byte too much, due to counting the trailing NUL +twice - once when calculating short_name_size, and once in the kzalloc. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 33 +++++++++++++++++++++++++-------- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d478c56..a93e401 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -95,7 +95,12 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 +-#define GUID_LEN 37 ++ ++/* ++ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) ++ * not including trailing NUL ++ */ ++#define GUID_LEN 36 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -887,7 +892,11 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + struct efivar_entry *var; + int namelen, i = 0, err = 0; + +- if (dentry->d_name.len < 38) ++ /* ++ * We need a GUID, plus at least one letter for the variable name, ++ * plus the '-' separator ++ */ ++ if (dentry->d_name.len < GUID_LEN + 2) + return -EINVAL; + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); +@@ -900,7 +909,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + goto out; + } + +- namelen = dentry->d_name.len - GUID_LEN; ++ /* length of the variable name itself: remove GUID and separator */ ++ namelen = dentry->d_name.len - GUID_LEN - 1; + + efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, + &var->var.VendorGuid); +@@ -994,8 +1004,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + len = utf16_strlen(entry->var.VariableName); + +- /* GUID plus trailing NULL */ +- name = kmalloc(len + 38, GFP_ATOMIC); ++ /* name, plus '-', plus GUID, plus NUL*/ ++ name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); + if (!name) + goto fail; + +@@ -1006,7 +1016,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); + +- name[len+GUID_LEN] = '\0'; ++ name[len+GUID_LEN+1] = '\0'; + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); +@@ -1435,11 +1445,18 @@ efivar_create_sysfs_entry(struct efivars *efivars, + efi_char16_t *variable_name, + efi_guid_t *vendor_guid) + { +- int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; ++ int i, short_name_size; + char *short_name; + struct efivar_entry *new_efivar; + +- short_name = kzalloc(short_name_size + 1, GFP_KERNEL); ++ /* ++ * Length of the variable bytes in ASCII, plus the '-' separator, ++ * plus the GUID, plus trailing NUL ++ */ ++ short_name_size = variable_name_size / sizeof(efi_char16_t) ++ + 1 + GUID_LEN + 1; ++ ++ short_name = kzalloc(short_name_size, GFP_KERNEL); + new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + + if (!short_name || !new_efivar) { +-- +1.7.12.1 + + +From 5d2cf34731c10e035387ae65f6cf461fd7a53304 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 16 Oct 2012 15:58:07 +0100 +Subject: [PATCH 12/17] efivarfs: Return an error if we fail to read a + variable + +Instead of always returning 0 in efivarfs_file_read(), even when we +fail to successfully read the variable, convert the EFI status to +something meaningful and return that to the caller. This way the user +will have some hint as to why the read failed. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 62 +++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 26 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index a93e401..277e426 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -653,6 +653,36 @@ static int efivarfs_file_open(struct inode *inode, struct file *file) + return 0; + } + ++static int efi_status_to_err(efi_status_t status) ++{ ++ int err; ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ err = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ err = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ err = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ err = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ err = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ err = -ENOENT; ++ break; ++ default: ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ + static ssize_t efivarfs_file_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) + { +@@ -711,29 +741,7 @@ static ssize_t efivarfs_file_write(struct file *file, + spin_unlock(&efivars->lock); + kfree(data); + +- switch (status) { +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- break; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- break; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- break; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- break; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- break; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- break; +- default: +- count = -EINVAL; +- } +- return count; ++ return efi_status_to_err(status); + } + + /* +@@ -791,12 +799,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) +- return 0; ++ return efi_status_to_err(status); + + data = kmalloc(datasize + 4, GFP_KERNEL); + + if (!data) +- return 0; ++ return -ENOMEM; + + spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, +@@ -805,8 +813,10 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + (data + 4)); + spin_unlock(&efivars->lock); + +- if (status != EFI_SUCCESS) ++ if (status != EFI_SUCCESS) { ++ size = efi_status_to_err(status); + goto out_free; ++ } + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, +-- +1.7.12.1 + + +From 0bdf9e5f271f74b7079d8bd06aea7973ffa43562 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Mon, 22 Oct 2012 15:23:29 +0100 +Subject: [PATCH 13/17] efivarfs: Replace magic number with sizeof(attributes) + +Seeing "+ 4" littered throughout the functions gets a bit +confusing. Use "sizeof(attributes)" which clearly explains what +quantity we're adding. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 277e426..2c04434 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -801,7 +801,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (status != EFI_BUFFER_TOO_SMALL) + return efi_status_to_err(status); + +- data = kmalloc(datasize + 4, GFP_KERNEL); ++ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); + + if (!data) + return -ENOMEM; +@@ -810,7 +810,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, +- (data + 4)); ++ (data + sizeof(attributes))); + spin_unlock(&efivars->lock); + + if (status != EFI_SUCCESS) { +@@ -818,9 +818,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + goto out_free; + } + +- memcpy(data, &attributes, 4); ++ memcpy(data, &attributes, sizeof(attributes)); + size = simple_read_from_buffer(userbuf, count, ppos, +- data, datasize + 4); ++ data, datasize + sizeof(attributes)); + out_free: + kfree(data); + +-- +1.7.12.1 + + +From 2835e3a8a7774d72c3e82b6f5350b4c6750c07db Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Mon, 22 Oct 2012 15:51:45 +0100 +Subject: [PATCH 14/17] efivarfs: Add unique magic number + +Using pstore's superblock magic number is no doubt going to cause +problems in the future. Give efivarfs its own magic number. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + include/linux/magic.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 2c04434..3b0cf9a 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -991,7 +991,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; +- sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_magic = EFIVARFS_MAGIC; + sb->s_op = &efivarfs_ops; + sb->s_time_gran = 1; + +diff --git a/include/linux/magic.h b/include/linux/magic.h +index e15192c..12f68c7 100644 +--- a/include/linux/magic.h ++++ b/include/linux/magic.h +@@ -27,6 +27,7 @@ + #define ISOFS_SUPER_MAGIC 0x9660 + #define JFFS2_SUPER_MAGIC 0x72b6 + #define PSTOREFS_MAGIC 0x6165676C ++#define EFIVARFS_MAGIC 0xde5e81e4 + + #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ + #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ +-- +1.7.12.1 + + +From 6cd03d922cfcdf802a0b7cb28a2d12b85064e1cf Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 23 Oct 2012 12:35:43 +0100 +Subject: [PATCH 15/17] efivarfs: Make 'datasize' unsigned long + +There's no reason to declare 'datasize' as an int, since the majority +of the functions it's passed to expect an unsigned long anyway. Plus, +this way we avoid any sign problems during arithmetic. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 3b0cf9a..6a858d1 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -692,7 +692,7 @@ static ssize_t efivarfs_file_write(struct file *file, + void *data; + u32 attributes; + struct inode *inode = file->f_mapping->host; +- int datasize = count - sizeof(attributes); ++ unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; + + if (count < sizeof(attributes)) +-- +1.7.12.1 + + +From b96ed46670ff62693e169066da6c44014b487da6 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 23 Oct 2012 12:41:03 +0100 +Subject: [PATCH 16/17] efivarfs: Return a consistent error when + efivarfs_get_inode() fails + +Instead of returning -ENOSPC if efivarfs_get_inode() fails we should +be returning -ENOMEM, since running out of memory is the only reason +it can fail. Furthermore, that's the error value used everywhere else +in this file. It's also less likely to confuse users that hit this +error case. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6a858d1..58cec62 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -911,7 +911,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) +- return -ENOSPC; ++ return -ENOMEM; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + if (!var) { +-- +1.7.12.1 + + +From d537167e87d99d6fffa04f7f36de80a9bc7ffd4f Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Fri, 26 Oct 2012 12:18:53 +0100 +Subject: [PATCH 17/17] efivarfs: Fix return value of efivarfs_file_write() + +We're stuffing a variable of type size_t (unsigned) into a ssize_t +(signed) which, even though both types should be the same number of +bits, it's just asking for sign issues to be introduced. + +Cc: Jeremy Kerr +Reported-by: Alan Cox +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 58cec62..9ac9340 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -694,6 +694,7 @@ static ssize_t efivarfs_file_write(struct file *file, + struct inode *inode = file->f_mapping->host; + unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; ++ ssize_t bytes = 0; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -706,22 +707,22 @@ static ssize_t efivarfs_file_write(struct file *file, + efivars = var->efivars; + + if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (attributes & ~(EFI_VARIABLE_MASK)) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + + if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (validate_var(&var->var, data, datasize) == false) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + +@@ -744,6 +745,8 @@ static ssize_t efivarfs_file_write(struct file *file, + return efi_status_to_err(status); + } + ++ bytes = count; ++ + /* + * Writing to the variable may have caused a change in size (which + * could either be an append or an overwrite), or the variable to be +@@ -778,7 +781,7 @@ static ssize_t efivarfs_file_write(struct file *file, + out: + kfree(data); + +- return count; ++ return bytes; + } + + static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index ca8951994..b86ecc69b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -688,6 +688,7 @@ Patch901: modsign-post-KS-jwb.patch # secure boot Patch1000: secure-boot-20121105.patch +Patch1001: efivarfs-3.6.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -1444,6 +1445,7 @@ ApplyPatch modsign-upstream-3.7.patch ApplyPatch modsign-post-KS-jwb.patch # secure boot +ApplyPatch efivarfs-3.6.patch ApplyPatch secure-boot-20121105.patch # Improved PCI support for UEFI @@ -2378,7 +2380,8 @@ fi # ||----w | # || || %changelog -* Mon Nov 05 2012 Josh Boyer - 3.6.6-2 +* Mon Nov 05 2012 Josh Boyer - 3.6.6-3 +- Backport efivarfs from efi/next for moktools - Fix build break without CONFIG_EFI set (reported by Peter W. Bowey) - Linux v3.6.6 From cd6bdb99f51fc71efe3c002bcb2cddf6bb620af0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Nov 2012 08:58:54 -0500 Subject: [PATCH 095/492] Add patch to not break modules_install for external module builds --- kernel.spec | 5 ++- modsign-post-KS-jwb.patch | 63 +++++++++----------------------------- modsign-upstream-3.7.patch | 34 ++++++++++++++++++++ 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/kernel.spec b/kernel.spec index b86ecc69b..a69036bbe 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2380,6 +2380,9 @@ fi # ||----w | # || || %changelog +* Wed Nov 07 2012 Josh Boyer +- Add patch to not break modules_install for external module builds + * Mon Nov 05 2012 Josh Boyer - 3.6.6-3 - Backport efivarfs from efi/next for moktools - Fix build break without CONFIG_EFI set (reported by Peter W. Bowey) diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch index ba942170f..1bafd22f5 100644 --- a/modsign-post-KS-jwb.patch +++ b/modsign-post-KS-jwb.patch @@ -1,58 +1,25 @@ -From f1fa90d02f50078a89da602d73dc9ab7743439ba Mon Sep 17 00:00:00 2001 +From 56713a28675b966e027a824a0130b80dffab209f Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Mon, 24 Sep 2012 10:46:36 -0400 -Subject: [PATCH 2/2] MODSIGN: Add modules_sign make target +Date: Mon, 5 Nov 2012 09:09:24 +1030 +Subject: [PATCH] MODSIGN: Add modules_sign make target If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this -patch will cause the modules to get a signature installed. The make target +patch will cause the modules to get a signature appended. The make target is intended to be run after 'make modules_install', and will modify the -modules in-place in the installed location. +modules in-place in the installed location. It can be used to produce +signed modules after they have been processed by distribution build +scripts. -The signature will be appended to the module, along with some information -about the signature size and a magic string that indicates the presence of -the signature. This requires private and public keys to be available. By -default these are expected to be found in files: - - signing_key.priv - signing_key.x509 - -in the base directory of the build. The first is the private key in PEM -form and the second is the X.509 certificate in DER form as can be generated -from openssl: - - openssl req \ - -new -x509 -outform PEM -out signing_key.x509 \ - -keyout signing_key.priv -nodes \ - -subj "/CN=H2G2/O=Magrathea/CN=Slartibartfast" - -If the secret key is not found then signing will be skipped and the unsigned -module from (1) will just be copied to foo.ko. - -If signing occurs, lines like the following will be seen: - - SIGN [M] /fs/foo/foo.ko - -will appear in the build log. If the signature step will be skipped and the -following will be seen: - - NO SIGN [M] /fs/foo/foo.ko - -NOTE! After the signature step, the signed module must not be passed through -strip. If you wish to strip or otherwise modify the kernel modules, use the -built-in stripping capabilities with 'make modules_install' or perform said -modifications before calling this make target. This restriction may affect -packaging tools (such as rpmbuild) and initramfs composition tools. - -Based heavily on work by: David Howells Signed-off-by: Josh Boyer +Signed-off-by: Rusty Russell (minor typo fix) --- - Makefile | 6 ++++++ - scripts/Makefile.modsign | 32 ++++++++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) + Makefile | 6 ++++++ + scripts/Makefile.modsign | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+), 0 deletions(-) create mode 100644 scripts/Makefile.modsign diff --git a/Makefile b/Makefile -index 89a2e2c..ac04c11 100644 +index 42d0e56..253aa1b 100644 --- a/Makefile +++ b/Makefile @@ -981,6 +981,12 @@ _modinst_post: _modinst_ @@ -70,7 +37,7 @@ index 89a2e2c..ac04c11 100644 # Modules not configured diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign new file mode 100644 -index 0000000..670d5dc +index 0000000..abfda62 --- /dev/null +++ b/scripts/Makefile.modsign @@ -0,0 +1,32 @@ @@ -103,9 +70,9 @@ index 0000000..670d5dc + $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) + +# Declare the contents of the .PHONY variable as phony. We keep that -+# # information in a variable se we can use it in if_changed and friends. ++# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) -- -1.7.11.7 +1.7.7.6 diff --git a/modsign-upstream-3.7.patch b/modsign-upstream-3.7.patch index 4ed27c8a5..33fd0592f 100644 --- a/modsign-upstream-3.7.patch +++ b/modsign-upstream-3.7.patch @@ -10961,3 +10961,37 @@ index d37d130..87ca59d 100755 -- 1.7.12.1 +From f6a79af8f3701b5a0df431a76adee212616154dc Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Tue, 6 Nov 2012 11:46:59 +1030 +Subject: [PATCH] modules: don't break modules_install on external modules + with no key. + +The script still spits out an error ("Can't read private key") but we +don't break modules_install. + +Reported-by: Bruno Wolff III +Original-patch-by: Josh Boyer +Signed-off-by: Rusty Russell +--- + scripts/Makefile.modinst | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst +index dda4b2b..ecbb447 100644 +--- a/scripts/Makefile.modinst ++++ b/scripts/Makefile.modinst +@@ -16,8 +16,9 @@ PHONY += $(modules) + __modinst: $(modules) + @: + ++# Don't stop modules_install if we can't sign external modules. + quiet_cmd_modules_install = INSTALL $@ +- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) ++ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) + + # Modules built outside the kernel source tree go into extra by default + INSTALL_MOD_DIR ?= extra +-- +1.7.6.5 + From bcf7eacdcf1b2ca46115dd71f5dd1620297c74b4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Nov 2012 10:07:04 -0500 Subject: [PATCH 096/492] Fix vanilla kernel builds (reported by Thorsten Leemhuis) --- kernel.spec | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index a69036bbe..92b4d25d0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -223,6 +223,9 @@ Summary: The Linux kernel %endif %if %{with_vanilla} +# Vanilla kernels before 3.7 don't contain modsign support. Remove this when +# we rebase to 3.7 +%define signmodules 0 %define nopatches 1 %endif @@ -1644,9 +1647,8 @@ BuildKernel() { %if %{signmodules} cp %{SOURCE11} . - %endif - chmod +x scripts/sign-file + %endif Arch=`head -1 .config | cut -b 3-` echo USING ARCH=$Arch @@ -2380,6 +2382,9 @@ fi # ||----w | # || || %changelog +* Fri Nov 09 2012 Josh Boyer +- Fix vanilla kernel builds (reported by Thorsten Leemhuis) + * Wed Nov 07 2012 Josh Boyer - Add patch to not break modules_install for external module builds From 40406340d224ff9bc2f15b579c488574ef7b1a24 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 12 Nov 2012 12:07:04 -0600 Subject: [PATCH 097/492] fix list_del corruption warning on USB audio with twinkle (rhbz 871078) --- USB-EHCI-urb-hcpriv-should-not-be-NULL.patch | 72 ++++++++++ USB-report-submission-of-active-URBs.patch | 46 +++++++ kernel.spec | 15 ++- ...crash-at-re-preparing-the-PCM-stream.patch | 125 ++++++++++++++++++ 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 USB-EHCI-urb-hcpriv-should-not-be-NULL.patch create mode 100644 USB-report-submission-of-active-URBs.patch create mode 100644 usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch diff --git a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch new file mode 100644 index 000000000..4b8e537c4 --- /dev/null +++ b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch @@ -0,0 +1,72 @@ +commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e +Author: Alan Stern +Date: Thu Nov 8 10:17:01 2012 -0500 + + USB: EHCI: bugfix: urb->hcpriv should not be NULL + + This patch (as1632b) fixes a bug in ehci-hcd. The USB core uses + urb->hcpriv to determine whether or not an URB is active; host + controller drivers are supposed to set this pointer to a non-NULL + value when an URB is queued. However ehci-hcd sets it to NULL for + isochronous URBs, which defeats the check in usbcore. + + In itself this isn't a big deal. But people have recently found that + certain sequences of actions will cause the snd-usb-audio driver to + reuse URBs without waiting for them to complete. In the absence of + proper checking by usbcore, the URBs get added to their endpoint list + twice. This leads to list corruption and a system freeze. + + The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for + isochronous URBs. Improving robustness always helps. + + Signed-off-by: Alan Stern + Reported-by: Artem S. Tashkinov + Reported-by: Christof Meerwald + CC: + Signed-off-by: Greg Kroah-Hartman + +diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c +index 4b66374..3d98902 100644 +--- a/drivers/usb/host/ehci-q.c ++++ b/drivers/usb/host/ehci-q.c +@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) + __releases(ehci->lock) + __acquires(ehci->lock) + { +- if (likely (urb->hcpriv != NULL)) { +- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; +- +- /* S-mask in a QH means it's an interrupt urb */ +- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { +- +- /* ... update hc-wide periodic stats (for usbfs) */ +- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; +- } ++ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { ++ /* ... update hc-wide periodic stats */ ++ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; + } + + if (unlikely(urb->unlinked)) { +diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c +index 2e14714..69ebee7 100644 +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1630,7 +1630,7 @@ static void itd_link_urb( + + /* don't need that schedule data any more */ + iso_sched_free (stream, iso_sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + ++ehci->isoc_count; + enable_periodic(ehci); +@@ -2029,7 +2029,7 @@ static void sitd_link_urb( + + /* don't need that schedule data any more */ + iso_sched_free (stream, sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + ++ehci->isoc_count; + enable_periodic(ehci); diff --git a/USB-report-submission-of-active-URBs.patch b/USB-report-submission-of-active-URBs.patch new file mode 100644 index 000000000..4496c913a --- /dev/null +++ b/USB-report-submission-of-active-URBs.patch @@ -0,0 +1,46 @@ +commit 2f02bc8af3abb846823811af65ec6cc46a4d525d +Author: Alan Stern +Date: Wed Nov 7 16:35:00 2012 -0500 + + USB: report submission of active URBs + + This patch (as1633) changes slightly the way usbcore handled + submissions of URBs that are already active. It will now return + -EBUSY rather than -EINVAL, and it will call WARN_ONCE to draw + people's attention to the bug. + + Signed-off-by: Alan Stern + Signed-off-by: Greg Kroah-Hartman + +diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt +index 8d1e2a9..9c3eb84 100644 +--- a/Documentation/usb/error-codes.txt ++++ b/Documentation/usb/error-codes.txt +@@ -21,6 +21,8 @@ Non-USB-specific: + + USB-specific: + ++-EBUSY The URB is already active. ++ + -ENODEV specified USB-device or bus doesn't exist + + -ENOENT specified interface or endpoint does not exist or +diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c +index 3662287..e0d9d94 100644 +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -321,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) + struct usb_host_endpoint *ep; + int is_out; + +- if (!urb || urb->hcpriv || !urb->complete) ++ if (!urb || !urb->complete) + return -EINVAL; ++ if (urb->hcpriv) { ++ WARN_ONCE(1, "URB %p submitted while active\n", urb); ++ return -EBUSY; ++ } ++ + dev = urb->dev; + if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) + return -ENODEV; diff --git a/kernel.spec b/kernel.spec index 92b4d25d0..57bddc128 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -791,6 +791,11 @@ Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch Patch22100: uprobes-upstream-backport.patch +#rhbz 871078 +Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +Patch22112: USB-report-submission-of-active-URBs.patch + # END OF PATCH DEFINITIONS %endif @@ -1529,6 +1534,11 @@ ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch ApplyPatch uprobes-upstream-backport.patch +#rhbz 871078 +ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +ApplyPatch USB-report-submission-of-active-URBs.patch + # END OF PATCH APPLICATIONS %endif @@ -2382,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 12 2012 Justin M. Forbes +- fix list_del corruption warning on USB audio with twinkle (rhbz 871078) + * Fri Nov 09 2012 Josh Boyer - Fix vanilla kernel builds (reported by Thorsten Leemhuis) diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch new file mode 100644 index 000000000..6d840ea2c --- /dev/null +++ b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch @@ -0,0 +1,125 @@ +At Thu, 08 Nov 2012 08:31:35 +0100, +Daniel Mack wrote: +(snip) +> >> We can't simply stop both endpoints in the prepare callback. +> > +> > The new function doesn't stop the stream by itself but it just syncs +> > if the stream is being stopped beforehand. So, it's safe to call it +> > there. +> > +> > Maybe the name was confusing. It should have been like +> > snd_usb_endpoint_sync_pending_stop() or such. +> +> Ah, right. I was errornously looking closer to Alan's patch but then +> replied to yours. Alright then - thanks for explaining :) + +OK, thanks for checking. + +FWIW, below is the patch I applied now to for-linus branch. +Renamed the function, added the comment and put NULL check to the +function to simplify. + + +Takashi + +--- +From: Takashi Iwai +Subject: [PATCH] ALSA: usb-audio: Fix crash at re-preparing the PCM stream + +There are bug reports of a crash with USB-audio devices when PCM +prepare is performed immediately after the stream is stopped via +trigger callback. It turned out that the problem is that we don't +wait until all URBs are killed. + +This patch adds a new function to synchronize the pending stop +operation on an endpoint, and calls in the prepare callback for +avoiding the crash above. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181 + +Reported-and-tested-by: Artem S. Tashkinov +Cc: [v3.6] +Signed-off-by: Takashi Iwai +--- + sound/usb/endpoint.c | 13 +++++++++++++ + sound/usb/endpoint.h | 1 + + sound/usb/pcm.c | 3 +++ + 3 files changed, 17 insertions(+) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 7f78c6d..34de6f2 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -35,6 +35,7 @@ + + #define EP_FLAG_ACTIVATED 0 + #define EP_FLAG_RUNNING 1 ++#define EP_FLAG_STOPPING 2 + + /* + * snd_usb_endpoint is a model that abstracts everything related to an +@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) + if (alive) + snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", + alive, ep->ep_num); ++ clear_bit(EP_FLAG_STOPPING, &ep->flags); + + return 0; + } + ++/* sync the pending stop operation; ++ * this function itself doesn't trigger the stop operation ++ */ ++void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) ++{ ++ if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) ++ wait_clear_urbs(ep); ++} ++ + /* + * unlink active urbs. + */ +@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + + if (wait) + wait_clear_urbs(ep); ++ else ++ set_bit(EP_FLAG_STOPPING, &ep->flags); + } + } + +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index 6376ccf..3d4c970 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); + void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); ++void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); + void snd_usb_endpoint_free(struct list_head *head); +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 37428f7..5c12a3f 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + if (snd_BUG_ON(!subs->data_endpoint)) + return -EIO; + ++ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); ++ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); ++ + /* some unit conversions in runtime */ + subs->data_endpoint->maxframesize = + bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); +-- +1.8.0 + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ From de28018acfd5d480226b9d05c0554437cf418dd2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Nov 2012 19:54:44 -0500 Subject: [PATCH 098/492] Fix module signing of kernel flavours --- kernel.spec | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 57bddc128..69b1b9e99 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1833,7 +1833,11 @@ BuildKernel() { %if %{signmodules} # Save off the .tmp_versions/ directory. We'll use it in the # __debug_install_post macro below to sign the right things + # Also save the signing keys so we actually sign the modules with the + # right key. cp -r .tmp_versions .tmp_versions.sign${Flavour:+.${Flavour}} + cp signing_key.priv signing_key.priv.sign${Flavour:+.${Flavour}} + cp signing_key.x509 signing_key.x509.sign${Flavour:+.${Flavour}} %endif # remove files that will be auto generated by depmod at rpm -i time @@ -1980,6 +1984,8 @@ find Documentation -type d | xargs chmod u+w Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAE.config | cut -b 3-` \ rm -rf .tmp_versions \ mv .tmp_versions.sign.PAE .tmp_versions \ + mv signing_key.priv.sign.PAE signing_key.priv \ + mv signing_key.x509.sign.PAE signing_key.x509 \ make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAE \ %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAE/extra/ \ fi \ @@ -1988,6 +1994,8 @@ find Documentation -type d | xargs chmod u+w Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-debug.config | cut -b 3-` \ rm -rf .tmp_versions \ mv .tmp_versions.sign.debug .tmp_versions \ + mv signing_key.priv.sign.debug signing_key.priv \ + mv signing_key.x509.sign.debug signing_key.x509 \ make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.debug \ %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.debug/extra/ \ fi \ @@ -1996,6 +2004,8 @@ find Documentation -type d | xargs chmod u+w Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAEdebug.config | cut -b 3-` \ rm -rf .tmp_versions \ mv .tmp_versions.sign.PAEdebug .tmp_versions \ + mv signing_key.priv.sign.PAEdebug signing_key.priv \ + mv signing_key.x509.sign.PAEdebug signing_key.x509 \ make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAEdebug \ %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAEdebug/extra/ \ fi \ @@ -2004,6 +2014,8 @@ find Documentation -type d | xargs chmod u+w Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}.config | cut -b 3-` \ rm -rf .tmp_versions \ mv .tmp_versions.sign .tmp_versions \ + mv signing_key.priv.sign signing_key.priv \ + mv signing_key.x509.sign signing_key.x509 \ make -s ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL} \ %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}/extra/ \ fi \ @@ -2392,6 +2404,9 @@ fi # ||----w | # || || %changelog +* Wed Nov 14 2012 Josh Boyer +- Fix module signing of kernel flavours + * Mon Nov 12 2012 Justin M. Forbes - fix list_del corruption warning on USB audio with twinkle (rhbz 871078) From c428a202043bfc560459734a8342eae90d26096b Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 15 Nov 2012 11:00:40 -0600 Subject: [PATCH 099/492] Fix panic in panic in smp_irq_move_cleanup_interrupt --- kernel.spec | 9 ++++- smp_irq_move_cleanup_interrupt.patch | 50 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 smp_irq_move_cleanup_interrupt.patch diff --git a/kernel.spec b/kernel.spec index 69b1b9e99..a67160be1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 7 +%global baserelease 8 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -796,6 +796,8 @@ Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch +Patch22113: smp_irq_move_cleanup_interrupt.patch + # END OF PATCH DEFINITIONS %endif @@ -1539,6 +1541,8 @@ ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch +ApplyPatch smp_irq_move_cleanup_interrupt.patch + # END OF PATCH APPLICATIONS %endif @@ -2404,6 +2408,9 @@ fi # ||----w | # || || %changelog +* Thu Nov 15 2012 Justin M. Forbes +- Fix panic in panic in smp_irq_move_cleanup_interrupt + * Wed Nov 14 2012 Josh Boyer - Fix module signing of kernel flavours diff --git a/smp_irq_move_cleanup_interrupt.patch b/smp_irq_move_cleanup_interrupt.patch new file mode 100644 index 000000000..c9b385a94 --- /dev/null +++ b/smp_irq_move_cleanup_interrupt.patch @@ -0,0 +1,50 @@ +commit 94777fc51b3ad85ff9f705ddf7cdd0eb3bbad5a6 +Author: Dimitri Sivanich +Date: Tue Oct 16 07:50:21 2012 -0500 + + x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt + + Posting this patch to fix an issue concerning sparse irq's that + I raised a while back. There was discussion about adding + refcounting to sparse irqs (to fix other potential race + conditions), but that does not appear to have been addressed + yet. This covers the only issue of this type that I've + encountered in this area. + + A NULL pointer dereference can occur in + smp_irq_move_cleanup_interrupt() if we haven't yet setup the + irq_cfg pointer in the irq_desc.irq_data.chip_data. + + In create_irq_nr() there is a window where we have set + vector_irq in __assign_irq_vector(), but not yet called + irq_set_chip_data() to set the irq_cfg pointer. + + Should an IRQ_MOVE_CLEANUP_VECTOR hit the cpu in question during + this time, smp_irq_move_cleanup_interrupt() will attempt to + process the aforementioned irq, but panic when accessing + irq_cfg. + + Only continue processing the irq if irq_cfg is non-NULL. + + Signed-off-by: Dimitri Sivanich + Cc: Suresh Siddha + Cc: Joerg Roedel + Cc: Yinghai Lu + Cc: Alexander Gordeev + Link: http://lkml.kernel.org/r/20121016125021.GA22935@sgi.com + Signed-off-by: Ingo Molnar + +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index c265593..1817fa9 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) + continue; + + cfg = irq_cfg(irq); ++ if (!cfg) ++ continue; ++ + raw_spin_lock(&desc->lock); + + /* From 2d2a20cadcfcb0b4b13f53c457c614c9521da7c7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Nov 2012 08:39:48 -0500 Subject: [PATCH 100/492] Don't WARN_ON empty queues in iwlwifi (rhbz 873001) --- iwlwifi-remove-queue-empty-warn-3.6.patch | 25 +++++++++++++++++++++++ kernel.spec | 15 ++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 iwlwifi-remove-queue-empty-warn-3.6.patch diff --git a/iwlwifi-remove-queue-empty-warn-3.6.patch b/iwlwifi-remove-queue-empty-warn-3.6.patch new file mode 100644 index 000000000..b8cf5a470 --- /dev/null +++ b/iwlwifi-remove-queue-empty-warn-3.6.patch @@ -0,0 +1,25 @@ +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index 105e3af..79a4ddc 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, + void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) + { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); +- u16 rd_ptr, wr_ptr; +- int n_bd = trans_pcie->txq[txq_id].q.n_bd; + + if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { + WARN_ONCE(1, "queue %d not used", txq_id); + return; + } + +- rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); +- wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); +- +- WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", +- txq_id, rd_ptr, wr_ptr); +- + iwl_txq_set_inactive(trans, txq_id); + IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); + } diff --git a/kernel.spec b/kernel.spec index a67160be1..f8de3c0e8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 8 +%global baserelease 9 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -796,8 +796,12 @@ Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch +#rhbz 869341 Patch22113: smp_irq_move_cleanup_interrupt.patch +#rhbz 873001 +Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch + # END OF PATCH DEFINITIONS %endif @@ -1541,8 +1545,12 @@ ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch +#rhbz 869341 ApplyPatch smp_irq_move_cleanup_interrupt.patch +#rhbz 873001 +ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch + # END OF PATCH APPLICATIONS %endif @@ -2408,8 +2416,11 @@ fi # ||----w | # || || %changelog +* Fri Nov 16 2012 Josh Boyer +- Don't WARN_ON empty queues in iwlwifi (rhbz 873001) + * Thu Nov 15 2012 Justin M. Forbes -- Fix panic in panic in smp_irq_move_cleanup_interrupt +- Fix panic in panic in smp_irq_move_cleanup_interrupt (rhbz 869341) * Wed Nov 14 2012 Josh Boyer - Fix module signing of kernel flavours From c1d9f3987328bb24c43b114cf3b74e405e8d8d2a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Nov 2012 08:43:51 -0500 Subject: [PATCH 101/492] Fix oops causing typo in keyspan driver (rhbz 870562) --- kernel.spec | 7 ++++ keyspan.patch | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 keyspan.patch diff --git a/kernel.spec b/kernel.spec index f8de3c0e8..7c639fccf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,6 +802,9 @@ Patch22113: smp_irq_move_cleanup_interrupt.patch #rhbz 873001 Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch +#rhbz 870562 +Patch22115: keyspan.patch + # END OF PATCH DEFINITIONS %endif @@ -1551,6 +1554,9 @@ ApplyPatch smp_irq_move_cleanup_interrupt.patch #rhbz 873001 ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch +#rhbz 870562 +ApplyPatch keyspan.patch + # END OF PATCH APPLICATIONS %endif @@ -2417,6 +2423,7 @@ fi # || || %changelog * Fri Nov 16 2012 Josh Boyer +- Fix oops causing typo in keyspan driver (rhbz 870562) - Don't WARN_ON empty queues in iwlwifi (rhbz 873001) * Thu Nov 15 2012 Justin M. Forbes diff --git a/keyspan.patch b/keyspan.patch new file mode 100644 index 000000000..43d116ea4 --- /dev/null +++ b/keyspan.patch @@ -0,0 +1,98 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.58.186.240 with SMTP id fn16csp155256vec; + Sat, 10 Nov 2012 01:14:20 -0800 (PST) +Received: by 10.68.130.197 with SMTP id og5mr40733607pbb.138.1352538859530; + Sat, 10 Nov 2012 01:14:19 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id pj1si1353832pbc.115.2012.11.10.01.14.15; + Sat, 10 Nov 2012 01:14:19 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1750798Ab2KJJOO (ORCPT + 33 others); + Sat, 10 Nov 2012 04:14:14 -0500 +Received: from canardo.mork.no ([148.122.252.1]:37367 "EHLO canardo.mork.no" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1750699Ab2KJJOM (ORCPT ); + Sat, 10 Nov 2012 04:14:12 -0500 +Received: from nemi.mork.no (nemi.mork.no [IPv6:2001:4620:9:2:216:eaff:feb3:788]) + (authenticated bits=0) + by canardo.mork.no (8.14.3/8.14.3) with ESMTP id qAA9E1cX010750 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); + Sat, 10 Nov 2012 10:14:02 +0100 +Received: from bjorn by nemi.mork.no with local (Exim 4.80) + (envelope-from ) + id 1TX78a-0007Li-AD; Sat, 10 Nov 2012 10:14:00 +0100 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +To: Richard +Cc: Greg Kroah-Hartman , + linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, + =?UTF-8?q?Bj=C3=B8rn=20Mork?= , + , Johan Hovold +Subject: [PATCH usb-linus] USB: keyspan: fix typo causing GPF on open +Date: Sat, 10 Nov 2012 10:13:42 +0100 +Message-Id: <1352538822-28221-1-git-send-email-bjorn@mork.no> +X-Mailer: git-send-email 1.7.10.4 +In-Reply-To: <509D5BCD.3010901@pacbell.net> +References: <509D5BCD.3010901@pacbell.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +X-Virus-Scanned: clamav-milter 0.97.6 at canardo +X-Virus-Status: Clean +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +Commit f79b2d0f (USB: keyspan: fix NULL-pointer dereferences and +memory leaks) had a small typo which made the driver use wrong +offsets when mapping serial port private data. This results in +in a GPF when the port is opened. + +Reported-by: Richard +Cc: +Cc: Johan Hovold +Signed-off-by: Bjørn Mork +--- +Hello Richard, + +I wonder if you are able to test and verify this? I do not guarantee +that there aren't other issues around, but this small typo looked like +an obvious killer... + +Bjørn + + drivers/usb/serial/keyspan.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 7179b0c..cff8dd5 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial) + static int keyspan_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; +- struct keyspan_port_private *s_priv; ++ struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; +@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) + if (!p_priv) + return -ENOMEM; + +- s_priv = usb_get_serial_data(port->serial); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ +-- +1.7.10.4 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html From 208c5d02042db524b781957e5489a0dac4d81469 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Nov 2012 11:22:44 -0500 Subject: [PATCH 102/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 7c639fccf..970140a1f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2422,7 +2422,7 @@ fi # ||----w | # || || %changelog -* Fri Nov 16 2012 Josh Boyer +* Fri Nov 16 2012 Josh Boyer - 3.6.6-9 - Fix oops causing typo in keyspan driver (rhbz 870562) - Don't WARN_ON empty queues in iwlwifi (rhbz 873001) From e3759352a4ba114b1c7afc63eb9166c01b4d3ff1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Sat, 17 Nov 2012 22:29:48 -0600 Subject: [PATCH 103/492] linux 3.6.7 --- kernel.spec | 13 +- ...de-by-zero-in-tcp-algorithm-illinois.patch | 117 ------------------ sources | 2 +- ...crash-at-re-preparing-the-PCM-stream.patch | 4 +- 4 files changed, 8 insertions(+), 128 deletions(-) delete mode 100644 net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch diff --git a/kernel.spec b/kernel.spec index 970140a1f..854f6ecb7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 9 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -786,9 +786,6 @@ Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -#rhbz 871923 871848 CVE-2012-4565 -Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch - Patch22100: uprobes-upstream-backport.patch #rhbz 871078 @@ -1538,9 +1535,6 @@ ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -#rhbz 871923 871848 CVE-2012-4565 -ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch - ApplyPatch uprobes-upstream-backport.patch #rhbz 871078 @@ -2422,6 +2416,9 @@ fi # ||----w | # || || %changelog +* Sat Nov 17 2012 Justin M. Forbes - 3.6.7-1 +- linux 3.6.7 + * Fri Nov 16 2012 Josh Boyer - 3.6.6-9 - Fix oops causing typo in keyspan driver (rhbz 870562) - Don't WARN_ON empty queues in iwlwifi (rhbz 873001) diff --git a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch deleted file mode 100644 index 109ee17b4..000000000 --- a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch +++ /dev/null @@ -1,117 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Jesper Dangaard Brouer -Newsgroups: gmane.linux.network -Subject: [net PATCH V2] net: fix divide by zero in tcp algorithm illinois -Date: Wed, 31 Oct 2012 13:45:32 +0100 -Lines: 63 -Approved: news@gmane.org -Message-ID: <20121031124318.30915.32293.stgit@dragon> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 7bit -X-Trace: ger.gmane.org 1351687472 19921 80.91.229.3 (31 Oct 2012 12:44:32 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 31 Oct 2012 12:44:32 +0000 (UTC) -Cc: Jesper Dangaard Brouer , netdev@vger.kernel.org, - Petr Matousek , - Stephen Hemminger , - Eric Dumazet -To: "David S. Miller" -Original-X-From: netdev-owner@vger.kernel.org Wed Oct 31 13:44:40 2012 -Return-path: -Envelope-to: linux-netdev-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1TTXex-0002V3-Qk - for linux-netdev-2@plane.gmane.org; Wed, 31 Oct 2012 13:44:40 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S932565Ab2JaMo0 (ORCPT ); - Wed, 31 Oct 2012 08:44:26 -0400 -Original-Received: from mx1.redhat.com ([209.132.183.28]:57345 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751941Ab2JaMoZ (ORCPT ); - Wed, 31 Oct 2012 08:44:25 -0400 -Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9VCiOkC014655 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Wed, 31 Oct 2012 08:44:24 -0400 -Original-Received: from dragon.localdomain (ovpn-116-61.ams2.redhat.com [10.36.116.61]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9VCiMuW008440; - Wed, 31 Oct 2012 08:44:23 -0400 -Original-Received: from [127.0.0.1] (localhost [IPv6:::1]) - by dragon.localdomain (Postfix) with ESMTP id 416D0E40666; - Wed, 31 Oct 2012 13:45:32 +0100 (CET) -User-Agent: StGIT/0.14.3 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:247871 -Archived-At: - -Reading TCP stats when using TCP Illinois congestion control algorithm -can cause a divide by zero kernel oops. - -The division by zero occur in tcp_illinois_info() at: - do_div(t, ca->cnt_rtt); -where ca->cnt_rtt can become zero (when rtt_reset is called) - -Steps to Reproduce: - 1. Register tcp_illinois: - # sysctl -w net.ipv4.tcp_congestion_control=illinois - 2. Monitor internal TCP information via command "ss -i" - # watch -d ss -i - 3. Establish new TCP conn to machine - -Either it fails at the initial conn, or else it needs to wait -for a loss or a reset. - -This is only related to reading stats. The function avg_delay() also -performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its -calling point in update_params(). Thus, simply fix tcp_illinois_info(). - -Function tcp_illinois_info() / get_info() is called without -socket lock. Thus, eliminate any race condition on ca->cnt_rtt -by using a local stack variable. Simply reuse info.tcpv_rttcnt, -as its already set to ca->cnt_rtt. -Function avg_delay() is not affected by this race condition, as -its called with the socket lock. - -Cc: Petr Matousek -Signed-off-by: Jesper Dangaard Brouer - ---- -V2: - Address Eric Dumazets input: - - Save 2 bytes of stack, by using info.tcpv_rttcnt. - - Help compiler, and define "u64 t" inside if() lexical scope. - - - net/ipv4/tcp_illinois.c | 8 +++++--- - 1 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c -index 813b43a..834857f 100644 ---- a/net/ipv4/tcp_illinois.c -+++ b/net/ipv4/tcp_illinois.c -@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, - .tcpv_rttcnt = ca->cnt_rtt, - .tcpv_minrtt = ca->base_rtt, - }; -- u64 t = ca->sum_rtt; - -- do_div(t, ca->cnt_rtt); -- info.tcpv_rtt = t; -+ if (info.tcpv_rttcnt > 0) { -+ u64 t = ca->sum_rtt; - -+ do_div(t, info.tcpv_rttcnt); -+ info.tcpv_rtt = t; -+ } - nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); - } - } - diff --git a/sources b/sources index d3c14f4b8..0d260fa79 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -11d6d8749d4612a77f43f0531c0f2824 patch-3.6.6.xz +134936c362d8812b5cafcf3c67afdce0 patch-3.6.7.xz diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch index 6d840ea2c..9f3e6f993 100644 --- a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +++ b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch @@ -105,8 +105,8 @@ index 37428f7..5c12a3f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - if (snd_BUG_ON(!subs->data_endpoint)) - return -EIO; + goto unlock; + } + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); From b0cdc7c3c52a170c28fb4f5a98debcda391ee84e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 19 Nov 2012 11:04:45 -0500 Subject: [PATCH 104/492] Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) --- block-fix-a-crash-when-block-device-is.patch | 214 +++++++++++++ ...-a-rw-semaphore-into-a-percpu-rw-sem.patch | 290 ++++++++++++++++++ ...lice_read-and-splice_write-functions.patch | 74 +++++ kernel.spec | 15 +- 4 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 block-fix-a-crash-when-block-device-is.patch create mode 100644 blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch create mode 100644 fs-lock-splice_read-and-splice_write-functions.patch diff --git a/block-fix-a-crash-when-block-device-is.patch b/block-fix-a-crash-when-block-device-is.patch new file mode 100644 index 000000000..af992830e --- /dev/null +++ b/block-fix-a-crash-when-block-device-is.patch @@ -0,0 +1,214 @@ +Fix a crash when block device is read and block size is changed at the same time + +commit b87570f5d349661814b262dd5fc40787700f80d6 +Author: Mikulas Patocka +Date: Wed Sep 26 07:46:40 2012 +0200 + + Fix a crash when block device is read and block size is changed at the same time + + The kernel may crash when block size is changed and I/O is issued + simultaneously. + + Because some subsystems (udev or lvm) may read any block device anytime, + the bug actually puts any code that changes a block device size in + jeopardy. + + The crash can be reproduced if you place "msleep(1000)" to + blkdev_get_blocks just before "bh->b_size = max_blocks << + inode->i_blkbits;". + Then, run "dd if=/dev/ram0 of=/dev/null bs=4k count=1 iflag=direct" + While it is waiting in msleep, run "blockdev --setbsz 2048 /dev/ram0" + You get a BUG. + + The direct and non-direct I/O is written with the assumption that block + size does not change. It doesn't seem practical to fix these crashes + one-by-one there may be many crash possibilities when block size changes + at a certain place and it is impossible to find them all and verify the + code. + + This patch introduces a new rw-lock bd_block_size_semaphore. The lock is + taken for read during I/O. It is taken for write when changing block + size. Consequently, block size can't be changed while I/O is being + submitted. + + For asynchronous I/O, the patch only prevents block size change while + the I/O is being submitted. The block size can change when the I/O is in + progress or when the I/O is being finished. This is acceptable because + there are no accesses to block size when asynchronous I/O is being + finished. + + The patch prevents block size changing while the device is mapped with + mmap. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Jens Axboe + +Index: linux-3.6.x86_64/drivers/char/raw.c +=================================================================== +--- linux-3.6.x86_64.orig/drivers/char/raw.c 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/drivers/char/raw.c 2012-11-16 17:12:37.381002516 -0500 +@@ -285,7 +285,7 @@ + + static const struct file_operations raw_fops = { + .read = do_sync_read, +- .aio_read = generic_file_aio_read, ++ .aio_read = blkdev_aio_read, + .write = do_sync_write, + .aio_write = blkdev_aio_write, + .fsync = blkdev_fsync, +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 +@@ -116,6 +116,8 @@ + + int set_blocksize(struct block_device *bdev, int size) + { ++ struct address_space *mapping; ++ + /* Size must be a power of two, and between 512 and PAGE_SIZE */ + if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) + return -EINVAL; +@@ -124,6 +126,20 @@ + if (size < bdev_logical_block_size(bdev)) + return -EINVAL; + ++ /* Prevent starting I/O or mapping the device */ ++ down_write(&bdev->bd_block_size_semaphore); ++ ++ /* Check that the block device is not memory mapped */ ++ mapping = bdev->bd_inode->i_mapping; ++ mutex_lock(&mapping->i_mmap_mutex); ++ if (!prio_tree_empty(&mapping->i_mmap) || ++ !list_empty(&mapping->i_mmap_nonlinear)) { ++ mutex_unlock(&mapping->i_mmap_mutex); ++ up_write(&bdev->bd_block_size_semaphore); ++ return -EBUSY; ++ } ++ mutex_unlock(&mapping->i_mmap_mutex); ++ + /* Don't change the size if it is same as current */ + if (bdev->bd_block_size != size) { + sync_blockdev(bdev); +@@ -131,6 +147,9 @@ + bdev->bd_inode->i_blkbits = blksize_bits(size); + kill_bdev(bdev); + } ++ ++ up_write(&bdev->bd_block_size_semaphore); ++ + return 0; + } + +@@ -472,6 +491,7 @@ + inode_init_once(&ei->vfs_inode); + /* Initialize mutex for freeze. */ + mutex_init(&bdev->bd_fsfreeze_mutex); ++ init_rwsem(&bdev->bd_block_size_semaphore); + } + + static inline void __bd_forget(struct inode *inode) +@@ -1567,6 +1587,22 @@ + return blkdev_ioctl(bdev, mode, cmd, arg); + } + ++ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, ++ unsigned long nr_segs, loff_t pos) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_aio_read(iocb, iov, nr_segs, pos); ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(blkdev_aio_read); ++ + /* + * Write data to the block device. Only intended for the block device itself + * and the raw driver which basically is a fake block device. +@@ -1578,12 +1614,16 @@ + unsigned long nr_segs, loff_t pos) + { + struct file *file = iocb->ki_filp; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); + struct blk_plug plug; + ssize_t ret; + + BUG_ON(iocb->ki_pos != pos); + + blk_start_plug(&plug); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); + if (ret > 0 || ret == -EIOCBQUEUED) { + ssize_t err; +@@ -1592,11 +1632,29 @@ + if (err < 0 && ret > 0) + ret = err; + } ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ + blk_finish_plug(&plug); ++ + return ret; + } + EXPORT_SYMBOL_GPL(blkdev_aio_write); + ++int blkdev_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_mmap(file, vma); ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ + /* + * Try to release a page associated with block device when the system + * is under memory pressure. +@@ -1627,9 +1685,9 @@ + .llseek = block_llseek, + .read = do_sync_read, + .write = do_sync_write, +- .aio_read = generic_file_aio_read, ++ .aio_read = blkdev_aio_read, + .aio_write = blkdev_aio_write, +- .mmap = generic_file_mmap, ++ .mmap = blkdev_mmap, + .fsync = blkdev_fsync, + .unlocked_ioctl = block_ioctl, + #ifdef CONFIG_COMPAT +Index: linux-3.6.x86_64/include/linux/fs.h +=================================================================== +--- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 +@@ -724,6 +724,8 @@ + int bd_fsfreeze_count; + /* Mutex for freeze */ + struct mutex bd_fsfreeze_mutex; ++ /* A semaphore that prevents I/O while block size is being changed */ ++ struct rw_semaphore bd_block_size_semaphore; + }; + + /* +@@ -2564,6 +2566,8 @@ + unsigned long *nr_segs, size_t *count, int access_flags); + + /* fs/block_dev.c */ ++extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, ++ unsigned long nr_segs, loff_t pos); + extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos); + extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, diff --git a/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch b/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch new file mode 100644 index 000000000..82caa6b76 --- /dev/null +++ b/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -0,0 +1,290 @@ +blockdev: turn a rw semaphore into a percpu rw semaphore + +commit 62ac665ff9fc07497ca524bd20d6a96893d11071 +Author: Mikulas Patocka +Date: Wed Sep 26 07:46:43 2012 +0200 + + blockdev: turn a rw semaphore into a percpu rw semaphore + + This avoids cache line bouncing when many processes lock the semaphore + for read. + + New percpu lock implementation + + The lock consists of an array of percpu unsigned integers, a boolean + variable and a mutex. + + When we take the lock for read, we enter rcu read section, check for a + "locked" variable. If it is false, we increase a percpu counter on the + current cpu and exit the rcu section. If "locked" is true, we exit the + rcu section, take the mutex and drop it (this waits until a writer + finished) and retry. + + Unlocking for read just decreases percpu variable. Note that we can + unlock on a difference cpu than where we locked, in this case the + counter underflows. The sum of all percpu counters represents the number + of processes that hold the lock for read. + + When we need to lock for write, we take the mutex, set "locked" variable + to true and synchronize rcu. Since RCU has been synchronized, no + processes can create new read locks. We wait until the sum of percpu + counters is zero - when it is, there are no readers in the critical + section. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Jens Axboe + +Index: linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt 2012-11-16 17:12:57.351936583 -0500 +@@ -0,0 +1,27 @@ ++Percpu rw semaphores ++-------------------- ++ ++Percpu rw semaphores is a new read-write semaphore design that is ++optimized for locking for reading. ++ ++The problem with traditional read-write semaphores is that when multiple ++cores take the lock for reading, the cache line containing the semaphore ++is bouncing between L1 caches of the cores, causing performance ++degradation. ++ ++Locking for reading it very fast, it uses RCU and it avoids any atomic ++instruction in the lock and unlock path. On the other hand, locking for ++writing is very expensive, it calls synchronize_rcu() that can take ++hundreds of microseconds. ++ ++The lock is declared with "struct percpu_rw_semaphore" type. ++The lock is initialized percpu_init_rwsem, it returns 0 on success and ++-ENOMEM on allocation failure. ++The lock must be freed with percpu_free_rwsem to avoid memory leak. ++ ++The lock is locked for read with percpu_down_read, percpu_up_read and ++for write with percpu_down_write, percpu_up_write. ++ ++The idea of using RCU for optimized rw-lock was introduced by ++Eric Dumazet . ++The code was written by Mikulas Patocka +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:27:41.217005828 -0500 +@@ -127,7 +127,7 @@ + return -EINVAL; + + /* Prevent starting I/O or mapping the device */ +- down_write(&bdev->bd_block_size_semaphore); ++ percpu_down_write(&bdev->bd_block_size_semaphore); + + /* Check that the block device is not memory mapped */ + mapping = bdev->bd_inode->i_mapping; +@@ -135,7 +135,7 @@ + if (!prio_tree_empty(&mapping->i_mmap) || + !list_empty(&mapping->i_mmap_nonlinear)) { + mutex_unlock(&mapping->i_mmap_mutex); +- up_write(&bdev->bd_block_size_semaphore); ++ percpu_up_write(&bdev->bd_block_size_semaphore); + return -EBUSY; + } + mutex_unlock(&mapping->i_mmap_mutex); +@@ -148,7 +148,7 @@ + kill_bdev(bdev); + } + +- up_write(&bdev->bd_block_size_semaphore); ++ percpu_up_write(&bdev->bd_block_size_semaphore); + + return 0; + } +@@ -460,6 +460,12 @@ + struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); + if (!ei) + return NULL; ++ ++ if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) { ++ kmem_cache_free(bdev_cachep, ei); ++ return NULL; ++ } ++ + return &ei->vfs_inode; + } + +@@ -468,6 +474,8 @@ + struct inode *inode = container_of(head, struct inode, i_rcu); + struct bdev_inode *bdi = BDEV_I(inode); + ++ percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore); ++ + kmem_cache_free(bdev_cachep, bdi); + } + +@@ -491,7 +499,6 @@ + inode_init_once(&ei->vfs_inode); + /* Initialize mutex for freeze. */ + mutex_init(&bdev->bd_fsfreeze_mutex); +- init_rwsem(&bdev->bd_block_size_semaphore); + } + + static inline void __bd_forget(struct inode *inode) +@@ -1593,11 +1600,11 @@ + ssize_t ret; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_aio_read(iocb, iov, nr_segs, pos); + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; + } +@@ -1622,7 +1629,7 @@ + + blk_start_plug(&plug); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); + if (ret > 0 || ret == -EIOCBQUEUED) { +@@ -1633,7 +1640,7 @@ + ret = err; + } + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + blk_finish_plug(&plug); + +@@ -1646,11 +1653,11 @@ + int ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_mmap(file, vma); + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; + } +Index: linux-3.6.x86_64/include/linux/fs.h +=================================================================== +--- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 ++++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:28:12.578901349 -0500 +@@ -415,6 +415,7 @@ + #include + #include + #include ++#include + + #include + +@@ -725,7 +726,7 @@ + /* Mutex for freeze */ + struct mutex bd_fsfreeze_mutex; + /* A semaphore that prevents I/O while block size is being changed */ +- struct rw_semaphore bd_block_size_semaphore; ++ struct percpu_rw_semaphore bd_block_size_semaphore; + }; + + /* +Index: linux-3.6.x86_64/include/linux/percpu-rwsem.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.6.x86_64/include/linux/percpu-rwsem.h 2012-11-16 17:12:57.354936574 -0500 +@@ -0,0 +1,89 @@ ++#ifndef _LINUX_PERCPU_RWSEM_H ++#define _LINUX_PERCPU_RWSEM_H ++ ++#include ++#include ++#include ++#include ++ ++struct percpu_rw_semaphore { ++ unsigned __percpu *counters; ++ bool locked; ++ struct mutex mtx; ++}; ++ ++static inline void percpu_down_read(struct percpu_rw_semaphore *p) ++{ ++ rcu_read_lock(); ++ if (unlikely(p->locked)) { ++ rcu_read_unlock(); ++ mutex_lock(&p->mtx); ++ this_cpu_inc(*p->counters); ++ mutex_unlock(&p->mtx); ++ return; ++ } ++ this_cpu_inc(*p->counters); ++ rcu_read_unlock(); ++} ++ ++static inline void percpu_up_read(struct percpu_rw_semaphore *p) ++{ ++ /* ++ * On X86, write operation in this_cpu_dec serves as a memory unlock ++ * barrier (i.e. memory accesses may be moved before the write, but ++ * no memory accesses are moved past the write). ++ * On other architectures this may not be the case, so we need smp_mb() ++ * there. ++ */ ++#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) ++ barrier(); ++#else ++ smp_mb(); ++#endif ++ this_cpu_dec(*p->counters); ++} ++ ++static inline unsigned __percpu_count(unsigned __percpu *counters) ++{ ++ unsigned total = 0; ++ int cpu; ++ ++ for_each_possible_cpu(cpu) ++ total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); ++ ++ return total; ++} ++ ++static inline void percpu_down_write(struct percpu_rw_semaphore *p) ++{ ++ mutex_lock(&p->mtx); ++ p->locked = true; ++ synchronize_rcu(); ++ while (__percpu_count(p->counters)) ++ msleep(1); ++ smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ ++} ++ ++static inline void percpu_up_write(struct percpu_rw_semaphore *p) ++{ ++ p->locked = false; ++ mutex_unlock(&p->mtx); ++} ++ ++static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) ++{ ++ p->counters = alloc_percpu(unsigned); ++ if (unlikely(!p->counters)) ++ return -ENOMEM; ++ p->locked = false; ++ mutex_init(&p->mtx); ++ return 0; ++} ++ ++static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) ++{ ++ free_percpu(p->counters); ++ p->counters = NULL; /* catch use after free bugs */ ++} ++ ++#endif diff --git a/fs-lock-splice_read-and-splice_write-functions.patch b/fs-lock-splice_read-and-splice_write-functions.patch new file mode 100644 index 000000000..938cbd9f5 --- /dev/null +++ b/fs-lock-splice_read-and-splice_write-functions.patch @@ -0,0 +1,74 @@ +Lock splice_read and splice_write functions + +commit 1a25b1c4ce189e3926f2981f3302352a930086db +Author: Mikulas Patocka +Date: Mon Oct 15 17:20:17 2012 -0400 + + Lock splice_read and splice_write functions + + Functions generic_file_splice_read and generic_file_splice_write access + the pagecache directly. For block devices these functions must be locked + so that block size is not changed while they are in progress. + + This patch is an additional fix for commit b87570f5d349 ("Fix a crash + when block device is read and block size is changed at the same time") + that locked aio_read, aio_write and mmap against block size change. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Linus Torvalds + +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:57.352936580 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:13:11.908887989 -0500 +@@ -1662,6 +1662,39 @@ + return ret; + } + ++static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ percpu_down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_splice_read(file, ppos, pipe, len, flags); ++ ++ percpu_up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ ++static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, ++ struct file *file, loff_t *ppos, size_t len, ++ unsigned int flags) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ percpu_down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_splice_write(pipe, file, ppos, len, flags); ++ ++ percpu_up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ ++ + /* + * Try to release a page associated with block device when the system + * is under memory pressure. +@@ -1700,8 +1733,8 @@ + #ifdef CONFIG_COMPAT + .compat_ioctl = compat_blkdev_ioctl, + #endif +- .splice_read = generic_file_splice_read, +- .splice_write = generic_file_splice_write, ++ .splice_read = blkdev_splice_read, ++ .splice_write = blkdev_splice_write, + }; + + int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/kernel.spec b/kernel.spec index 854f6ecb7..e584991a7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -802,6 +802,11 @@ Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch #rhbz 870562 Patch22115: keyspan.patch +#rhbz 812129 +Patch22120: block-fix-a-crash-when-block-device-is.patch +Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +Patch22122: fs-lock-splice_read-and-splice_write-functions.patch + # END OF PATCH DEFINITIONS %endif @@ -1551,6 +1556,11 @@ ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch #rhbz 870562 ApplyPatch keyspan.patch +#rhbz 812129 +ApplyPatch block-fix-a-crash-when-block-device-is.patch +ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch + # END OF PATCH APPLICATIONS %endif @@ -2416,6 +2426,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 19 2012 Josh Boyer +- Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) + * Sat Nov 17 2012 Justin M. Forbes - 3.6.7-1 - linux 3.6.7 From 8b21b3a41b533b6dfa976505d491e008f40755f4 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 20 Nov 2012 12:01:52 +0000 Subject: [PATCH 105/492] Change the minimum mmap address back to 32768 on ARM systems (thanks to Jon Masters) --- config-arm-generic | 3 +++ kernel.spec | 3 +++ 2 files changed, 6 insertions(+) diff --git a/config-arm-generic b/config-arm-generic index e0507a0f1..625c61111 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -63,6 +63,9 @@ CONFIG_CPU_IDLE=y # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/kernel.spec b/kernel.spec index e584991a7..5a8f330cd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2426,6 +2426,9 @@ fi # ||----w | # || || %changelog +* Tue Nov 20 2012 Peter Robinson +- Change the minimum mmap address back to 32768 on ARM systems (thanks to Jon Masters) + * Mon Nov 19 2012 Josh Boyer - Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) From ddbf9b7f28343244502635bc6f4ed2d9f18ebd81 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 07:51:30 -0500 Subject: [PATCH 106/492] Add support for BCM20702A0 (rhbz 874791) --- Bluetooth-Add-support-for-BCM20702A0.patch | 107 +++++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch new file mode 100644 index 000000000..73f00fc43 --- /dev/null +++ b/Bluetooth-Add-support-for-BCM20702A0.patch @@ -0,0 +1,107 @@ +From 7f198e1cc6d4fda9c84c0da4fc3aafb441342f78 Mon Sep 17 00:00:00 2001 +From: Jaroslav Resler +Date: Tue, 11 Sep 2012 17:25:32 +0800 +Subject: [PATCH 1/2] Bluetooth: Add support for BCM20702A0 [04ca, 2003] + +Add another vendor specific ID for BCM20702A0. + +output of usb-devices: +T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=04ca ProdID=2003 Rev= 1.12 +S: Manufacturer=Broadcom Corp +S: Product=BCM20702A0 +S: SerialNumber=446D57861623 +C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) +E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms +E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms +I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) + +Signed-off-by: Cho, Yu-Chen +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/btusb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 654e248..b167944 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, + +-- +1.8.0 + + +From a5f86c3423428c8e28b6501d0e9c3929ca91f07d Mon Sep 17 00:00:00 2001 +From: Jeff Cook +Date: Fri, 9 Nov 2012 16:39:48 -0700 +Subject: [PATCH 2/2] Bluetooth: Add support for BCM20702A0 [0b05, 17b5] + +Vendor-specific ID for BCM20702A0. +Support for bluetooth over Asus Wi-Fi GO!, included with Asus P8Z77-V +Deluxe. + +T: Bus=07 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 +D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0b05 ProdID=17b5 Rev=01.12 +S: Manufacturer=Broadcom Corp +S: Product=BCM20702A0 +S: SerialNumber=94DBC98AC113 +C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) +I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) +I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) +I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) + +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Cook +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/btusb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index b167944..6dc44ff 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0b05, 0x17b5) }, + { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 5a8f330cd..6a69baa30 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -807,6 +807,9 @@ Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch Patch22122: fs-lock-splice_read-and-splice_write-functions.patch +#rhbz 874791 +Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH DEFINITIONS %endif @@ -1561,6 +1564,9 @@ ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch +#rhbz 874791 +ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH APPLICATIONS %endif @@ -2426,6 +2432,9 @@ fi # ||----w | # || || %changelog +* Tue Nov 20 2012 Josh Boyer +- Add support for BCM20702A0 (rhbz 874791) + * Tue Nov 20 2012 Peter Robinson - Change the minimum mmap address back to 32768 on ARM systems (thanks to Jon Masters) From 9bb5a1f4aa2dd899b62da6f5478c7e69e379a735 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 08:18:51 -0500 Subject: [PATCH 107/492] Add VC_MUTE ioctl (rhbz 859485) --- kernel.spec | 9 +- vt-Drop-K_OFF-for-VC_MUTE.patch | 250 ++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 vt-Drop-K_OFF-for-VC_MUTE.patch diff --git a/kernel.spec b/kernel.spec index 6a69baa30..e23334b18 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -810,6 +810,9 @@ Patch22122: fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 859485 +Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch + # END OF PATCH DEFINITIONS %endif @@ -1567,6 +1570,9 @@ ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 859485 +ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch + # END OF PATCH APPLICATIONS %endif @@ -2433,6 +2439,7 @@ fi # || || %changelog * Tue Nov 20 2012 Josh Boyer +- Add VC_MUTE ioctl (rhbz 859485) - Add support for BCM20702A0 (rhbz 874791) * Tue Nov 20 2012 Peter Robinson diff --git a/vt-Drop-K_OFF-for-VC_MUTE.patch b/vt-Drop-K_OFF-for-VC_MUTE.patch new file mode 100644 index 000000000..ab85411cb --- /dev/null +++ b/vt-Drop-K_OFF-for-VC_MUTE.patch @@ -0,0 +1,250 @@ +Path: news.gmane.org!not-for-mail +From: Adam Jackson +Newsgroups: gmane.linux.kernel +Subject: [PATCH] vt: Drop K_OFF for VC_MUTE +Date: Fri, 16 Nov 2012 13:32:34 -0500 +Lines: 205 +Approved: news@gmane.org +Message-ID: <1353090754-30233-1-git-send-email-ajax@redhat.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: ger.gmane.org 1353090772 20663 80.91.229.3 (16 Nov 2012 18:32:52 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Fri, 16 Nov 2012 18:32:52 +0000 (UTC) +Cc: Arthur Taylor , + Greg Kroah-Hartman +To: linux-kernel@vger.kernel.org +Original-X-From: linux-kernel-owner@vger.kernel.org Fri Nov 16 19:33:03 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1TZQim-0000aG-BI + for glk-linux-kernel-3@plane.gmane.org; Fri, 16 Nov 2012 19:32:56 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753232Ab2KPSck (ORCPT ); + Fri, 16 Nov 2012 13:32:40 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:32172 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752810Ab2KPSci (ORCPT ); + Fri, 16 Nov 2012 13:32:38 -0500 +Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qAGIWaM7020116 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Fri, 16 Nov 2012 13:32:36 -0500 +Original-Received: from ihatethathostname.lab.bos.redhat.com (ihatethathostname.lab.bos.redhat.com [10.16.43.238]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id qAGIWZD7010099; + Fri, 16 Nov 2012 13:32:35 -0500 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1395620 +Archived-At: + +The "don't enqueue stuff" semantics of K_OFF shouldn't be a function of +the keyboard map state; we should be able to switch among cooked/raw/ +unicode without changing whether events are delivered. Otherwise - if +changing to K_UNICODE undoes K_OFF - then suddenly Alt-F2 under +Gnome will switch VT instead of summoning the "run command" dialog. + +Drop the K_OFF handling and replace it with a new "mute" ioctl pair. +Anybody using K_OFF would already need to be prepared to handle it +throwing -EINVAL for old kernel compatibility, so userspace will degrade +gracefully. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=859485 +Cc: Arthur Taylor +Cc: Greg Kroah-Hartman +Tested-by: Josh Boyer +Signed-off-by: Adam Jackson +--- + drivers/tty/vt/keyboard.c | 40 +++++++++++++++++++++++++++++++++------- + drivers/tty/vt/vt_ioctl.c | 13 +++++++++++++ + include/linux/kbd_kern.h | 6 +++--- + include/linux/vt_kern.h | 2 ++ + include/linux/kd.h | 5 +++++ + 5 files changed, 56 insertions(+), 10 deletions(-) + +diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c +index 681765b..08d1d57 100644 +--- a/drivers/tty/vt/keyboard.c ++++ b/drivers/tty/vt/keyboard.c +@@ -657,7 +657,7 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) + return; + if ((kbd->kbdmode == VC_RAW || + kbd->kbdmode == VC_MEDIUMRAW || +- kbd->kbdmode == VC_OFF) && ++ vc_kbd_mode(kbd, VC_MUTE)) && + value != KVAL(K_SAK)) + return; /* SAK is allowed even in raw mode */ + fn_handler[value](vc); +@@ -1381,7 +1381,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) + if (rc == NOTIFY_STOP) + return; + +- if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT) ++ if ((raw_mode || vc_kbd_mode(kbd, VC_MUTE)) && type != KT_SPEC && type != KT_SHIFT) + return; + + (*k_handler[type])(vc, keysym & 0xff, !down); +@@ -1731,9 +1731,6 @@ int vt_do_kdskbmode(int console, unsigned int arg) + kbd->kbdmode = VC_UNICODE; + do_compute_shiftstate(); + break; +- case K_OFF: +- kbd->kbdmode = VC_OFF; +- break; + default: + ret = -EINVAL; + } +@@ -1742,6 +1739,30 @@ int vt_do_kdskbmode(int console, unsigned int arg) + } + + /** ++ * vt_do_kdskbmute - set keyboard event mute ++ * @console: the console to use ++ * @arg: the requested mode ++ * ++ * Update the keyboard mute state while holding the correct locks. ++ * Return 0 for success or an error code. ++ */ ++int vt_do_kdskbmute(int console, unsigned int arg) ++{ ++ struct kbd_struct * kbd = kbd_table + console; ++ int ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&kbd_event_lock, flags); ++ if (arg) ++ set_vc_kbd_mode(kbd, VC_MUTE); ++ else ++ clr_vc_kbd_mode(kbd, VC_MUTE); ++ spin_unlock_irqrestore(&kbd_event_lock, flags); ++ return ret; ++} ++ ++ ++/** + * vt_do_kdskbmeta - set keyboard meta state + * @console: the console to use + * @arg: the requested meta state +@@ -2068,13 +2089,18 @@ int vt_do_kdgkbmode(int console) + return K_MEDIUMRAW; + case VC_UNICODE: + return K_UNICODE; +- case VC_OFF: +- return K_OFF; + default: + return K_XLATE; + } + } + ++int vt_do_kdgkbmute(int console) ++{ ++ struct kbd_struct * kbd = kbd_table + console; ++ /* This is a spot read so needs no locking */ ++ return vc_kbd_mode(kbd, VC_MUTE); ++} ++ + /** + * vt_do_kdgkbmeta - report meta status + * @console: console to report +diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c +index b841f56..f0951e2 100644 +--- a/drivers/tty/vt/vt_ioctl.c ++++ b/drivers/tty/vt/vt_ioctl.c +@@ -477,6 +477,19 @@ int vt_ioctl(struct tty_struct *tty, + ret = put_user(uival, (int __user *)arg); + break; + ++ case KDSKBMUTE: ++ if (!perm) ++ return -EPERM; ++ ret = vt_do_kdskbmute(console, arg); ++ if (ret == 0) ++ tty_ldisc_flush(tty); ++ break; ++ ++ case KDGKBMUTE: ++ uival = vt_do_kdgkbmute(console); ++ ret = put_user(uival, (int __user *)arg); ++ break; ++ + /* this could be folded into KDSKBMODE, but for compatibility + reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ + case KDSKBMETA: +diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h +index b7c8cdc..9386143 100644 +--- a/include/linux/kbd_kern.h ++++ b/include/linux/kbd_kern.h +@@ -48,19 +48,19 @@ struct kbd_struct { + #define VC_CAPSLOCK 2 /* capslock mode */ + #define VC_KANALOCK 3 /* kanalock mode */ + +- unsigned char kbdmode:3; /* one 3-bit value */ ++ unsigned char kbdmode:2; /* one 2-bit value */ + #define VC_XLATE 0 /* translate keycodes using keymap */ + #define VC_MEDIUMRAW 1 /* medium raw (keycode) mode */ + #define VC_RAW 2 /* raw (scancode) mode */ + #define VC_UNICODE 3 /* Unicode mode */ +-#define VC_OFF 4 /* disabled mode */ + +- unsigned char modeflags:5; ++ unsigned char modeflags:6; + #define VC_APPLIC 0 /* application key mode */ + #define VC_CKMODE 1 /* cursor key mode */ + #define VC_REPEAT 2 /* keyboard repeat */ + #define VC_CRLF 3 /* 0 - enter sends CR, 1 - enter sends CRLF */ + #define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */ ++#define VC_MUTE 5 /* don't generate events */ + }; + + extern int kbd_init(void); +diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h +index 50ae7d0..a886915 100644 +--- a/include/linux/vt_kern.h ++++ b/include/linux/vt_kern.h +@@ -168,6 +168,7 @@ extern void hide_boot_cursor(bool hide); + + /* keyboard provided interfaces */ + extern int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm); ++extern int vt_do_kdskbmute(int console, unsigned int arg); + extern int vt_do_kdskbmode(int console, unsigned int arg); + extern int vt_do_kdskbmeta(int console, unsigned int arg); + extern int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, +@@ -177,6 +178,7 @@ extern int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, + extern int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, + int perm); + extern int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm); ++extern int vt_do_kdgkbmute(int console); + extern int vt_do_kdgkbmode(int console); + extern int vt_do_kdgkbmeta(int console); + extern void vt_reset_unicode(int console); +diff --git a/include/linux/kd.h b/include/linux/kd.h +index 87b7cc4..c3de63c 100644 +--- a/include/linux/kd.h ++++ b/include/linux/kd.h +@@ -81,6 +81,7 @@ struct unimapinit { + #define K_XLATE 0x01 + #define K_MEDIUMRAW 0x02 + #define K_UNICODE 0x03 ++/* K_OFF is no longer implemented, but preserved for source compatibility */ + #define K_OFF 0x04 + #define KDGKBMODE 0x4B44 /* gets current keyboard mode */ + #define KDSKBMODE 0x4B45 /* sets current keyboard mode */ +@@ -150,6 +151,10 @@ struct kbd_repeat { + /* earlier this field was misnamed "rate" */ + }; + ++/* get/set event mute */ ++#define KDGKBMUTE 0x4B50 ++#define KDSKBMUTE 0x4B51 ++ + #define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate; + * actually used values are returned */ + +-- +1.7.11.7 + From 645afa77c180dd8dcac359226c6b78a973e14180 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 12:41:18 -0500 Subject: [PATCH 108/492] CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) --- ...opcode-oops-on-SET_SREGS-with-OSXSAV.patch | 83 +++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch diff --git a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch new file mode 100644 index 000000000..890bf495e --- /dev/null +++ b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch @@ -0,0 +1,83 @@ +From 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 Mon Sep 17 00:00:00 2001 +From: Petr Matousek +Date: Tue, 6 Nov 2012 19:24:07 +0100 +Subject: [PATCH] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit + set (CVE-2012-4461) + +On hosts without the XSAVE support unprivileged local user can trigger +oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest +cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN +ioctl. + +invalid opcode: 0000 [#2] SMP +Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables +... +Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae +EIP: 0060:[] EFLAGS: 00210246 CPU: 0 +EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] +EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 +ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 + DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 +task.ti=d7c62000) +Stack: + 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 + ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 + c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 +Call Trace: + [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] +... + [] ? syscall_call+0x7/0xb +Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 +1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 +d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 +EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP +0068:d7c63e70 + +QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID +and then sets them later. So guest's X86_FEATURE_XSAVE should be masked +out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with +X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with +X86_FEATURE_XSAVE even on hosts that do not support it, might be +susceptible to this attack from inside the guest as well. + +Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. + +Signed-off-by: Petr Matousek +Signed-off-by: Marcelo Tosatti +--- + arch/x86/kvm/cpuid.h | 3 +++ + arch/x86/kvm/x86.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h +index a10e460..58fc514 100644 +--- a/arch/x86/kvm/cpuid.h ++++ b/arch/x86/kvm/cpuid.h +@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + ++ if (!static_cpu_has(X86_FEATURE_XSAVE)) ++ return 0; ++ + best = kvm_find_cpuid_entry(vcpu, 1, 0); + return best && (best->ecx & bit(X86_FEATURE_XSAVE)); + } +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 224a7e7..4f76417 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5781,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + int pending_vec, max_bits, idx; + struct desc_ptr dt; + ++ if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) ++ return -EINVAL; ++ + dt.size = sregs->idt.limit; + dt.address = sregs->idt.base; + kvm_x86_ops->set_idt(vcpu, &dt); +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index e23334b18..c0fb718c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -813,6 +813,9 @@ Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 859485 Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch +#rhbz CVE-2012-4461 862900 878518 +Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch + # END OF PATCH DEFINITIONS %endif @@ -1573,6 +1576,9 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 859485 ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch +#rhbz CVE-2012-4461 862900 878518 +ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch + # END OF PATCH APPLICATIONS %endif @@ -2439,6 +2445,7 @@ fi # || || %changelog * Tue Nov 20 2012 Josh Boyer +- CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) - Add VC_MUTE ioctl (rhbz 859485) - Add support for BCM20702A0 (rhbz 874791) From a6a4f9ae820b8132b2e50578efc86df668aaed28 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 14:23:08 -0500 Subject: [PATCH 109/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index c0fb718c9..74428d03d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2444,7 +2444,7 @@ fi # ||----w | # || || %changelog -* Tue Nov 20 2012 Josh Boyer +* Tue Nov 20 2012 Josh Boyer - 3.6.7-5 - CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) - Add VC_MUTE ioctl (rhbz 859485) - Add support for BCM20702A0 (rhbz 874791) From 4703e152a9dd525e40272ee2f26ae651ffe1313c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 09:03:26 -0500 Subject: [PATCH 110/492] CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) --- exec-do-not-leave-bprm-interp-on-stack.patch | 118 +++++++++++++++ exec-use-eloop-for-max-recursion-depth.patch | 144 +++++++++++++++++++ kernel.spec | 13 +- 3 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 exec-do-not-leave-bprm-interp-on-stack.patch create mode 100644 exec-use-eloop-for-max-recursion-depth.patch diff --git a/exec-do-not-leave-bprm-interp-on-stack.patch b/exec-do-not-leave-bprm-interp-on-stack.patch new file mode 100644 index 000000000..2a4b2dd28 --- /dev/null +++ b/exec-do-not-leave-bprm-interp-on-stack.patch @@ -0,0 +1,118 @@ +From 20ae2081584450e552735a3df968ce5b5946a607 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 26 Nov 2012 08:56:37 -0500 +Subject: [PATCH 1/2] exec: do not leave bprm->interp on stack + +If a series of scripts are executed, each triggering module loading via +unprintable bytes in the script header, kernel stack contents can leak +into the command line. + +Normally execution of binfmt_script and binfmt_misc happens recursively. +However, when modules are enabled, and unprintable bytes exist in the +bprm->buf, execution will restart after attempting to load matching binfmt +modules. Unfortunately, the logic in binfmt_script and binfmt_misc does +not expect to get restarted. They leave bprm->interp pointing to their +local stack. This means on restart bprm->interp is left pointing into +unused stack memory which can then be copied into the userspace argv +areas. + +After additional study, it seems that both recursion and restart remains +the desirable way to handle exec with scripts, misc, and modules. As +such, we need to protect the changes to interp. + +This changes the logic to require allocation for any changes to the +bprm->interp. To avoid adding a new kmalloc to every exec, the default +value is left as-is. Only when passing through binfmt_script or +binfmt_misc does an allocation take place. + +For a proof of concept, see DoTest.sh from: +http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/ + +Signed-off-by: Kees Cook +Cc: halfdog +Cc: P J P +Cc: Alexander Viro +Cc: +Signed-off-by: Andrew Morton +--- + fs/binfmt_misc.c | 5 ++++- + fs/binfmt_script.c | 4 +++- + fs/exec.c | 15 +++++++++++++++ + include/linux/binfmts.h | 1 + + 4 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index 790b3cd..772428d 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -176,7 +176,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + goto _error; + bprm->argc ++; + +- bprm->interp = iname; /* for binfmt_script */ ++ /* Update interp in case binfmt_script needs it. */ ++ retval = bprm_change_interp(iname, bprm); ++ if (retval < 0) ++ goto _error; + + interp_file = open_exec (iname); + retval = PTR_ERR (interp_file); +diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c +index d3b8c1f..df49d48 100644 +--- a/fs/binfmt_script.c ++++ b/fs/binfmt_script.c +@@ -82,7 +82,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) + retval = copy_strings_kernel(1, &i_name, bprm); + if (retval) return retval; + bprm->argc++; +- bprm->interp = interp; ++ retval = bprm_change_interp(interp, bprm); ++ if (retval < 0) ++ return retval; + + /* + * OK, now restart the process with the interpreter's dentry. +diff --git a/fs/exec.c b/fs/exec.c +index fab2c6d..59896ae 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1202,9 +1202,24 @@ void free_bprm(struct linux_binprm *bprm) + mutex_unlock(¤t->signal->cred_guard_mutex); + abort_creds(bprm->cred); + } ++ /* If a binfmt changed the interp, free it. */ ++ if (bprm->interp != bprm->filename) ++ kfree(bprm->interp); + kfree(bprm); + } + ++int bprm_change_interp(char *interp, struct linux_binprm *bprm) ++{ ++ /* If a binfmt changed the interp, free it first. */ ++ if (bprm->interp != bprm->filename) ++ kfree(bprm->interp); ++ bprm->interp = kstrdup(interp, GFP_KERNEL); ++ if (!bprm->interp) ++ return -ENOMEM; ++ return 0; ++} ++EXPORT_SYMBOL(bprm_change_interp); ++ + /* + * install the new credentials for this executable + */ +diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h +index 366422b..eb53e15 100644 +--- a/include/linux/binfmts.h ++++ b/include/linux/binfmts.h +@@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, + unsigned long stack_top, + int executable_stack); + extern int bprm_mm_init(struct linux_binprm *bprm); ++extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); + extern int copy_strings_kernel(int argc, const char *const *argv, + struct linux_binprm *bprm); + extern int prepare_bprm_creds(struct linux_binprm *bprm); +-- +1.8.0 + diff --git a/exec-use-eloop-for-max-recursion-depth.patch b/exec-use-eloop-for-max-recursion-depth.patch new file mode 100644 index 000000000..cbaff2f7a --- /dev/null +++ b/exec-use-eloop-for-max-recursion-depth.patch @@ -0,0 +1,144 @@ +From 4ae8186cd77835b45f1b35edb4ce70309287bfc3 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 26 Nov 2012 09:02:11 -0500 +Subject: [PATCH 2/2] exec: use -ELOOP for max recursion depth + +To avoid an explosion of request_module calls on a chain of abusive +scripts, fail maximum recursion with -ELOOP instead of -ENOEXEC. As soon +as maximum recursion depth is hit, the error will fail all the way back +up the chain, aborting immediately. + +This also has the side-effect of stopping the user's shell from attempting +to reexecute the top-level file as a shell script. As seen in the +dash source: + + if (cmd != path_bshell && errno == ENOEXEC) { + *argv-- = cmd; + *argv = cmd = path_bshell; + goto repeat; + } + +The above logic was designed for running scripts automatically that lacked +the "#!" header, not to re-try failed recursion. On a legitimate -ENOEXEC, +things continue to behave as the shell expects. + +Additionally, when tracking recursion, the binfmt handlers should not be +involved. The recursion being tracked is the depth of calls through +search_binary_handler(), so that function should be exclusively responsible +for tracking the depth. + +Signed-off-by: Kees Cook +Cc: halfdog +Cc: P J P +Cc: Alexander Viro +Signed-off-by: Andrew Morton +--- + fs/binfmt_em86.c | 1 - + fs/binfmt_misc.c | 6 ------ + fs/binfmt_script.c | 4 +--- + fs/exec.c | 10 +++++----- + include/linux/binfmts.h | 2 -- + 5 files changed, 6 insertions(+), 17 deletions(-) + +diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c +index 2790c7e..575796a 100644 +--- a/fs/binfmt_em86.c ++++ b/fs/binfmt_em86.c +@@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) + return -ENOEXEC; + } + +- bprm->recursion_depth++; /* Well, the bang-shell is implicit... */ + allow_write_access(bprm->file); + fput(bprm->file); + bprm->file = NULL; +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index 772428d..f0f1a06 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + if (!enabled) + goto _ret; + +- retval = -ENOEXEC; +- if (bprm->recursion_depth > BINPRM_MAX_RECURSION) +- goto _ret; +- + /* to keep locking time low, we copy the interpreter string */ + read_lock(&entries_lock); + fmt = check_file(bprm); +@@ -200,8 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + if (retval < 0) + goto _error; + +- bprm->recursion_depth++; +- + retval = search_binary_handler (bprm, regs); + if (retval < 0) + goto _error; +diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c +index df49d48..8ae4be1 100644 +--- a/fs/binfmt_script.c ++++ b/fs/binfmt_script.c +@@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) + char interp[BINPRM_BUF_SIZE]; + int retval; + +- if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || +- (bprm->recursion_depth > BINPRM_MAX_RECURSION)) ++ if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) + return -ENOEXEC; + /* + * This section does the #! interpretation. + * Sorta complicated, but hopefully it will work. -TYT + */ + +- bprm->recursion_depth++; + allow_write_access(bprm->file); + fput(bprm->file); + bprm->file = NULL; +diff --git a/fs/exec.c b/fs/exec.c +index 59896ae..541cc51 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1398,6 +1398,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + struct linux_binfmt *fmt; + pid_t old_pid, old_vpid; + ++ /* This allows 4 levels of binfmt rewrites before failing hard. */ ++ if (depth > 5) ++ return -ELOOP; ++ + retval = security_bprm_check(bprm); + if (retval) + return retval; +@@ -1422,12 +1426,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + if (!try_module_get(fmt->module)) + continue; + read_unlock(&binfmt_lock); ++ bprm->recursion_depth = depth + 1; + retval = fn(bprm, regs); +- /* +- * Restore the depth counter to its starting value +- * in this call, so we don't have to rely on every +- * load_binary function to restore it on return. +- */ + bprm->recursion_depth = depth; + if (retval >= 0) { + if (depth == 0) { +diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h +index eb53e15..5bab59b 100644 +--- a/include/linux/binfmts.h ++++ b/include/linux/binfmts.h +@@ -68,8 +68,6 @@ struct linux_binprm { + #define BINPRM_FLAGS_EXECFD_BIT 1 + #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) + +-#define BINPRM_MAX_RECURSION 4 +- + /* Function parameter for binfmt->coredump */ + struct coredump_params { + long signr; +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 74428d03d..d91671e73 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -816,6 +816,10 @@ Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz CVE-2012-4461 862900 878518 Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +#rhbz CVE-2012-4530 868285 880147 +Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch +Patch21229: exec-use-eloop-for-max-recursion-depth.patch + # END OF PATCH DEFINITIONS %endif @@ -1579,6 +1583,10 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz CVE-2012-4461 862900 878518 ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +#rhbz CVE-2012-4530 868285 880147 +ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch +ApplyPatch exec-use-eloop-for-max-recursion-depth.patch + # END OF PATCH APPLICATIONS %endif @@ -2444,6 +2452,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 26 2012 Josh Boyer +- CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) + * Tue Nov 20 2012 Josh Boyer - 3.6.7-5 - CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) - Add VC_MUTE ioctl (rhbz 859485) From 2bfaae5754784b00a4587fc1ffa8dfea7719cdc8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 10:45:44 -0500 Subject: [PATCH 111/492] Enable CONFIG_UIO_PDRV on ppc64 (rhbz 878180) --- config-powerpc64 | 2 ++ config-powerpc64p7 | 2 ++ kernel.spec | 1 + 3 files changed, 5 insertions(+) diff --git a/config-powerpc64 b/config-powerpc64 index ccd0e85d4..82f4c603b 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -164,6 +164,8 @@ CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m +CONFIG_UIO_PDRV=m + CONFIG_HW_RANDOM_PSERIES=m CONFIG_CRYPTO_DEV_NX=m diff --git a/config-powerpc64p7 b/config-powerpc64p7 index ef6ac78e1..e8e826a88 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -155,6 +155,8 @@ CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m +CONFIG_UIO_PDRV=m + CONFIG_HW_RANDOM_PSERIES=m CONFIG_CRYPTO_DEV_NX=m diff --git a/kernel.spec b/kernel.spec index d91671e73..04965d1ba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2453,6 +2453,7 @@ fi # || || %changelog * Mon Nov 26 2012 Josh Boyer +- Enable CONFIG_UIO_PDRV on ppc64 (rhbz 878180) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) * Tue Nov 20 2012 Josh Boyer - 3.6.7-5 From 8d6940a8b21e19d2553f27b8932c1a519219ce2d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 13:42:22 -0500 Subject: [PATCH 112/492] Fix ata command timeout oops in mvsas (rhbz 869629) --- ...as-Fix-oops-when-ata-commond-timeout.patch | 102 ++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 109 insertions(+) create mode 100644 SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch diff --git a/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch b/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch new file mode 100644 index 000000000..0d83e8d03 --- /dev/null +++ b/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch @@ -0,0 +1,102 @@ +From 95ab000388974d8ffef8257306b4be6e8778b768 Mon Sep 17 00:00:00 2001 +From: Jianpeng Ma +Date: Sat, 4 Aug 2012 10:34:14 +0800 +Subject: [PATCH] [SCSI] mvsas: Fix oops when ata commond timeout. + +Kernel message follows: + +[ 511.712011] sd 11:0:0:0: [sdf] command ffff8800a4e81400 timed out +[ 511.712022] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 +[ 511.712024] sas: trying to find task 0xffff8800a4d24c80 +[ 511.712026] sas: sas_scsi_find_task: aborting task 0xffff8800a4d24c80 +[ 511.712029] drivers/scsi/mvsas/mv_sas.c 1631:mvs_abort_task() +mvi=ffff8800b5300000 task=ffff8800a4d24c80 slot=ffff8800b5325038 +slot_idx=x0 +[ 511.712035] BUG: unable to handle kernel NULL pointer dereference at +0000000000000058 +[ 511.712040] IP: [] _raw_spin_lock_irqsave+0xc/0x30 +[ 511.712047] PGD 0 +[ 511.712049] Oops: 0002 [#1] SMP +[ 511.712052] Modules linked in: mvsas libsas scsi_transport_sas +raid456 async_pq async_xor xor async_memcpy async_raid6_recov raid6_pq +async_tx [last unloaded: mvsas] +[ 511.712062] CPU 3 +[ 511.712066] Pid: 7322, comm: scsi_eh_11 Not tainted 3.5.0+ #106 To Be +Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M. +[ 511.712068] RIP: 0010:[] [] +_raw_spin_lock_irqsave+0xc/0x30 +[ 511.712073] RSP: 0018:ffff880098d3bcb0 EFLAGS: 00010086 +[ 511.712074] RAX: 0000000000000286 RBX: 0000000000000058 RCX: +00000000000000c3 +[ 511.712076] RDX: 0000000000000100 RSI: 0000000000000046 RDI: +0000000000000058 +[ 511.712078] RBP: ffff880098d3bcb0 R08: 000000000000000a R09: +0000000000000000 +[ 511.712080] R10: 00000000000004e8 R11: 00000000000004e7 R12: +ffff8800a4d24c80 +[ 511.712082] R13: 0000000000000050 R14: ffff8800b5325038 R15: +ffff8800a4eafe00 +[ 511.712084] FS: 0000000000000000(0000) GS:ffff8800bdb80000(0000) +knlGS:0000000000000000 +[ 511.712086] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +[ 511.712088] CR2: 0000000000000058 CR3: 00000000a4ce6000 CR4: +00000000000407e0 +[ 511.712090] DR0: 0000000000000000 DR1: 0000000000000000 DR2: +0000000000000000 +[ 511.712091] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: +0000000000000400 +[ 511.712093] Process scsi_eh_11 (pid: 7322, threadinfo +ffff880098d3a000, task ffff8800a61dde40) +[ 511.712095] Stack: +[ 511.712096] ffff880098d3bce0 ffffffff81060683 ffff880000000000 +0000000000000000 +[ 511.712099] ffff8800a4d24c80 ffff8800b5300000 ffff880098d3bcf0 +ffffffffa0076a88 +[ 511.712102] ffff880098d3bd50 ffffffffa0079bb5 ffff880000000000 +ffff880000000018 +[ 511.712106] Call Trace: +[ 511.712110] [] complete+0x23/0x60 +[ 511.712115] [] mvs_tmf_timedout+0x18/0x20 [mvsas] +[ 511.712119] [] mvs_slot_complete+0x765/0x7d0 +[mvsas] +[ 511.712125] [] sas_scsi_recover_host+0x55d/0xdb0 +[libsas] +[ 511.712128] [] ? idle_balance+0xe0/0x130 +[ 511.712133] [] scsi_error_handler+0xcc/0x470 +[ 511.712136] [] ? __schedule+0x370/0x730 +[ 511.712139] [] ? __wake_up_common+0x58/0x90 +[ 511.712142] [] ? scsi_eh_get_sense+0x110/0x110 +[ 511.712146] [] kthread+0x8e/0xa0 +[ 511.712150] [] kernel_thread_helper+0x4/0x10 +[ 511.712153] [] ? flush_kthread_work+0x120/0x120 +[ 511.712156] [] ? gs_change+0xb/0xb +[ 511.712157] Code: 8a 00 01 00 00 89 d0 f0 66 0f b1 0f 66 39 d0 0f 94 +c0 0f b6 c0 5d c3 0f 1f 84 00 00 00 00 00 55 48 89 e5 9c 58 fa ba 00 01 +00 00 66 0f c1 17 0f b6 ce 38 d1 74 11 0f 1f 84 00 00 00 00 00 f3 +[ 511.712191] RIP [] _raw_spin_lock_irqsave+0xc/0x30 +[ 511.712194] RSP +[ 511.712196] CR2: 0000000000000058 +[ 511.712198] ---[ end trace a781c7b1e65db92c ]--- + +Signed-off-by: Jianpeng Ma +Signed-off-by: James Bottomley +--- + drivers/scsi/mvsas/mv_sas.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 4539d59..a3776d6 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) + mv_dprintk("mvs_abort_task() mvi=%p task=%p " + "slot=%p slot_idx=x%x\n", + mvi, task, slot, slot_idx); +- mvs_tmf_timedout((unsigned long)task); ++ task->task_state_flags |= SAS_TASK_STATE_ABORTED; + mvs_slot_task_free(mvi, task, slot, slot_idx); + rc = TMF_RESP_FUNC_COMPLETE; + goto out; +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 04965d1ba..023926030 100644 --- a/kernel.spec +++ b/kernel.spec @@ -820,6 +820,9 @@ Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch +#rhbz 869629 +Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch + # END OF PATCH DEFINITIONS %endif @@ -1587,6 +1590,9 @@ ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch +#rhbz 869629 +ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch + # END OF PATCH APPLICATIONS %endif @@ -2453,6 +2459,7 @@ fi # || || %changelog * Mon Nov 26 2012 Josh Boyer +- Fix ata command timeout oops in mvsas (rhbz 869629) - Enable CONFIG_UIO_PDRV on ppc64 (rhbz 878180) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) From 84597ee776071f1918618995b3834eb0a79fb8ce Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 14:15:41 -0500 Subject: [PATCH 113/492] Fix ACPI video after _DOD errors (rhbz 869383) --- ...-Ignore-errors-after-_DOD-evaluation.patch | 45 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 ACPI-video-Ignore-errors-after-_DOD-evaluation.patch diff --git a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch new file mode 100644 index 000000000..425acc7a0 --- /dev/null +++ b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch @@ -0,0 +1,45 @@ +From fba4e087361605d1eed63343bb08811f097c83ee Mon Sep 17 00:00:00 2001 +From: Igor Murzov +Date: Sat, 13 Oct 2012 04:41:25 +0400 +Subject: [PATCH] ACPI video: Ignore errors after _DOD evaluation. + +There are systems where video module known to work fine regardless +of broken _DOD and ignoring returned value here doesn't cause +any issues later. This should fix brightness controls on some laptops. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 + +Signed-off-by: Igor Murzov +Reviewed-by: Sergey V +Signed-off-by: Zhang Rui +--- + drivers/acpi/video.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index f94d4c8..0230cb6 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -1345,12 +1345,15 @@ static int + acpi_video_bus_get_devices(struct acpi_video_bus *video, + struct acpi_device *device) + { +- int status; ++ int status = 0; + struct acpi_device *dev; + +- status = acpi_video_device_enumerate(video); +- if (status) +- return status; ++ /* ++ * There are systems where video module known to work fine regardless ++ * of broken _DOD and ignoring returned value here doesn't cause ++ * any issues later. ++ */ ++ acpi_video_device_enumerate(video); + + list_for_each_entry(dev, &device->children, node) { + +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 023926030..f812f376c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -823,6 +823,9 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +#rhbz 869383 +Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch + # END OF PATCH DEFINITIONS %endif @@ -1593,6 +1596,9 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +#rhbz 869383 +ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch + # END OF PATCH APPLICATIONS %endif @@ -2459,6 +2465,7 @@ fi # || || %changelog * Mon Nov 26 2012 Josh Boyer +- Fix ACPI video after _DOD errors (rhbz 869383) - Fix ata command timeout oops in mvsas (rhbz 869629) - Enable CONFIG_UIO_PDRV on ppc64 (rhbz 878180) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) From e9b768c5e793428cb896b53d023b261fb0445eb2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 14:48:18 -0500 Subject: [PATCH 114/492] Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) --- ...t-ring-address-before-enabling-recei.patch | 62 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 69 insertions(+) create mode 100644 8139cp-revert-set-ring-address-before-enabling-recei.patch diff --git a/8139cp-revert-set-ring-address-before-enabling-recei.patch b/8139cp-revert-set-ring-address-before-enabling-recei.patch new file mode 100644 index 000000000..d9ca2f2a7 --- /dev/null +++ b/8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -0,0 +1,62 @@ +From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?fran=C3=A7ois=20romieu?= +Date: Wed, 21 Nov 2012 10:07:29 +0000 +Subject: [PATCH] 8139cp: revert "set ring address before enabling receiver" + +This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. + +The original patch was tested with emulated hardware. Real +hardware chokes. + +Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 + +Signed-off-by: Francois Romieu +Acked-by: Jeff Garzik +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 1c81825..b01f83a 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) + + cpw8(Config5, cpr8(Config5) & PMEStatus); + ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ + cpw16(MultiIntr, 0); + + cpw8_f(Cfg9346, Cfg9346_Lock); +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index f812f376c..9e6564181 100644 --- a/kernel.spec +++ b/kernel.spec @@ -826,6 +826,9 @@ Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 869383 Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +#rhbz 851278 +Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch + # END OF PATCH DEFINITIONS %endif @@ -1599,6 +1602,9 @@ ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 869383 ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +#rhbz 851278 +ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch + # END OF PATCH APPLICATIONS %endif @@ -2465,6 +2471,7 @@ fi # || || %changelog * Mon Nov 26 2012 Josh Boyer +- Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) - Fix ACPI video after _DOD errors (rhbz 869383) - Fix ata command timeout oops in mvsas (rhbz 869629) - Enable CONFIG_UIO_PDRV on ppc64 (rhbz 878180) From c5c071b35c1c73ef87b811f41696cad95003c364 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 15:37:25 -0500 Subject: [PATCH 115/492] Linux v3.6.8 --- ...-Ignore-errors-after-_DOD-evaluation.patch | 45 ------- ...ifs_lookup-on-hashed-negative-dentry.patch | 19 --- kernel.spec | 27 +--- keyspan.patch | 98 -------------- ...de_insert-suspicious-rcu-dereference.patch | 54 -------- sources | 2 +- ...crash-at-re-preparing-the-PCM-stream.patch | 125 ------------------ 7 files changed, 6 insertions(+), 364 deletions(-) delete mode 100644 ACPI-video-Ignore-errors-after-_DOD-evaluation.patch delete mode 100644 dont-call-cifs_lookup-on-hashed-negative-dentry.patch delete mode 100644 keyspan.patch delete mode 100644 selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch delete mode 100644 usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch diff --git a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch deleted file mode 100644 index 425acc7a0..000000000 --- a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From fba4e087361605d1eed63343bb08811f097c83ee Mon Sep 17 00:00:00 2001 -From: Igor Murzov -Date: Sat, 13 Oct 2012 04:41:25 +0400 -Subject: [PATCH] ACPI video: Ignore errors after _DOD evaluation. - -There are systems where video module known to work fine regardless -of broken _DOD and ignoring returned value here doesn't cause -any issues later. This should fix brightness controls on some laptops. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 - -Signed-off-by: Igor Murzov -Reviewed-by: Sergey V -Signed-off-by: Zhang Rui ---- - drivers/acpi/video.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c -index f94d4c8..0230cb6 100644 ---- a/drivers/acpi/video.c -+++ b/drivers/acpi/video.c -@@ -1345,12 +1345,15 @@ static int - acpi_video_bus_get_devices(struct acpi_video_bus *video, - struct acpi_device *device) - { -- int status; -+ int status = 0; - struct acpi_device *dev; - -- status = acpi_video_device_enumerate(video); -- if (status) -- return status; -+ /* -+ * There are systems where video module known to work fine regardless -+ * of broken _DOD and ignoring returned value here doesn't cause -+ * any issues later. -+ */ -+ acpi_video_device_enumerate(video); - - list_for_each_entry(dev, &device->children, node) { - --- -1.8.0 - diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch deleted file mode 100644 index 4e25f9d20..000000000 --- a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch +++ /dev/null @@ -1,19 +0,0 @@ -@@ -, +, @@ - cifs_atomic_open - fs/cifs/dir.c | 6 ++++++ - 1 file changed, 6 insertions(+) ---- a/fs/cifs/dir.c -+++ a/fs/cifs/dir.c -@@ -398,6 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, - * in network traffic in the other paths. - */ - if (!(oflags & O_CREAT)) { -+ /* Check for hashed negative dentry. We have already revalidated -+ * the dentry and it is fine. No need to perform another lookup. -+ */ -+ if (!d_unhashed(direntry)) -+ return -ENOENT; -+ - struct dentry *res = cifs_lookup(inode, direntry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); diff --git a/kernel.spec b/kernel.spec index 9e6564181..f544da917 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -769,9 +769,6 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 846037 Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 867344 -Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch - #rhbz 869904 869909 CVE-2012-4508 Patch22080: 0001-ext4-ext4_inode_info-diet.patch Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -789,7 +786,6 @@ Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch Patch22100: uprobes-upstream-backport.patch #rhbz 871078 -Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch @@ -799,9 +795,6 @@ Patch22113: smp_irq_move_cleanup_interrupt.patch #rhbz 873001 Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch -#rhbz 870562 -Patch22115: keyspan.patch - #rhbz 812129 Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -823,9 +816,6 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch -#rhbz 869383 -Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch - #rhbz 851278 Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -1545,9 +1535,6 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 846037 ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch -#rhbz 867344 -ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch - #rhbz 869904 869909 CVE-2012-4508 ApplyPatch 0001-ext4-ext4_inode_info-diet.patch ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -1565,7 +1552,6 @@ ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch ApplyPatch uprobes-upstream-backport.patch #rhbz 871078 -ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch @@ -1575,9 +1561,6 @@ ApplyPatch smp_irq_move_cleanup_interrupt.patch #rhbz 873001 ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch -#rhbz 870562 -ApplyPatch keyspan.patch - #rhbz 812129 ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -1599,9 +1582,6 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch -#rhbz 869383 -ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch - #rhbz 851278 ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -2470,6 +2450,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 26 2012 Josh Boyer - 3.6.8-1 +- Linux v3.6.8 + * Mon Nov 26 2012 Josh Boyer - Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) - Fix ACPI video after _DOD errors (rhbz 869383) diff --git a/keyspan.patch b/keyspan.patch deleted file mode 100644 index 43d116ea4..000000000 --- a/keyspan.patch +++ /dev/null @@ -1,98 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.58.186.240 with SMTP id fn16csp155256vec; - Sat, 10 Nov 2012 01:14:20 -0800 (PST) -Received: by 10.68.130.197 with SMTP id og5mr40733607pbb.138.1352538859530; - Sat, 10 Nov 2012 01:14:19 -0800 (PST) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id pj1si1353832pbc.115.2012.11.10.01.14.15; - Sat, 10 Nov 2012 01:14:19 -0800 (PST) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1750798Ab2KJJOO (ORCPT + 33 others); - Sat, 10 Nov 2012 04:14:14 -0500 -Received: from canardo.mork.no ([148.122.252.1]:37367 "EHLO canardo.mork.no" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1750699Ab2KJJOM (ORCPT ); - Sat, 10 Nov 2012 04:14:12 -0500 -Received: from nemi.mork.no (nemi.mork.no [IPv6:2001:4620:9:2:216:eaff:feb3:788]) - (authenticated bits=0) - by canardo.mork.no (8.14.3/8.14.3) with ESMTP id qAA9E1cX010750 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); - Sat, 10 Nov 2012 10:14:02 +0100 -Received: from bjorn by nemi.mork.no with local (Exim 4.80) - (envelope-from ) - id 1TX78a-0007Li-AD; Sat, 10 Nov 2012 10:14:00 +0100 -From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= -To: Richard -Cc: Greg Kroah-Hartman , - linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, - =?UTF-8?q?Bj=C3=B8rn=20Mork?= , - , Johan Hovold -Subject: [PATCH usb-linus] USB: keyspan: fix typo causing GPF on open -Date: Sat, 10 Nov 2012 10:13:42 +0100 -Message-Id: <1352538822-28221-1-git-send-email-bjorn@mork.no> -X-Mailer: git-send-email 1.7.10.4 -In-Reply-To: <509D5BCD.3010901@pacbell.net> -References: <509D5BCD.3010901@pacbell.net> -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -X-Virus-Scanned: clamav-milter 0.97.6 at canardo -X-Virus-Status: Clean -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -Commit f79b2d0f (USB: keyspan: fix NULL-pointer dereferences and -memory leaks) had a small typo which made the driver use wrong -offsets when mapping serial port private data. This results in -in a GPF when the port is opened. - -Reported-by: Richard -Cc: -Cc: Johan Hovold -Signed-off-by: Bjørn Mork ---- -Hello Richard, - -I wonder if you are able to test and verify this? I do not guarantee -that there aren't other issues around, but this small typo looked like -an obvious killer... - -Bjørn - - drivers/usb/serial/keyspan.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c -index 7179b0c..cff8dd5 100644 ---- a/drivers/usb/serial/keyspan.c -+++ b/drivers/usb/serial/keyspan.c -@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial) - static int keyspan_port_probe(struct usb_serial_port *port) - { - struct usb_serial *serial = port->serial; -- struct keyspan_port_private *s_priv; -+ struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; - const struct keyspan_device_details *d_details; - struct callbacks *cback; -@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) - if (!p_priv) - return -ENOMEM; - -- s_priv = usb_get_serial_data(port->serial); - p_priv->device_details = d_details; - - /* Setup values for the various callback routines */ --- -1.7.10.4 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch b/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch deleted file mode 100644 index 43fddf73d..000000000 --- a/selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Dave Jones <> -Subject: Fix sel_netnode_insert suspicious rcu dereference. - - -I reported this a year ago (https://lkml.org/lkml/2011/4/20/308). -It's still a problem apparently ... - -=============================== -[ INFO: suspicious RCU usage. ] -3.5.0-rc1+ #63 Not tainted -------------------------------- -security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage! -other info that might help us debug this: - - -rcu_scheduler_active = 1, debug_locks = 0 -1 lock held by trinity-child1/8750: - #0: (sel_netnode_lock){+.....}, at: [] sel_netnode_sid+0x16a/0x3e0 -stack backtrace: -Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63 -Call Trace: - [] lockdep_rcu_suspicious+0xfd/0x130 - [] sel_netnode_sid+0x3b1/0x3e0 - [] ? sel_netnode_find+0x1a0/0x1a0 - [] selinux_socket_bind+0xf6/0x2c0 - [] ? trace_hardirqs_off+0xd/0x10 - [] ? lock_release_holdtime.part.9+0x15/0x1a0 - [] ? lock_hrtimer_base+0x31/0x60 - [] security_socket_bind+0x16/0x20 - [] sys_bind+0x7a/0x100 - [] ? sysret_check+0x22/0x5d - [] ? trace_hardirqs_on_caller+0x10d/0x1a0 - [] ? trace_hardirqs_on_thunk+0x3a/0x3f - [] system_call_fastpath+0x16/0x1b -This patch below does what Paul McKenney suggested in the previous thread. - -Signed-off-by: Dave Jones - -diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c -index 28f911c..c5454c0 100644 ---- a/security/selinux/netnode.c -+++ b/security/selinux/netnode.c -@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) - if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { - struct sel_netnode *tail; - tail = list_entry( -- rcu_dereference(sel_netnode_hash[idx].list.prev), -+ rcu_dereference_protected(sel_netnode_hash[idx].list.prev, -+ lockdep_is_held(&sel_netnode_lock)), - struct sel_netnode, list); - list_del_rcu(&tail->list); - kfree_rcu(tail, rcu); - - diff --git a/sources b/sources index 0d260fa79..891bb1e74 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -134936c362d8812b5cafcf3c67afdce0 patch-3.6.7.xz +f248294551c34753c5c019c8d513280c patch-3.6.8.xz diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch deleted file mode 100644 index 9f3e6f993..000000000 --- a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +++ /dev/null @@ -1,125 +0,0 @@ -At Thu, 08 Nov 2012 08:31:35 +0100, -Daniel Mack wrote: -(snip) -> >> We can't simply stop both endpoints in the prepare callback. -> > -> > The new function doesn't stop the stream by itself but it just syncs -> > if the stream is being stopped beforehand. So, it's safe to call it -> > there. -> > -> > Maybe the name was confusing. It should have been like -> > snd_usb_endpoint_sync_pending_stop() or such. -> -> Ah, right. I was errornously looking closer to Alan's patch but then -> replied to yours. Alright then - thanks for explaining :) - -OK, thanks for checking. - -FWIW, below is the patch I applied now to for-linus branch. -Renamed the function, added the comment and put NULL check to the -function to simplify. - - -Takashi - ---- -From: Takashi Iwai -Subject: [PATCH] ALSA: usb-audio: Fix crash at re-preparing the PCM stream - -There are bug reports of a crash with USB-audio devices when PCM -prepare is performed immediately after the stream is stopped via -trigger callback. It turned out that the problem is that we don't -wait until all URBs are killed. - -This patch adds a new function to synchronize the pending stop -operation on an endpoint, and calls in the prepare callback for -avoiding the crash above. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181 - -Reported-and-tested-by: Artem S. Tashkinov -Cc: [v3.6] -Signed-off-by: Takashi Iwai ---- - sound/usb/endpoint.c | 13 +++++++++++++ - sound/usb/endpoint.h | 1 + - sound/usb/pcm.c | 3 +++ - 3 files changed, 17 insertions(+) - -diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c -index 7f78c6d..34de6f2 100644 ---- a/sound/usb/endpoint.c -+++ b/sound/usb/endpoint.c -@@ -35,6 +35,7 @@ - - #define EP_FLAG_ACTIVATED 0 - #define EP_FLAG_RUNNING 1 -+#define EP_FLAG_STOPPING 2 - - /* - * snd_usb_endpoint is a model that abstracts everything related to an -@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) - if (alive) - snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", - alive, ep->ep_num); -+ clear_bit(EP_FLAG_STOPPING, &ep->flags); - - return 0; - } - -+/* sync the pending stop operation; -+ * this function itself doesn't trigger the stop operation -+ */ -+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) -+{ -+ if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) -+ wait_clear_urbs(ep); -+} -+ - /* - * unlink active urbs. - */ -@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, - - if (wait) - wait_clear_urbs(ep); -+ else -+ set_bit(EP_FLAG_STOPPING, &ep->flags); - } - } - -diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h -index 6376ccf..3d4c970 100644 ---- a/sound/usb/endpoint.h -+++ b/sound/usb/endpoint.h -@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); - void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, - int force, int can_sleep, int wait); -+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); - void snd_usb_endpoint_free(struct list_head *head); -diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c -index 37428f7..5c12a3f 100644 ---- a/sound/usb/pcm.c -+++ b/sound/usb/pcm.c -@@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - goto unlock; - } - -+ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); -+ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); -+ - /* some unit conversions in runtime */ - subs->data_endpoint->maxframesize = - bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); --- -1.8.0 - - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ From 8ad1d7750baf1e125812d01ee00b82810062e40f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 16:31:08 -0500 Subject: [PATCH 116/492] And... drop that selinux patch from kernel.spec too --- kernel.spec | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index f544da917..2ffa2db50 100644 --- a/kernel.spec +++ b/kernel.spec @@ -766,9 +766,6 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 846037 -Patch22067: selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch - #rhbz 869904 869909 CVE-2012-4508 Patch22080: 0001-ext4-ext4_inode_info-diet.patch Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -1532,9 +1529,6 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 846037 -ApplyPatch selinux-Fix-sel_netnode_insert-suspicious-rcu-dereference.patch - #rhbz 869904 869909 CVE-2012-4508 ApplyPatch 0001-ext4-ext4_inode_info-diet.patch ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch From bbc321ab364ae01405934c2618fc044a568f3de6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Nov 2012 14:01:21 -0500 Subject: [PATCH 117/492] Update patches for 8139cp issues from David Woodhouse (rhbz 851278) --- ...e-enable-interrupts-after-tx-timeout.patch | 29 +++++ ...t-ring-address-before-enabling-recei.patch | 62 ----------- ...t-ring-address-after-enabling-C-mode.patch | 100 ++++++++++++++++++ kernel.spec | 11 +- 4 files changed, 137 insertions(+), 65 deletions(-) create mode 100644 8139cp-re-enable-interrupts-after-tx-timeout.patch delete mode 100644 8139cp-revert-set-ring-address-before-enabling-recei.patch create mode 100644 8139cp-set-ring-address-after-enabling-C-mode.patch diff --git a/8139cp-re-enable-interrupts-after-tx-timeout.patch b/8139cp-re-enable-interrupts-after-tx-timeout.patch new file mode 100644 index 000000000..c0196188e --- /dev/null +++ b/8139cp-re-enable-interrupts-after-tx-timeout.patch @@ -0,0 +1,29 @@ +From 01ffc0a7f1c1801a2354719dedbc32aff45b987d Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 24 Nov 2012 12:11:21 +0000 +Subject: [PATCH] 8139cp: re-enable interrupts after tx timeout + +Recovery doesn't work too well if we leave interrupts disabled... + +Signed-off-by: David Woodhouse +Acked-by: Francois Romieu +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 3de318d..6cb96b4 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -1219,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev) + cp_clean_rings(cp); + rc = cp_init_rings(cp); + cp_start_hw(cp); ++ cp_enable_irq(cp); + + netif_wake_queue(dev); + +-- +1.7.6.5 + diff --git a/8139cp-revert-set-ring-address-before-enabling-recei.patch b/8139cp-revert-set-ring-address-before-enabling-recei.patch deleted file mode 100644 index d9ca2f2a7..000000000 --- a/8139cp-revert-set-ring-address-before-enabling-recei.patch +++ /dev/null @@ -1,62 +0,0 @@ -From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?fran=C3=A7ois=20romieu?= -Date: Wed, 21 Nov 2012 10:07:29 +0000 -Subject: [PATCH] 8139cp: revert "set ring address before enabling receiver" - -This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. - -The original patch was tested with emulated hardware. Real -hardware chokes. - -Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 - -Signed-off-by: Francois Romieu -Acked-by: Jeff Garzik -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c -index 1c81825..b01f83a 100644 ---- a/drivers/net/ethernet/realtek/8139cp.c -+++ b/drivers/net/ethernet/realtek/8139cp.c -@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) - cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - -- cpw32_f(HiTxRingAddr, 0); -- cpw32_f(HiTxRingAddr + 4, 0); -- -- ring_dma = cp->ring_dma; -- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -- -- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -- - cp_start_hw(cp); - cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ - -@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) - - cpw8(Config5, cpr8(Config5) & PMEStatus); - -+ cpw32_f(HiTxRingAddr, 0); -+ cpw32_f(HiTxRingAddr + 4, 0); -+ -+ ring_dma = cp->ring_dma; -+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -+ -+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -+ - cpw16(MultiIntr, 0); - - cpw8_f(Cfg9346, Cfg9346_Lock); --- -1.8.0 - diff --git a/8139cp-set-ring-address-after-enabling-C-mode.patch b/8139cp-set-ring-address-after-enabling-C-mode.patch new file mode 100644 index 000000000..33bd340e9 --- /dev/null +++ b/8139cp-set-ring-address-after-enabling-C-mode.patch @@ -0,0 +1,100 @@ +From a9dbe40fc10cea2efe6e1ff9e03c62dd7579c5ba Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Wed, 21 Nov 2012 10:27:19 +0000 +Subject: [PATCH] 8139cp: set ring address after enabling C+ mode + +This fixes (for me) a regression introduced by commit b01af457 ("8139cp: +set ring address before enabling receiver"). That commit configured the +descriptor ring addresses earlier in the initialisation sequence, in +order to avoid the possibility of triggering stray DMA before the +correct address had been set up. + +Unfortunately, it seems that the hardware will scribble garbage into the +TxRingAddr registers when we enable "plus mode" Tx in the CpCmd +register. Observed on a Traverse Geos router board. + +To deal with this, while not reintroducing the problem which led to the +original commit, we augment cp_start_hw() to write to the CpCmd register +*first*, then set the descriptor ring addresses, and then finally to +enable Rx and Tx in the original 8139 Cmd register. The datasheet +actually indicates that we should enable Tx/Rx in the Cmd register +*before* configuring the descriptor addresses, but that would appear to +re-introduce the problem that the offending commit b01af457 was trying +to solve. And this variant appears to work fine on real hardware. + +Signed-off-by: David Woodhouse +Cc: stable@kernel.org [3.5+] +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 40 +++++++++++++++++++++++---------- + 1 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 1c81825..5166d94 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -957,7 +957,35 @@ static void cp_reset_hw (struct cp_private *cp) + + static inline void cp_start_hw (struct cp_private *cp) + { ++ dma_addr_t ring_dma; ++ + cpw16(CpCmd, cp->cpcmd); ++ ++ /* ++ * These (at least TxRingAddr) need to be configured after the ++ * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33 ++ * (C+ Command Register) recommends that these and more be configured ++ * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware ++ * it's been observed that the TxRingAddr is actually reset to garbage ++ * when C+ mode Tx is enabled in CpCmd. ++ */ ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ /* ++ * Strictly speaking, the datasheet says this should be enabled ++ * *before* setting the descriptor addresses. But what, then, would ++ * prevent it from doing DMA to random unconfigured addresses? ++ * This variant appears to work fine. ++ */ + cpw8(Cmd, RxOn | TxOn); + } + +@@ -969,7 +997,6 @@ static void cp_enable_irq(struct cp_private *cp) + static void cp_init_hw (struct cp_private *cp) + { + struct net_device *dev = cp->dev; +- dma_addr_t ring_dma; + + cp_reset_hw(cp); + +@@ -979,17 +1006,6 @@ static void cp_init_hw (struct cp_private *cp) + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index 2ffa2db50..f9d9f4f4d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -814,7 +814,8 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 -Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch +Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch +Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch # END OF PATCH DEFINITIONS @@ -1577,7 +1578,8 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 -ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch +ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch +ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch # END OF PATCH APPLICATIONS @@ -2444,6 +2446,9 @@ fi # ||----w | # || || %changelog +* Tue Nov 27 2012 Josh Boyer +- Update patches for 8139cp issues from David Woodhouse (rhbz 851278) + * Mon Nov 26 2012 Josh Boyer - 3.6.8-1 - Linux v3.6.8 From d974a4b4e7d0ded7620bf9f0e966460e192ae4fd Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 29 Nov 2012 14:12:21 +0000 Subject: [PATCH 118/492] Update some ARM GPIO and I2C configs --- config-arm-generic | 1 + config-arm-omap | 3 +-- config-arm-tegra | 2 +- kernel.spec | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 625c61111..d44eda51d 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -101,6 +101,7 @@ CONFIG_LBDAF=y CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_GPIOLIB=y CONFIG_PINCTRL_SINGLE=m CONFIG_USB_ULPI=y diff --git a/config-arm-omap b/config-arm-omap index b35ccd1dd..8e314ce1d 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -153,7 +153,6 @@ CONFIG_WL_TI=y CONFIG_WLCORE_SDIO=m CONFIG_TI_ST=m # CONFIG_TI_CPSW is not set -CONFIG_GPIOLIB=y CONFIG_MTD_NAND_OMAP2=y CONFIG_MTD_NAND_OMAP_PREFETCH=y CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y @@ -188,7 +187,7 @@ CONFIG_TI_DAVINCI_CPDMA=m CONFIG_LEDS_PWM=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_HDQ_MASTER_OMAP=m -CONFIG_I2C_OMAP=y +CONFIG_I2C_OMAP=m CONFIG_SPI_OMAP24XX=y CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m diff --git a/config-arm-tegra b/config-arm-tegra index 748edc51c..78ddf0722 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -24,7 +24,7 @@ CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_TEGRA_IOMMU_GART=y CONFIG_TEGRA_IOMMU_SMMU=y -CONFIG_I2C_TEGRA=y +CONFIG_I2C_TEGRA=m # This block is temporary until we work out why the MMC modules don't work as modules CONFIG_MMC=y diff --git a/kernel.spec b/kernel.spec index f9d9f4f4d..29369c41f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2446,6 +2446,9 @@ fi # ||----w | # || || %changelog +* Thu Nov 29 2012 Peter Robinson +- Update some ARM GPIO and I2C configs + * Tue Nov 27 2012 Josh Boyer - Update patches for 8139cp issues from David Woodhouse (rhbz 851278) From 77b6d85730e6bf7e9f7df6ae1dd4202b5c7d96dc Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 3 Dec 2012 16:29:42 -0600 Subject: [PATCH 119/492] Linux 3.6.9 --- ...opcode-oops-on-SET_SREGS-with-OSXSAV.patch | 83 ------------------- iwlwifi-remove-queue-empty-warn-3.6.patch | 25 ------ kernel.spec | 19 ++--- sources | 2 +- 4 files changed, 6 insertions(+), 123 deletions(-) delete mode 100644 KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch delete mode 100644 iwlwifi-remove-queue-empty-warn-3.6.patch diff --git a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch deleted file mode 100644 index 890bf495e..000000000 --- a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 Mon Sep 17 00:00:00 2001 -From: Petr Matousek -Date: Tue, 6 Nov 2012 19:24:07 +0100 -Subject: [PATCH] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit - set (CVE-2012-4461) - -On hosts without the XSAVE support unprivileged local user can trigger -oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest -cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN -ioctl. - -invalid opcode: 0000 [#2] SMP -Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables -... -Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae -EIP: 0060:[] EFLAGS: 00210246 CPU: 0 -EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] -EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 -ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 - DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 -Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 -task.ti=d7c62000) -Stack: - 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 - ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 - c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 -Call Trace: - [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] -... - [] ? syscall_call+0x7/0xb -Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 -1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 -d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 -EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP -0068:d7c63e70 - -QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID -and then sets them later. So guest's X86_FEATURE_XSAVE should be masked -out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with -X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with -X86_FEATURE_XSAVE even on hosts that do not support it, might be -susceptible to this attack from inside the guest as well. - -Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. - -Signed-off-by: Petr Matousek -Signed-off-by: Marcelo Tosatti ---- - arch/x86/kvm/cpuid.h | 3 +++ - arch/x86/kvm/x86.c | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h -index a10e460..58fc514 100644 ---- a/arch/x86/kvm/cpuid.h -+++ b/arch/x86/kvm/cpuid.h -@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) - { - struct kvm_cpuid_entry2 *best; - -+ if (!static_cpu_has(X86_FEATURE_XSAVE)) -+ return 0; -+ - best = kvm_find_cpuid_entry(vcpu, 1, 0); - return best && (best->ecx & bit(X86_FEATURE_XSAVE)); - } -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 224a7e7..4f76417 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -5781,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, - int pending_vec, max_bits, idx; - struct desc_ptr dt; - -+ if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) -+ return -EINVAL; -+ - dt.size = sregs->idt.limit; - dt.address = sregs->idt.base; - kvm_x86_ops->set_idt(vcpu, &dt); --- -1.8.0 - diff --git a/iwlwifi-remove-queue-empty-warn-3.6.patch b/iwlwifi-remove-queue-empty-warn-3.6.patch deleted file mode 100644 index b8cf5a470..000000000 --- a/iwlwifi-remove-queue-empty-warn-3.6.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c -index 105e3af..79a4ddc 100644 ---- a/drivers/net/wireless/iwlwifi/pcie/tx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c -@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, - void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) - { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); -- u16 rd_ptr, wr_ptr; -- int n_bd = trans_pcie->txq[txq_id].q.n_bd; - - if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { - WARN_ONCE(1, "queue %d not used", txq_id); - return; - } - -- rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); -- wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); -- -- WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", -- txq_id, rd_ptr, wr_ptr); -- - iwl_txq_set_inactive(trans, txq_id); - IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); - } diff --git a/kernel.spec b/kernel.spec index 29369c41f..d418ea728 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -789,9 +789,6 @@ Patch22112: USB-report-submission-of-active-URBs.patch #rhbz 869341 Patch22113: smp_irq_move_cleanup_interrupt.patch -#rhbz 873001 -Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch - #rhbz 812129 Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -803,9 +800,6 @@ Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 859485 Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz CVE-2012-4461 862900 878518 -Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch - #rhbz CVE-2012-4530 868285 880147 Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch @@ -1553,9 +1547,6 @@ ApplyPatch USB-report-submission-of-active-URBs.patch #rhbz 869341 ApplyPatch smp_irq_move_cleanup_interrupt.patch -#rhbz 873001 -ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch - #rhbz 812129 ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -1567,9 +1558,6 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 859485 ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz CVE-2012-4461 862900 878518 -ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch - #rhbz CVE-2012-4530 868285 880147 ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch @@ -2446,6 +2434,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 03 2012 Justin M. Forbes 3.6.9-1 +- Linux 3.6.9 + * Thu Nov 29 2012 Peter Robinson - Update some ARM GPIO and I2C configs diff --git a/sources b/sources index 891bb1e74..7369b3635 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -f248294551c34753c5c019c8d513280c patch-3.6.8.xz +a7c656034599f90dcbc50895b69022aa patch-3.6.9.xz From e0377be22b9c1fb620b7858d51c4a2bc36ec2a76 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Dec 2012 18:20:15 -0500 Subject: [PATCH 120/492] Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) --- kernel.spec | 11 +- radeon-evergreen-3.6.9-fixes.mbox | 376 ++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 radeon-evergreen-3.6.9-fixes.mbox diff --git a/kernel.spec b/kernel.spec index d418ea728..c2e0eaf07 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -811,6 +811,9 @@ Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 855275 +Patch21236: radeon-evergreen-3.6.9-fixes.mbox + # END OF PATCH DEFINITIONS %endif @@ -1569,6 +1572,9 @@ ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 855275 +ApplyPatch radeon-evergreen-3.6.9-fixes.mbox + # END OF PATCH APPLICATIONS %endif @@ -2434,6 +2440,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 03 2012 Josh Boyer - 3.6.9-2 +- Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) + * Mon Dec 03 2012 Justin M. Forbes 3.6.9-1 - Linux 3.6.9 diff --git a/radeon-evergreen-3.6.9-fixes.mbox b/radeon-evergreen-3.6.9-fixes.mbox new file mode 100644 index 000000000..96628fd2d --- /dev/null +++ b/radeon-evergreen-3.6.9-fixes.mbox @@ -0,0 +1,376 @@ +From 8e502f50fdade16ab4540159218be5d81b678d11 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:12:05 -0500 +Subject: [PATCH 1/3] drm/radeon/dce4+: don't use radeon_crtc for vblank + callback + +Upstream commit 4a15903db02026728d0cf2755c6fabae16b8db6a + +This might be called before we've allocated the radeon_crtcs + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/evergreen.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index e93b80a..0c79d9e 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -37,6 +37,16 @@ + #define EVERGREEN_PFP_UCODE_SIZE 1120 + #define EVERGREEN_PM4_UCODE_SIZE 1376 + ++static const u32 crtc_offsets[6] = ++{ ++ EVERGREEN_CRTC0_REGISTER_OFFSET, ++ EVERGREEN_CRTC1_REGISTER_OFFSET, ++ EVERGREEN_CRTC2_REGISTER_OFFSET, ++ EVERGREEN_CRTC3_REGISTER_OFFSET, ++ EVERGREEN_CRTC4_REGISTER_OFFSET, ++ EVERGREEN_CRTC5_REGISTER_OFFSET ++}; ++ + static void evergreen_gpu_init(struct radeon_device *rdev); + void evergreen_fini(struct radeon_device *rdev); + void evergreen_pcie_gen2_enable(struct radeon_device *rdev); +@@ -109,17 +119,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) + */ + void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) + { +- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + int i; + +- if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { ++ if (crtc >= rdev->num_crtc) ++ return; ++ ++ if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { +- if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) ++ if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { +- if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) ++ if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) + break; + udelay(1); + } +-- +1.8.0 + + +From 027eb4090e4261a9b9f5cce47493657d12f2caf3 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:15:21 -0500 +Subject: [PATCH 2/3] drm/radeon: properly handle mc_stop/mc_resume on + evergreen+ (v2) + +Upstream commit 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 + +- Stop the displays from accessing the FB +- Block CPU access +- Turn off MC client access + +This should fix issues some users have seen, especially +with UEFI, when changing the MC FB location that result +in hangs or display corruption. + +v2: fix crtc enabled check noticed by Luca Tettamanti + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/evergreen.c | 169 +++++++++++++++------------------ + drivers/gpu/drm/radeon/evergreen_reg.h | 2 + + drivers/gpu/drm/radeon/evergreend.h | 7 ++ + drivers/gpu/drm/radeon/radeon_asic.h | 1 + + 4 files changed, 88 insertions(+), 91 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 0c79d9e..10b34b8 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1241,116 +1241,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) + + void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) + { ++ u32 crtc_enabled, tmp, frame_count, blackout; ++ int i, j; ++ + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); + +- /* Stop all video */ ++ /* disable VGA render */ + WREG32(VGA_RENDER_CONTROL, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); +- } +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); +- } +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); ++ /* blank the display controllers */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; ++ if (crtc_enabled) { ++ save->crtc_enabled[i] = true; ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { ++ radeon_wait_for_vblank(rdev, i); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ } ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { ++ radeon_wait_for_vblank(rdev, i); ++ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ } ++ } ++ /* wait for the next frame */ ++ frame_count = radeon_get_vblank_counter(rdev, i); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (radeon_get_vblank_counter(rdev, i) != frame_count) ++ break; ++ udelay(1); ++ } ++ } + } + +- WREG32(D1VGA_CONTROL, 0); +- WREG32(D2VGA_CONTROL, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_D3VGA_CONTROL, 0); +- WREG32(EVERGREEN_D4VGA_CONTROL, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_D5VGA_CONTROL, 0); +- WREG32(EVERGREEN_D6VGA_CONTROL, 0); ++ radeon_mc_wait_for_idle(rdev); ++ ++ blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); ++ if ((blackout & BLACKOUT_MODE_MASK) != 1) { ++ /* Block CPU access */ ++ WREG32(BIF_FB_EN, 0); ++ /* blackout the MC */ ++ blackout &= ~BLACKOUT_MODE_MASK; ++ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); + } + } + + void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) + { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); ++ u32 tmp, frame_count; ++ int i, j; + +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ /* update crtc base addresses */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + } +- + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); +- /* Unlock host access */ ++ ++ /* unblackout the MC */ ++ tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); ++ tmp &= ~BLACKOUT_MODE_MASK; ++ WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); ++ /* allow CPU access */ ++ WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); ++ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (save->crtc_enabled) { ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ } ++ /* wait for the next frame */ ++ frame_count = radeon_get_vblank_counter(rdev, i); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (radeon_get_vblank_counter(rdev, i) != frame_count) ++ break; ++ udelay(1); ++ } ++ } ++ } ++ /* Unlock vga access */ + WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); + mdelay(1); + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); +diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h +index 8beac10..034f4c2 100644 +--- a/drivers/gpu/drm/radeon/evergreen_reg.h ++++ b/drivers/gpu/drm/radeon/evergreen_reg.h +@@ -218,6 +218,8 @@ + #define EVERGREEN_CRTC_CONTROL 0x6e70 + # define EVERGREEN_CRTC_MASTER_EN (1 << 0) + # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) ++#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 ++# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) + #define EVERGREEN_CRTC_STATUS 0x6e8c + # define EVERGREEN_CRTC_V_BLANK (1 << 0) + #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 +diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h +index 302af4f..2bc0f6a 100644 +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -87,6 +87,10 @@ + + #define CONFIG_MEMSIZE 0x5428 + ++#define BIF_FB_EN 0x5490 ++#define FB_READ_EN (1 << 0) ++#define FB_WRITE_EN (1 << 1) ++ + #define CP_STRMOUT_CNTL 0x84FC + + #define CP_COHER_CNTL 0x85F0 +@@ -434,6 +438,9 @@ + #define NOOFCHAN_MASK 0x00003000 + #define MC_SHARED_CHREMAP 0x2008 + ++#define MC_SHARED_BLACKOUT_CNTL 0x20ac ++#define BLACKOUT_MODE_MASK 0x00000007 ++ + #define MC_ARB_RAMCFG 0x2760 + #define NOOFBANK_SHIFT 0 + #define NOOFBANK_MASK 0x00000003 +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index 18c38d1..132429e 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -389,6 +389,7 @@ void r700_cp_fini(struct radeon_device *rdev); + struct evergreen_mc_save { + u32 vga_render_control; + u32 vga_hdp_control; ++ bool crtc_enabled[RADEON_MAX_CRTCS]; + }; + + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); +-- +1.8.0 + + +From 5d46a79118cc6a8f5e30e39f19ad997bb2191b53 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:15:55 -0500 +Subject: [PATCH 3/3] drm/radeon: properly track the crtc not_enabled case + evergreen_mc_stop() + +Upstream commit 804cc4a0ad3a896ca295f771a28c6eb36ced7903 + +The save struct is not initialized previously so explicitly +mark the crtcs as not used when they are not in use. + +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/radeon/evergreen.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 10b34b8..5528fea 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1276,6 +1276,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + break; + udelay(1); + } ++ } else { ++ save->crtc_enabled[i] = false; + } + } + +-- +1.8.0 + From 8c7aca4e02c4a78c519e97dc1685949a255acb56 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 5 Dec 2012 16:03:03 -0500 Subject: [PATCH 121/492] Team driver updates (Jiri Pirko) --- kernel.spec | 5 +++ team-net-next-20121205.patch | 60 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 team-net-next-20121205.patch diff --git a/kernel.spec b/kernel.spec index c2e0eaf07..4d23e107c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -664,6 +664,7 @@ Patch110: vmbugon-warnon.patch Patch150: team-net-next-20120808.patch Patch151: team-net-next-update-20120927.patch +Patch152: team-net-next-20121205.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch @@ -1383,6 +1384,7 @@ ApplyPatch vmbugon-warnon.patch ApplyPatch team-net-next-20120808.patch ApplyPatch team-net-next-update-20120927.patch +ApplyPatch team-net-next-20121205.patch # Architecture patches # x86(-64) @@ -2440,6 +2442,9 @@ fi # ||----w | # || || %changelog +* Wed Dec 05 2012 Dave Jones +- Team driver updates (Jiri Pirko) + * Mon Dec 03 2012 Josh Boyer - 3.6.9-2 - Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) diff --git a/team-net-next-20121205.patch b/team-net-next-20121205.patch new file mode 100644 index 000000000..51249f9c1 --- /dev/null +++ b/team-net-next-20121205.patch @@ -0,0 +1,60 @@ + +Backport fixes from linus's tree. + +upstream commits backported: +commit 403f43c937d24832b18524f65415c0bbba6b5064 + team: bcast: convert return value of team_dev_queue_xmit() to bool correctly +commit 3ed7147189d2fbe8ac6da95db2fd9d6d52f53ce9 + team: fix hw_features setup + +Signed-off-by: Jiri Pirko +--- + drivers/net/team/team.c | 4 +++- + drivers/net/team/team_mode_broadcast.c | 6 +++--- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 5d8e1cb..f504773 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1792,10 +1792,12 @@ static void team_setup(struct net_device *dev) + + dev->features |= NETIF_F_LLTX; + dev->features |= NETIF_F_GRO; +- dev->hw_features = NETIF_F_HW_VLAN_TX | ++ dev->hw_features = TEAM_VLAN_FEATURES | ++ NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; + ++ dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM); + dev->features |= dev->hw_features; + } + +diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c +index 9db0171..c5db428 100644 +--- a/drivers/net/team/team_mode_broadcast.c ++++ b/drivers/net/team/team_mode_broadcast.c +@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) + if (last) { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { +- ret = team_dev_queue_xmit(team, last, +- skb2); ++ ret = !team_dev_queue_xmit(team, last, ++ skb2); + if (!sum_ret) + sum_ret = ret; + } +@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) + } + } + if (last) { +- ret = team_dev_queue_xmit(team, last, skb); ++ ret = !team_dev_queue_xmit(team, last, skb); + if (!sum_ret) + sum_ret = ret; + } +-- +1.7.11.7 + From 6cd918b5725f66525f6f06d7bd9098c65c27faf6 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 11 Dec 2012 07:56:36 -0600 Subject: [PATCH 122/492] Linux 3.6.10 --- ...ing-address-before-enabling-receiver.patch | 64 +++ kernel.spec | 15 +- radeon-evergreen-3.6.9-fixes.mbox | 376 ------------------ sources | 2 +- 4 files changed, 72 insertions(+), 385 deletions(-) create mode 100644 8139cp-revert-set-ring-address-before-enabling-receiver.patch delete mode 100644 radeon-evergreen-3.6.9-fixes.mbox diff --git a/8139cp-revert-set-ring-address-before-enabling-receiver.patch b/8139cp-revert-set-ring-address-before-enabling-receiver.patch new file mode 100644 index 000000000..07ae2c28d --- /dev/null +++ b/8139cp-revert-set-ring-address-before-enabling-receiver.patch @@ -0,0 +1,64 @@ +From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 +From: Francois Romieu +Date: Wed, 21 Nov 2012 10:07:29 +0000 +Subject: 8139cp: revert "set ring address before enabling receiver" + +From: Francois Romieu + +commit b26623dab7eeb1e9f5898c7a49458789dd492f20 upstream. + +This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. + +The original patch was tested with emulated hardware. Real +hardware chokes. + +Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 + +Signed-off-by: Francois Romieu +Acked-by: Jeff Garzik +Signed-off-by: David S. Miller +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_privat + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_privat + + cpw8(Config5, cpr8(Config5) & PMEStatus); + ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ + cpw16(MultiIntr, 0); + + cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/kernel.spec b/kernel.spec index 4d23e107c..bc971f8a3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -809,12 +809,10 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 +Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 855275 -Patch21236: radeon-evergreen-3.6.9-fixes.mbox - # END OF PATCH DEFINITIONS %endif @@ -1571,12 +1569,10 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 +ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 855275 -ApplyPatch radeon-evergreen-3.6.9-fixes.mbox - # END OF PATCH APPLICATIONS %endif @@ -2442,6 +2438,9 @@ fi # ||----w | # || || %changelog +* Tue Dec 11 2012 Justin M. Forbes 3.6.10-1 +- Linux 3.6.10 + * Wed Dec 05 2012 Dave Jones - Team driver updates (Jiri Pirko) diff --git a/radeon-evergreen-3.6.9-fixes.mbox b/radeon-evergreen-3.6.9-fixes.mbox deleted file mode 100644 index 96628fd2d..000000000 --- a/radeon-evergreen-3.6.9-fixes.mbox +++ /dev/null @@ -1,376 +0,0 @@ -From 8e502f50fdade16ab4540159218be5d81b678d11 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:12:05 -0500 -Subject: [PATCH 1/3] drm/radeon/dce4+: don't use radeon_crtc for vblank - callback - -Upstream commit 4a15903db02026728d0cf2755c6fabae16b8db6a - -This might be called before we've allocated the radeon_crtcs - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/evergreen.c | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index e93b80a..0c79d9e 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -37,6 +37,16 @@ - #define EVERGREEN_PFP_UCODE_SIZE 1120 - #define EVERGREEN_PM4_UCODE_SIZE 1376 - -+static const u32 crtc_offsets[6] = -+{ -+ EVERGREEN_CRTC0_REGISTER_OFFSET, -+ EVERGREEN_CRTC1_REGISTER_OFFSET, -+ EVERGREEN_CRTC2_REGISTER_OFFSET, -+ EVERGREEN_CRTC3_REGISTER_OFFSET, -+ EVERGREEN_CRTC4_REGISTER_OFFSET, -+ EVERGREEN_CRTC5_REGISTER_OFFSET -+}; -+ - static void evergreen_gpu_init(struct radeon_device *rdev); - void evergreen_fini(struct radeon_device *rdev); - void evergreen_pcie_gen2_enable(struct radeon_device *rdev); -@@ -109,17 +119,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) - */ - void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) - { -- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - int i; - -- if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { -+ if (crtc >= rdev->num_crtc) -+ return; -+ -+ if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { - for (i = 0; i < rdev->usec_timeout; i++) { -- if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) -+ if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) - break; - udelay(1); - } - for (i = 0; i < rdev->usec_timeout; i++) { -- if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) -+ if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) - break; - udelay(1); - } --- -1.8.0 - - -From 027eb4090e4261a9b9f5cce47493657d12f2caf3 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:15:21 -0500 -Subject: [PATCH 2/3] drm/radeon: properly handle mc_stop/mc_resume on - evergreen+ (v2) - -Upstream commit 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 - -- Stop the displays from accessing the FB -- Block CPU access -- Turn off MC client access - -This should fix issues some users have seen, especially -with UEFI, when changing the MC FB location that result -in hangs or display corruption. - -v2: fix crtc enabled check noticed by Luca Tettamanti - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/evergreen.c | 169 +++++++++++++++------------------ - drivers/gpu/drm/radeon/evergreen_reg.h | 2 + - drivers/gpu/drm/radeon/evergreend.h | 7 ++ - drivers/gpu/drm/radeon/radeon_asic.h | 1 + - 4 files changed, 88 insertions(+), 91 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 0c79d9e..10b34b8 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1241,116 +1241,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) - - void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) - { -+ u32 crtc_enabled, tmp, frame_count, blackout; -+ int i, j; -+ - save->vga_render_control = RREG32(VGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - -- /* Stop all video */ -+ /* disable VGA render */ - WREG32(VGA_RENDER_CONTROL, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -- } -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -- } -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ /* blank the display controllers */ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; -+ if (crtc_enabled) { -+ save->crtc_enabled[i] = true; -+ if (ASIC_IS_DCE6(rdev)) { -+ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); -+ if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { -+ radeon_wait_for_vblank(rdev, i); -+ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; -+ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); -+ } -+ } else { -+ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); -+ if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { -+ radeon_wait_for_vblank(rdev, i); -+ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; -+ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); -+ } -+ } -+ /* wait for the next frame */ -+ frame_count = radeon_get_vblank_counter(rdev, i); -+ for (j = 0; j < rdev->usec_timeout; j++) { -+ if (radeon_get_vblank_counter(rdev, i) != frame_count) -+ break; -+ udelay(1); -+ } -+ } - } - -- WREG32(D1VGA_CONTROL, 0); -- WREG32(D2VGA_CONTROL, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_D3VGA_CONTROL, 0); -- WREG32(EVERGREEN_D4VGA_CONTROL, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_D5VGA_CONTROL, 0); -- WREG32(EVERGREEN_D6VGA_CONTROL, 0); -+ radeon_mc_wait_for_idle(rdev); -+ -+ blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); -+ if ((blackout & BLACKOUT_MODE_MASK) != 1) { -+ /* Block CPU access */ -+ WREG32(BIF_FB_EN, 0); -+ /* blackout the MC */ -+ blackout &= ~BLACKOUT_MODE_MASK; -+ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); - } - } - - void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) - { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -+ u32 tmp, frame_count; -+ int i, j; - -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ /* update crtc base addresses */ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)rdev->mc.vram_start); - } -- - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); -- /* Unlock host access */ -+ -+ /* unblackout the MC */ -+ tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); -+ tmp &= ~BLACKOUT_MODE_MASK; -+ WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); -+ /* allow CPU access */ -+ WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); -+ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ if (save->crtc_enabled) { -+ if (ASIC_IS_DCE6(rdev)) { -+ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); -+ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; -+ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); -+ } else { -+ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); -+ tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; -+ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); -+ } -+ /* wait for the next frame */ -+ frame_count = radeon_get_vblank_counter(rdev, i); -+ for (j = 0; j < rdev->usec_timeout; j++) { -+ if (radeon_get_vblank_counter(rdev, i) != frame_count) -+ break; -+ udelay(1); -+ } -+ } -+ } -+ /* Unlock vga access */ - WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(VGA_RENDER_CONTROL, save->vga_render_control); -diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h -index 8beac10..034f4c2 100644 ---- a/drivers/gpu/drm/radeon/evergreen_reg.h -+++ b/drivers/gpu/drm/radeon/evergreen_reg.h -@@ -218,6 +218,8 @@ - #define EVERGREEN_CRTC_CONTROL 0x6e70 - # define EVERGREEN_CRTC_MASTER_EN (1 << 0) - # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) -+#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 -+# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) - #define EVERGREEN_CRTC_STATUS 0x6e8c - # define EVERGREEN_CRTC_V_BLANK (1 << 0) - #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 -diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h -index 302af4f..2bc0f6a 100644 ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -87,6 +87,10 @@ - - #define CONFIG_MEMSIZE 0x5428 - -+#define BIF_FB_EN 0x5490 -+#define FB_READ_EN (1 << 0) -+#define FB_WRITE_EN (1 << 1) -+ - #define CP_STRMOUT_CNTL 0x84FC - - #define CP_COHER_CNTL 0x85F0 -@@ -434,6 +438,9 @@ - #define NOOFCHAN_MASK 0x00003000 - #define MC_SHARED_CHREMAP 0x2008 - -+#define MC_SHARED_BLACKOUT_CNTL 0x20ac -+#define BLACKOUT_MODE_MASK 0x00000007 -+ - #define MC_ARB_RAMCFG 0x2760 - #define NOOFBANK_SHIFT 0 - #define NOOFBANK_MASK 0x00000003 -diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h -index 18c38d1..132429e 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.h -+++ b/drivers/gpu/drm/radeon/radeon_asic.h -@@ -389,6 +389,7 @@ void r700_cp_fini(struct radeon_device *rdev); - struct evergreen_mc_save { - u32 vga_render_control; - u32 vga_hdp_control; -+ bool crtc_enabled[RADEON_MAX_CRTCS]; - }; - - void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); --- -1.8.0 - - -From 5d46a79118cc6a8f5e30e39f19ad997bb2191b53 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:15:55 -0500 -Subject: [PATCH 3/3] drm/radeon: properly track the crtc not_enabled case - evergreen_mc_stop() - -Upstream commit 804cc4a0ad3a896ca295f771a28c6eb36ced7903 - -The save struct is not initialized previously so explicitly -mark the crtcs as not used when they are not in use. - -Signed-off-by: Alex Deucher -Cc: stable@vger.kernel.org ---- - drivers/gpu/drm/radeon/evergreen.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 10b34b8..5528fea 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1276,6 +1276,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav - break; - udelay(1); - } -+ } else { -+ save->crtc_enabled[i] = false; - } - } - --- -1.8.0 - diff --git a/sources b/sources index 7369b3635..eebf282fc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -a7c656034599f90dcbc50895b69022aa patch-3.6.9.xz +406a52f90a2ddc78a3ecdf4fe46e7cf7 patch-3.6.10.xz From 90c0d2496b55397b022430f5b98ab4855c1249bf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Dec 2012 12:03:22 -0500 Subject: [PATCH 123/492] Fix IBSS scanning in mac80211 (rhbz 883414) --- kernel.spec | 12 ++- mac80211-fix-ibss-scanning.patch | 132 +++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-ibss-scanning.patch diff --git a/kernel.spec b/kernel.spec index bc971f8a3..fd6e2b9a4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -813,6 +813,9 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 883414 +Patch21234: mac80211-fix-ibss-scanning.patch + # END OF PATCH DEFINITIONS %endif @@ -1573,6 +1576,10 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 883414 +ApplyPatch mac80211-fix-ibss-scanning.patch + + # END OF PATCH APPLICATIONS %endif @@ -2438,6 +2445,9 @@ fi # ||----w | # || || %changelog +* Tue Dec 11 2012 Josh Boyer +- Fix IBSS scanning in mac80211 (rhbz 883414) + * Tue Dec 11 2012 Justin M. Forbes 3.6.10-1 - Linux 3.6.10 diff --git a/mac80211-fix-ibss-scanning.patch b/mac80211-fix-ibss-scanning.patch new file mode 100644 index 000000000..c2bc698a0 --- /dev/null +++ b/mac80211-fix-ibss-scanning.patch @@ -0,0 +1,132 @@ +Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this +can trigger Microcode errors on iwlwifi and iwlegacy drivers. + +Also rename ieee80211_request_internal_scan() function since it is only +used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). + +This patch should address: +https://bugzilla.redhat.com/show_bug.cgi?id=883414 +https://bugzilla.kernel.org/show_bug.cgi?id=49411 + +Reported-by: Jesse Kahtava +Reported-by: Mikko Rapeli +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/ibss.c | 9 ++++----- + net/mac80211/ieee80211_i.h | 6 +++--- + net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- + 3 files changed, 31 insertions(+), 18 deletions(-) + +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index c21e33d..d9df6b8 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) + sdata_info(sdata, + "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, ++ NULL); + } + + static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) + IEEE80211_SCAN_INTERVAL)) { + sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, +- ifibss->fixed_channel ? ifibss->channel : NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ++ ifibss->ssid_len, chan); + } else { + int interval = IEEE80211_SCAN_INTERVAL; + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 156e583..bc48d4d 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + + /* scan/BSS handling */ + void ieee80211_scan_work(struct work_struct *work); +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan); ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan); + int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req); + void ieee80211_scan_cancel(struct ieee80211_local *local); +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 43e60b5..fab706f 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + return res; + } + +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan) ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan) + { + struct ieee80211_local *local = sdata->local; + int ret = -EBUSY; +@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + + /* fill internal scan request */ + if (!chan) { +- int i, nchan = 0; ++ int i, max_n; ++ int n_ch = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; +- for (i = 0; +- i < local->hw.wiphy->bands[band]->n_channels; +- i++) { +- local->int_scan_req->channels[nchan] = ++ ++ max_n = local->hw.wiphy->bands[band]->n_channels; ++ for (i = 0; i < max_n; i++) { ++ struct ieee80211_channel *tmp_ch = + &local->hw.wiphy->bands[band]->channels[i]; +- nchan++; ++ ++ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED)) ++ continue; ++ ++ local->int_scan_req->channels[n_ch] = tmp_ch; ++ n_ch++; + } + } + +- local->int_scan_req->n_channels = nchan; ++ if (WARN_ON_ONCE(n_ch == 0)) ++ goto unlock; ++ ++ local->int_scan_req->n_channels = n_ch; + } else { ++ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED))) ++ goto unlock; ++ + local->int_scan_req->channels[0] = chan; + local->int_scan_req->n_channels = 1; + } +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 389b1121b3af730774ac88d7387b41dd7900085a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Dec 2012 12:42:20 -0500 Subject: [PATCH 124/492] Update secure boot patches to include MoK support --- kernel.spec | 9 +- ...121105.patch => secure-boot-20121210.patch | 227 ++++++++++-------- 2 files changed, 126 insertions(+), 110 deletions(-) rename secure-boot-20121105.patch => secure-boot-20121210.patch (88%) diff --git a/kernel.spec b/kernel.spec index fd6e2b9a4..fe2fac5b6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -691,7 +691,7 @@ Patch900: modsign-upstream-3.7.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20121105.patch +Patch1000: secure-boot-20121210.patch Patch1001: efivarfs-3.6.patch # Improve PCI support on UEFI @@ -1475,7 +1475,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.6.patch -ApplyPatch secure-boot-20121105.patch +ApplyPatch secure-boot-20121210.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -2445,7 +2445,8 @@ fi # ||----w | # || || %changelog -* Tue Dec 11 2012 Josh Boyer +* Tue Dec 11 2012 Josh Boyer - 3.6.10-4 +- Update secure boot patches to include MoK support - Fix IBSS scanning in mac80211 (rhbz 883414) * Tue Dec 11 2012 Justin M. Forbes 3.6.10-1 diff --git a/secure-boot-20121105.patch b/secure-boot-20121210.patch similarity index 88% rename from secure-boot-20121105.patch rename to secure-boot-20121210.patch index 67a08201d..eb26740f9 100644 --- a/secure-boot-20121105.patch +++ b/secure-boot-20121210.patch @@ -1,7 +1,7 @@ -From 57c0dbcbafaa724313c672830ff0087f56a84c47 Mon Sep 17 00:00:00 2001 +From f58576110ddec23d466e78bfd3dd7e8a3a2ce30b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/14] Secure boot: Add new capability +Subject: [PATCH 01/19] Secure boot: Add new capability Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. @@ -32,13 +32,13 @@ index d10b7ed..4345bc8 100644 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) -- -1.7.11.4 +1.8.0.1 -From 95fd8148be46036e20fc64c480104d2a2b454e27 Mon Sep 17 00:00:00 2001 +From 1f57285279e256a905c329eaf5ab181460db3a85 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 02/14] PCI: Lock down BAR access in secure boot environments +Subject: [PATCH 02/19] PCI: Lock down BAR access in secure boot environments Any hardware that can potentially generate DMA has to be locked down from userspace in order to avoid it being possible for an attacker to cause @@ -53,10 +53,10 @@ Signed-off-by: Matthew Garrett 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index 6869009..c03fb85 100644 +index f39378d..1db1e74 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c -@@ -542,6 +542,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, +@@ -546,6 +546,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, loff_t init_off = off; u8 *data = (u8*) buf; @@ -66,7 +66,7 @@ index 6869009..c03fb85 100644 if (off > dev->cfg_size) return 0; if (off + count > dev->cfg_size) { -@@ -844,6 +847,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +@@ -852,6 +855,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, resource_size_t start, end; int i; @@ -76,7 +76,7 @@ index 6869009..c03fb85 100644 for (i = 0; i < PCI_ROM_RESOURCE; i++) if (res == &pdev->resource[i]) break; -@@ -951,6 +957,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, +@@ -959,6 +965,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { @@ -87,10 +87,10 @@ index 6869009..c03fb85 100644 } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index 27911b5..ac8c9a5 100644 +index af028c7..53372eb 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c -@@ -135,6 +135,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof +@@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof int size = dp->size; int cnt; @@ -100,7 +100,7 @@ index 27911b5..ac8c9a5 100644 if (pos >= size) return 0; if (nbytes >= size) -@@ -211,6 +214,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, +@@ -219,6 +222,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, #endif /* HAVE_PCI_MMAP */ int ret = 0; @@ -110,7 +110,7 @@ index 27911b5..ac8c9a5 100644 switch (cmd) { case PCIIOC_CONTROLLER: ret = pci_domain_nr(dev->bus); -@@ -251,7 +257,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) +@@ -259,7 +265,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) struct pci_filp_private *fpriv = file->private_data; int i, ret; @@ -133,13 +133,13 @@ index e1c1ec5..97e785f 100644 dev = pci_get_bus_and_slot(bus, dfn); -- -1.7.11.4 +1.8.0.1 -From 2d23d2726583d79062e58abcc32c7dd027d312aa Mon Sep 17 00:00:00 2001 +From 6e8a17b89dae1074335c0b702063c0bf9791ab94 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 03/14] x86: Lock down IO port access in secure boot +Subject: [PATCH 03/19] x86: Lock down IO port access in secure boot environments IO port access would permit users to gain access to PCI configuration @@ -190,13 +190,13 @@ index e5eedfa..1e0a660 100644 return -EFAULT; while (count-- > 0 && i < 65536) { -- -1.7.11.4 +1.8.0.1 -From e063cb2f3a667d2540682d4bdbef91fdb23b1a84 Mon Sep 17 00:00:00 2001 +From ea20d072eba1e2ee57edd2fd43d51b7fb034365a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 04/14] ACPI: Limit access to custom_method +Subject: [PATCH 04/19] ACPI: Limit access to custom_method It must be impossible for even root to get code executed in kernel context under a secure boot environment. custom_method effectively allows arbitrary @@ -222,13 +222,13 @@ index 5d42c24..247d58b 100644 /* parse the table header to get the table length */ if (count <= sizeof(struct acpi_table_header)) -- -1.7.11.4 +1.8.0.1 -From a1cccbd084c7355dcb2be7ae2934f168ce9ba9d5 Mon Sep 17 00:00:00 2001 +From 30955d49acbb357528e4fd36f41b0e7893fa5485 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 05/14] asus-wmi: Restrict debugfs interface +Subject: [PATCH 05/19] asus-wmi: Restrict debugfs interface We have no way of validating what all of the Asus WMI methods do on a given machine, and there's a risk that some will allow hardware state to @@ -241,10 +241,10 @@ Signed-off-by: Matthew Garrett 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 2eb9fe8..61e055d 100644 +index c0e9ff4..3c10167 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -1523,6 +1523,9 @@ static int show_dsts(struct seq_file *m, void *data) +@@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data) int err; u32 retval = -1; @@ -254,7 +254,7 @@ index 2eb9fe8..61e055d 100644 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); if (err < 0) -@@ -1539,6 +1542,9 @@ static int show_devs(struct seq_file *m, void *data) +@@ -1537,6 +1540,9 @@ static int show_devs(struct seq_file *m, void *data) int err; u32 retval = -1; @@ -264,7 +264,7 @@ index 2eb9fe8..61e055d 100644 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, &retval); -@@ -1563,6 +1569,9 @@ static int show_call(struct seq_file *m, void *data) +@@ -1561,6 +1567,9 @@ static int show_call(struct seq_file *m, void *data) union acpi_object *obj; acpi_status status; @@ -275,13 +275,13 @@ index 2eb9fe8..61e055d 100644 1, asus->debug.method_id, &input, &output); -- -1.7.11.4 +1.8.0.1 -From 1c9e53b626268f82509062751eda14e8572717cf Mon Sep 17 00:00:00 2001 +From ce5f692463e82e824d4bf7c190959831d04232bf Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 06/14] Restrict /dev/mem and /dev/kmem in secure boot setups +Subject: [PATCH 06/19] Restrict /dev/mem and /dev/kmem in secure boot setups Allowing users to write to address space makes it possible for the kernel to be subverted. Restrict this when we need to protect the kernel. @@ -316,13 +316,13 @@ index 1e0a660..33eb947 100644 unsigned long to_write = min_t(unsigned long, count, (unsigned long)high_memory - p); -- -1.7.11.4 +1.8.0.1 -From fbf919bf372b9a7a08bdacac8129d47ced1b1f19 Mon Sep 17 00:00:00 2001 +From c43e7120ff4edf57a162271404844edb185fb45b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 07/14] Secure boot: Add a dummy kernel parameter that will +Subject: [PATCH 07/19] Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset @@ -382,13 +382,13 @@ index de728ac..7e6e83f 100644 * prepare_kernel_cred - Prepare a set of credentials for a kernel service * @daemon: A userspace daemon to be used as a reference -- -1.7.11.4 +1.8.0.1 -From 43ed7865d867ae692e30227d66fa58cdecbd9269 Mon Sep 17 00:00:00 2001 +From 15f6071a2d551bb19f8bbc2a44de8957ca43fc73 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 08/14] efi: Enable secure boot lockdown automatically when +Subject: [PATCH 08/19] efi: Enable secure boot lockdown automatically when enabled in firmware The firmware has a set of flags that indicate whether secure boot is enabled @@ -418,10 +418,10 @@ index cf5437d..7f9ed48 100644 2D0/A00 ALL e820_map E820 memory map table (array of struct e820entry) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index b3e0227..3789356 100644 +index 90201aa..bdf0eb7 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -724,6 +724,36 @@ fail: +@@ -726,6 +726,36 @@ fail: return status; } @@ -458,7 +458,7 @@ index b3e0227..3789356 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1018,6 +1048,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1020,6 +1050,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -482,10 +482,10 @@ index 2ad874c..c7338e0 100644 __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index f4b9b80..239bf2a 100644 +index 5cee802..b4f4666 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -947,6 +947,9 @@ void __init setup_arch(char **cmdline_p) +@@ -961,6 +961,9 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -509,13 +509,13 @@ index ebbed2c..a24faf1 100644 * check for validity of credentials */ -- -1.7.11.4 +1.8.0.1 -From 3acf1ceb5f6f3be9103c9da16ddc24afc6d8b02a Mon Sep 17 00:00:00 2001 +From 805ead5a371f8bab3336754993f15379d9637d5b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 09/14] acpi: Ignore acpi_rsdp kernel parameter in a secure +Subject: [PATCH 09/19] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment This option allows userspace to pass the RSDP address to the kernel. This @@ -541,13 +541,13 @@ index 9eaf708..f94341b 100644 #endif -- -1.7.11.4 +1.8.0.1 -From 03fb06d272ddc1062e610521c5cfdbe42f251209 Mon Sep 17 00:00:00 2001 +From 8b079695bbb544aacd00786b3e34f627d9bf149e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 10/14] SELinux: define mapping for new Secure Boot capability +Subject: [PATCH 10/19] SELinux: define mapping for new Secure Boot capability Add the name of the new Secure Boot capability. This allows SELinux policies to properly map CAP_COMPROMISE_KERNEL to the appropriate @@ -574,13 +574,13 @@ index df2de54..70e2834 100644 { "tun_socket", { COMMON_SOCK_PERMS, NULL } }, -- -1.7.11.4 +1.8.0.1 -From 0cfaa5ecf01f8eaaa2a84d88b7258a94ac9a1bfe Mon Sep 17 00:00:00 2001 +From a3dc33319e9d4b6d912816ed1664e52050eae82e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 11/14] kexec: Disable in a secure boot environment +Subject: [PATCH 11/19] kexec: Disable in a secure boot environment kexec could be used as a vector for a malicious user to use a signed kernel to circumvent the secure boot trust model. In the long run we'll want to @@ -606,13 +606,13 @@ index 0668d58..8b976a5 100644 /* -- -1.7.11.4 +1.8.0.1 -From 895c46276788b3711aee05a1a1d685eff69d48b9 Mon Sep 17 00:00:00 2001 +From 5f68872e3aebae91a6681ed4a4e97527ff3dd238 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Jun 2012 21:29:46 -0400 -Subject: [PATCH 12/14] Documentation: kernel-parameters.txt remove +Subject: [PATCH 12/19] Documentation: kernel-parameters.txt remove capability.disable Remove the documentation for capability.disable. The code supporting this @@ -647,13 +647,13 @@ index 93978d5..e3e5f8c 100644 See Documentation/s390/CommonIO for details. -- -1.7.11.4 +1.8.0.1 -From 1cc529e97756554953187fe48b9b8cf0e24b9bc7 Mon Sep 17 00:00:00 2001 +From ce17d3ac9c1a311633ff4fb90528f8634557a2eb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH] modsign: Always enforce module signing in a Secure Boot +Subject: [PATCH 13/19] modsign: Always enforce module signing in a Secure Boot environment If a machine is booted into a Secure Boot environment, we need to @@ -669,7 +669,7 @@ Signed-off-by: Josh Boyer 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c -index 7e6e83f..2b0b980 100644 +index 7e6e83f..6e828e2 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -623,11 +623,19 @@ void __init cred_init(void) @@ -693,7 +693,7 @@ index 7e6e83f..2b0b980 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index de16959..7d4c50a 100644 +index e0785b3..b964a03 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ @@ -709,14 +709,14 @@ index de16959..7d4c50a 100644 static int param_set_bool_enable_only(const char *val, const struct kernel_param *kp) -- -1.7.11.4 +1.8.0.1 -From 945f3829d0d376c5e0c790b57c4fa9e875d602d3 Mon Sep 17 00:00:00 2001 + +From b8b58cc7b0b8c56170bdf75afff2ec6bc92546a9 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 1/2] Add EFI signature data types, such as are used for - containing hashes, keys and certificates for - cryptographic verification. +Subject: [PATCH 14/19] Add EFI signature data types, such as are used for + containing hashes, keys and certificates for cryptographic verification. Signed-off-by: David Howells --- @@ -724,7 +724,7 @@ Signed-off-by: David Howells 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index 8670eb1..836c797 100644 +index 5782114..6add02a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, @@ -762,15 +762,14 @@ index 8670eb1..836c797 100644 * All runtime access to EFI goes through this structure: */ -- -1.7.12.1 +1.8.0.1 -From 5934634101936bc4ee4636df7269e00c4979911c Mon Sep 17 00:00:00 2001 +From f39503e9b88375a450274ab1b5c1eb07f2f2db3c Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 2/2] Add an EFI signature blob parser and key loader. X.509 - certificates are loaded into the specified keyring as - asymmetric type keys. +Subject: [PATCH 15/19] Add an EFI signature blob parser and key loader. X.509 + certificates are loaded into the specified keyring as asymmetric type keys. Signed-off-by: David Howells --- @@ -923,10 +922,10 @@ index 0000000..59b859a + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index 836c797..9cc3250 100644 +index 6add02a..c7c3ec4 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -536,6 +536,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -533,6 +533,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -938,14 +937,14 @@ index 836c797..9cc3250 100644 * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- -1.7.12.1 +1.8.0.1 -From a06f449cee6152ce8f0a051593fceb82d26e4f16 Mon Sep 17 00:00:00 2001 +From a4051b85c5ec179b2ec6b1fede399612462cf77d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:29:49 -0400 -Subject: [PATCH] EFI: Add in-kernel variable to determine if Secure Boot is - enabled +Subject: [PATCH 16/19] EFI: Add in-kernel variable to determine if Secure Boot + is enabled There are a few cases where in-kernel functions may need to know if Secure Boot is enabled. The added capability check cannot be used as the @@ -991,10 +990,10 @@ index 72d8899..882d794 100644 .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h -index 54b5936..411997f 100644 +index c7c3ec4..2450bee 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -575,11 +575,14 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -570,11 +570,14 @@ extern int __init efi_setup_pcdp_console(char *); # ifdef CONFIG_X86 extern int efi_enabled; extern bool efi_64bit; @@ -1010,12 +1009,13 @@ index 54b5936..411997f 100644 /* -- -1.7.12.1 +1.8.0.1 -From 2a5f33b264daffd717b509bc5ac3cdc060b5573e Mon Sep 17 00:00:00 2001 + +From ad30518e2a4d52c680aa388c24fbd640d5f9beb1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 2/3] MODSIGN: Add module certificate blacklist keyring +Subject: [PATCH 17/19] MODSIGN: Add module certificate blacklist keyring This adds an additional keyring that is used to store certificates that are blacklisted. This keyring is searched first when loading signed modules @@ -1031,10 +1031,10 @@ Signed-off-by: Josh Boyer 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig -index 6fdd6e3..7a9bf00 100644 +index abc6e63..78f3e280 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE +@@ -1613,6 +1613,14 @@ config MODULE_SIG_FORCE Reject unsigned modules or signed modules for which we don't have a key. Without this, such modules will simply taint the kernel. @@ -1098,7 +1098,7 @@ index 24f9247..51a8380 100644 extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index ea1b1df..602aa24 100644 +index d492a23..39131d3 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, @@ -1130,14 +1130,13 @@ index ea1b1df..602aa24 100644 &key_type_asymmetric, id); if (IS_ERR(key)) -- -1.7.12.1 +1.8.0.1 - -From ddd5e2e1b775fb19aeec7fb842e707fc35347bc0 Mon Sep 17 00:00:00 2001 +From 6953646e8248c27c81996d538cbd9177357b80d4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH] MODSIGN: Import certificates from UEFI Secure Boot +Subject: [PATCH 18/19] MODSIGN: Import certificates from UEFI Secure Boot Secure Boot stores a list of allowed certificates in the 'db' variable. This imports those certificates into the module signing keyring. This @@ -1153,32 +1152,35 @@ signed with those from loading. Signed-off-by: Josh Boyer --- - include/linux/efi.h | 3 ++ - init/Kconfig | 9 ++++++ + include/linux/efi.h | 6 ++++ + init/Kconfig | 9 +++++ kernel/Makefile | 3 ++ - kernel/modsign_uefi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 99 insertions(+) + kernel/modsign_uefi.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 115 insertions(+) create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index ff72468..509755e 100644 +index 2450bee..d5c2cff 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -318,6 +318,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -318,6 +318,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, #define EFI_CERT_X509_GUID \ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) +#define EFI_IMAGE_SECURITY_DATABASE_GUID \ + EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) ++ ++#define EFI_SHIM_LOCK_GUID \ ++ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) + typedef struct { efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index 7a9bf00..9c4c529 100644 +index 78f3e280..754ee66 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST +@@ -1621,6 +1621,15 @@ config MODULE_SIG_BLACKLIST should not pass module signature verification. If a module is signed with something in this keyring, the load will be rejected. @@ -1195,10 +1197,10 @@ index 7a9bf00..9c4c529 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/Makefile b/kernel/Makefile -index 0dfeca4..ff1468f 100644 +index d3611c8..927a264 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o +@@ -56,6 +56,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o @@ -1206,7 +1208,7 @@ index 0dfeca4..ff1468f 100644 obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o -@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o +@@ -114,6 +115,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o $(obj)/configs.o: $(obj)/config_data.h @@ -1217,10 +1219,10 @@ index 0dfeca4..ff1468f 100644 targets += config_data.gz diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c new file mode 100644 -index 0000000..049669d +index 0000000..8c30978 --- /dev/null +++ b/kernel/modsign_uefi.c -@@ -0,0 +1,84 @@ +@@ -0,0 +1,97 @@ +#include +#include +#include @@ -1265,8 +1267,9 @@ index 0000000..049669d +static int __init load_uefi_certs(void) +{ + efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; -+ void *db = NULL, *dbx = NULL; -+ unsigned long dbsize = 0, dbxsize = 0; ++ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; ++ void *db = NULL, *dbx = NULL, *mok = NULL; ++ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; + int rc = 0; + + /* Check if SB is enabled and just return if not */ @@ -1280,18 +1283,29 @@ index 0000000..049669d + goto err; + } + ++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); ++ if (!mok) { ++ pr_info("Couldn't get MokListRT\n"); ++ } ++ + /* Get dbx. It might not exist, so it isn't an error if we can't + * get it. + */ + dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); + if (!dbx) { -+ pr_err("Couldn't get dbx list\n"); ++ pr_info("Couldn't get dbx list\n"); + } + + rc = parse_efi_signature_list(db, dbsize, modsign_keyring); + if (rc) + pr_err("Couldn't parse db signatures: %d\n", rc); + ++ if (mok) { ++ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); ++ } ++ + if (dbx) { + rc = parse_efi_signature_list(dbx, dbxsize, + modsign_blacklist); @@ -1301,18 +1315,19 @@ index 0000000..049669d + +err: + kfree(db); ++ kfree(mok); + kfree(dbx); + return rc; +} +late_initcall(load_uefi_certs); -- -1.7.12.1 +1.8.0.1 -From 924e09f1b267c407ca037171bc6f8f90b09265d6 Mon Sep 17 00:00:00 2001 +From 90b1c60f09f2ad45c59b8e6320397f2769e4bdb5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH] hibernate: Disable in a Secure Boot environment +Subject: [PATCH 19/19] hibernate: Disable in a Secure Boot environment There is currently no way to verify the resume image when returning from hibernate. This might compromise the secure boot trust model, @@ -1402,5 +1417,5 @@ index 4ed81e7..b11a0f4 100644 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -- -1.7.12.1 +1.8.0.1 From 666877e44ae2765e68fde594256401f51bcf5c67 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Dec 2012 15:12:08 -0500 Subject: [PATCH 125/492] Fix infinite loop in efi signature parser - Don't error out if db doesn't exist --- kernel.spec | 10 +- ...121210.patch => secure-boot-20121212.patch | 185 ++++++++++-------- 2 files changed, 115 insertions(+), 80 deletions(-) rename secure-boot-20121210.patch => secure-boot-20121212.patch (89%) diff --git a/kernel.spec b/kernel.spec index fe2fac5b6..71e317bd6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -691,7 +691,7 @@ Patch900: modsign-upstream-3.7.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20121210.patch +Patch1000: secure-boot-20121212.patch Patch1001: efivarfs-3.6.patch # Improve PCI support on UEFI @@ -1475,7 +1475,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.6.patch -ApplyPatch secure-boot-20121210.patch +ApplyPatch secure-boot-20121212.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -2445,6 +2445,10 @@ fi # ||----w | # || || %changelog +* Wed Dec 12 2012 Josh Boyer +- Fix infinite loop in efi signature parser +- Don't error out if db doesn't exist + * Tue Dec 11 2012 Josh Boyer - 3.6.10-4 - Update secure boot patches to include MoK support - Fix IBSS scanning in mac80211 (rhbz 883414) diff --git a/secure-boot-20121210.patch b/secure-boot-20121212.patch similarity index 89% rename from secure-boot-20121210.patch rename to secure-boot-20121212.patch index eb26740f9..d435eb217 100644 --- a/secure-boot-20121210.patch +++ b/secure-boot-20121212.patch @@ -1,7 +1,7 @@ -From f58576110ddec23d466e78bfd3dd7e8a3a2ce30b Mon Sep 17 00:00:00 2001 +From 925befaba2477067aa12fa1fdc9fcc135c80b4fd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/19] Secure boot: Add new capability +Subject: [PATCH 01/20] Secure boot: Add new capability Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. @@ -35,10 +35,10 @@ index d10b7ed..4345bc8 100644 1.8.0.1 -From 1f57285279e256a905c329eaf5ab181460db3a85 Mon Sep 17 00:00:00 2001 +From 1c5873679d750bda038d22210d9fd40c8673211f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 02/19] PCI: Lock down BAR access in secure boot environments +Subject: [PATCH 02/20] PCI: Lock down BAR access in secure boot environments Any hardware that can potentially generate DMA has to be locked down from userspace in order to avoid it being possible for an attacker to cause @@ -136,10 +136,10 @@ index e1c1ec5..97e785f 100644 1.8.0.1 -From 6e8a17b89dae1074335c0b702063c0bf9791ab94 Mon Sep 17 00:00:00 2001 +From f067c7702f46b85d06da6c34dd907b44e594c2cf Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 03/19] x86: Lock down IO port access in secure boot +Subject: [PATCH 03/20] x86: Lock down IO port access in secure boot environments IO port access would permit users to gain access to PCI configuration @@ -193,10 +193,10 @@ index e5eedfa..1e0a660 100644 1.8.0.1 -From ea20d072eba1e2ee57edd2fd43d51b7fb034365a Mon Sep 17 00:00:00 2001 +From 95b440833e9002bc7e1950f403f2fb2953b69317 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 04/19] ACPI: Limit access to custom_method +Subject: [PATCH 04/20] ACPI: Limit access to custom_method It must be impossible for even root to get code executed in kernel context under a secure boot environment. custom_method effectively allows arbitrary @@ -225,10 +225,10 @@ index 5d42c24..247d58b 100644 1.8.0.1 -From 30955d49acbb357528e4fd36f41b0e7893fa5485 Mon Sep 17 00:00:00 2001 +From fd40b868d55992f71acffa74b559923ffde81638 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 05/19] asus-wmi: Restrict debugfs interface +Subject: [PATCH 05/20] asus-wmi: Restrict debugfs interface We have no way of validating what all of the Asus WMI methods do on a given machine, and there's a risk that some will allow hardware state to @@ -278,10 +278,10 @@ index c0e9ff4..3c10167 100644 1.8.0.1 -From ce5f692463e82e824d4bf7c190959831d04232bf Mon Sep 17 00:00:00 2001 +From 470e4dbf6215d40a340b3ad7fd6d4533ffbf6a6d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 06/19] Restrict /dev/mem and /dev/kmem in secure boot setups +Subject: [PATCH 06/20] Restrict /dev/mem and /dev/kmem in secure boot setups Allowing users to write to address space makes it possible for the kernel to be subverted. Restrict this when we need to protect the kernel. @@ -319,10 +319,10 @@ index 1e0a660..33eb947 100644 1.8.0.1 -From c43e7120ff4edf57a162271404844edb185fb45b Mon Sep 17 00:00:00 2001 +From fdb24af2d20faea8bae60058f0cda8db8be9394d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 07/19] Secure boot: Add a dummy kernel parameter that will +Subject: [PATCH 07/20] Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset @@ -385,10 +385,10 @@ index de728ac..7e6e83f 100644 1.8.0.1 -From 15f6071a2d551bb19f8bbc2a44de8957ca43fc73 Mon Sep 17 00:00:00 2001 +From 033a0db83fe140b040a5f5a5754ba326b0d4f587 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 08/19] efi: Enable secure boot lockdown automatically when +Subject: [PATCH 08/20] efi: Enable secure boot lockdown automatically when enabled in firmware The firmware has a set of flags that indicate whether secure boot is enabled @@ -512,10 +512,10 @@ index ebbed2c..a24faf1 100644 1.8.0.1 -From 805ead5a371f8bab3336754993f15379d9637d5b Mon Sep 17 00:00:00 2001 +From 7a24fb283b72797e219a3283c5cf880ebb80443f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 09/19] acpi: Ignore acpi_rsdp kernel parameter in a secure +Subject: [PATCH 09/20] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment This option allows userspace to pass the RSDP address to the kernel. This @@ -544,10 +544,10 @@ index 9eaf708..f94341b 100644 1.8.0.1 -From 8b079695bbb544aacd00786b3e34f627d9bf149e Mon Sep 17 00:00:00 2001 +From a21ccbd8461fd9780c348faa78bbd3d13db04e3d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 10/19] SELinux: define mapping for new Secure Boot capability +Subject: [PATCH 10/20] SELinux: define mapping for new Secure Boot capability Add the name of the new Secure Boot capability. This allows SELinux policies to properly map CAP_COMPROMISE_KERNEL to the appropriate @@ -577,10 +577,10 @@ index df2de54..70e2834 100644 1.8.0.1 -From a3dc33319e9d4b6d912816ed1664e52050eae82e Mon Sep 17 00:00:00 2001 +From 01af02988477c4bde39436adec1edfd1499709d9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 11/19] kexec: Disable in a secure boot environment +Subject: [PATCH 11/20] kexec: Disable in a secure boot environment kexec could be used as a vector for a malicious user to use a signed kernel to circumvent the secure boot trust model. In the long run we'll want to @@ -609,10 +609,10 @@ index 0668d58..8b976a5 100644 1.8.0.1 -From 5f68872e3aebae91a6681ed4a4e97527ff3dd238 Mon Sep 17 00:00:00 2001 +From 883409d0fadeefe2c44d7034d2acc0e366c339f3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Jun 2012 21:29:46 -0400 -Subject: [PATCH 12/19] Documentation: kernel-parameters.txt remove +Subject: [PATCH 12/20] Documentation: kernel-parameters.txt remove capability.disable Remove the documentation for capability.disable. The code supporting this @@ -650,10 +650,10 @@ index 93978d5..e3e5f8c 100644 1.8.0.1 -From ce17d3ac9c1a311633ff4fb90528f8634557a2eb Mon Sep 17 00:00:00 2001 +From b2ee7008ee39d04b3439f81e42586ee8e16af2e9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH 13/19] modsign: Always enforce module signing in a Secure Boot +Subject: [PATCH 13/20] modsign: Always enforce module signing in a Secure Boot environment If a machine is booted into a Secure Boot environment, we need to @@ -712,10 +712,10 @@ index e0785b3..b964a03 100644 1.8.0.1 -From b8b58cc7b0b8c56170bdf75afff2ec6bc92546a9 Mon Sep 17 00:00:00 2001 +From 4fe6ecce3e9168f538fc8970fe8a964438beabbb Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 14/19] Add EFI signature data types, such as are used for +Subject: [PATCH 14/20] Add EFI signature data types, such as are used for containing hashes, keys and certificates for cryptographic verification. Signed-off-by: David Howells @@ -724,10 +724,10 @@ Signed-off-by: David Howells 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index 5782114..6add02a 100644 +index bff4b5e..52ce2c4 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -317,6 +317,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, #define EFI_FILE_SYSTEM_GUID \ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) @@ -740,7 +740,7 @@ index 5782114..6add02a 100644 typedef struct { efi_guid_t guid; u64 table; -@@ -447,6 +453,20 @@ typedef struct { +@@ -452,6 +458,20 @@ typedef struct { #define EFI_INVALID_TABLE_ADDR (~0UL) @@ -765,10 +765,10 @@ index 5782114..6add02a 100644 1.8.0.1 -From f39503e9b88375a450274ab1b5c1eb07f2f2db3c Mon Sep 17 00:00:00 2001 +From 768ab9ef88b2caa9588e577fe547792dfe513fca Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 15/19] Add an EFI signature blob parser and key loader. X.509 +Subject: [PATCH 15/20] Add an EFI signature blob parser and key loader. X.509 certificates are loaded into the specified keyring as asymmetric type keys. Signed-off-by: David Howells @@ -922,10 +922,10 @@ index 0000000..59b859a + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index 6add02a..c7c3ec4 100644 +index 52ce2c4..54b5936 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -533,6 +533,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -538,6 +538,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -940,10 +940,10 @@ index 6add02a..c7c3ec4 100644 1.8.0.1 -From a4051b85c5ec179b2ec6b1fede399612462cf77d Mon Sep 17 00:00:00 2001 +From 967a1b02af199f07fd7603bda2f0aeec50b412b9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:29:49 -0400 -Subject: [PATCH 16/19] EFI: Add in-kernel variable to determine if Secure Boot +Subject: [PATCH 16/20] EFI: Add in-kernel variable to determine if Secure Boot is enabled There are a few cases where in-kernel functions may need to know if @@ -990,10 +990,10 @@ index 72d8899..882d794 100644 .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h -index c7c3ec4..2450bee 100644 +index 54b5936..411997f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -570,11 +570,14 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -575,11 +575,14 @@ extern int __init efi_setup_pcdp_console(char *); # ifdef CONFIG_X86 extern int efi_enabled; extern bool efi_64bit; @@ -1012,10 +1012,10 @@ index c7c3ec4..2450bee 100644 1.8.0.1 -From ad30518e2a4d52c680aa388c24fbd640d5f9beb1 Mon Sep 17 00:00:00 2001 +From 6e946d64dc843d9caa587780801de035b38fd4b3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 17/19] MODSIGN: Add module certificate blacklist keyring +Subject: [PATCH 17/20] MODSIGN: Add module certificate blacklist keyring This adds an additional keyring that is used to store certificates that are blacklisted. This keyring is searched first when loading signed modules @@ -1133,17 +1133,18 @@ index d492a23..39131d3 100644 1.8.0.1 -From 6953646e8248c27c81996d538cbd9177357b80d4 Mon Sep 17 00:00:00 2001 +From 02905ddf41b18af3c3dd5d99771eba4e453d24ca Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH 18/19] MODSIGN: Import certificates from UEFI Secure Boot +Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot Secure Boot stores a list of allowed certificates in the 'db' variable. This imports those certificates into the module signing keyring. This allows for a third party signing certificate to be used in conjunction with signed modules. By importing the public certificate into the 'db' variable, a user can allow a module signed with that certificate to -load. +load. The shim UEFI bootloader has a similar certificate list stored +in the 'MokListRT' variable. We import those as well. In the opposite case, Secure Boot maintains a list of disallowed certificates in the 'dbx' variable. We load those certificates into @@ -1153,17 +1154,17 @@ signed with those from loading. Signed-off-by: Josh Boyer --- include/linux/efi.h | 6 ++++ - init/Kconfig | 9 +++++ + init/Kconfig | 9 ++++++ kernel/Makefile | 3 ++ - kernel/modsign_uefi.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 115 insertions(+) + kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 108 insertions(+) create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index 2450bee..d5c2cff 100644 +index 411997f..31f84ff 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -318,6 +318,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -323,6 +323,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, #define EFI_CERT_X509_GUID \ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) @@ -1219,10 +1220,10 @@ index d3611c8..927a264 100644 targets += config_data.gz diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c new file mode 100644 -index 0000000..8c30978 +index 0000000..76a5a34 --- /dev/null +++ b/kernel/modsign_uefi.c -@@ -0,0 +1,97 @@ +@@ -0,0 +1,90 @@ +#include +#include +#include @@ -1276,47 +1277,40 @@ index 0000000..8c30978 + if (!secure_boot_enabled) + return 0; + ++ /* Get db, MokListRT, and dbx. They might not exist, so it isn't ++ * an error if we can't get them. ++ */ + db = get_cert_list(L"db", &secure_var, &dbsize); + if (!db) { -+ pr_err("Couldn't get db list\n"); -+ rc = -1; -+ goto err; ++ pr_err("MODSIGN: Couldn't get UEFI db list\n"); ++ } else { ++ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse db signatures: %d\n", rc); ++ kfree(db); + } + + mok = get_cert_list(L"MokListRT", &mok_var, &moksize); + if (!mok) { -+ pr_info("Couldn't get MokListRT\n"); -+ } -+ -+ /* Get dbx. It might not exist, so it isn't an error if we can't -+ * get it. -+ */ -+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); -+ if (!dbx) { -+ pr_info("Couldn't get dbx list\n"); -+ } -+ -+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse db signatures: %d\n", rc); -+ -+ if (mok) { ++ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); ++ } else { + rc = parse_efi_signature_list(mok, moksize, modsign_keyring); + if (rc) + pr_err("Couldn't parse MokListRT signatures: %d\n", rc); ++ kfree(mok); + } + -+ if (dbx) { ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); ++ if (!dbx) { ++ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); ++ } else { + rc = parse_efi_signature_list(dbx, dbxsize, + modsign_blacklist); + if (rc) + pr_err("Couldn't parse dbx signatures: %d\n", rc); ++ kfree(dbx); + } + -+err: -+ kfree(db); -+ kfree(mok); -+ kfree(dbx); + return rc; +} +late_initcall(load_uefi_certs); @@ -1324,10 +1318,10 @@ index 0000000..8c30978 1.8.0.1 -From 90b1c60f09f2ad45c59b8e6320397f2769e4bdb5 Mon Sep 17 00:00:00 2001 +From b1bc4417dcec5c603baae2de2523bdf3a0c96b11 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH 19/19] hibernate: Disable in a Secure Boot environment +Subject: [PATCH 19/20] hibernate: Disable in a Secure Boot environment There is currently no way to verify the resume image when returning from hibernate. This might compromise the secure boot trust model, @@ -1419,3 +1413,40 @@ index 4ed81e7..b11a0f4 100644 -- 1.8.0.1 + +From 96c9c61996828908833b680149525b4b7acff664 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 12 Dec 2012 11:48:49 -0500 +Subject: [PATCH 20/20] Don't soft lockup on bad EFI signature lists + +If a signature list is read from an UEFI variable and that contains bogus +data, we can go into an infinite loop in efi_parse_signature_list. Notably, +if one of the entries in the list has a signature_size that is larger than +the actual signature size, it will fail the elsize < esize test. Simply +continuing in the loop without modifying the data or size variables just +leads to the same list entry being parsed repeatedly. + +Since the data is bogus, but we can't tell which value is actually +incorrect, we need to stop parsing the list. Just return -EBADMSG instead. + +Signed-off-by: Josh Boyer +--- + crypto/asymmetric_keys/efi_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c +index 59b859a..a0b8a3a 100644 +--- a/crypto/asymmetric_keys/efi_parser.c ++++ b/crypto/asymmetric_keys/efi_parser.c +@@ -61,7 +61,7 @@ int __init parse_efi_signature_list(const void *data, size_t size, struct key *k + elsize < esize || + elsize % esize != 0) { + pr_devel("- bad size combo @%x\n", offs); +- continue; ++ return -EBADMSG; + } + + if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { +-- +1.8.0.1 + From 2dfbeb616a52169a0297003a7245cd5cb4ba952e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 14 Dec 2012 12:00:42 -0500 Subject: [PATCH 126/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 71e317bd6..fd7464fbf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2445,7 +2445,7 @@ fi # ||----w | # || || %changelog -* Wed Dec 12 2012 Josh Boyer +* Wed Dec 12 2012 Josh Boyer - 3.6.10-5 - Fix infinite loop in efi signature parser - Don't error out if db doesn't exist From 820fdaa80958b1c359c928088af5ad2cbf3afe8b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 09:04:27 -0500 Subject: [PATCH 127/492] Fix oops in sony-laptop setup (rhbz 873107) --- ...-do-proper-memcpy-for-ACPI_TYPE_INTE.patch | 50 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch diff --git a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch new file mode 100644 index 000000000..857c73c51 --- /dev/null +++ b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch @@ -0,0 +1,50 @@ +From 690b1ad9d2032d6f2565d44f6564590d47835ae8 Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Thu, 29 Nov 2012 01:30:43 +0800 +Subject: [PATCH 1/2] ACPI sony-laptop: do proper memcpy for ACPI_TYPE_INTEGER + acpi_object + +the return value of __call_snc_method can either be +an ACPI_TYPE_BUFFER object or a ACPI_TYPE_INTEGER object. +do proper memcpy for ACPI_TYPE_INTEGER object. + +https://bugzilla.kernel.org/show_bug.cgi?id=50111 + +Signed-off-by: Zhang Rui +--- + drivers/platform/x86/sony-laptop.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c +index daaddec..92e0da2 100644 +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -792,20 +792,19 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, + if (!object) + return -EINVAL; + +- if (object->type == ACPI_TYPE_BUFFER) ++ if (object->type == ACPI_TYPE_BUFFER) { + len = MIN(buflen, object->buffer.length); +- +- else if (object->type == ACPI_TYPE_INTEGER) ++ memcpy(buffer, object->buffer.pointer, len); ++ } else if (object->type == ACPI_TYPE_INTEGER) { + len = MIN(buflen, sizeof(object->integer.value)); +- +- else { ++ memcpy(buffer, (void *)&object->integer.value, len); ++ } else { + pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", + ACPI_TYPE_BUFFER, object->type); + kfree(object); + return -EINVAL; + } + +- memcpy(buffer, object->buffer.pointer, len); + kfree(object); + return 0; + } +-- +1.7.9.5 + diff --git a/kernel.spec b/kernel.spec index fd7464fbf..88a28779f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -816,6 +816,9 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 883414 Patch21234: mac80211-fix-ibss-scanning.patch +#rhbz 873107 +Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch + # END OF PATCH DEFINITIONS %endif @@ -1579,6 +1582,9 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 883414 ApplyPatch mac80211-fix-ibss-scanning.patch +#rhbz 873107 +ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch + # END OF PATCH APPLICATIONS @@ -2445,6 +2451,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 17 2012 Josh Boyer +- Fix oops in sony-laptop setup (rhbz 873107) + * Wed Dec 12 2012 Josh Boyer - 3.6.10-5 - Fix infinite loop in efi signature parser - Don't error out if db doesn't exist From 0689821d3cb11e672f32a9909a0396d3c0da4314 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Mon, 17 Dec 2012 12:41:41 -0600 Subject: [PATCH 128/492] disable gpiolib on vexpress for Jon Masters --- config-arm-versatile | 2 ++ kernel.spec | 3 +++ 2 files changed, 5 insertions(+) diff --git a/config-arm-versatile b/config-arm-versatile index 9c379361b..89d4f7b09 100644 --- a/config-arm-versatile +++ b/config-arm-versatile @@ -93,3 +93,5 @@ CONFIG_PATA_PLATFORM=m CONFIG_PATA_OF_PLATFORM=m # CONFIG_NET_VENDOR_BROADCOM is not set +# unset on versatille for jon masters +# CONFIG_GPIOLIB is not set diff --git a/kernel.spec b/kernel.spec index 88a28779f..0d0e4c238 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2451,6 +2451,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 17 2012 Dennis Gilmore +- disable gpiolib on vexpress + * Mon Dec 17 2012 Josh Boyer - Fix oops in sony-laptop setup (rhbz 873107) From 87a62d8ad6e7ac3c9d2ce4a769254e8734f93ebe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 14:56:57 -0500 Subject: [PATCH 129/492] Linux v3.6.11 --- USB-EHCI-urb-hcpriv-should-not-be-NULL.patch | 72 -- i82975x-edac-fix.patch | 855 ------------------- kernel.spec | 13 +- sources | 2 +- 4 files changed, 6 insertions(+), 936 deletions(-) delete mode 100644 USB-EHCI-urb-hcpriv-should-not-be-NULL.patch delete mode 100644 i82975x-edac-fix.patch diff --git a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch deleted file mode 100644 index 4b8e537c4..000000000 --- a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +++ /dev/null @@ -1,72 +0,0 @@ -commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e -Author: Alan Stern -Date: Thu Nov 8 10:17:01 2012 -0500 - - USB: EHCI: bugfix: urb->hcpriv should not be NULL - - This patch (as1632b) fixes a bug in ehci-hcd. The USB core uses - urb->hcpriv to determine whether or not an URB is active; host - controller drivers are supposed to set this pointer to a non-NULL - value when an URB is queued. However ehci-hcd sets it to NULL for - isochronous URBs, which defeats the check in usbcore. - - In itself this isn't a big deal. But people have recently found that - certain sequences of actions will cause the snd-usb-audio driver to - reuse URBs without waiting for them to complete. In the absence of - proper checking by usbcore, the URBs get added to their endpoint list - twice. This leads to list corruption and a system freeze. - - The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for - isochronous URBs. Improving robustness always helps. - - Signed-off-by: Alan Stern - Reported-by: Artem S. Tashkinov - Reported-by: Christof Meerwald - CC: - Signed-off-by: Greg Kroah-Hartman - -diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c -index 4b66374..3d98902 100644 ---- a/drivers/usb/host/ehci-q.c -+++ b/drivers/usb/host/ehci-q.c -@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) - __releases(ehci->lock) - __acquires(ehci->lock) - { -- if (likely (urb->hcpriv != NULL)) { -- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; -- -- /* S-mask in a QH means it's an interrupt urb */ -- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { -- -- /* ... update hc-wide periodic stats (for usbfs) */ -- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; -- } -+ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { -+ /* ... update hc-wide periodic stats */ -+ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; - } - - if (unlikely(urb->unlinked)) { -diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c -index 2e14714..69ebee7 100644 ---- a/drivers/usb/host/ehci-sched.c -+++ b/drivers/usb/host/ehci-sched.c -@@ -1630,7 +1630,7 @@ static void itd_link_urb( - - /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); -- urb->hcpriv = NULL; -+ urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -@@ -2029,7 +2029,7 @@ static void sitd_link_urb( - - /* don't need that schedule data any more */ - iso_sched_free (stream, sched); -- urb->hcpriv = NULL; -+ urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); diff --git a/i82975x-edac-fix.patch b/i82975x-edac-fix.patch deleted file mode 100644 index f44ac7791..000000000 --- a/i82975x-edac-fix.patch +++ /dev/null @@ -1,855 +0,0 @@ -commit 9370a8d717720f6b17221490fea8d798396d9f2f -Author: Mauro Carvalho Chehab -Date: Mon Oct 15 21:49:35 2012 -0300 - - i82975x_edac: Use the edac standard debug macro - - Instead of declaring its own debug macro, that requires - to uncomment part of the code, use the edac standard macro - to add the debug code, and the edac debug level to print it, - just like any other EDAC driver. - - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index a980204..f998d2c 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -435,11 +435,9 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, - } - } - --/* #define i82975x_DEBUG_IOMEM */ -- --#ifdef i82975x_DEBUG_IOMEM --static void i82975x_print_dram_timings(void __iomem *mch_window) -+static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) - { -+#ifdef CONFIG_EDAC_DEBUG - /* - * The register meanings are from Intel specs; - * (shows 13-5-5-5 for 800-DDR2) -@@ -448,26 +446,63 @@ static void i82975x_print_dram_timings(void __iomem *mch_window) - */ - static const int caslats[4] = { 5, 4, 3, 6 }; - u32 dtreg[2]; -+ u8 c0drb[4]; -+ u8 c1drb[4]; -+ -+ if (!edac_debug_level) -+ return; -+ -+ i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -+ mchbar, mch_window); -+ -+ c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -+ c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -+ c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -+ c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -+ c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -+ c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -+ c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -+ c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -+ i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -+ i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -+ i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -+ i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -+ i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -+ i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -+ i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -+ i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); -+ -+ i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -+ ((drc[0] >> 21) & 3) == 1 ? -+ "ECC enabled" : "ECC disabled"); -+ i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -+ ((drc[1] >> 21) & 3) == 1 ? -+ "ECC enabled" : "ECC disabled"); -+ -+ i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -+ readw(mch_window + I82975X_C0BNKARC)); -+ i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -+ readw(mch_window + I82975X_C1BNKARC)); - - dtreg[0] = readl(mch_window + 0x114); - dtreg[1] = readl(mch_window + 0x194); -- i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n" -+ i82975x_printk(KERN_INFO, -+ "DRAM Timings : Ch0 Ch1\n" - " RAS Active Min = %d %d\n" - " CAS latency = %d %d\n" - " RAS to CAS = %d %d\n" - " RAS precharge = %d %d\n", - (dtreg[0] >> 19 ) & 0x0f, -- (dtreg[1] >> 19) & 0x0f, -+ (dtreg[1] >> 19) & 0x0f, - caslats[(dtreg[0] >> 8) & 0x03], -- caslats[(dtreg[1] >> 8) & 0x03], -+ caslats[(dtreg[1] >> 8) & 0x03], - ((dtreg[0] >> 4) & 0x07) + 2, -- ((dtreg[1] >> 4) & 0x07) + 2, -+ ((dtreg[1] >> 4) & 0x07) + 2, - (dtreg[0] & 0x07) + 2, -- (dtreg[1] & 0x07) + 2 -+ (dtreg[1] & 0x07) + 2 - ); -- --} - #endif -+} - - static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - { -@@ -480,10 +515,6 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - u32 drc[2]; - struct i82975x_error_info discard; - int chans; --#ifdef i82975x_DEBUG_IOMEM -- u8 c0drb[4]; -- u8 c1drb[4]; --#endif - - edac_dbg(0, "\n"); - -@@ -495,45 +526,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ - mch_window = ioremap_nocache(mchbar, 0x1000); - --#ifdef i82975x_DEBUG_IOMEM -- i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -- mchbar, mch_window); -- -- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); --#endif -- - drc[0] = readl(mch_window + I82975X_DRC_CH0M0); - drc[1] = readl(mch_window + I82975X_DRC_CH1M0); --#ifdef i82975x_DEBUG_IOMEM -- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -- ((drc[0] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); -- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -- ((drc[1] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); - -- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -- readw(mch_window + I82975X_C0BNKARC)); -- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -- readw(mch_window + I82975X_C1BNKARC)); -- i82975x_print_dram_timings(mch_window); -- goto fail1; --#endif -+ i82975x_print_dram_config(mch_window, mchbar, drc); -+ - if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { - i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); - goto fail1; - -commit 8992ed2f4295eab137e1713fa16be5546a759373 -Author: Mauro Carvalho Chehab -Date: Mon Oct 15 21:48:48 2012 -0300 - - i82975x_edac: Fix dimm label initialization - - The driver has only 4 hardcoded labels, but allows much more memory. - Fix it by removing the hardcoded logic, using snprintf() instead. - - [ 19.833972] general protection fault: 0000 [#1] SMP - [ 19.837733] Modules linked in: i82975x_edac(+) edac_core firewire_ohci firewire_core crc_itu_t nouveau mxm_wmi wmi video i2c_algo_bit drm_kms_helper ttm drm i2c_core - [ 19.837733] CPU 0 - [ 19.837733] Pid: 390, comm: udevd Not tainted 3.6.1-1.fc17.x86_64.debug #1 Dell Inc. Precision WorkStation 390 /0MY510 - [ 19.837733] RIP: 0010:[] [] strncpy+0x18/0x30 - [ 19.837733] RSP: 0018:ffff880078535b68 EFLAGS: 00010202 - [ 19.837733] RAX: ffff880069fa9708 RBX: ffff880078588000 RCX: ffff880069fa9708 - [ 19.837733] RDX: 000000000000001f RSI: 5f706f5f63616465 RDI: ffff880069fa9708 - [ 19.837733] RBP: ffff880078535b68 R08: ffff880069fa9727 R09: 000000000000fffe - [ 19.837733] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000003 - [ 19.837733] R13: 0000000000000000 R14: ffff880069fa9290 R15: ffff880079624a80 - [ 19.837733] FS: 00007f3de01ee840(0000) GS:ffff88007c400000(0000) knlGS:0000000000000000 - [ 19.837733] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 - [ 19.837733] CR2: 00007f3de00b9000 CR3: 0000000078dbc000 CR4: 00000000000007f0 - [ 19.837733] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 - [ 19.837733] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 - [ 19.837733] Process udevd (pid: 390, threadinfo ffff880078534000, task ffff880079642450) - [ 19.837733] Stack: - [ 19.837733] ffff880078535c18 ffffffffa017c6b8 00040000816d627f ffff880079624a88 - [ 19.837733] ffffc90004cd6000 ffff880079624520 ffff88007ac21148 0000000000000000 - [ 19.837733] 0000000000000000 0004000000000000 feda000078535bc8 ffffffff810d696d - [ 19.837733] Call Trace: - [ 19.837733] [] i82975x_init_one+0x2e6/0x3e6 [i82975x_edac] - ... - - Fix bug reported at: - https://bugzilla.redhat.com/show_bug.cgi?id=848149 - And, very likely: - https://bbs.archlinux.org/viewtopic.php?id=148033 - https://bugzilla.kernel.org/show_bug.cgi?id=47171 - - Cc: Alan Cox - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index 069e26c..a980204 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) - static void i82975x_init_csrows(struct mem_ctl_info *mci, - struct pci_dev *pdev, void __iomem *mch_window) - { -- static const char *labels[4] = { -- "DIMM A1", "DIMM A2", -- "DIMM B1", "DIMM B2" -- }; - struct csrow_info *csrow; - unsigned long last_cumul_size; - u8 value; -@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, - dimm = mci->csrows[index]->channels[chan]->dimm; - - dimm->nr_pages = nr_pages / csrow->nr_channels; -- strncpy(csrow->channels[chan]->dimm->label, -- labels[(index >> 1) + (chan * 2)], -- EDAC_MC_LABEL_LEN); -+ -+ snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", -+ (chan == 0) ? 'A' : 'B', -+ index); - dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ - dimm->dtype = i82975x_dram_type(mch_window, index); - dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ -commit 6e7636c972951ba0c6c640758b1dcc7667cb2415 -Author: Mauro Carvalho Chehab -Date: Tue Oct 16 15:30:23 2012 -0300 - - i82975x_edac: rewrite the entire fill/report logic - - There are so many bugs at the fill/error report logic that - the code ended by being re-written. - - Issues solved: - - - DIMM labels were "randomly" filled: they won't - match the memory layout, due to a series of bugs on it; - - - The memory controller supports 3 different modes: - single, dual interleaved and dual async. The logic there were - written considering the dual interleaved one (yet, some - single mode support was there); - - - The boundary limit to decide on each channel the error happens, - at dual interleaved mode, is given by bit 6 of the error address, - and not bit 1. The practical effect is that Corrected errors - will have a 50% of chance of pointing to the right DIMM. Only - the DIMM pair logic were OK; - - - The asymetric mode weren't properly supported. The driver would - handle an asymetric mode as 'single mode', with doesn't actually - match it, creating some weird real/virtual DIMM mappings. - - - Some other random bugs got fixed. - - Tested on a Dell Precision N390, on dual interleaved mode. - - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index f998d2c..082e91e 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -6,7 +6,17 @@ - * GNU General Public License. - * - * Written by Arvind R. -- * Copied from i82875p_edac.c source: -+ * Copied from i82875p_edac.c source, -+ * -+ * (c) 2012 Mauro Carvalho Chehab -+ * Driver re-written in order to fix lots of issues on it: -+ * - Fix Single Mode; -+ * - Add support for Asymetrical mode -+ * - Fix several issues with Interleaved mode -+ * - Fix memory label logic -+ * -+ * Intel datasheet: Intel(R) 975X Express Chipset Datasheet -+ * http://www.intel.com/assets/pdf/datasheet/310158.pdf - */ - - #include -@@ -29,8 +39,8 @@ - #define PCI_DEVICE_ID_INTEL_82975_0 0x277c - #endif /* PCI_DEVICE_ID_INTEL_82975_0 */ - --#define I82975X_NR_DIMMS 8 --#define I82975X_NR_CSROWS(nr_chans) (I82975X_NR_DIMMS / (nr_chans)) -+#define DIMMS_PER_CHANNEL 4 -+#define NUM_CHANNELS 2 - - /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */ - #define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b) -@@ -112,7 +122,7 @@ NOTE: Only ONE of the three must be enabled - /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */ - /* Intel 82975x memory mapped register space */ - --#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */ -+#define I82975X_DRB_SHIFT 25 /* fixed 2^25 = 32 MiB grain */ - - #define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8) - * -@@ -152,6 +162,10 @@ NOTE: Only ONE of the three must be enabled - #define I82975X_DRA_CH1R01 0x188 - #define I82975X_DRA_CH1R23 0x189 - -+/* Channels 0/1 DRAM Timing Register 1 */ -+#define I82975X_C0DRT1 0x114 -+#define I82975X_C1DRT1 0x194 -+ - - #define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b) - * -@@ -206,8 +220,16 @@ enum i82975x_chips { - I82975X = 0, - }; - -+struct mem_range { -+ u32 start, end; -+}; -+ - struct i82975x_pvt { -- void __iomem *mch_window; -+ void __iomem *mch_window; -+ int num_channels; -+ bool is_symetric; -+ u8 drb[DIMMS_PER_CHANNEL][NUM_CHANNELS]; -+ struct mem_range page[DIMMS_PER_CHANNEL][NUM_CHANNELS]; - }; - - struct i82975x_dev_info { -@@ -278,8 +300,10 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, - static int i82975x_process_error_info(struct mem_ctl_info *mci, - struct i82975x_error_info *info, int handle_errors) - { -- int row, chan; -- unsigned long offst, page; -+ struct i82975x_pvt *pvt = mci->pvt_info; -+ struct mem_range *range; -+ unsigned int row, chan, grain; -+ unsigned long offst, page; - - if (!(info->errsts2 & 0x0003)) - return 0; -@@ -293,36 +317,70 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, - info->errsts = info->errsts2; - } - -+ /* Calculate page and offset of the error */ -+ - page = (unsigned long) info->eap; - page >>= 1; -+ - if (info->xeap & 1) - page |= 0x80000000; - page >>= (PAGE_SHIFT - 1); -- row = edac_mc_find_csrow_by_page(mci, page); -- -- if (row == -1) { -- i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n" -- "\tXEAP=%u\n" -- "\t EAP=0x%08x\n" -- "\tPAGE=0x%08x\n", -- (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); -- return 0; -+ -+ if (pvt->is_symetric) -+ grain = 1 << 7; -+ else -+ grain = 1 << 6; -+ -+ offst = info->eap & ((1 << PAGE_SHIFT) - (1 << grain)); -+ -+ /* -+ * Search for the DIMM chip that match the error page. -+ * -+ * On Symmetric mode, this will always return channel = 0, as -+ * both channel A and B ranges are identical. -+ * A latter logic will determinte the channel on symetric mode -+ * -+ * On asymetric mode or single mode, there will be just one match, -+ * that will point to the csrow with the error. -+ */ -+ for (chan = 0; chan < pvt->num_channels; chan++) { -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ range = &pvt->page[row][chan]; -+ -+ if (page >= range->start && page <= range->end) -+ goto found; -+ } - } -- chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; -- offst = info->eap -- & ((1 << PAGE_SHIFT) - -- (1 << mci->csrows[row]->channels[chan]->dimm->grain)); -+ chan = -1; -+ row = -1; - -- if (info->errsts & 0x0002) -+found: -+ if (info->errsts & 0x0002) { -+ /* -+ * On uncorrected error, ECC doesn't allow do determine the -+ * channel where the error has occurred. -+ */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, - page, offst, 0, - row, -1, -1, - "i82975x UE", ""); -- else -- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, -- page, offst, info->derrsyn, -- row, chan ? chan : 0, -1, -- "i82975x CE", ""); -+ return 1; -+ } -+ -+ if (pvt->is_symetric && row >= 0) { -+ /* -+ * On Symetric mode, the memory switch happens after each -+ * cache line (64 byte boundary). Channel 0 goes first. -+ */ -+ if (info->eap & (1 << 6)) -+ chan = 1; -+ else -+ chan = 0; -+ } -+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, -+ page, offst, info->derrsyn, -+ row, chan, -1, -+ "i82975x CE", ""); - - return 1; - } -@@ -331,111 +389,143 @@ static void i82975x_check(struct mem_ctl_info *mci) - { - struct i82975x_error_info info; - -- edac_dbg(1, "MC%d\n", mci->mc_idx); -+ edac_dbg(4, "MC%d\n", mci->mc_idx); - i82975x_get_error_info(mci, &info); - i82975x_process_error_info(mci, &info, 1); - } - --/* Return 1 if dual channel mode is active. Else return 0. */ --static int dual_channel_active(void __iomem *mch_window) -+/** -+ * detect_memory_style - Detect on what mode the memory controller is programmed -+ * -+ * @pvt: pointer to the private structure -+ * -+ * This function detects how many channels are in use, and if the memory -+ * controller is in symetric (interleaved) or asymetric mode. There's no -+ * need to distinguish between asymetric and single mode, as the routines -+ * that fill the csrows data and handle error are written in order to handle -+ * both at the same way. -+ */ -+static void detect_memory_style(struct i82975x_pvt *pvt) - { -- /* -- * We treat interleaved-symmetric configuration as dual-channel - EAP's -- * bit-0 giving the channel of the error location. -- * -- * All other configurations are treated as single channel - the EAP's -- * bit-0 will resolve ok in symmetric area of mixed -- * (symmetric/asymmetric) configurations -- */ -- u8 drb[4][2]; - int row; -- int dualch; -+ bool has_chan_a = false; -+ bool has_chan_b = false; -+ -+ pvt->is_symetric = true; -+ pvt->num_channels = 0; -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ pvt->drb[row][0] = readb(pvt->mch_window + I82975X_DRB + row); -+ pvt->drb[row][1] = readb(pvt->mch_window + I82975X_DRB + row + 0x80); -+ -+ /* On symetric mode, both channels have the same boundaries */ -+ if (pvt->drb[row][0] != pvt->drb[row][1]) -+ pvt->is_symetric = false; - -- for (dualch = 1, row = 0; dualch && (row < 4); row++) { -- drb[row][0] = readb(mch_window + I82975X_DRB + row); -- drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80); -- dualch = dualch && (drb[row][0] == drb[row][1]); -+ if (pvt->drb[row][0]) -+ has_chan_a = true; -+ if (pvt->drb[row][1]) -+ has_chan_b = true; - } -- return dualch; --} - --static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) --{ -- /* -- * ECC is possible on i92975x ONLY with DEV_X8 -- */ -- return DEV_X8; -+ if (has_chan_a) -+ pvt->num_channels++; -+ -+ if (has_chan_b) -+ pvt->num_channels++; - } - - static void i82975x_init_csrows(struct mem_ctl_info *mci, -- struct pci_dev *pdev, void __iomem *mch_window) -+ struct i82975x_pvt *pvt, -+ struct pci_dev *pdev) - { -- struct csrow_info *csrow; -- unsigned long last_cumul_size; -- u8 value; -- u32 cumul_size, nr_pages; -- int index, chan; -- struct dimm_info *dimm; -- enum dev_type dtype; -- -- last_cumul_size = 0; -+ struct dimm_info *dimm; -+ struct mem_range *range; -+ u8 boundary; -+ u32 initial_page = 0, last_page; -+ int row, chan; - - /* -- * 82875 comment: -- * The dram row boundary (DRB) reg values are boundary address -- * for each DRAM row with a granularity of 32 or 64MB (single/dual -- * channel operation). DRB regs are cumulative; therefore DRB7 will -- * contain the total memory contained in all rows. -- * -+ * This chipset provides 3 address modes: -+ * Single channel - either Channel A or channel B is filled -+ * Dual channel, interleaved: Memory is organized in pairs, -+ * where channel A gets the lower address for each pair -+ * Dual channel, asymmetric: Channel A memory goes first. -+ * In order to cover all modes, we need to start describing -+ * memories considering the dual channel, asymmetric one. - */ - -- for (index = 0; index < mci->nr_csrows; index++) { -- csrow = mci->csrows[index]; -- -- value = readb(mch_window + I82975X_DRB + index + -- ((index >= 4) ? 0x80 : 0)); -- cumul_size = value; -- cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); -- /* -- * Adjust cumul_size w.r.t number of channels -- * -- */ -- if (csrow->nr_channels > 1) -- cumul_size <<= 1; -- edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); -- -- nr_pages = cumul_size - last_cumul_size; -- if (!nr_pages) -- continue; -- -+ for (chan = 0; chan < pvt->num_channels; chan++) { - /* -- * Initialise dram labels -- * index values: -- * [0-7] for single-channel; i.e. csrow->nr_channels = 1 -- * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 -+ * On symetric mode, both channels start from address 0 - */ -- dtype = i82975x_dram_type(mch_window, index); -- for (chan = 0; chan < csrow->nr_channels; chan++) { -- dimm = mci->csrows[index]->channels[chan]->dimm; -- -- dimm->nr_pages = nr_pages / csrow->nr_channels; -- -- snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", -- (chan == 0) ? 'A' : 'B', -- index); -- dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ -- dimm->dtype = i82975x_dram_type(mch_window, index); -+ if (pvt->is_symetric) -+ initial_page = 0; -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ boundary = pvt->drb[row][chan]; -+ dimm = mci->csrows[row]->channels[chan]->dimm; -+ -+ last_page = boundary << (I82975X_DRB_SHIFT - PAGE_SHIFT); -+ dimm->nr_pages = last_page - initial_page; -+ if (!dimm->nr_pages) -+ continue; -+ -+ range = &pvt->page[row][chan]; -+ range->start = initial_page; -+ range->end = range->start + dimm->nr_pages - 1; -+ -+ /* -+ * Grain is one cache-line: -+ * On dual symetric mode, it is 128 Bytes; -+ * On single mode or asymetric, it is 64 bytes. -+ */ -+ if (pvt->is_symetric) { -+ dimm->grain = 1 << 7; -+ -+ /* -+ * In dual interleaved mode, the addresses -+ * need to be multiplied by 2, as both -+ * channels are interlaced, and the boundary -+ * limit there actually match each DIMM size -+ */ -+ range->start <<= 1; -+ range->end <<= 1; -+ } else { -+ dimm->grain = 1 << 6; -+ } -+ -+ snprintf(dimm->label, -+ EDAC_MC_LABEL_LEN, "DIMM %c%d", -+ (chan == 0) ? 'A' : 'B', row); - dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ - dimm->edac_mode = EDAC_SECDED; /* only supported */ -- } - -- csrow->first_page = last_cumul_size; -- csrow->last_page = cumul_size - 1; -- last_cumul_size = cumul_size; -+ /* -+ * This chipset supports both x8 and x16 memories, -+ * but datasheet doesn't describe how to distinguish -+ * between them. -+ * -+ * Also, the "Rank" comment at initial_page 17 says that -+ * ECC is only available with x8 memories. As this -+ * driver doesn't even initialize without ECC, better -+ * to assume that everything is x8. This is not -+ * actually true, on a mixed ECC/non-ECC scenario. -+ */ -+ dimm->dtype = DEV_X8; -+ -+ edac_dbg(1, -+ "%s: from page 0x%08x to 0x%08x (size: 0x%08x pages)\n", -+ dimm->label, -+ range->start, range->end, -+ dimm->nr_pages); -+ initial_page = last_page; -+ } - } - } - --static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) -+static void i82975x_print_dram_config(struct i82975x_pvt *pvt, -+ u32 mchbar, u32 *drc) - { - #ifdef CONFIG_EDAC_DEBUG - /* -@@ -444,63 +534,57 @@ static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 - * Asus P5W Bios reports 15-5-4-4 - * What's your religion? - */ -- static const int caslats[4] = { 5, 4, 3, 6 }; -- u32 dtreg[2]; -- u8 c0drb[4]; -- u8 c1drb[4]; -+ static const int caslats[4] = { 5, 4, 3, 6 }; -+ u32 dtreg[2]; -+ int row; - -+ /* Show memory config if debug level is 1 or upper */ - if (!edac_debug_level) - return; - - i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -- mchbar, mch_window); -- -- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); -- -- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -+ mchbar, pvt->mch_window); -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ if (row) -+ /* Only show if at least one bank is filled */ -+ if ((pvt->drb[row][0] == pvt->drb[row-1][0]) && -+ (pvt->drb[row][1] == pvt->drb[row-1][1])) -+ continue; -+ -+ i82975x_printk(KERN_INFO, -+ "DRAM%i Rank Boundary Address: Channel A: 0x%08x; Channel B: 0x%08x\n", -+ row, -+ pvt->drb[row][0], -+ pvt->drb[row][1]); -+ } -+ -+ i82975x_printk(KERN_INFO, "DRAM Controller mode Channel A: = 0x%08x (%s); Channel B: 0x%08x (%s)\n", -+ drc[0], - ((drc[0] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); -- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -+ "ECC enabled" : "ECC disabled", -+ drc[1], - ((drc[1] >> 21) & 3) == 1 ? - "ECC enabled" : "ECC disabled"); - -- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -- readw(mch_window + I82975X_C0BNKARC)); -- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -- readw(mch_window + I82975X_C1BNKARC)); -- -- dtreg[0] = readl(mch_window + 0x114); -- dtreg[1] = readl(mch_window + 0x194); -- i82975x_printk(KERN_INFO, -- "DRAM Timings : Ch0 Ch1\n" -- " RAS Active Min = %d %d\n" -- " CAS latency = %d %d\n" -- " RAS to CAS = %d %d\n" -- " RAS precharge = %d %d\n", -- (dtreg[0] >> 19 ) & 0x0f, -- (dtreg[1] >> 19) & 0x0f, -- caslats[(dtreg[0] >> 8) & 0x03], -- caslats[(dtreg[1] >> 8) & 0x03], -- ((dtreg[0] >> 4) & 0x07) + 2, -- ((dtreg[1] >> 4) & 0x07) + 2, -+ i82975x_printk(KERN_INFO, "Bank Architecture Channel A: 0x%08x, Channel B: 0x%08x\n", -+ readw(pvt->mch_window + I82975X_C0BNKARC), -+ readw(pvt->mch_window + I82975X_C1BNKARC)); -+ -+ dtreg[0] = readl(pvt->mch_window + I82975X_C0DRT1); -+ dtreg[1] = readl(pvt->mch_window + I82975X_C1DRT1); -+ i82975x_printk(KERN_INFO, "DRAM Timings : ChA ChB\n"); -+ i82975x_printk(KERN_INFO, " RAS Active Min = %2d %2d\n", -+ (dtreg[0] >> 19 ) & 0x0f,(dtreg[1] >> 19) & 0x0f); -+ i82975x_printk(KERN_INFO, " CAS latency = %2d %2d\n", -+ caslats[(dtreg[0] >> 8) & 0x03], -+ caslats[(dtreg[1] >> 8) & 0x03]); -+ i82975x_printk(KERN_INFO, " RAS to CAS = %2d %2d\n", -+ ((dtreg[0] >> 4) & 0x07) + 2, -+ ((dtreg[1] >> 4) & 0x07) + 2); -+ i82975x_printk(KERN_INFO, " RAS precharge = %2d %2d\n", - (dtreg[0] & 0x07) + 2, -- (dtreg[1] & 0x07) + 2 -- ); -+ (dtreg[1] & 0x07) + 2); - #endif - } - -@@ -509,12 +593,10 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - int rc = -ENODEV; - struct mem_ctl_info *mci; - struct edac_mc_layer layers[2]; -- struct i82975x_pvt *pvt; -- void __iomem *mch_window; -+ struct i82975x_pvt tmp_pvt, *pvt; - u32 mchbar; - u32 drc[2]; - struct i82975x_error_info discard; -- int chans; - - edac_dbg(0, "\n"); - -@@ -524,26 +606,35 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - goto fail0; - } - mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ -- mch_window = ioremap_nocache(mchbar, 0x1000); -+ tmp_pvt.mch_window = ioremap_nocache(mchbar, 0x1000); -+ if (!tmp_pvt.mch_window) { -+ i82975x_printk(KERN_ERR, "Couldn't map MCHBAR registers.\n"); -+ rc = -ENOMEM; -+ goto fail0; -+ } - -- drc[0] = readl(mch_window + I82975X_DRC_CH0M0); -- drc[1] = readl(mch_window + I82975X_DRC_CH1M0); -+ drc[0] = readl(tmp_pvt.mch_window + I82975X_DRC_CH0M0); -+ drc[1] = readl(tmp_pvt.mch_window + I82975X_DRC_CH1M0); -+ -+ detect_memory_style(&tmp_pvt); -+ if (!tmp_pvt.num_channels) { -+ edac_dbg(3, "No memories installed? This shouldn't be running!\n"); -+ goto fail0; -+ } - -- i82975x_print_dram_config(mch_window, mchbar, drc); -+ i82975x_print_dram_config(&tmp_pvt, mchbar, drc); - - if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { - i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); - goto fail1; - } - -- chans = dual_channel_active(mch_window) + 1; -- - /* assuming only one controller, index thus is 0 */ - layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; -- layers[0].size = I82975X_NR_DIMMS; -+ layers[0].size = DIMMS_PER_CHANNEL; - layers[0].is_virt_csrow = true; - layers[1].type = EDAC_MC_LAYER_CHANNEL; -- layers[1].size = I82975X_NR_CSROWS(chans); -+ layers[1].size = tmp_pvt.num_channels; - layers[1].is_virt_csrow = false; - mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); - if (!mci) { -@@ -562,10 +653,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - mci->dev_name = pci_name(pdev); - mci->edac_check = i82975x_check; - mci->ctl_page_to_phys = NULL; -+ - edac_dbg(3, "init pvt\n"); - pvt = (struct i82975x_pvt *) mci->pvt_info; -- pvt->mch_window = mch_window; -- i82975x_init_csrows(mci, pdev, mch_window); -+ *pvt = tmp_pvt; -+ -+ i82975x_init_csrows(mci, pvt, pdev); - mci->scrub_mode = SCRUB_HW_SRC; - i82975x_get_error_info(mci, &discard); /* clear counters */ - -@@ -583,7 +676,7 @@ fail2: - edac_mc_free(mci); - - fail1: -- iounmap(mch_window); -+ iounmap(tmp_pvt.mch_window); - fail0: - return rc; - } diff --git a/kernel.spec b/kernel.spec index 0d0e4c238..716c136ba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -735,8 +735,6 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch -Patch19001: i82975x-edac-fix.patch - Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -784,7 +782,6 @@ Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch Patch22100: uprobes-upstream-backport.patch #rhbz 871078 -Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch #rhbz 869341 @@ -1520,8 +1517,6 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch lis3-improve-handling-of-null-rate.patch -ApplyPatch i82975x-edac-fix.patch - ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -1550,7 +1545,6 @@ ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch ApplyPatch uprobes-upstream-backport.patch #rhbz 871078 -ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch #rhbz 869341 @@ -2451,6 +2445,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 17 2012 Josh Boyer +- Linux v3.6.11 + * Mon Dec 17 2012 Dennis Gilmore - disable gpiolib on vexpress diff --git a/sources b/sources index eebf282fc..fdb1a3193 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -406a52f90a2ddc78a3ecdf4fe46e7cf7 patch-3.6.10.xz +bd4bba74093405887d521309a74c19e9 patch-3.6.11.xz From e423a47e766dd2353cdcc0d7bcc47ef2142d12f4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 16:14:55 -0500 Subject: [PATCH 130/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 716c136ba..687b6be74 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2445,7 +2445,7 @@ fi # ||----w | # || || %changelog -* Mon Dec 17 2012 Josh Boyer +* Mon Dec 17 2012 Josh Boyer - 3.6.11-3 - Linux v3.6.11 * Mon Dec 17 2012 Dennis Gilmore From e88e9e6c4c2e866527b472c274b158ab2c248702 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Jan 2013 09:08:37 -0500 Subject: [PATCH 131/492] BR the hostname package (rhbz 886113) --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 687b6be74..a9f7cb358 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -532,7 +532,7 @@ ExclusiveOS: Linux BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config, hmaccalc -BuildRequires: net-tools +BuildRequires: net-tools, hostname BuildRequires: xmlto, asciidoc %if %{with_sparse} BuildRequires: sparse >= 0.4.1 @@ -2445,6 +2445,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 02 2013 Josh Boyer +- BR the hostname package (rhbz 886113) + * Mon Dec 17 2012 Josh Boyer - 3.6.11-3 - Linux v3.6.11 From 8b89f2ce460b7964492297a9119465a81f093020 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Jan 2013 10:30:41 -0500 Subject: [PATCH 132/492] Fix autofs issue in 3.6 (rhbz 874372) --- ...-do-blind-d_drop-in-nfs_prime_dcache.patch | 27 +++++++++++++++++++ kernel.spec | 9 ++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 don-t-do-blind-d_drop-in-nfs_prime_dcache.patch diff --git a/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch b/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch new file mode 100644 index 000000000..d4e837ab1 --- /dev/null +++ b/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch @@ -0,0 +1,27 @@ +From 696199f8ccf7fc6d17ef89c296ad3b6c78c52d9c Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 29 Nov 2012 22:00:51 -0500 +Subject: [PATCH] don't do blind d_drop() in nfs_prime_dcache() + +Signed-off-by: Al Viro +--- + fs/nfs/dir.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index ce8cb92..99489cf 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) + nfs_refresh_inode(dentry->d_inode, entry->fattr); + goto out; + } else { +- d_drop(dentry); ++ if (d_invalidate(dentry) != 0) ++ goto out; + dput(dentry); + } + } +-- +1.8.0.1 + diff --git a/kernel.spec b/kernel.spec index a9f7cb358..57af99470 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -816,6 +816,9 @@ Patch21234: mac80211-fix-ibss-scanning.patch #rhbz 873107 Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 874372 +Patch21238: don-t-do-blind-d_drop-in-nfs_prime_dcache.patch + # END OF PATCH DEFINITIONS %endif @@ -1579,6 +1582,9 @@ ApplyPatch mac80211-fix-ibss-scanning.patch #rhbz 873107 ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 874372 +ApplyPatch don-t-do-blind-d_drop-in-nfs_prime_dcache.patch + # END OF PATCH APPLICATIONS @@ -2446,6 +2452,7 @@ fi # || || %changelog * Wed Jan 02 2013 Josh Boyer +- Fix autofs issue in 3.6 (rhbz 874372) - BR the hostname package (rhbz 886113) * Mon Dec 17 2012 Josh Boyer - 3.6.11-3 From 03fb1ee5742974bcb13c03b06a67ea00767693de Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 3 Jan 2013 15:47:05 -0500 Subject: [PATCH 133/492] Rebase to 3.7.1 --- 0001-ext4-ext4_inode_info-diet.patch | 121 - ...io_unwritten-a-more-appropriate-name.patch | 97 - 0003-ext4-fix-unwritten-counter-leakage.patch | 112 - 0004-ext4-completed_io-locking-cleanup.patch | 520 - ...io-nonlocked-reads-with-defrag-worke.patch | 144 - ...ize-unlocked-dio-reads-with-truncate.patch | 65 - ...runcate-due-to-nonlocked-dio-readers.patch | 41 - ...-truncate-with-owerwrite-DIO-workers.patch | 61 - ...nch_hole-should-wait-for-DIO-writers.patch | 125 - ...ext_remove_space-for-punch_hole-case.patch | 60 - ...t4_flush_completed_IO-wait-semantics.patch | 176 - ...allocate-with-ext4_convert_unwritten.patch | 46 - Bluetooth-Add-support-for-BCM20702A0.patch | 64 - ...as-Fix-oops-when-ata-commond-timeout.patch | 102 - arm-fix_radio_shark.patch | 15 - arm-highbank-sata-fix.patch | 599 - block-fix-a-crash-when-block-device-is.patch | 214 - ...-a-rw-semaphore-into-a-percpu-rw-sem.patch | 290 - config-arm-generic | 47 +- config-arm-imx | 10 + config-arm-kirkwood | 5 + config-arm-omap | 45 +- config-arm-tegra | 1 - config-generic | 120 +- config-powerpc-generic | 8 + config-powerpc64 | 5 +- config-powerpc64p7 | 5 +- config-s390x | 9 + config-sparc64-generic | 14 + config-x86-32-generic | 4 + config-x86-generic | 3 +- config-x86_64-generic | 3 + ...-do-blind-d_drop-in-nfs_prime_dcache.patch | 27 - efivarfs-3.7.patch | 1630 +++ exec-do-not-leave-bprm-interp-on-stack.patch | 12 +- exec-use-eloop-for-max-recursion-depth.patch | 14 +- ...lice_read-and-splice_write-functions.patch | 74 - handle-efi-roms.patch | 96 +- kernel.spec | 2150 +-- linux-2.6-serial-460800.patch | 4 +- lis3-improve-handling-of-null-rate.patch | 2 +- modsign-upstream-3.7.patch | 10997 ---------------- smp_irq_move_cleanup_interrupt.patch | 50 - sources | 4 +- team-net-next-20120808.patch | 499 - team-net-next-20121205.patch | 60 - team-net-next-update-20120927.patch | 335 - uprobes-upstream-backport.patch | 1376 -- vt-Drop-K_OFF-for-VC_MUTE.patch | 8 +- 49 files changed, 1944 insertions(+), 18525 deletions(-) delete mode 100644 0001-ext4-ext4_inode_info-diet.patch delete mode 100644 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch delete mode 100644 0003-ext4-fix-unwritten-counter-leakage.patch delete mode 100644 0004-ext4-completed_io-locking-cleanup.patch delete mode 100644 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch delete mode 100644 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch delete mode 100644 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch delete mode 100644 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch delete mode 100644 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch delete mode 100644 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch delete mode 100644 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch delete mode 100644 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch delete mode 100644 SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch delete mode 100644 arm-fix_radio_shark.patch delete mode 100644 arm-highbank-sata-fix.patch delete mode 100644 block-fix-a-crash-when-block-device-is.patch delete mode 100644 blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch delete mode 100644 don-t-do-blind-d_drop-in-nfs_prime_dcache.patch create mode 100644 efivarfs-3.7.patch delete mode 100644 fs-lock-splice_read-and-splice_write-functions.patch delete mode 100644 modsign-upstream-3.7.patch delete mode 100644 smp_irq_move_cleanup_interrupt.patch delete mode 100644 team-net-next-20120808.patch delete mode 100644 team-net-next-20121205.patch delete mode 100644 team-net-next-update-20120927.patch delete mode 100644 uprobes-upstream-backport.patch diff --git a/0001-ext4-ext4_inode_info-diet.patch b/0001-ext4-ext4_inode_info-diet.patch deleted file mode 100644 index c7858ecc6..000000000 --- a/0001-ext4-ext4_inode_info-diet.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 50b61634cf8d09f9ef334919b859735d381cbe39 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 28 Sep 2012 23:21:09 -0400 -Subject: [PATCH 01/13] ext4: ext4_inode_info diet - -Generic inode has unused i_private pointer which may be used as cur_aio_dio -storage. - -TODO: If cur_aio_dio will be passed as an argument to get_block_t this allow - to have concurent AIO_DIO requests. - -Reviewed-by: Zheng Liu -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit f45ee3a1ea438af96e4fd2c0b16d195e67ef235f) ---- - fs/ext4/ext4.h | 12 ++++++++++-- - fs/ext4/extents.c | 4 ++-- - fs/ext4/inode.c | 6 +++--- - fs/ext4/super.c | 1 - - 4 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index c3411d4..80afc8f 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -912,8 +912,6 @@ struct ext4_inode_info { - struct list_head i_completed_io_list; - spinlock_t i_completed_io_lock; - atomic_t i_ioend_count; /* Number of outstanding io_end structs */ -- /* current io_end structure for async DIO write*/ -- ext4_io_end_t *cur_aio_dio; - atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ - - spinlock_t i_block_reservation_lock; -@@ -1332,6 +1330,16 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, - } - } - -+static inline ext4_io_end_t *ext4_inode_aio(struct inode *inode) -+{ -+ return inode->i_private; -+} -+ -+static inline void ext4_inode_aio_set(struct inode *inode, ext4_io_end_t *io) -+{ -+ inode->i_private = io; -+} -+ - /* - * Inode dynamic state flags - */ -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index aabbb3f..51fbef1 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -3600,7 +3600,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, - { - int ret = 0; - int err = 0; -- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; -+ ext4_io_end_t *io = ext4_inode_aio(inode); - - ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical " - "block %llu, max_blocks %u, flags %x, allocated %u\n", -@@ -3858,7 +3858,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, - unsigned int allocated = 0, offset = 0; - unsigned int allocated_clusters = 0; - struct ext4_allocation_request ar; -- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; -+ ext4_io_end_t *io = ext4_inode_aio(inode); - ext4_lblk_t cluster_offset; - - ext_debug("blocks %u/%u requested for inode %lu\n", -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index dff171c..acadd2b 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3054,7 +3054,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - * hook to the iocb. - */ - iocb->private = NULL; -- EXT4_I(inode)->cur_aio_dio = NULL; -+ ext4_inode_aio_set(inode, NULL); - if (!is_sync_kiocb(iocb)) { - ext4_io_end_t *io_end = - ext4_init_io_end(inode, GFP_NOFS); -@@ -3071,7 +3071,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - * is a unwritten extents needs to be converted - * when IO is completed. - */ -- EXT4_I(inode)->cur_aio_dio = iocb->private; -+ ext4_inode_aio_set(inode, io_end); - } - - if (overwrite) -@@ -3091,7 +3091,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - NULL, - DIO_LOCKING); - if (iocb->private) -- EXT4_I(inode)->cur_aio_dio = NULL; -+ ext4_inode_aio_set(inode, NULL); - /* - * The io_end structure takes a reference to the inode, - * that structure needs to be destroyed and the -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index c6e0cb3..270e58f 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -956,7 +956,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) - ei->jinode = NULL; - INIT_LIST_HEAD(&ei->i_completed_io_list); - spin_lock_init(&ei->i_completed_io_lock); -- ei->cur_aio_dio = NULL; - ei->i_sync_tid = 0; - ei->i_datasync_tid = 0; - atomic_set(&ei->i_ioend_count, 0); --- -1.7.12.rc0.22.gcdd159b - diff --git a/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch b/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch deleted file mode 100644 index cfd13f386..000000000 --- a/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 027d1aa67e32c2c80851105c6d962f3db46eb476 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 28 Sep 2012 23:24:52 -0400 -Subject: [PATCH 02/13] ext4: give i_aiodio_unwritten a more appropriate name - -AIO/DIO prefix is wrong because it account unwritten extents which -also may be scheduled from buffered write endio - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit e27f41e1b789e60e7d8cc9c81fd93ca49ef31f13) ---- - fs/ext4/ext4.h | 4 ++-- - fs/ext4/file.c | 6 +++--- - fs/ext4/page-io.c | 2 +- - fs/ext4/super.c | 2 +- - 4 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 80afc8f..28dfd9b 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -912,7 +912,7 @@ struct ext4_inode_info { - struct list_head i_completed_io_list; - spinlock_t i_completed_io_lock; - atomic_t i_ioend_count; /* Number of outstanding io_end structs */ -- atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ -+ atomic_t i_unwritten; /* Nr. of inflight conversions pending */ - - spinlock_t i_block_reservation_lock; - -@@ -1326,7 +1326,7 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, - { - if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { - io_end->flag |= EXT4_IO_END_UNWRITTEN; -- atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); -+ atomic_inc(&EXT4_I(inode)->i_unwritten); - } - } - -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 3b0e3bd..39335bd 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -55,11 +55,11 @@ static int ext4_release_file(struct inode *inode, struct file *filp) - return 0; - } - --static void ext4_aiodio_wait(struct inode *inode) -+static void ext4_unwritten_wait(struct inode *inode) - { - wait_queue_head_t *wq = ext4_ioend_wq(inode); - -- wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); -+ wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_unwritten) == 0)); - } - - /* -@@ -116,7 +116,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, - "performance will be poor.", - inode->i_ino, current->comm); - mutex_lock(ext4_aio_mutex(inode)); -- ext4_aiodio_wait(inode); -+ ext4_unwritten_wait(inode); - } - - BUG_ON(iocb->ki_pos != pos); -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index dcdeef1..de77e31 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -113,7 +113,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - if (io->flag & EXT4_IO_END_DIRECT) - inode_dio_done(inode); - /* Wake up anyone waiting on unwritten extent conversion */ -- if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) -+ if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) - wake_up_all(ext4_ioend_wq(io->inode)); - return ret; - } -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 270e58f..1b6b425 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -959,7 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) - ei->i_sync_tid = 0; - ei->i_datasync_tid = 0; - atomic_set(&ei->i_ioend_count, 0); -- atomic_set(&ei->i_aiodio_unwritten, 0); -+ atomic_set(&ei->i_unwritten, 0); - - return &ei->vfs_inode; - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/0003-ext4-fix-unwritten-counter-leakage.patch b/0003-ext4-fix-unwritten-counter-leakage.patch deleted file mode 100644 index 2f1d0d813..000000000 --- a/0003-ext4-fix-unwritten-counter-leakage.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 6a0e905bb7320571ed5fdd2d5efa3d642630b4f7 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 28 Sep 2012 23:36:25 -0400 -Subject: [PATCH 03/13] ext4: fix unwritten counter leakage - -ext4_set_io_unwritten_flag() will increment i_unwritten counter, so -once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back -on error path. - - - add missed error checks to prevent counter leakage - - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal - that conversion finished. - - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. - -Visible effect of this bug is that unaligned aio_stress may deadlock - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 82e54229118785badffb4ef5ba4803df25fe007f) ---- - fs/ext4/extents.c | 21 ++++++++++++++------- - fs/ext4/page-io.c | 6 +++++- - 2 files changed, 19 insertions(+), 8 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 51fbef1..e04eb4f 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -3615,6 +3615,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, - if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { - ret = ext4_split_unwritten_extents(handle, inode, map, - path, flags); -+ if (ret <= 0) -+ goto out; - /* - * Flag the inode(non aio case) or end_io struct (aio case) - * that this IO needs to conversion to written when IO is -@@ -3860,6 +3862,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, - struct ext4_allocation_request ar; - ext4_io_end_t *io = ext4_inode_aio(inode); - ext4_lblk_t cluster_offset; -+ int set_unwritten = 0; - - ext_debug("blocks %u/%u requested for inode %lu\n", - map->m_lblk, map->m_len, inode->i_ino); -@@ -4082,13 +4085,8 @@ got_allocated_blocks: - * For non asycn direct IO case, flag the inode state - * that we need to perform conversion when IO is done. - */ -- if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { -- if (io) -- ext4_set_io_unwritten_flag(inode, io); -- else -- ext4_set_inode_state(inode, -- EXT4_STATE_DIO_UNWRITTEN); -- } -+ if ((flags & EXT4_GET_BLOCKS_PRE_IO)) -+ set_unwritten = 1; - if (ext4_should_dioread_nolock(inode)) - map->m_flags |= EXT4_MAP_UNINIT; - } -@@ -4100,6 +4098,15 @@ got_allocated_blocks: - if (!err) - err = ext4_ext_insert_extent(handle, inode, path, - &newex, flags); -+ -+ if (!err && set_unwritten) { -+ if (io) -+ ext4_set_io_unwritten_flag(inode, io); -+ else -+ ext4_set_inode_state(inode, -+ EXT4_STATE_DIO_UNWRITTEN); -+ } -+ - if (err && free_on_err) { - int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? - EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0; -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index de77e31..9970022 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io) - int i; - - BUG_ON(!io); -+ BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); -+ - if (io->page) - put_page(io->page); - for (i = 0; i < io->num_io_pages; i++) -@@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - ssize_t size = io->size; - int ret = 0; - -+ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -+ - ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," - "list->prev 0x%p\n", - io, inode->i_ino, io->list.next, io->list.prev); -@@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - "(inode %lu, offset %llu, size %zd, error %d)", - inode->i_ino, offset, size, ret); - } -- -+ io->flag &= ~EXT4_IO_END_UNWRITTEN; - if (io->iocb) - aio_complete(io->iocb, io->result, 0); - --- -1.7.12.rc0.22.gcdd159b - diff --git a/0004-ext4-completed_io-locking-cleanup.patch b/0004-ext4-completed_io-locking-cleanup.patch deleted file mode 100644 index a358a7952..000000000 --- a/0004-ext4-completed_io-locking-cleanup.patch +++ /dev/null @@ -1,520 +0,0 @@ -From e23394806df0768ed2dac87484590d2f3a730d55 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sat, 29 Sep 2012 00:14:55 -0400 -Subject: [PATCH 04/13] ext4: completed_io locking cleanup - -Current unwritten extent conversion state-machine is very fuzzy. -- For unknown reason it performs conversion under i_mutex. What for? - My diagnosis: - We already protect extent tree with i_data_sem, truncate and punch_hole - should wait for DIO, so the only data we have to protect is end_io->flags - modification, but only flush_completed_IO and end_io_work modified this - flags and we can serialize them via i_completed_io_lock. - - Currently all these games with mutex_trylock result in the following deadlock - truncate: kworker: - ext4_setattr ext4_end_io_work - mutex_lock(i_mutex) - inode_dio_wait(inode) ->BLOCK - DEADLOCK<- mutex_trylock() - inode_dio_done() - #TEST_CASE1_BEGIN - MNT=/mnt_scrach - unlink $MNT/file - fallocate -l $((1024*1024*1024)) $MNT/file - aio-stress -I 100000 -O -s 100m -n -t 1 -c 10 -o 2 -o 3 $MNT/file - sleep 2 - truncate -s 0 $MNT/file - #TEST_CASE1_END - -Or use 286's xfstests https://github.com/dmonakhov/xfstests/blob/devel/286 - -This patch makes state machine simple and clean: - -(1) xxx_end_io schedule final extent conversion simply by calling - ext4_add_complete_io(), which append it to ei->i_completed_io_list - NOTE1: because of (2A) work should be queued only if - ->i_completed_io_list was empty, otherwise the work is scheduled already. - -(2) ext4_flush_completed_IO is responsible for handling all pending - end_io from ei->i_completed_io_list - Flushing sequence consists of following stages: - A) LOCKED: Atomically drain completed_io_list to local_list - B) Perform extents conversion - C) LOCKED: move converted io's to to_free list for final deletion - This logic depends on context which we was called from. - D) Final end_io context destruction - NOTE1: i_mutex is no longer required because end_io->flags modification - is protected by ei->ext4_complete_io_lock - -Full list of changes: -- Move all completion end_io related routines to page-io.c in order to improve - logic locality -- Move open coded logic from various xx_end_xx routines to ext4_add_complete_io() -- remove EXT4_IO_END_FSYNC -- Improve SMP scalability by removing useless i_mutex which does not - protect io->flags anymore. -- Reduce lock contention on i_completed_io_lock by optimizing list walk. -- Rename ext4_end_io_nolock to end4_end_io and make it static -- Check flush completion status to ext4_ext_punch_hole(). Because it is - not good idea to punch blocks from corrupted inode. - -Changes since V3 (in request to Jan's comments): - Fall back to active flush_completed_IO() approach in order to prevent - performance issues with nolocked DIO reads. -Changes since V2: - Fix use-after-free caused by race truncate vs end_io_work - -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 28a535f9a0df060569dcc786e5bc2e1de43d7dc7) ---- - fs/ext4/ext4.h | 3 +- - fs/ext4/extents.c | 4 +- - fs/ext4/fsync.c | 81 ------------------------- - fs/ext4/indirect.c | 6 +- - fs/ext4/inode.c | 25 +------- - fs/ext4/page-io.c | 171 +++++++++++++++++++++++++++++++++++------------------ - 6 files changed, 121 insertions(+), 169 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 28dfd9b..7687d15 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -186,7 +186,6 @@ struct mpage_da_data { - #define EXT4_IO_END_ERROR 0x0002 - #define EXT4_IO_END_QUEUED 0x0004 - #define EXT4_IO_END_DIRECT 0x0008 --#define EXT4_IO_END_IN_FSYNC 0x0010 - - struct ext4_io_page { - struct page *p_page; -@@ -2408,11 +2407,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, - - /* page-io.c */ - extern int __init ext4_init_pageio(void); -+extern void ext4_add_complete_io(ext4_io_end_t *io_end); - extern void ext4_exit_pageio(void); - extern void ext4_ioend_wait(struct inode *); - extern void ext4_free_io_end(ext4_io_end_t *io); - extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); --extern int ext4_end_io_nolock(ext4_io_end_t *io); - extern void ext4_io_submit(struct ext4_io_submit *io); - extern int ext4_bio_write_page(struct ext4_io_submit *io, - struct page *page, -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index e04eb4f..1fbf2ff 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4815,7 +4815,9 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - } - - /* finish any pending end_io work */ -- ext4_flush_completed_IO(inode); -+ err = ext4_flush_completed_IO(inode); -+ if (err) -+ return err; - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c -index 2a1dcea..520b058 100644 ---- a/fs/ext4/fsync.c -+++ b/fs/ext4/fsync.c -@@ -34,87 +34,6 @@ - - #include - --static void dump_completed_IO(struct inode * inode) --{ --#ifdef EXT4FS_DEBUG -- struct list_head *cur, *before, *after; -- ext4_io_end_t *io, *io0, *io1; -- unsigned long flags; -- -- if (list_empty(&EXT4_I(inode)->i_completed_io_list)){ -- ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino); -- return; -- } -- -- ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino); -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){ -- cur = &io->list; -- before = cur->prev; -- io0 = container_of(before, ext4_io_end_t, list); -- after = cur->next; -- io1 = container_of(after, ext4_io_end_t, list); -- -- ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", -- io, inode->i_ino, io0, io1); -- } -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); --#endif --} -- --/* -- * This function is called from ext4_sync_file(). -- * -- * When IO is completed, the work to convert unwritten extents to -- * written is queued on workqueue but may not get immediately -- * scheduled. When fsync is called, we need to ensure the -- * conversion is complete before fsync returns. -- * The inode keeps track of a list of pending/completed IO that -- * might needs to do the conversion. This function walks through -- * the list and convert the related unwritten extents for completed IO -- * to written. -- * The function return the number of pending IOs on success. -- */ --int ext4_flush_completed_IO(struct inode *inode) --{ -- ext4_io_end_t *io; -- struct ext4_inode_info *ei = EXT4_I(inode); -- unsigned long flags; -- int ret = 0; -- int ret2 = 0; -- -- dump_completed_IO(inode); -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- while (!list_empty(&ei->i_completed_io_list)){ -- io = list_entry(ei->i_completed_io_list.next, -- ext4_io_end_t, list); -- list_del_init(&io->list); -- io->flag |= EXT4_IO_END_IN_FSYNC; -- /* -- * Calling ext4_end_io_nolock() to convert completed -- * IO to written. -- * -- * When ext4_sync_file() is called, run_queue() may already -- * about to flush the work corresponding to this io structure. -- * It will be upset if it founds the io structure related -- * to the work-to-be schedule is freed. -- * -- * Thus we need to keep the io structure still valid here after -- * conversion finished. The io structure has a flag to -- * avoid double converting from both fsync and background work -- * queue work. -- */ -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- ret = ext4_end_io_nolock(io); -- if (ret < 0) -- ret2 = ret; -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- io->flag &= ~EXT4_IO_END_IN_FSYNC; -- } -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- return (ret2 < 0) ? ret2 : 0; --} -- - /* - * If we're not journaling and this is a just-created file, we have to - * sync our parent directory (if it was freshly created) since -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 830e1b2..61f13e5 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -807,11 +807,9 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - - retry: - if (rw == READ && ext4_should_dioread_nolock(inode)) { -- if (unlikely(!list_empty(&ei->i_completed_io_list))) { -- mutex_lock(&inode->i_mutex); -+ if (unlikely(!list_empty(&ei->i_completed_io_list))) - ext4_flush_completed_IO(inode); -- mutex_unlock(&inode->i_mutex); -- } -+ - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index acadd2b..dd3fd23 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -2879,9 +2879,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, - { - struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; - ext4_io_end_t *io_end = iocb->private; -- struct workqueue_struct *wq; -- unsigned long flags; -- struct ext4_inode_info *ei; - - /* if not async direct IO or dio with 0 bytes write, just return */ - if (!io_end || !size) -@@ -2910,24 +2907,14 @@ out: - io_end->iocb = iocb; - io_end->result = ret; - } -- wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; -- -- /* Add the io_end to per-inode completed aio dio list*/ -- ei = EXT4_I(io_end->inode); -- spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &ei->i_completed_io_list); -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); - -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - } - - static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) - { - ext4_io_end_t *io_end = bh->b_private; -- struct workqueue_struct *wq; - struct inode *inode; -- unsigned long flags; - - if (!test_clear_buffer_uninit(bh) || !io_end) - goto out; -@@ -2946,15 +2933,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) - */ - inode = io_end->inode; - ext4_set_io_unwritten_flag(inode, io_end); -- -- /* Add the io_end to per-inode completed io list*/ -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); -- -- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - out: - bh->b_private = NULL; - bh->b_end_io = NULL; -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 9970022..5b24c40 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -71,6 +71,7 @@ void ext4_free_io_end(ext4_io_end_t *io) - int i; - - BUG_ON(!io); -+ BUG_ON(!list_empty(&io->list)); - BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); - - if (io->page) -@@ -83,21 +84,14 @@ void ext4_free_io_end(ext4_io_end_t *io) - kmem_cache_free(io_end_cachep, io); - } - --/* -- * check a range of space and convert unwritten extents to written. -- * -- * Called with inode->i_mutex; we depend on this when we manipulate -- * io->flag, since we could otherwise race with ext4_flush_completed_IO() -- */ --int ext4_end_io_nolock(ext4_io_end_t *io) -+/* check a range of space and convert unwritten extents to written. */ -+static int ext4_end_io(ext4_io_end_t *io) - { - struct inode *inode = io->inode; - loff_t offset = io->offset; - ssize_t size = io->size; - int ret = 0; - -- BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -- - ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," - "list->prev 0x%p\n", - io, inode->i_ino, io->list.next, io->list.prev); -@@ -110,7 +104,6 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - "(inode %lu, offset %llu, size %zd, error %d)", - inode->i_ino, offset, size, ret); - } -- io->flag &= ~EXT4_IO_END_UNWRITTEN; - if (io->iocb) - aio_complete(io->iocb, io->result, 0); - -@@ -122,51 +115,122 @@ int ext4_end_io_nolock(ext4_io_end_t *io) - return ret; - } - --/* -- * work on completed aio dio IO, to convert unwritten extents to extents -- */ --static void ext4_end_io_work(struct work_struct *work) -+static void dump_completed_IO(struct inode *inode) -+{ -+#ifdef EXT4FS_DEBUG -+ struct list_head *cur, *before, *after; -+ ext4_io_end_t *io, *io0, *io1; -+ unsigned long flags; -+ -+ if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { -+ ext4_debug("inode %lu completed_io list is empty\n", -+ inode->i_ino); -+ return; -+ } -+ -+ ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); -+ list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { -+ cur = &io->list; -+ before = cur->prev; -+ io0 = container_of(before, ext4_io_end_t, list); -+ after = cur->next; -+ io1 = container_of(after, ext4_io_end_t, list); -+ -+ ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", -+ io, inode->i_ino, io0, io1); -+ } -+#endif -+} -+ -+/* Add the io_end to per-inode completed end_io list. */ -+void ext4_add_complete_io(ext4_io_end_t *io_end) - { -- ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); -- struct inode *inode = io->inode; -- struct ext4_inode_info *ei = EXT4_I(inode); -- unsigned long flags; -+ struct ext4_inode_info *ei = EXT4_I(io_end->inode); -+ struct workqueue_struct *wq; -+ unsigned long flags; -+ -+ BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); -+ wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; - - spin_lock_irqsave(&ei->i_completed_io_lock, flags); -- if (io->flag & EXT4_IO_END_IN_FSYNC) -- goto requeue; -- if (list_empty(&io->list)) { -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- goto free; -+ if (list_empty(&ei->i_completed_io_list)) { -+ io_end->flag |= EXT4_IO_END_QUEUED; -+ queue_work(wq, &io_end->work); - } -+ list_add_tail(&io_end->list, &ei->i_completed_io_list); -+ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -+} - -- if (!mutex_trylock(&inode->i_mutex)) { -- bool was_queued; --requeue: -- was_queued = !!(io->flag & EXT4_IO_END_QUEUED); -- io->flag |= EXT4_IO_END_QUEUED; -- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- /* -- * Requeue the work instead of waiting so that the work -- * items queued after this can be processed. -- */ -- queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); -- /* -- * To prevent the ext4-dio-unwritten thread from keeping -- * requeueing end_io requests and occupying cpu for too long, -- * yield the cpu if it sees an end_io request that has already -- * been requeued. -- */ -- if (was_queued) -- yield(); -- return; -+static int ext4_do_flush_completed_IO(struct inode *inode, -+ ext4_io_end_t *work_io) -+{ -+ ext4_io_end_t *io; -+ struct list_head unwritten, complete, to_free; -+ unsigned long flags; -+ struct ext4_inode_info *ei = EXT4_I(inode); -+ int err, ret = 0; -+ -+ INIT_LIST_HEAD(&complete); -+ INIT_LIST_HEAD(&to_free); -+ -+ spin_lock_irqsave(&ei->i_completed_io_lock, flags); -+ dump_completed_IO(inode); -+ list_replace_init(&ei->i_completed_io_list, &unwritten); -+ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -+ -+ while (!list_empty(&unwritten)) { -+ io = list_entry(unwritten.next, ext4_io_end_t, list); -+ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); -+ list_del_init(&io->list); -+ -+ err = ext4_end_io(io); -+ if (unlikely(!ret && err)) -+ ret = err; -+ -+ list_add_tail(&io->list, &complete); -+ } -+ /* It is important to update all flags for all end_io in one shot w/o -+ * dropping the lock.*/ -+ spin_lock_irqsave(&ei->i_completed_io_lock, flags); -+ while (!list_empty(&complete)) { -+ io = list_entry(complete.next, ext4_io_end_t, list); -+ io->flag &= ~EXT4_IO_END_UNWRITTEN; -+ /* end_io context can not be destroyed now because it still -+ * used by queued worker. Worker thread will destroy it later */ -+ if (io->flag & EXT4_IO_END_QUEUED) -+ list_del_init(&io->list); -+ else -+ list_move(&io->list, &to_free); -+ } -+ /* If we are called from worker context, it is time to clear queued -+ * flag, and destroy it's end_io if it was converted already */ -+ if (work_io) { -+ work_io->flag &= ~EXT4_IO_END_QUEUED; -+ if (!(work_io->flag & EXT4_IO_END_UNWRITTEN)) -+ list_add_tail(&work_io->list, &to_free); - } -- list_del_init(&io->list); - spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); -- (void) ext4_end_io_nolock(io); -- mutex_unlock(&inode->i_mutex); --free: -- ext4_free_io_end(io); -+ -+ while (!list_empty(&to_free)) { -+ io = list_entry(to_free.next, ext4_io_end_t, list); -+ list_del_init(&io->list); -+ ext4_free_io_end(io); -+ } -+ return ret; -+} -+ -+/* -+ * work on completed aio dio IO, to convert unwritten extents to extents -+ */ -+static void ext4_end_io_work(struct work_struct *work) -+{ -+ ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); -+ ext4_do_flush_completed_IO(io->inode, io); -+} -+ -+int ext4_flush_completed_IO(struct inode *inode) -+{ -+ return ext4_do_flush_completed_IO(inode, NULL); - } - - ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) -@@ -199,9 +263,7 @@ static void buffer_io_error(struct buffer_head *bh) - static void ext4_end_bio(struct bio *bio, int error) - { - ext4_io_end_t *io_end = bio->bi_private; -- struct workqueue_struct *wq; - struct inode *inode; -- unsigned long flags; - int i; - sector_t bi_sector = bio->bi_sector; - -@@ -259,14 +321,7 @@ static void ext4_end_bio(struct bio *bio, int error) - return; - } - -- /* Add the io_end to per-inode completed io list*/ -- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); -- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); -- -- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; -- /* queue the work to convert unwritten extents to written */ -- queue_work(wq, &io_end->work); -+ ext4_add_complete_io(io_end); - } - - void ext4_io_submit(struct ext4_io_submit *io) --- -1.7.12.rc0.22.gcdd159b - diff --git a/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch b/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch deleted file mode 100644 index cf53b8dab..000000000 --- a/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 994f567b2e99c82913a279ff438269c771b68a4b Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sat, 29 Sep 2012 00:41:21 -0400 -Subject: [PATCH 05/13] ext4: serialize dio nonlocked reads with defrag - workers - -Inode's block defrag and ext4_change_inode_journal_flag() may -affect nonlocked DIO reads result, so proper synchronization -required. - -- Add missed inode_dio_wait() calls where appropriate -- Check inode state under extra i_dio_count reference. - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 17335dcc471199717839b2fa3492ca36f70f1168) - -Conflicts: - fs/ext4/move_extent.c ---- - fs/ext4/ext4.h | 17 +++++++++++++++++ - fs/ext4/indirect.c | 14 ++++++++++++++ - fs/ext4/inode.c | 5 +++++ - fs/ext4/move_extent.c | 8 ++++++++ - 4 files changed, 44 insertions(+) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 7687d15..3e740e9 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -1352,6 +1352,8 @@ enum { - EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ - EXT4_STATE_NEWENTRY, /* File just added to dir */ - EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ -+ EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read -+ nolocking */ - }; - - #define EXT4_INODE_BIT_FNS(name, field, offset) \ -@@ -2459,6 +2461,21 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) - set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); - } - -+/* -+ * Disable DIO read nolock optimization, so new dioreaders will be forced -+ * to grab i_mutex -+ */ -+static inline void ext4_inode_block_unlocked_dio(struct inode *inode) -+{ -+ ext4_set_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); -+ smp_mb(); -+} -+static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) -+{ -+ smp_mb(); -+ ext4_clear_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); -+} -+ - #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) - - /* For ioend & aio unwritten conversion wait queues */ -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 61f13e5..8d849da 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -810,11 +810,25 @@ retry: - if (unlikely(!list_empty(&ei->i_completed_io_list))) - ext4_flush_completed_IO(inode); - -+ /* -+ * Nolock dioread optimization may be dynamically disabled -+ * via ext4_inode_block_unlocked_dio(). Check inode's state -+ * while holding extra i_dio_count ref. -+ */ -+ atomic_inc(&inode->i_dio_count); -+ smp_mb(); -+ if (unlikely(ext4_test_inode_state(inode, -+ EXT4_STATE_DIOREAD_LOCK))) { -+ inode_dio_done(inode); -+ goto locked; -+ } - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, - ext4_get_block, NULL, NULL, 0); -+ inode_dio_done(inode); - } else { -+locked: - ret = blockdev_direct_IO(rw, iocb, inode, iov, - offset, nr_segs, ext4_get_block); - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index dd3fd23..2bd7526 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4706,6 +4706,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) - return err; - } - -+ /* Wait for all existing dio workers */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); -+ - jbd2_journal_lock_updates(journal); - - /* -@@ -4725,6 +4729,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) - ext4_set_aops(inode); - - jbd2_journal_unlock_updates(journal); -+ ext4_inode_resume_unlocked_dio(inode); - - /* Finally we can mark the inode as dirty. */ - -diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c -index c5826c6..fd1e32e 100644 ---- a/fs/ext4/move_extent.c -+++ b/fs/ext4/move_extent.c -@@ -1214,6 +1214,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, - /* Protect orig and donor inodes against a truncate */ - mext_inode_double_lock(orig_inode, donor_inode); - -+ /* Wait for all existing dio workers */ -+ ext4_inode_block_unlocked_dio(orig_inode); -+ ext4_inode_block_unlocked_dio(donor_inode); -+ inode_dio_wait(orig_inode); -+ inode_dio_wait(donor_inode); -+ - /* Protect extent tree against block allocations via delalloc */ - double_down_write_data_sem(orig_inode, donor_inode); - /* Check the filesystem environment whether move_extent can be done */ -@@ -1413,6 +1419,8 @@ out: - kfree(holecheck_path); - } - double_up_write_data_sem(orig_inode, donor_inode); -+ ext4_inode_resume_unlocked_dio(orig_inode); -+ ext4_inode_resume_unlocked_dio(donor_inode); - mext_inode_double_unlock(orig_inode, donor_inode); - - return ret; --- -1.7.12.rc0.22.gcdd159b - diff --git a/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch b/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch deleted file mode 100644 index bddcc6024..000000000 --- a/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4c4679fc02744ec3955e88faf5e8b6844fa8cbd3 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sat, 29 Sep 2012 00:55:23 -0400 -Subject: [PATCH 06/13] ext4: serialize unlocked dio reads with truncate - -Current serialization will works only for DIO which holds -i_mutex, but nonlocked DIO following race is possible: - -dio_nolock_read_task truncate_task - ->ext4_setattr() - ->inode_dio_wait() -->ext4_ext_direct_IO - ->ext4_ind_direct_IO - ->__blockdev_direct_IO - ->ext4_get_block - ->truncate_setsize() - ->ext4_truncate() - #alloc truncated blocks - #to other inode - ->submit_io() - #INFORMATION LEAK - -In order to serialize with unlocked DIO reads we have to -rearrange wait sequence -1) update i_size first -2) if i_size about to be reduced wait for outstanding DIO requests -3) and only after that truncate inode blocks - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 1c9114f9c0f10f58dd7e568a7152025af47b27e5) ---- - fs/ext4/inode.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 2bd7526..b84322d 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4277,7 +4277,6 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - } - - if (attr->ia_valid & ATTR_SIZE) { -- inode_dio_wait(inode); - - if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); -@@ -4326,8 +4325,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - } - - if (attr->ia_valid & ATTR_SIZE) { -- if (attr->ia_size != i_size_read(inode)) -+ if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); -+ /* Inode size will be reduced, wait for dio in flight */ -+ if (orphan) -+ inode_dio_wait(inode); -+ } - ext4_truncate(inode); - } - --- -1.7.12.rc0.22.gcdd159b - diff --git a/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch b/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch deleted file mode 100644 index 768215f48..000000000 --- a/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ab7b8a329e12369d58e5fa59ba2e2c90370f12ef Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sat, 29 Sep 2012 00:56:15 -0400 -Subject: [PATCH 07/13] ext4: endless truncate due to nonlocked dio readers - -If we have enough aggressive DIO readers, truncate and other dio -waiters will wait forever inside inode_dio_wait(). It is reasonable -to disable nonlock DIO read optimization during truncate. - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 1b65007e9870e0021397b548e8cd6bbc584f9152) ---- - fs/ext4/inode.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index b84322d..3b03dd6 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4327,9 +4327,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) - if (attr->ia_valid & ATTR_SIZE) { - if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); -- /* Inode size will be reduced, wait for dio in flight */ -- if (orphan) -+ /* Inode size will be reduced, wait for dio in flight. -+ * Temporarily disable dioread_nolock to prevent -+ * livelock. */ -+ if (orphan) { -+ ext4_inode_block_unlocked_dio(inode); - inode_dio_wait(inode); -+ ext4_inode_resume_unlocked_dio(inode); -+ } - } - ext4_truncate(inode); - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch b/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch deleted file mode 100644 index c7733ed74..000000000 --- a/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 69e4026a2d104ffcf1b935bc889f8abcbfbb29ec Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sat, 29 Sep 2012 00:58:26 -0400 -Subject: [PATCH 08/13] ext4: serialize truncate with owerwrite DIO workers - -Jan Kara have spotted interesting issue: -There are potential data corruption issue with direct IO overwrites -racing with truncate: - Like: - dio write truncate_task - ->ext4_ext_direct_IO - ->overwrite == 1 - ->down_read(&EXT4_I(inode)->i_data_sem); - ->mutex_unlock(&inode->i_mutex); - ->ext4_setattr() - ->inode_dio_wait() - ->truncate_setsize() - ->ext4_truncate() - ->down_write(&EXT4_I(inode)->i_data_sem); - ->__blockdev_direct_IO - ->ext4_get_block - ->submit_io() - ->up_read(&EXT4_I(inode)->i_data_sem); - # truncate data blocks, allocate them to - # other inode - bad stuff happens because - # dio is still in flight. - -In order to serialize with truncate dio worker should grab extra i_dio_count -reference before drop i_mutex. - -Reviewed-by: Jan Kara -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 1f555cfa29e8f787d675e8390f88ce517a37271a) ---- - fs/ext4/inode.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 3b03dd6..484a327 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -3008,6 +3008,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - overwrite = *((int *)iocb->private); - - if (overwrite) { -+ atomic_inc(&inode->i_dio_count); - down_read(&EXT4_I(inode)->i_data_sem); - mutex_unlock(&inode->i_mutex); - } -@@ -3105,6 +3106,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - retake_lock: - /* take i_mutex locking again if we do a ovewrite dio */ - if (overwrite) { -+ inode_dio_done(inode); - up_read(&EXT4_I(inode)->i_data_sem); - mutex_lock(&inode->i_mutex); - } --- -1.7.12.rc0.22.gcdd159b - diff --git a/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch b/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch deleted file mode 100644 index 4d7636668..000000000 --- a/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 71a6398a4b59ddcf920dfb68872b5a771c606e3a Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sun, 30 Sep 2012 23:03:42 -0400 -Subject: [PATCH 09/13] ext4: punch_hole should wait for DIO writers - -punch_hole is the place where we have to wait for all existing writers -(writeback, aio, dio), but currently we simply flush pended end_io request -which is not sufficient. Other issue is that punch_hole performed w/o i_mutex -held which obviously result in dangerous data corruption due to -write-after-free. - -This patch performs following changes: -- Guard punch_hole with i_mutex -- Recheck inode flags under i_mutex -- Block all new dio readers in order to prevent information leak caused by - read-after-free pattern. -- punch_hole now wait for all writers in flight - NOTE: XXX write-after-free race is still possible because new dirty pages - may appear due to mmap(), and currently there is no easy way to stop - writeback while punch_hole is in progress. - -[ Fixed error return from ext4_ext_punch_hole() to make sure that we - release i_mutex before returning EPERM or ETXTBUSY -- Ted ] - -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 02d262dffcf4c74e5c4612ee736bdb94f18ed5b9) ---- - fs/ext4/extents.c | 53 ++++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 36 insertions(+), 17 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 1fbf2ff..202eb4d 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4776,9 +4776,32 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - loff_t first_page_offset, last_page_offset; - int credits, err = 0; - -+ /* -+ * Write out all dirty pages to avoid race conditions -+ * Then release them. -+ */ -+ if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { -+ err = filemap_write_and_wait_range(mapping, -+ offset, offset + length - 1); -+ -+ if (err) -+ return err; -+ } -+ -+ mutex_lock(&inode->i_mutex); -+ /* It's not possible punch hole on append only file */ -+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { -+ err = -EPERM; -+ goto out_mutex; -+ } -+ if (IS_SWAPFILE(inode)) { -+ err = -ETXTBSY; -+ goto out_mutex; -+ } -+ - /* No need to punch hole beyond i_size */ - if (offset >= inode->i_size) -- return 0; -+ goto out_mutex; - - /* - * If the hole extends beyond i_size, set the hole -@@ -4796,33 +4819,25 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - first_page_offset = first_page << PAGE_CACHE_SHIFT; - last_page_offset = last_page << PAGE_CACHE_SHIFT; - -- /* -- * Write out all dirty pages to avoid race conditions -- * Then release them. -- */ -- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { -- err = filemap_write_and_wait_range(mapping, -- offset, offset + length - 1); -- -- if (err) -- return err; -- } -- - /* Now release the pages */ - if (last_page_offset > first_page_offset) { - truncate_pagecache_range(inode, first_page_offset, - last_page_offset - 1); - } - -- /* finish any pending end_io work */ -+ /* Wait all existing dio workers, newcomers will block on i_mutex */ -+ ext4_inode_block_unlocked_dio(inode); -+ inode_dio_wait(inode); - err = ext4_flush_completed_IO(inode); - if (err) -- return err; -+ goto out_dio; - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -- if (IS_ERR(handle)) -- return PTR_ERR(handle); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out_dio; -+ } - - err = ext4_orphan_add(handle, inode); - if (err) -@@ -4916,6 +4931,10 @@ out: - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); - ext4_journal_stop(handle); -+out_dio: -+ ext4_inode_resume_unlocked_dio(inode); -+out_mutex: -+ mutex_unlock(&inode->i_mutex); - return err; - } - int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, --- -1.7.12.rc0.22.gcdd159b - diff --git a/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch b/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch deleted file mode 100644 index d161bb765..000000000 --- a/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 66d08dd92b82dabfd64853aa4edde1547fdf9ef7 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Sun, 30 Sep 2012 23:03:50 -0400 -Subject: [PATCH 10/13] ext4: fix ext_remove_space for punch_hole case - -Inode is allowed to have empty leaf only if it this is blockless inode. - -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 6f2080e64487b9963f9c6ff8a252e1abce98f2d4) ---- - fs/ext4/extents.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 202eb4d..b1c92c0 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -2572,7 +2572,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, - struct ext4_ext_path *path = NULL; - ext4_fsblk_t partial_cluster = 0; - handle_t *handle; -- int i = 0, err; -+ int i = 0, err = 0; - - ext_debug("truncate since %u to %u\n", start, end); - -@@ -2604,12 +2604,16 @@ again: - return PTR_ERR(path); - } - depth = ext_depth(inode); -+ /* Leaf not may not exist only if inode has no blocks at all */ - ex = path[depth].p_ext; - if (!ex) { -- ext4_ext_drop_refs(path); -- kfree(path); -- path = NULL; -- goto cont; -+ if (depth) { -+ EXT4_ERROR_INODE(inode, -+ "path[%d].p_hdr == NULL", -+ depth); -+ err = -EIO; -+ } -+ goto out; - } - - ee_block = le32_to_cpu(ex->ee_block); -@@ -2641,8 +2645,6 @@ again: - goto out; - } - } --cont: -- - /* - * We start scanning from right side, freeing all the blocks - * after i_size and walking into the tree depth-wise. --- -1.7.12.rc0.22.gcdd159b - diff --git a/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch b/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch deleted file mode 100644 index 517b20129..000000000 --- a/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +++ /dev/null @@ -1,176 +0,0 @@ -From ca6d3910cbf8854f3f3b9846391f669733899101 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 5 Oct 2012 11:31:55 -0400 -Subject: [PATCH 11/13] ext4: fix ext4_flush_completed_IO wait semantics - -BUG #1) All places where we call ext4_flush_completed_IO are broken - because buffered io and DIO/AIO goes through three stages - 1) submitted io, - 2) completed io (in i_completed_io_list) conversion pended - 3) finished io (conversion done) - And by calling ext4_flush_completed_IO we will flush only - requests which were in (2) stage, which is wrong because: - 1) punch_hole and truncate _must_ wait for all outstanding unwritten io - regardless to it's state. - 2) fsync and nolock_dio_read should also wait because there is - a time window between end_page_writeback() and ext4_add_complete_io() - As result integrity fsync is broken in case of buffered write - to fallocated region: - fsync blkdev_completion - ->filemap_write_and_wait_range - ->ext4_end_bio - ->end_page_writeback - <-- filemap_write_and_wait_range return - ->ext4_flush_completed_IO - sees empty i_completed_io_list but pended - conversion still exist - ->ext4_add_complete_io - -BUG #2) Race window becomes wider due to the 'ext4: completed_io -locking cleanup V4' patch series - -This patch make following changes: -1) ext4_flush_completed_io() now first try to flush completed io and when - wait for any outstanding unwritten io via ext4_unwritten_wait() -2) Rename function to more appropriate name. -3) Assert that all callers of ext4_flush_unwritten_io should hold i_mutex to - prevent endless wait - -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Jan Kara -(cherry picked from commit c278531d39f3158bfee93dc67da0b77e09776de2) ---- - fs/ext4/ext4.h | 3 ++- - fs/ext4/extents.c | 6 +++--- - fs/ext4/file.c | 2 +- - fs/ext4/fsync.c | 2 +- - fs/ext4/indirect.c | 8 +++++--- - fs/ext4/page-io.c | 11 +++++++---- - 6 files changed, 19 insertions(+), 13 deletions(-) - -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 3e740e9..7f13292 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -1941,7 +1941,7 @@ extern void ext4_htree_free_dir_info(struct dir_private_info *p); - - /* fsync.c */ - extern int ext4_sync_file(struct file *, loff_t, loff_t, int); --extern int ext4_flush_completed_IO(struct inode *); -+extern int ext4_flush_unwritten_io(struct inode *); - - /* hash.c */ - extern int ext4fs_dirhash(const char *name, int len, struct -@@ -2361,6 +2361,7 @@ extern const struct file_operations ext4_dir_operations; - extern const struct inode_operations ext4_file_inode_operations; - extern const struct file_operations ext4_file_operations; - extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); -+extern void ext4_unwritten_wait(struct inode *inode); - - /* namei.c */ - extern const struct inode_operations ext4_dir_inode_operations; -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index b1c92c0..37f46eb 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4250,7 +4250,7 @@ void ext4_ext_truncate(struct inode *inode) - * finish any pending end_io work so we won't run the risk of - * converting any truncated blocks to initialized later - */ -- ext4_flush_completed_IO(inode); -+ ext4_flush_unwritten_io(inode); - - /* - * probably first extent we're gonna free will be last in block -@@ -4829,10 +4829,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) - - /* Wait all existing dio workers, newcomers will block on i_mutex */ - ext4_inode_block_unlocked_dio(inode); -- inode_dio_wait(inode); -- err = ext4_flush_completed_IO(inode); -+ err = ext4_flush_unwritten_io(inode); - if (err) - goto out_dio; -+ inode_dio_wait(inode); - - credits = ext4_writepage_trans_blocks(inode); - handle = ext4_journal_start(inode, credits); -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 39335bd..ca6f07a 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -55,7 +55,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) - return 0; - } - --static void ext4_unwritten_wait(struct inode *inode) -+void ext4_unwritten_wait(struct inode *inode) - { - wait_queue_head_t *wq = ext4_ioend_wq(inode); - -diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c -index 520b058..76051c6 100644 ---- a/fs/ext4/fsync.c -+++ b/fs/ext4/fsync.c -@@ -138,7 +138,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) - if (inode->i_sb->s_flags & MS_RDONLY) - goto out; - -- ret = ext4_flush_completed_IO(inode); -+ ret = ext4_flush_unwritten_io(inode); - if (ret < 0) - goto out; - -diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c -index 8d849da..792e388 100644 ---- a/fs/ext4/indirect.c -+++ b/fs/ext4/indirect.c -@@ -807,9 +807,11 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - - retry: - if (rw == READ && ext4_should_dioread_nolock(inode)) { -- if (unlikely(!list_empty(&ei->i_completed_io_list))) -- ext4_flush_completed_IO(inode); -- -+ if (unlikely(atomic_read(&EXT4_I(inode)->i_unwritten))) { -+ mutex_lock(&inode->i_mutex); -+ ext4_flush_unwritten_io(inode); -+ mutex_unlock(&inode->i_mutex); -+ } - /* - * Nolock dioread optimization may be dynamically disabled - * via ext4_inode_block_unlocked_dio(). Check inode's state -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 5b24c40..68e896e 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -189,8 +189,6 @@ static int ext4_do_flush_completed_IO(struct inode *inode, - - list_add_tail(&io->list, &complete); - } -- /* It is important to update all flags for all end_io in one shot w/o -- * dropping the lock.*/ - spin_lock_irqsave(&ei->i_completed_io_lock, flags); - while (!list_empty(&complete)) { - io = list_entry(complete.next, ext4_io_end_t, list); -@@ -228,9 +226,14 @@ static void ext4_end_io_work(struct work_struct *work) - ext4_do_flush_completed_IO(io->inode, io); - } - --int ext4_flush_completed_IO(struct inode *inode) -+int ext4_flush_unwritten_io(struct inode *inode) - { -- return ext4_do_flush_completed_IO(inode, NULL); -+ int ret; -+ WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && -+ !(inode->i_state & I_FREEING)); -+ ret = ext4_do_flush_completed_IO(inode, NULL); -+ ext4_unwritten_wait(inode); -+ return ret; - } - - ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) --- -1.7.12.rc0.22.gcdd159b - diff --git a/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch b/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch deleted file mode 100644 index 3fcaef1f2..000000000 --- a/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 9f00d109efeaf4d12d56c8e46cd13af80e344f97 Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Fri, 5 Oct 2012 11:32:02 -0400 -Subject: [PATCH 12/13] ext4: serialize fallocate with - ext4_convert_unwritten_extents - -Fallocate should wait for pended ext4_convert_unwritten_extents() -otherwise following race may happen: - -ftruncate( ,12288); -fallocate( ,0, 4096) -io_sibmit( ,0, 4096); /* Write to fallocated area, split extent if needed */ -fallocate( ,0, 8192); /* Grow extent and broke assumption about extent */ - -Later kwork completion will do: - ->ext4_convert_unwritten_extents (0, 4096) - ->ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_IO_CONVERT_EXT); - ->ext4_ext_map_blocks() /* Will find new extent: ex = [0,2] !!!!!! */ - ->ext4_ext_handle_uninitialized_extents() - ->ext4_convert_unwritten_extents_endio() - /* convert [0,2] extent to initialized, but only[0,1] was written */ - -Signed-off-by: Dmitry Monakhov -Signed-off-by: "Theodore Ts'o" -(cherry picked from commit 60d4616f3dc63371b3dc367e5e88fd4b4f037f65) ---- - fs/ext4/extents.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 37f46eb..ea2db86 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4410,6 +4410,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) - */ - if (len <= EXT_UNINIT_MAX_LEN << blkbits) - flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; -+ -+ /* Prevent race condition between unwritten */ -+ ext4_flush_unwritten_io(inode); - retry: - while (ret >= 0 && ret < max_blocks) { - map.m_lblk = map.m_lblk + ret; --- -1.7.12.rc0.22.gcdd159b - diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch index 73f00fc43..99178d757 100644 --- a/Bluetooth-Add-support-for-BCM20702A0.patch +++ b/Bluetooth-Add-support-for-BCM20702A0.patch @@ -1,67 +1,3 @@ -From 7f198e1cc6d4fda9c84c0da4fc3aafb441342f78 Mon Sep 17 00:00:00 2001 -From: Jaroslav Resler -Date: Tue, 11 Sep 2012 17:25:32 +0800 -Subject: [PATCH 1/2] Bluetooth: Add support for BCM20702A0 [04ca, 2003] - -Add another vendor specific ID for BCM20702A0. - -output of usb-devices: -T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 -D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=04ca ProdID=2003 Rev= 1.12 -S: Manufacturer=Broadcom Corp -S: Product=BCM20702A0 -S: SerialNumber=446D57861623 -C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA -I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms -E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms -E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms -I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms -I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms -I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms -I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms -I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms -I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb -E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms -E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms -I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) -E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms -E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms -I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) - -Signed-off-by: Cho, Yu-Chen -Signed-off-by: Gustavo Padovan ---- - drivers/bluetooth/btusb.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 654e248..b167944 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { - { USB_DEVICE(0x0c10, 0x0000) }, - - /* Broadcom BCM20702A0 */ -+ { USB_DEVICE(0x04ca, 0x2003) }, - { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x413c, 0x8197) }, - --- -1.8.0 - - From a5f86c3423428c8e28b6501d0e9c3929ca91f07d Mon Sep 17 00:00:00 2001 From: Jeff Cook Date: Fri, 9 Nov 2012 16:39:48 -0700 diff --git a/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch b/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch deleted file mode 100644 index 0d83e8d03..000000000 --- a/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 95ab000388974d8ffef8257306b4be6e8778b768 Mon Sep 17 00:00:00 2001 -From: Jianpeng Ma -Date: Sat, 4 Aug 2012 10:34:14 +0800 -Subject: [PATCH] [SCSI] mvsas: Fix oops when ata commond timeout. - -Kernel message follows: - -[ 511.712011] sd 11:0:0:0: [sdf] command ffff8800a4e81400 timed out -[ 511.712022] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 -[ 511.712024] sas: trying to find task 0xffff8800a4d24c80 -[ 511.712026] sas: sas_scsi_find_task: aborting task 0xffff8800a4d24c80 -[ 511.712029] drivers/scsi/mvsas/mv_sas.c 1631:mvs_abort_task() -mvi=ffff8800b5300000 task=ffff8800a4d24c80 slot=ffff8800b5325038 -slot_idx=x0 -[ 511.712035] BUG: unable to handle kernel NULL pointer dereference at -0000000000000058 -[ 511.712040] IP: [] _raw_spin_lock_irqsave+0xc/0x30 -[ 511.712047] PGD 0 -[ 511.712049] Oops: 0002 [#1] SMP -[ 511.712052] Modules linked in: mvsas libsas scsi_transport_sas -raid456 async_pq async_xor xor async_memcpy async_raid6_recov raid6_pq -async_tx [last unloaded: mvsas] -[ 511.712062] CPU 3 -[ 511.712066] Pid: 7322, comm: scsi_eh_11 Not tainted 3.5.0+ #106 To Be -Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M. -[ 511.712068] RIP: 0010:[] [] -_raw_spin_lock_irqsave+0xc/0x30 -[ 511.712073] RSP: 0018:ffff880098d3bcb0 EFLAGS: 00010086 -[ 511.712074] RAX: 0000000000000286 RBX: 0000000000000058 RCX: -00000000000000c3 -[ 511.712076] RDX: 0000000000000100 RSI: 0000000000000046 RDI: -0000000000000058 -[ 511.712078] RBP: ffff880098d3bcb0 R08: 000000000000000a R09: -0000000000000000 -[ 511.712080] R10: 00000000000004e8 R11: 00000000000004e7 R12: -ffff8800a4d24c80 -[ 511.712082] R13: 0000000000000050 R14: ffff8800b5325038 R15: -ffff8800a4eafe00 -[ 511.712084] FS: 0000000000000000(0000) GS:ffff8800bdb80000(0000) -knlGS:0000000000000000 -[ 511.712086] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b -[ 511.712088] CR2: 0000000000000058 CR3: 00000000a4ce6000 CR4: -00000000000407e0 -[ 511.712090] DR0: 0000000000000000 DR1: 0000000000000000 DR2: -0000000000000000 -[ 511.712091] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: -0000000000000400 -[ 511.712093] Process scsi_eh_11 (pid: 7322, threadinfo -ffff880098d3a000, task ffff8800a61dde40) -[ 511.712095] Stack: -[ 511.712096] ffff880098d3bce0 ffffffff81060683 ffff880000000000 -0000000000000000 -[ 511.712099] ffff8800a4d24c80 ffff8800b5300000 ffff880098d3bcf0 -ffffffffa0076a88 -[ 511.712102] ffff880098d3bd50 ffffffffa0079bb5 ffff880000000000 -ffff880000000018 -[ 511.712106] Call Trace: -[ 511.712110] [] complete+0x23/0x60 -[ 511.712115] [] mvs_tmf_timedout+0x18/0x20 [mvsas] -[ 511.712119] [] mvs_slot_complete+0x765/0x7d0 -[mvsas] -[ 511.712125] [] sas_scsi_recover_host+0x55d/0xdb0 -[libsas] -[ 511.712128] [] ? idle_balance+0xe0/0x130 -[ 511.712133] [] scsi_error_handler+0xcc/0x470 -[ 511.712136] [] ? __schedule+0x370/0x730 -[ 511.712139] [] ? __wake_up_common+0x58/0x90 -[ 511.712142] [] ? scsi_eh_get_sense+0x110/0x110 -[ 511.712146] [] kthread+0x8e/0xa0 -[ 511.712150] [] kernel_thread_helper+0x4/0x10 -[ 511.712153] [] ? flush_kthread_work+0x120/0x120 -[ 511.712156] [] ? gs_change+0xb/0xb -[ 511.712157] Code: 8a 00 01 00 00 89 d0 f0 66 0f b1 0f 66 39 d0 0f 94 -c0 0f b6 c0 5d c3 0f 1f 84 00 00 00 00 00 55 48 89 e5 9c 58 fa ba 00 01 -00 00 66 0f c1 17 0f b6 ce 38 d1 74 11 0f 1f 84 00 00 00 00 00 f3 -[ 511.712191] RIP [] _raw_spin_lock_irqsave+0xc/0x30 -[ 511.712194] RSP -[ 511.712196] CR2: 0000000000000058 -[ 511.712198] ---[ end trace a781c7b1e65db92c ]--- - -Signed-off-by: Jianpeng Ma -Signed-off-by: James Bottomley ---- - drivers/scsi/mvsas/mv_sas.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c -index 4539d59..a3776d6 100644 ---- a/drivers/scsi/mvsas/mv_sas.c -+++ b/drivers/scsi/mvsas/mv_sas.c -@@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) - mv_dprintk("mvs_abort_task() mvi=%p task=%p " - "slot=%p slot_idx=x%x\n", - mvi, task, slot, slot_idx); -- mvs_tmf_timedout((unsigned long)task); -+ task->task_state_flags |= SAS_TASK_STATE_ABORTED; - mvs_slot_task_free(mvi, task, slot, slot_idx); - rc = TMF_RESP_FUNC_COMPLETE; - goto out; --- -1.8.0 - diff --git a/arm-fix_radio_shark.patch b/arm-fix_radio_shark.patch deleted file mode 100644 index 63296a90e..000000000 --- a/arm-fix_radio_shark.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig -index ff3af6e..f99fa25 100644 ---- a/sound/pci/Kconfig -+++ b/sound/pci/Kconfig -@@ -2,8 +2,8 @@ - - config SND_TEA575X - tristate -- depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO -- default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO -+ depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK -+ default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - - menuconfig SND_PCI - bool "PCI sound devices" diff --git a/arm-highbank-sata-fix.patch b/arm-highbank-sata-fix.patch deleted file mode 100644 index fda7b219e..000000000 --- a/arm-highbank-sata-fix.patch +++ /dev/null @@ -1,599 +0,0 @@ -From: Mark Langsdorf -Date: Thu, 6 Sep 2012 21:03:30 +0000 (-0500) -Subject: ata: add platform driver for Calxeda AHCI controller -X-Git-Tag: next-20121002~68^2~5 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=8996b89d6bc98ae2f6d6e6e624a42a3f89d06949;hp=100f586bd0959fe0e52b8a0b8cb49a3df1c6b044 - -ata: add platform driver for Calxeda AHCI controller - -Calxeda highbank SATA phy has intermittent problems bringing up a link -with Gen3 drives. Retrying the phy hard reset can work-around this issue, -but each reset also disables spread spectrum support. The reset function -also needs to reprogram the phy to enable spread spectrum support. - -Create a new driver based on ahci_platform to support the Calxeda Highbank -SATA controller. - -Signed-off-by: Mark Langsdorf -Signed-off-by: Rob Herring -Signed-off-by: Jeff Garzik ---- - -diff --git a/Documentation/devicetree/bindings/arm/calxeda/combophy.txt b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt -new file mode 100644 -index 0000000..6622bdb ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt -@@ -0,0 +1,17 @@ -+Calxeda Highbank Combination Phys for SATA -+ -+Properties: -+- compatible : Should be "calxeda,hb-combophy" -+- #phy-cells: Should be 1. -+- reg : Address and size for Combination Phy registers. -+- phydev: device ID for programming the combophy. -+ -+Example: -+ -+ combophy5: combo-phy@fff5d000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff5d000 0x1000>; -+ phydev = <31>; -+ }; -+ -diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt -index 8bb8a76..147c1f6 100644 ---- a/Documentation/devicetree/bindings/ata/ahci-platform.txt -+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt -@@ -8,9 +8,17 @@ Required properties: - - interrupts : - - reg : - -+Optional properties: -+- calxeda,port-phys: phandle-combophy and lane assignment, which maps each -+ SATA port to a combophy and a lane within that -+ combophy -+ - Example: - sata@ffe08000 { - compatible = "calxeda,hb-ahci"; - reg = <0xffe08000 0x1000>; - interrupts = <115>; -+ calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1 -+ &combophy0 2 &combophy0 3>; -+ - }; -diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts -index 9fecf1a..5204cf7 100644 ---- a/arch/arm/boot/dts/highbank.dts -+++ b/arch/arm/boot/dts/highbank.dts -@@ -121,6 +121,9 @@ - compatible = "calxeda,hb-ahci"; - reg = <0xffe08000 0x10000>; - interrupts = <0 83 4>; -+ calxeda,port-phys = <&combophy5 0 &combophy0 0 -+ &combophy0 1 &combophy0 2 -+ &combophy0 3>; - }; - - sdhci@ffe0e000 { -@@ -306,5 +309,19 @@ - reg = <0xfff51000 0x1000>; - interrupts = <0 80 4 0 81 4 0 82 4>; - }; -+ -+ combophy0: combo-phy@fff58000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff58000 0x1000>; -+ phydev = <5>; -+ }; -+ -+ combophy5: combo-phy@fff5d000 { -+ compatible = "calxeda,hb-combophy"; -+ #phy-cells = <1>; -+ reg = <0xfff5d000 0x1000>; -+ phydev = <31>; -+ }; - }; - }; -diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig -index 27cecd3..e08d322 100644 ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG - help - This option enables the taskfile dumping and NCQ debugging. - -+config SATA_HIGHBANK -+ tristate "Calxeda Highbank SATA support" -+ help -+ This option enables support for the Calxeda Highbank SoC's -+ onboard SATA. -+ -+ If unsure, say N. -+ - config SATA_MV - tristate "Marvell SATA support" - help -diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile -index a454a13..8b384f1 100644 ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL) += sata_fsl.o - obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o - obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o -+obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o -diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c -index 09728e0..dc187c7 100644 ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -277,7 +277,6 @@ static int ahci_resume(struct device *dev) - SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); - - static const struct of_device_id ahci_of_match[] = { -- { .compatible = "calxeda,hb-ahci", }, - { .compatible = "snps,spear-ahci", }, - {}, - }; -diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c -new file mode 100644 -index 0000000..0d7c4c2 ---- /dev/null -+++ b/drivers/ata/sata_highbank.c -@@ -0,0 +1,450 @@ -+/* -+ * Calxeda Highbank AHCI SATA platform driver -+ * Copyright 2012 Calxeda, Inc. -+ * -+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program. If not, see . -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "ahci.h" -+ -+#define CPHY_MAP(dev, addr) ((((dev) & 0x1f) << 7) | (((addr) >> 9) & 0x7f)) -+#define CPHY_ADDR(addr) (((addr) & 0x1ff) << 2) -+#define SERDES_CR_CTL 0x80a0 -+#define SERDES_CR_ADDR 0x80a1 -+#define SERDES_CR_DATA 0x80a2 -+#define CR_BUSY 0x0001 -+#define CR_START 0x0001 -+#define CR_WR_RDN 0x0002 -+#define CPHY_RX_INPUT_STS 0x2002 -+#define CPHY_SATA_OVERRIDE 0x4000 -+#define CPHY_OVERRIDE 0x2005 -+#define SPHY_LANE 0x100 -+#define SPHY_HALF_RATE 0x0001 -+#define CPHY_SATA_DPLL_MODE 0x0700 -+#define CPHY_SATA_DPLL_SHIFT 8 -+#define CPHY_SATA_DPLL_RESET (1 << 11) -+#define CPHY_PHY_COUNT 6 -+#define CPHY_LANE_COUNT 4 -+#define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) -+ -+static DEFINE_SPINLOCK(cphy_lock); -+/* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based -+ * sata ports to their phys and then to their lanes within the phys -+ */ -+struct phy_lane_info { -+ void __iomem *phy_base; -+ u8 lane_mapping; -+ u8 phy_devs; -+}; -+static struct phy_lane_info port_data[CPHY_PORT_COUNT]; -+ -+static u32 __combo_phy_reg_read(u8 sata_port, u32 addr) -+{ -+ u32 data; -+ u8 dev = port_data[sata_port].phy_devs; -+ spin_lock(&cphy_lock); -+ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); -+ data = readl(port_data[sata_port].phy_base + CPHY_ADDR(addr)); -+ spin_unlock(&cphy_lock); -+ return data; -+} -+ -+static void __combo_phy_reg_write(u8 sata_port, u32 addr, u32 data) -+{ -+ u8 dev = port_data[sata_port].phy_devs; -+ spin_lock(&cphy_lock); -+ writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); -+ writel(data, port_data[sata_port].phy_base + CPHY_ADDR(addr)); -+ spin_unlock(&cphy_lock); -+} -+ -+static void combo_phy_wait_for_ready(u8 sata_port) -+{ -+ while (__combo_phy_reg_read(sata_port, SERDES_CR_CTL) & CR_BUSY) -+ udelay(5); -+} -+ -+static u32 combo_phy_read(u8 sata_port, u32 addr) -+{ -+ combo_phy_wait_for_ready(sata_port); -+ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); -+ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_START); -+ combo_phy_wait_for_ready(sata_port); -+ return __combo_phy_reg_read(sata_port, SERDES_CR_DATA); -+} -+ -+static void combo_phy_write(u8 sata_port, u32 addr, u32 data) -+{ -+ combo_phy_wait_for_ready(sata_port); -+ __combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); -+ __combo_phy_reg_write(sata_port, SERDES_CR_DATA, data); -+ __combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_WR_RDN | CR_START); -+} -+ -+static void highbank_cphy_disable_overrides(u8 sata_port) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp; -+ if (unlikely(port_data[sata_port].phy_base == NULL)) -+ return; -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); -+ tmp &= ~CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+} -+ -+static void cphy_override_rx_mode(u8 sata_port, u32 val) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp; -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); -+ tmp &= ~CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp |= CPHY_SATA_OVERRIDE; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp &= ~CPHY_SATA_DPLL_MODE; -+ tmp |= val << CPHY_SATA_DPLL_SHIFT; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp |= CPHY_SATA_DPLL_RESET; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ tmp &= ~CPHY_SATA_DPLL_RESET; -+ combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); -+ -+ msleep(15); -+} -+ -+static void highbank_cphy_override_lane(u8 sata_port) -+{ -+ u8 lane = port_data[sata_port].lane_mapping; -+ u32 tmp, k = 0; -+ -+ if (unlikely(port_data[sata_port].phy_base == NULL)) -+ return; -+ do { -+ tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + -+ lane * SPHY_LANE); -+ } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); -+ cphy_override_rx_mode(sata_port, 3); -+} -+ -+static int highbank_initialize_phys(struct device *dev, void __iomem *addr) -+{ -+ struct device_node *sata_node = dev->of_node; -+ int phy_count = 0, phy, port = 0; -+ void __iomem *cphy_base[CPHY_PHY_COUNT]; -+ struct device_node *phy_nodes[CPHY_PHY_COUNT]; -+ memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); -+ memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); -+ -+ do { -+ u32 tmp; -+ struct of_phandle_args phy_data; -+ if (of_parse_phandle_with_args(sata_node, -+ "calxeda,port-phys", "#phy-cells", -+ port, &phy_data)) -+ break; -+ for (phy = 0; phy < phy_count; phy++) { -+ if (phy_nodes[phy] == phy_data.np) -+ break; -+ } -+ if (phy_nodes[phy] == NULL) { -+ phy_nodes[phy] = phy_data.np; -+ cphy_base[phy] = of_iomap(phy_nodes[phy], 0); -+ if (cphy_base[phy] == NULL) { -+ return 0; -+ } -+ phy_count += 1; -+ } -+ port_data[port].lane_mapping = phy_data.args[0]; -+ of_property_read_u32(phy_nodes[phy], "phydev", &tmp); -+ port_data[port].phy_devs = tmp; -+ port_data[port].phy_base = cphy_base[phy]; -+ of_node_put(phy_data.np); -+ port += 1; -+ } while (port < CPHY_PORT_COUNT); -+ return 0; -+} -+ -+static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, -+ unsigned long deadline) -+{ -+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); -+ struct ata_port *ap = link->ap; -+ struct ahci_port_priv *pp = ap->private_data; -+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; -+ struct ata_taskfile tf; -+ bool online; -+ u32 sstatus; -+ int rc; -+ int retry = 10; -+ -+ ahci_stop_engine(ap); -+ -+ /* clear D2H reception area to properly wait for D2H FIS */ -+ ata_tf_init(link->device, &tf); -+ tf.command = 0x80; -+ ata_tf_to_fis(&tf, 0, 0, d2h_fis); -+ -+ do { -+ highbank_cphy_disable_overrides(link->ap->port_no); -+ rc = sata_link_hardreset(link, timing, deadline, &online, NULL); -+ highbank_cphy_override_lane(link->ap->port_no); -+ -+ /* If the status is 1, we are connected, but the link did not -+ * come up. So retry resetting the link again. -+ */ -+ if (sata_scr_read(link, SCR_STATUS, &sstatus)) -+ break; -+ if (!(sstatus & 0x3)) -+ break; -+ } while (!online && retry--); -+ -+ ahci_start_engine(ap); -+ -+ if (online) -+ *class = ahci_dev_classify(ap); -+ -+ return rc; -+} -+ -+static struct ata_port_operations ahci_highbank_ops = { -+ .inherits = &ahci_ops, -+ .hardreset = ahci_highbank_hardreset, -+}; -+ -+static const struct ata_port_info ahci_highbank_port_info = { -+ .flags = AHCI_FLAG_COMMON, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ahci_highbank_ops, -+}; -+ -+static struct scsi_host_template ahci_highbank_platform_sht = { -+ AHCI_SHT("highbank-ahci"), -+}; -+ -+static const struct of_device_id ahci_of_match[] = { -+ { .compatible = "calxeda,hb-ahci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ahci_of_match); -+ -+static int __init ahci_highbank_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ahci_host_priv *hpriv; -+ struct ata_host *host; -+ struct resource *mem; -+ int irq; -+ int n_ports; -+ int i; -+ int rc; -+ struct ata_port_info pi = ahci_highbank_port_info; -+ const struct ata_port_info *ppi[] = { &pi, NULL }; -+ -+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!mem) { -+ dev_err(dev, "no mmio space\n"); -+ return -EINVAL; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "no irq\n"); -+ return -EINVAL; -+ } -+ -+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); -+ if (!hpriv) { -+ dev_err(dev, "can't alloc ahci_host_priv\n"); -+ return -ENOMEM; -+ } -+ -+ hpriv->flags |= (unsigned long)pi.private_data; -+ -+ hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); -+ if (!hpriv->mmio) { -+ dev_err(dev, "can't map %pR\n", mem); -+ return -ENOMEM; -+ } -+ -+ rc = highbank_initialize_phys(dev, hpriv->mmio); -+ if (rc) -+ return rc; -+ -+ -+ ahci_save_initial_config(dev, hpriv, 0, 0); -+ -+ /* prepare host */ -+ if (hpriv->cap & HOST_CAP_NCQ) -+ pi.flags |= ATA_FLAG_NCQ; -+ -+ if (hpriv->cap & HOST_CAP_PMP) -+ pi.flags |= ATA_FLAG_PMP; -+ -+ ahci_set_em_messages(hpriv, &pi); -+ -+ /* CAP.NP sometimes indicate the index of the last enabled -+ * port, at other times, that of the last possible port, so -+ * determining the maximum port number requires looking at -+ * both CAP.NP and port_map. -+ */ -+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -+ -+ host = ata_host_alloc_pinfo(dev, ppi, n_ports); -+ if (!host) { -+ rc = -ENOMEM; -+ goto err0; -+ } -+ -+ host->private_data = hpriv; -+ -+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -+ host->flags |= ATA_HOST_PARALLEL_SCAN; -+ -+ if (pi.flags & ATA_FLAG_EM) -+ ahci_reset_em(host); -+ -+ for (i = 0; i < host->n_ports; i++) { -+ struct ata_port *ap = host->ports[i]; -+ -+ ata_port_desc(ap, "mmio %pR", mem); -+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -+ -+ /* set enclosure management message type */ -+ if (ap->flags & ATA_FLAG_EM) -+ ap->em_message_type = hpriv->em_msg_type; -+ -+ /* disabled/not-implemented port */ -+ if (!(hpriv->port_map & (1 << i))) -+ ap->ops = &ata_dummy_port_ops; -+ } -+ -+ rc = ahci_reset_controller(host); -+ if (rc) -+ goto err0; -+ -+ ahci_init_controller(host); -+ ahci_print_info(host, "platform"); -+ -+ rc = ata_host_activate(host, irq, ahci_interrupt, 0, -+ &ahci_highbank_platform_sht); -+ if (rc) -+ goto err0; -+ -+ return 0; -+err0: -+ return rc; -+} -+ -+static int __devexit ahci_highbank_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ata_host *host = dev_get_drvdata(dev); -+ -+ ata_host_detach(host); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ahci_highbank_suspend(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ void __iomem *mmio = hpriv->mmio; -+ u32 ctl; -+ int rc; -+ -+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -+ dev_err(dev, "firmware update required for suspend/resume\n"); -+ return -EIO; -+ } -+ -+ /* -+ * AHCI spec rev1.1 section 8.3.3: -+ * Software must disable interrupts prior to requesting a -+ * transition of the HBA to D3 state. -+ */ -+ ctl = readl(mmio + HOST_CTL); -+ ctl &= ~HOST_IRQ_EN; -+ writel(ctl, mmio + HOST_CTL); -+ readl(mmio + HOST_CTL); /* flush */ -+ -+ rc = ata_host_suspend(host, PMSG_SUSPEND); -+ if (rc) -+ return rc; -+ -+ return 0; -+} -+ -+static int ahci_highbank_resume(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ int rc; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+#endif -+ -+SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, -+ ahci_highbank_suspend, ahci_highbank_resume); -+ -+static struct platform_driver ahci_highbank_driver = { -+ .remove = __devexit_p(ahci_highbank_remove), -+ .driver = { -+ .name = "highbank-ahci", -+ .owner = THIS_MODULE, -+ .of_match_table = ahci_of_match, -+ .pm = &ahci_highbank_pm_ops, -+ }, -+ .probe = ahci_highbank_probe, -+}; -+ -+module_platform_driver(ahci_highbank_driver); -+ -+MODULE_DESCRIPTION("Calxeda Highbank AHCI SATA platform driver"); -+MODULE_AUTHOR("Mark Langsdorf "); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("sata:highbank"); diff --git a/block-fix-a-crash-when-block-device-is.patch b/block-fix-a-crash-when-block-device-is.patch deleted file mode 100644 index af992830e..000000000 --- a/block-fix-a-crash-when-block-device-is.patch +++ /dev/null @@ -1,214 +0,0 @@ -Fix a crash when block device is read and block size is changed at the same time - -commit b87570f5d349661814b262dd5fc40787700f80d6 -Author: Mikulas Patocka -Date: Wed Sep 26 07:46:40 2012 +0200 - - Fix a crash when block device is read and block size is changed at the same time - - The kernel may crash when block size is changed and I/O is issued - simultaneously. - - Because some subsystems (udev or lvm) may read any block device anytime, - the bug actually puts any code that changes a block device size in - jeopardy. - - The crash can be reproduced if you place "msleep(1000)" to - blkdev_get_blocks just before "bh->b_size = max_blocks << - inode->i_blkbits;". - Then, run "dd if=/dev/ram0 of=/dev/null bs=4k count=1 iflag=direct" - While it is waiting in msleep, run "blockdev --setbsz 2048 /dev/ram0" - You get a BUG. - - The direct and non-direct I/O is written with the assumption that block - size does not change. It doesn't seem practical to fix these crashes - one-by-one there may be many crash possibilities when block size changes - at a certain place and it is impossible to find them all and verify the - code. - - This patch introduces a new rw-lock bd_block_size_semaphore. The lock is - taken for read during I/O. It is taken for write when changing block - size. Consequently, block size can't be changed while I/O is being - submitted. - - For asynchronous I/O, the patch only prevents block size change while - the I/O is being submitted. The block size can change when the I/O is in - progress or when the I/O is being finished. This is acceptable because - there are no accesses to block size when asynchronous I/O is being - finished. - - The patch prevents block size changing while the device is mapped with - mmap. - - Signed-off-by: Mikulas Patocka - Signed-off-by: Jens Axboe - -Index: linux-3.6.x86_64/drivers/char/raw.c -=================================================================== ---- linux-3.6.x86_64.orig/drivers/char/raw.c 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/drivers/char/raw.c 2012-11-16 17:12:37.381002516 -0500 -@@ -285,7 +285,7 @@ - - static const struct file_operations raw_fops = { - .read = do_sync_read, -- .aio_read = generic_file_aio_read, -+ .aio_read = blkdev_aio_read, - .write = do_sync_write, - .aio_write = blkdev_aio_write, - .fsync = blkdev_fsync, -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 -@@ -116,6 +116,8 @@ - - int set_blocksize(struct block_device *bdev, int size) - { -+ struct address_space *mapping; -+ - /* Size must be a power of two, and between 512 and PAGE_SIZE */ - if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) - return -EINVAL; -@@ -124,6 +126,20 @@ - if (size < bdev_logical_block_size(bdev)) - return -EINVAL; - -+ /* Prevent starting I/O or mapping the device */ -+ down_write(&bdev->bd_block_size_semaphore); -+ -+ /* Check that the block device is not memory mapped */ -+ mapping = bdev->bd_inode->i_mapping; -+ mutex_lock(&mapping->i_mmap_mutex); -+ if (!prio_tree_empty(&mapping->i_mmap) || -+ !list_empty(&mapping->i_mmap_nonlinear)) { -+ mutex_unlock(&mapping->i_mmap_mutex); -+ up_write(&bdev->bd_block_size_semaphore); -+ return -EBUSY; -+ } -+ mutex_unlock(&mapping->i_mmap_mutex); -+ - /* Don't change the size if it is same as current */ - if (bdev->bd_block_size != size) { - sync_blockdev(bdev); -@@ -131,6 +147,9 @@ - bdev->bd_inode->i_blkbits = blksize_bits(size); - kill_bdev(bdev); - } -+ -+ up_write(&bdev->bd_block_size_semaphore); -+ - return 0; - } - -@@ -472,6 +491,7 @@ - inode_init_once(&ei->vfs_inode); - /* Initialize mutex for freeze. */ - mutex_init(&bdev->bd_fsfreeze_mutex); -+ init_rwsem(&bdev->bd_block_size_semaphore); - } - - static inline void __bd_forget(struct inode *inode) -@@ -1567,6 +1587,22 @@ - return blkdev_ioctl(bdev, mode, cmd, arg); - } - -+ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t pos) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_aio_read(iocb, iov, nr_segs, pos); -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(blkdev_aio_read); -+ - /* - * Write data to the block device. Only intended for the block device itself - * and the raw driver which basically is a fake block device. -@@ -1578,12 +1614,16 @@ - unsigned long nr_segs, loff_t pos) - { - struct file *file = iocb->ki_filp; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); - struct blk_plug plug; - ssize_t ret; - - BUG_ON(iocb->ki_pos != pos); - - blk_start_plug(&plug); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ - ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); - if (ret > 0 || ret == -EIOCBQUEUED) { - ssize_t err; -@@ -1592,11 +1632,29 @@ - if (err < 0 && ret > 0) - ret = err; - } -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ - blk_finish_plug(&plug); -+ - return ret; - } - EXPORT_SYMBOL_GPL(blkdev_aio_write); - -+int blkdev_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_mmap(file, vma); -+ -+ up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ - /* - * Try to release a page associated with block device when the system - * is under memory pressure. -@@ -1627,9 +1685,9 @@ - .llseek = block_llseek, - .read = do_sync_read, - .write = do_sync_write, -- .aio_read = generic_file_aio_read, -+ .aio_read = blkdev_aio_read, - .aio_write = blkdev_aio_write, -- .mmap = generic_file_mmap, -+ .mmap = blkdev_mmap, - .fsync = blkdev_fsync, - .unlocked_ioctl = block_ioctl, - #ifdef CONFIG_COMPAT -Index: linux-3.6.x86_64/include/linux/fs.h -=================================================================== ---- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:35.127010280 -0500 -+++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 -@@ -724,6 +724,8 @@ - int bd_fsfreeze_count; - /* Mutex for freeze */ - struct mutex bd_fsfreeze_mutex; -+ /* A semaphore that prevents I/O while block size is being changed */ -+ struct rw_semaphore bd_block_size_semaphore; - }; - - /* -@@ -2564,6 +2566,8 @@ - unsigned long *nr_segs, size_t *count, int access_flags); - - /* fs/block_dev.c */ -+extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t pos); - extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); - extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, diff --git a/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch b/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch deleted file mode 100644 index 82caa6b76..000000000 --- a/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +++ /dev/null @@ -1,290 +0,0 @@ -blockdev: turn a rw semaphore into a percpu rw semaphore - -commit 62ac665ff9fc07497ca524bd20d6a96893d11071 -Author: Mikulas Patocka -Date: Wed Sep 26 07:46:43 2012 +0200 - - blockdev: turn a rw semaphore into a percpu rw semaphore - - This avoids cache line bouncing when many processes lock the semaphore - for read. - - New percpu lock implementation - - The lock consists of an array of percpu unsigned integers, a boolean - variable and a mutex. - - When we take the lock for read, we enter rcu read section, check for a - "locked" variable. If it is false, we increase a percpu counter on the - current cpu and exit the rcu section. If "locked" is true, we exit the - rcu section, take the mutex and drop it (this waits until a writer - finished) and retry. - - Unlocking for read just decreases percpu variable. Note that we can - unlock on a difference cpu than where we locked, in this case the - counter underflows. The sum of all percpu counters represents the number - of processes that hold the lock for read. - - When we need to lock for write, we take the mutex, set "locked" variable - to true and synchronize rcu. Since RCU has been synchronized, no - processes can create new read locks. We wait until the sum of percpu - counters is zero - when it is, there are no readers in the critical - section. - - Signed-off-by: Mikulas Patocka - Signed-off-by: Jens Axboe - -Index: linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt 2012-11-16 17:12:57.351936583 -0500 -@@ -0,0 +1,27 @@ -+Percpu rw semaphores -+-------------------- -+ -+Percpu rw semaphores is a new read-write semaphore design that is -+optimized for locking for reading. -+ -+The problem with traditional read-write semaphores is that when multiple -+cores take the lock for reading, the cache line containing the semaphore -+is bouncing between L1 caches of the cores, causing performance -+degradation. -+ -+Locking for reading it very fast, it uses RCU and it avoids any atomic -+instruction in the lock and unlock path. On the other hand, locking for -+writing is very expensive, it calls synchronize_rcu() that can take -+hundreds of microseconds. -+ -+The lock is declared with "struct percpu_rw_semaphore" type. -+The lock is initialized percpu_init_rwsem, it returns 0 on success and -+-ENOMEM on allocation failure. -+The lock must be freed with percpu_free_rwsem to avoid memory leak. -+ -+The lock is locked for read with percpu_down_read, percpu_up_read and -+for write with percpu_down_write, percpu_up_write. -+ -+The idea of using RCU for optimized rw-lock was introduced by -+Eric Dumazet . -+The code was written by Mikulas Patocka -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:27:41.217005828 -0500 -@@ -127,7 +127,7 @@ - return -EINVAL; - - /* Prevent starting I/O or mapping the device */ -- down_write(&bdev->bd_block_size_semaphore); -+ percpu_down_write(&bdev->bd_block_size_semaphore); - - /* Check that the block device is not memory mapped */ - mapping = bdev->bd_inode->i_mapping; -@@ -135,7 +135,7 @@ - if (!prio_tree_empty(&mapping->i_mmap) || - !list_empty(&mapping->i_mmap_nonlinear)) { - mutex_unlock(&mapping->i_mmap_mutex); -- up_write(&bdev->bd_block_size_semaphore); -+ percpu_up_write(&bdev->bd_block_size_semaphore); - return -EBUSY; - } - mutex_unlock(&mapping->i_mmap_mutex); -@@ -148,7 +148,7 @@ - kill_bdev(bdev); - } - -- up_write(&bdev->bd_block_size_semaphore); -+ percpu_up_write(&bdev->bd_block_size_semaphore); - - return 0; - } -@@ -460,6 +460,12 @@ - struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); - if (!ei) - return NULL; -+ -+ if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) { -+ kmem_cache_free(bdev_cachep, ei); -+ return NULL; -+ } -+ - return &ei->vfs_inode; - } - -@@ -468,6 +474,8 @@ - struct inode *inode = container_of(head, struct inode, i_rcu); - struct bdev_inode *bdi = BDEV_I(inode); - -+ percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore); -+ - kmem_cache_free(bdev_cachep, bdi); - } - -@@ -491,7 +499,6 @@ - inode_init_once(&ei->vfs_inode); - /* Initialize mutex for freeze. */ - mutex_init(&bdev->bd_fsfreeze_mutex); -- init_rwsem(&bdev->bd_block_size_semaphore); - } - - static inline void __bd_forget(struct inode *inode) -@@ -1593,11 +1600,11 @@ - ssize_t ret; - struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_aio_read(iocb, iov, nr_segs, pos); - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; - } -@@ -1622,7 +1629,7 @@ - - blk_start_plug(&plug); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); - if (ret > 0 || ret == -EIOCBQUEUED) { -@@ -1633,7 +1640,7 @@ - ret = err; - } - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - blk_finish_plug(&plug); - -@@ -1646,11 +1653,11 @@ - int ret; - struct block_device *bdev = I_BDEV(file->f_mapping->host); - -- down_read(&bdev->bd_block_size_semaphore); -+ percpu_down_read(&bdev->bd_block_size_semaphore); - - ret = generic_file_mmap(file, vma); - -- up_read(&bdev->bd_block_size_semaphore); -+ percpu_up_read(&bdev->bd_block_size_semaphore); - - return ret; - } -Index: linux-3.6.x86_64/include/linux/fs.h -=================================================================== ---- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 -+++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:28:12.578901349 -0500 -@@ -415,6 +415,7 @@ - #include - #include - #include -+#include - - #include - -@@ -725,7 +726,7 @@ - /* Mutex for freeze */ - struct mutex bd_fsfreeze_mutex; - /* A semaphore that prevents I/O while block size is being changed */ -- struct rw_semaphore bd_block_size_semaphore; -+ struct percpu_rw_semaphore bd_block_size_semaphore; - }; - - /* -Index: linux-3.6.x86_64/include/linux/percpu-rwsem.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-3.6.x86_64/include/linux/percpu-rwsem.h 2012-11-16 17:12:57.354936574 -0500 -@@ -0,0 +1,89 @@ -+#ifndef _LINUX_PERCPU_RWSEM_H -+#define _LINUX_PERCPU_RWSEM_H -+ -+#include -+#include -+#include -+#include -+ -+struct percpu_rw_semaphore { -+ unsigned __percpu *counters; -+ bool locked; -+ struct mutex mtx; -+}; -+ -+static inline void percpu_down_read(struct percpu_rw_semaphore *p) -+{ -+ rcu_read_lock(); -+ if (unlikely(p->locked)) { -+ rcu_read_unlock(); -+ mutex_lock(&p->mtx); -+ this_cpu_inc(*p->counters); -+ mutex_unlock(&p->mtx); -+ return; -+ } -+ this_cpu_inc(*p->counters); -+ rcu_read_unlock(); -+} -+ -+static inline void percpu_up_read(struct percpu_rw_semaphore *p) -+{ -+ /* -+ * On X86, write operation in this_cpu_dec serves as a memory unlock -+ * barrier (i.e. memory accesses may be moved before the write, but -+ * no memory accesses are moved past the write). -+ * On other architectures this may not be the case, so we need smp_mb() -+ * there. -+ */ -+#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) -+ barrier(); -+#else -+ smp_mb(); -+#endif -+ this_cpu_dec(*p->counters); -+} -+ -+static inline unsigned __percpu_count(unsigned __percpu *counters) -+{ -+ unsigned total = 0; -+ int cpu; -+ -+ for_each_possible_cpu(cpu) -+ total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); -+ -+ return total; -+} -+ -+static inline void percpu_down_write(struct percpu_rw_semaphore *p) -+{ -+ mutex_lock(&p->mtx); -+ p->locked = true; -+ synchronize_rcu(); -+ while (__percpu_count(p->counters)) -+ msleep(1); -+ smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ -+} -+ -+static inline void percpu_up_write(struct percpu_rw_semaphore *p) -+{ -+ p->locked = false; -+ mutex_unlock(&p->mtx); -+} -+ -+static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) -+{ -+ p->counters = alloc_percpu(unsigned); -+ if (unlikely(!p->counters)) -+ return -ENOMEM; -+ p->locked = false; -+ mutex_init(&p->mtx); -+ return 0; -+} -+ -+static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) -+{ -+ free_percpu(p->counters); -+ p->counters = NULL; /* catch use after free bugs */ -+} -+ -+#endif diff --git a/config-arm-generic b/config-arm-generic index d44eda51d..89fc4356a 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -12,6 +12,7 @@ CONFIG_AEABI=y CONFIG_OABI_COMPAT=y CONFIG_VFP=y CONFIG_ARM_UNWIND=y +# CONFIG_ARCH_MULTI_V7 is not set CONFIG_SMP=y CONFIG_NR_CPUS=4 @@ -27,6 +28,7 @@ CONFIG_FPE_FASTFPE=y CONFIG_HIGHPTE=y CONFIG_HW_PERF_EVENTS=y CONFIG_UACCESS_WITH_MEMCPY=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set # Generic ARM Errata CONFIG_ARM_ERRATA_720789=y @@ -35,13 +37,14 @@ CONFIG_ARM_ERRATA_742230=y CONFIG_ARM_ERRATA_742231=y CONFIG_ARM_ERRATA_754327=y CONFIG_ARM_ERRATA_764369=y - +CONFIG_ARM_ERRATA_775420=y # Generic ARM config options CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZBOOT_ROM_BSS=0 CONFIG_LOCAL_TIMERS=y +CONFIG_ATAGS=y CONFIG_ATAGS_PROC=y CONFIG_PL330_DMA=y @@ -63,9 +66,6 @@ CONFIG_CPU_IDLE=y # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -75,6 +75,16 @@ CONFIG_SUSPEND=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + +# CONFIG_XEN is not set + +CONFIG_PINCTRL=y +CONFIG_PINCONF=y + +CONFIG_COMMON_CLK=y + CONFIG_THERMAL=y CONFIG_ETHERNET=y @@ -84,24 +94,20 @@ CONFIG_PERF_COUNTERS=y CONFIG_CC_STACKPROTECTOR=y -CONFIG_AUTO_ZRELADDR=y - CONFIG_SECCOMP=y CONFIG_STRICT_DEVMEM=y CONFIG_SPARSE_IRQ=y # Generic HW for all ARM platforms -CONFIG_LEDS=y -CONFIG_LEDS_CPU=y CONFIG_LEDS_GPIO=m CONFIG_LBDAF=y +CONFIG_GPIOLIB=y CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m -CONFIG_GPIOLIB=y CONFIG_PINCTRL_SINGLE=m CONFIG_USB_ULPI=y @@ -136,10 +142,13 @@ CONFIG_MMC_SPI=m CONFIG_MMC_DW=m CONFIG_MMC_DW_PLTFM=m CONFIG_MMC_DW_PCI=m +# CONFIG_MMC_DW_EXYNOS is not set # CONFIG_MMC_DW_IDMAC is not set CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set + # Generic GPIO options CONFIG_GENERIC_GPIO=y @@ -234,12 +243,15 @@ CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_DEBUG is not set # HW crypto and rng +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m CONFIG_HW_RANDOM_ATMEL=m CONFIG_HW_RANDOM_EXYNOS=m # Device tree CONFIG_OF=y CONFIG_USE_OF=y +CONFIG_OF_IRQ=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y CONFIG_PROC_DEVICETREE=y @@ -252,6 +264,7 @@ CONFIG_OF_PCI_IRQ=y CONFIG_I2C_MUX_PINCTRL=m CONFIG_OF_MDIO=m CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_MDIO_BUS_MUX_MMIOREG=m CONFIG_BPF_JIT=y @@ -263,6 +276,7 @@ CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_RTC_DRV_88PM80X=m CONFIG_RTC_DRV_PL030=m CONFIG_RTC_DRV_PL031=m +CONFIG_RTC_DRV_SNVS=m CONFIG_RFKILL_REGULATOR=m CONFIG_INPUT_88PM80X_ONKEY=y CONFIG_INPUT_GP2A=m @@ -272,14 +286,22 @@ CONFIG_SERIAL_AMBA_PL010=m CONFIG_SERIAL_AMBA_PL011=m CONFIG_GPIO_PL061=y CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_ADNP=m CONFIG_PL310_ERRATA_753970=y CONFIG_MFD_88PM800=m CONFIG_MFD_88PM805=m +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_MAX8907 is not set + CONFIG_REGULATOR_VIRTUAL_CONSUMER=m CONFIG_REGULATOR_USERSPACE_CONSUMER=m CONFIG_REGULATOR_GPIO=m CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_FAN53555=m CONFIG_REGULATOR_ISL6271A=m CONFIG_REGULATOR_MAX1586=m CONFIG_REGULATOR_MAX8649=m @@ -292,6 +314,12 @@ CONFIG_REGULATOR_TPS6507X=m CONFIG_CHARGER_MANAGER=y CONFIG_EXTCON_GPIO=m +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_PINCTRL_EXYNOS4 is not set + +# CONFIG_AUTO_ZRELADDR is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + # CONFIG_VFIO is not set # CONFIG_XIP_KERNEL is not set @@ -356,3 +384,4 @@ CONFIG_EXTCON_GPIO=m # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_CS89x0 is not set +# CONFIG_DVB_USB_PCTV452E is not set diff --git a/config-arm-imx b/config-arm-imx index bddff88ab..8ffd96559 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -7,6 +7,7 @@ CONFIG_NEON=y # CONFIG_THUMB2_KERNEL is not set CONFIG_CPU_FREQ_IMX=y +CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y CONFIG_MACH_ARMADILLO5X0=y @@ -67,6 +68,7 @@ CONFIG_I2C_IMX=m CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_MCP23S08=m # CONFIG_GPIO_MC9S08DZ60 is not set +CONFIG_PINCTRL_IMX35=y CONFIG_PINCTRL_IMX51=y CONFIG_PINCTRL_IMX53=y CONFIG_USB_EHCI_MXC=y @@ -77,6 +79,12 @@ CONFIG_MMC_MXC=m CONFIG_RTC_MXC=y CONFIG_RTC_DRV_MXC=m +CONFIG_DRM_IMX=m +CONFIG_DRM_IMX_FB_HELPER=m +CONFIG_DRM_IMX_PARALLEL_DISPLAY=m +CONFIG_DRM_IMX_IPUV3_CORE=m +CONFIG_DRM_IMX_IPUV3=m +CONFIG_VIDEO_CODA=m CONFIG_BACKLIGHT_PWM=m CONFIG_LEDS_PWM=m @@ -104,6 +112,8 @@ CONFIG_SND_SOC_IMX_SGTL5000=m CONFIG_PL310_ERRATA_769419=y CONFIG_LEDS_RENESAS_TPU=y +CONFIG_MFD_MAX8907=m + CONFIG_FB_IMX=m # CONFIG_NET_VENDOR_BROADCOM is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index c8d0ec181..ff1dad7df 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -6,6 +6,7 @@ CONFIG_ARCH_KIRKWOOD_DT=y CONFIG_MACH_D2NET_V2=y CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_DOCKSTAR_DT=y CONFIG_MACH_DREAMPLUG_DT=y CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_DLINK_KIRKWOOD_DT=y @@ -14,6 +15,8 @@ CONFIG_MACH_GURUPLUG=y CONFIG_MACH_ICONNECT_DT=y CONFIG_MACH_IB62X0_DT=y CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_IOMEGA_IX2_200_DT=y +CONFIG_MACH_KM_KIRKWOOD_DT=y CONFIG_MACH_LSXL_DT=y CONFIG_MACH_MV88F6281GTW_GE=y CONFIG_MACH_NETSPACE_V2=y @@ -48,6 +51,8 @@ CONFIG_LEDS_NETXBIG=m CONFIG_RTC_DRV_MV=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m +CONFIG_PINCTRL_MVEBU=y +CONFIG_PINCTRL_KIRKWOOD=y # CONFIG_CPU_FEROCEON_OLD_ID is not set # CONFIG_INPUT_GP2A is not set diff --git a/config-arm-omap b/config-arm-omap index 8e314ce1d..68421b06e 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -176,6 +176,7 @@ CONFIG_TWL4030_POWER=y CONFIG_TWL4030_CODEC=y CONFIG_TWL4030_WATCHDOG=m CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_TWL6040=m CONFIG_CHARGER_TWL4030=m CONFIG_TWL6030_PWM=m CONFIG_TWL6040_CORE=y @@ -185,19 +186,23 @@ CONFIG_TI_DAVINCI_MDIO=m CONFIG_TI_DAVINCI_CPDMA=m CONFIG_LEDS_PWM=m +CONFIG_LEDS_LP8788=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_HDQ_MASTER_OMAP=m CONFIG_I2C_OMAP=m CONFIG_SPI_OMAP24XX=y CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m +CONFIG_MFD_LP8788=y CONFIG_REGULATOR_TWL4030=y +CONFIG_REGULATOR_LP8788=y # Enable V4L2 drivers for OMAP2+ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_VPFE_CAPTURE=m CONFIG_VIDEO_OMAP2_VOUT=m +CONFIG_VIDEO_DM6446_CCDC=m # CONFIG_VIDEO_OMAP3 is not set # Also enable vivi driver - useful for testing a full kernelspace V4L2 driver CONFIG_V4L_TEST_DRIVERS=y @@ -228,6 +233,7 @@ CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y CONFIG_PANEL_TFP410=m +CONFIG_PANEL_TAAL=m CONFIG_PANEL_PICODLP=m CONFIG_BACKLIGHT_PANDORA=m @@ -240,21 +246,22 @@ CONFIG_PANEL_NEC_NL8048HL11_01B=y CONFIG_PANEL_TPO_TD043MTEA1=y CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_MCBSP=y -CONFIG_SND_OMAP_SOC_MCPDM=y -CONFIG_SND_OMAP_SOC_OVERO=y -CONFIG_SND_OMAP_SOC_OMAP3EVM=y -CONFIG_SND_OMAP_SOC_AM3517EVM=y -CONFIG_SND_OMAP_SOC_SDP3430=y -CONFIG_SND_OMAP_SOC_SDP4430=y -CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y -CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y -CONFIG_SND_OMAP_SOC_ZOOM2=y +CONFIG_SND_OMAP_SOC_MCBSP=m +CONFIG_SND_OMAP_SOC_MCPDM=m +CONFIG_SND_OMAP_SOC_OVERO=m +CONFIG_SND_OMAP_SOC_OMAP3EVM=m +CONFIG_SND_OMAP_SOC_AM3517EVM=m +CONFIG_SND_OMAP_SOC_SDP3430=m +CONFIG_SND_OMAP_SOC_SDP4430=m +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=m +CONFIG_SND_OMAP_SOC_ZOOM2=m CONFIG_SND_OMAP_SOC_IGEP0020=y CONFIG_SND_OMAP_SOC_OMAP_HDMI=y # Because alsa is modular http://www.spinics.net/lists/linux-omap/msg67307.html # CONFIG_SND_OMAP_SOC_OMAP4_HDMI is not set CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_OMAP_SOC_RX51 is not set # CONFIG_SND_SOC_ALL_CODECS is not set @@ -292,19 +299,21 @@ CONFIG_TWL4030_USB=y CONFIG_TWL6030_USB=y CONFIG_RTC_DRV_TWL4030=y -CONFIG_TIDSPBRIDGE=m -CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +CONFIG_IR_RX51=m + +# CONFIG_TIDSPBRIDGE is not set +# CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 # CONFIG_TIDSPBRIDGE_DEBUG is not set -CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_RECOVERY=y # CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set -CONFIG_TIDSPBRIDGE_WDT3=y -CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 +# CONFIG_TIDSPBRIDGE_WDT3=y +# CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 # CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set # CONFIG_TIDSPBRIDGE_BACKTRACE is not set -CONFIG_OMAP_REMOTEPROC=m -CONFIG_OMAP_BANDGAP=m -CONFIG_OMAP_IOVMM=m +# CONFIG_OMAP_REMOTEPROC is not set +# CONFIG_OMAP_BANDGAP is not set +# CONFIG_OMAP_IOVMM is not set CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m diff --git a/config-arm-tegra b/config-arm-tegra index 78ddf0722..894b5dbef 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -18,7 +18,6 @@ CONFIG_MACH_WARIO=y CONFIG_MACH_VENTANA=y CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_NR_CPUS=4 CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_TEGRA_IOMMU_GART=y diff --git a/config-generic b/config-generic index 8fca0dc4b..e9a9307f8 100644 --- a/config-generic +++ b/config-generic @@ -190,30 +190,76 @@ CONFIG_EXTRA_FIRMWARE="" # Memory Technology Devices (MTD) # CONFIG_MTD=m +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +# CONFIG_MTD_BLKDEVS is not set +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set # CONFIG_MTD_OOPS is not set # CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# # CONFIG_MTD_CFI is not set # CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_TS5500 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# Self-contained MTD device drivers +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# # CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set # CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_BCH is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_LPDDR is not set CONFIG_MTD_UBI=m - +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set # # Parallel port support @@ -433,6 +479,7 @@ CONFIG_ATA_BMDMA=y CONFIG_ATA_VERBOSE_ERROR=y CONFIG_ATA_SFF=y CONFIG_ATA_PIIX=y +# CONFIG_SATA_HIGHBANK is not set CONFIG_ATA_ACPI=y CONFIG_BLK_DEV_SX8=m CONFIG_PDC_ADMA=m @@ -603,6 +650,7 @@ CONFIG_TCP_MD5SIG=y # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y CONFIG_UNIX_DIAG=m CONFIG_NET_KEY=m @@ -682,6 +730,7 @@ CONFIG_IPV6_MIP6=y CONFIG_IPV6_SIT=m CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_GRE is not set CONFIG_IPV6_SUBTREES=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_MROUTE=y @@ -825,7 +874,6 @@ CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_ECN=m @@ -833,6 +881,8 @@ CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_REJECT=y CONFIG_IP_NF_TARGET_TTL=m +CONFIG_NF_NAT_IPV4=m +CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m @@ -864,6 +914,9 @@ CONFIG_IP6_NF_SECURITY=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_HL=m +CONFIG_NF_NAT_IPV6=m +# CONFIG_IP6_NF_TARGET_MASQUERADE is not set +# CONFIG_IP6_NF_TARGET_NPT is not set # # Bridge: Netfilter Configuration @@ -1053,6 +1106,7 @@ CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m CONFIG_MACVTAP=m +CONFIG_VXLAN=m CONFIG_EQUALIZER=m CONFIG_TUN=m CONFIG_VETH=m @@ -1305,6 +1359,7 @@ CONFIG_NET_VENDOR_XIRCOM=y CONFIG_PCMCIA_XIRC2PS=m CONFIG_PHYLIB=y +CONFIG_AT803X_PHY=m CONFIG_AMD_PHY=m CONFIG_BROADCOM_PHY=m CONFIG_BCM87XX_PHY=m @@ -1360,6 +1415,7 @@ CONFIG_MLX4_EN_DCB=y CONFIG_SFC=m CONFIG_SFC_MCDI_MON=y CONFIG_SFC_SRIOV=y +CONFIG_SFC_PTP=y # CONFIG_SFC_MTD is not set @@ -1474,6 +1530,7 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y CONFIG_BRCMFMAC_SDIO_OOB=y CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCMISCAN is not set # CONFIG_BRCMDBG is not set # CONFIG_HERMES is not set # CONFIG_HOSTAP is not set @@ -2020,6 +2077,7 @@ CONFIG_TIFM_CORE=m CONFIG_TIFM_7XX1=m CONFIG_TCG_TPM=m CONFIG_TCG_TIS=m +# CONFIG_TCG_TIS_I2C_INFINEON is not set CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m # CONFIG_TCG_INFINEON is not set @@ -2046,6 +2104,7 @@ CONFIG_CYCLADES=m # CONFIG_ISI is not set # CONFIG_RIO is not set CONFIG_SERIAL_JSM=m +# CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_MFD_HSU is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set @@ -2054,6 +2113,7 @@ CONFIG_SERIAL_JSM=m # # Non-8250 serial port support # +# CONFIG_SERIAL_KGDB_NMI is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_XILINX_PS_UART is not set @@ -2142,6 +2202,7 @@ CONFIG_SENSORS_ADM1026=m CONFIG_SENSORS_ADM1029=m CONFIG_SENSORS_ADM1031=m CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7410=m CONFIG_SENSORS_ADS7828=m CONFIG_SENSORS_ADT7462=m CONFIG_SENSORS_ADT7470=m @@ -2261,6 +2322,7 @@ CONFIG_SENSORS_LTC2978=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set @@ -2275,6 +2337,7 @@ CONFIG_W1_CON=y CONFIG_W1_MASTER_DS2490=m CONFIG_W1_MASTER_DS2482=m CONFIG_W1_MASTER_DS1WM=m +# CONFIG_HDQ_MASTER_OMAP is not set CONFIG_W1_SLAVE_THERM=m CONFIG_W1_SLAVE_SMEM=m CONFIG_W1_SLAVE_DS2408=m @@ -2346,6 +2409,7 @@ CONFIG_W83697UG_WDT=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_TPM=m # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_RTC_DEBUG is not set @@ -2379,6 +2443,7 @@ CONFIG_RTC_DRV_RS5C372=m # CONFIG_RTC_DRV_TEST is not set CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_DS2404=m CONFIG_RTC_DRV_STK17TA8=m # CONFIG_RTC_DRV_S35390A is not set CONFIG_RTC_DRV_RX8581=m @@ -2436,6 +2501,8 @@ CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y CONFIG_DRM_VIA=m CONFIG_DRM_NOUVEAU=m +CONFIG_NOUVEAU_DEBUG=5 +CONFIG_NOUVEAU_DEBUG_DEFAULT=3 CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y # CONFIG_DRM_PSB is not set @@ -2443,6 +2510,7 @@ CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_UDL=m CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_VMWGFX_FBCON is not set CONFIG_DRM_VGEM=m # @@ -2458,6 +2526,8 @@ CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=8192 CONFIG_HANGCHECK_TIMER=m +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_MEDIA_PCI_SUPPORT=y # # Multimedia devices # @@ -2515,6 +2585,7 @@ CONFIG_VIDEO_CX231XX_RC=y CONFIG_VIDEO_HEXIUM_ORION=m CONFIG_VIDEO_HEXIUM_GEMINI=m CONFIG_VIDEO_IVTV=m +# CONFIG_VIDEO_IVTV_ALSA is not set CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m CONFIG_VIDEO_PVRUSB2_DVB=y @@ -2526,6 +2597,8 @@ CONFIG_VIDEO_SAA7134_ALSA=m CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7134_RC=y CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160=m +CONFIG_VIDEO_STK1160_AC97=y CONFIG_VIDEO_W9966=m CONFIG_VIDEO_ZORAN=m CONFIG_VIDEO_ZORAN_AVS6EYES=m @@ -2589,6 +2662,7 @@ CONFIG_DVB_BT8XX=m CONFIG_DVB_BUDGET_CORE=m CONFIG_DVB_PLUTO2=m CONFIG_SMS_SIANO_MDTV=m +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_SMS_USB_DRV=m CONFIG_SMS_SDIO_DRV=m CONFIG_DVB_TTUSB_DEC=m @@ -2606,6 +2680,7 @@ CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_USB_TECHNISAT_USB2=m +# CONFIG_DVB_USB_V2 is not set CONFIG_DVB_AV7110=m CONFIG_DVB_AV7110_OSD=y @@ -2618,7 +2693,10 @@ CONFIG_DVB_TTUSB_BUDGET=m CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_B2C2_FLEXCOP=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set + CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set CONFIG_DVB_B2C2_FLEXCOP_USB=m # CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set CONFIG_DVB_USB=m @@ -2690,9 +2768,13 @@ CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m CONFIG_IR_GPIO_CIR=m CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_V4L_TEST_DRIVERS is not set + # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set # @@ -3066,6 +3148,7 @@ CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y CONFIG_HID_PRIMAX=m +CONFIG_HID_PS3REMOTE=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m CONFIG_HID_GYRATION=m @@ -3085,6 +3168,7 @@ CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m +# CONFIG_HID_SENSOR_HUB is not set CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m CONFIG_HID_UCLOGIC=m @@ -3276,6 +3360,7 @@ CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_SERIAL_MOS7720=m CONFIG_USB_SERIAL_MOS7715_PARPORT=y # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_ZTE is not set CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_MOTOROLA=m CONFIG_USB_SERIAL_NAVMAN=m @@ -3316,6 +3401,7 @@ CONFIG_USB_ADUTUX=m CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m +# CONFIG_OMAP_USB2 is not set CONFIG_USB_ATM=m CONFIG_USB_CXACRU=m # CONFIG_USB_C67X00_HCD is not set @@ -3334,6 +3420,7 @@ CONFIG_USB_FILE_STORAGE=m CONFIG_USB_IOWARRIOR=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m +CONFIG_USB_EZUSB_FX2=m CONFIG_USB_LCD=m CONFIG_USB_LD=m CONFIG_USB_LEGOTOWER=m @@ -3584,6 +3671,7 @@ CONFIG_RPCSEC_GSS_KRB5=m CONFIG_CIFS=m CONFIG_CIFS_STATS=y # CONFIG_CIFS_STATS2 is not set +CONFIG_CIFS_SMB2=y CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y @@ -3755,6 +3843,7 @@ CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_VM_RB is not set # revisit this if performance isn't horrible # CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set @@ -3768,7 +3857,6 @@ CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_BACKTRACE_SELF_TEST is not set CONFIG_LATENCYTOP=y CONFIG_RESOURCE_COUNTERS=y -# CONFIG_MEMCG is not set # CONFIG_COMPAT_BRK is not set # CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set @@ -3919,6 +4007,8 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=m CONFIG_BACKLIGHT_PROGEAR=m # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630 is not set +# CONFIG_BACKLIGHT_LM3639 is not set CONFIG_FB_NVIDIA_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y CONFIG_FB_RADEON_BACKLIGHT=y @@ -3970,10 +4060,15 @@ CONFIG_KEXEC=y CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set CONFIG_THERMAL_HWMON=y +# CONFIG_CPU_THERMAL is not set CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y +# +# Bus devices +# +# CONFIG_OMAP_OCP2SCP is not set CONFIG_CONNECTOR=y CONFIG_PROC_EVENTS=y @@ -4008,6 +4103,8 @@ CONFIG_NET_VENDOR_SMC=y # CONFIG_MOUSE_ATIXL is not set +# CONFIG_MEDIA_PARPORT_SUPPORT is not set + CONFIG_RADIO_ADAPTERS=y CONFIG_RADIO_TEA5764=m CONFIG_RADIO_SAA7706H=m @@ -4054,6 +4151,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_PCA9633 is not set CONFIG_LEDS_DELL_NETBOOKS=m # CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m @@ -4061,12 +4159,14 @@ CONFIG_LEDS_TRIGGER_ONESHOT=m CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m +# CONFIG_LEDS_TRIGGER_CPU is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_ALIX2=m CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m CONFIG_LEDS_LM3530=m +# CONFIG_LEDS_LM3642 is not set CONFIG_LEDS_LM3556=m CONFIG_LEDS_BLINKM=m CONFIG_LEDS_LP3944=m @@ -4100,6 +4200,8 @@ CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_TRACE_BRANCH_PROFILING is not set CONFIG_FUNCTION_PROFILER=y CONFIG_RING_BUFFER_BENCHMARK=m +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y # CONFIG_FUNCTION_GRAPH_TRACER is not set @@ -4315,9 +4417,19 @@ CONFIG_ALTERA_STAPL=m # CONFIG_WIMAX_GDM72XX is not set # CONFIG_IPACK_BUS is not set # CONFIG_CSR_WIFI is not set -# +# CONFIG_ZCACHE2 is not set +# CONFIG_NET_VENDOR_SILICOM is not set +# CONFIG_SBYPASS is not set +# CONFIG_BPCTL is not set +# CONFIG_CED1401 is not set +# CONFIG_DGRP is not set # END OF STAGING +# +# Remoteproc drivers (EXPERIMENTAL) +# +# CONFIG_STE_MODEM_RPROC is not set + CONFIG_LIBFC=m CONFIG_LIBFCOE=m CONFIG_FCOE=m diff --git a/config-powerpc-generic b/config-powerpc-generic index a263acc80..a6ef1c4df 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -372,3 +372,11 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_FAIL_IOMMU is not set + +# CONFIG_PPC_DENORMALISATION is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + diff --git a/config-powerpc64 b/config-powerpc64 index 82f4c603b..7c0477cf1 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -167,7 +167,10 @@ CONFIG_HW_RANDOM_AMD=m CONFIG_UIO_PDRV=m CONFIG_HW_RANDOM_PSERIES=m -CONFIG_CRYPTO_DEV_NX=m +CONFIG_CRYPTO_DEV_NX=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_DEV_NX_ENCRYPT=m +CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y diff --git a/config-powerpc64p7 b/config-powerpc64p7 index e8e826a88..9a8289588 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -158,7 +158,10 @@ CONFIG_HW_RANDOM_AMD=m CONFIG_UIO_PDRV=m CONFIG_HW_RANDOM_PSERIES=m -CONFIG_CRYPTO_DEV_NX=m +CONFIG_CRYPTO_DEV_NX=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_DEV_NX_ENCRYPT=m +CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y diff --git a/config-s390x b/config-s390x index 451512e9a..41e41c53c 100644 --- a/config-s390x +++ b/config-s390x @@ -241,3 +241,12 @@ CONFIG_STRICT_DEVMEM=y CONFIG_CRYPTO_GHASH_S390=m CONFIG_NET_CORE=y CONFIG_ETHERNET=y + +CONFIG_BPF_JIT=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_SCM_BUS is not set +# CONFIG_EADM_SCH is not set +# CONFIG_SCM_BLOCK is not set +# CONFIG_SCM_BLOCK_CLUSTER_WRITE is not set +# CONFIG_S390_PTDUMP is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set diff --git a/config-sparc64-generic b/config-sparc64-generic index ebc891d8a..e15e2ef18 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -201,3 +201,17 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y CONFIG_BPF_JIT=y # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_IRQ_DOMAIN_DEBUG is not set + +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_CRYPTO_CRC32C_SPARC64 is not set +# CONFIG_CRYPTO_MD5_SPARC64 is not set +# CONFIG_CRYPTO_SHA1_SPARC64 is not set +# CONFIG_CRYPTO_SHA256_SPARC64 is not set +# CONFIG_CRYPTO_SHA512_SPARC64 is not set +# CONFIG_CRYPTO_AES_SPARC64 is not set +# CONFIG_CRYPTO_CAMELLIA_SPARC64 is not set +# CONFIG_CRYPTO_DES_SPARC64 is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + diff --git a/config-x86-32-generic b/config-x86-32-generic index b1a04993a..1216d47e6 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -190,6 +190,7 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_X86_INTEL_MID is not set CONFIG_MFD_CS5535=m +# CONFIG_MFD_SYSCON is not set # I2O enabled only for 32-bit x86, disabled for PAE kernel CONFIG_I2O=m @@ -211,5 +212,8 @@ CONFIG_I2O_BUS=m # CONFIG_GEOS is not set # CONFIG_NET5501 is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set # CONFIG_GPIO_SODAVILLE is not set +# CONFIG_GPIO_ADNP is not set # CONFIG_BACKLIGHT_OT200 is not set +# CONFIG_RTC_DRV_SNVS is not set diff --git a/config-x86-generic b/config-x86-generic index b26f42d9f..2bcd498eb 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -91,10 +91,11 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_ACPI_BGRT=m +CONFIG_ACPI_BGRT=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_PCC_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_SPEEDSTEP_CENTRINO is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index 342b8620a..6003f11c0 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -46,6 +46,8 @@ CONFIG_CRYPTO_SHA1_SSSE3=m CONFIG_CRYPTO_BLOWFISH_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m CONFIG_CRYPTO_CAMELLIA_X86_64=m +CONFIG_CRYPTO_CAST5_AVX_X86_64=m +CONFIG_CRYPTO_CAST6_AVX_X86_64=m CONFIG_CRYPTO_SERPENT_AVX_X86_64=m CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m @@ -107,6 +109,7 @@ CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y CONFIG_RCU_FANOUT=64 +# CONFIG_RCU_USER_QS is not set CONFIG_INTEL_TXT=y diff --git a/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch b/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch deleted file mode 100644 index d4e837ab1..000000000 --- a/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 696199f8ccf7fc6d17ef89c296ad3b6c78c52d9c Mon Sep 17 00:00:00 2001 -From: Al Viro -Date: Thu, 29 Nov 2012 22:00:51 -0500 -Subject: [PATCH] don't do blind d_drop() in nfs_prime_dcache() - -Signed-off-by: Al Viro ---- - fs/nfs/dir.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index ce8cb92..99489cf 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) - nfs_refresh_inode(dentry->d_inode, entry->fattr); - goto out; - } else { -- d_drop(dentry); -+ if (d_invalidate(dentry) != 0) -+ goto out; - dput(dentry); - } - } --- -1.8.0.1 - diff --git a/efivarfs-3.7.patch b/efivarfs-3.7.patch new file mode 100644 index 000000000..300910716 --- /dev/null +++ b/efivarfs-3.7.patch @@ -0,0 +1,1630 @@ +From cb6f23ee9601297c3c70d0cfe3d77dfde9bd119d Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 01/17] efi: Add support for a UEFI variable filesystem + +The existing EFI variables code only supports variables of up to 1024 +bytes. This limitation existed in version 0.99 of the EFI specification, +but was removed before any full releases. Since variables can now be +larger than a single page, sysfs isn't the best interface for this. So, +instead, let's add a filesystem. Variables can be read, written and +created, with the first 4 bytes of each variable representing its UEFI +attributes. The create() method doesn't actually commit to flash since +zero-length variables can't exist per-spec. + +Updates from Jeremy Kerr . + +Signed-off-by: Matthew Garrett +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 384 ++++++++++++++++++++++++++++++++++++++++++++- + include/linux/efi.h | 5 + + 2 files changed, 383 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d10c987..b605c48 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -80,6 +80,10 @@ + #include + #include + ++#include ++#include ++#include ++ + #include + + #define EFIVARS_VERSION "0.08" +@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 ++#define GUID_LEN 37 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -108,7 +113,6 @@ struct efi_variable { + __u32 Attributes; + } __attribute__((packed)); + +- + struct efivar_entry { + struct efivars *efivars; + struct efi_variable var; +@@ -122,6 +126,9 @@ struct efivar_attribute { + ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); + }; + ++static struct efivars __efivars; ++static struct efivar_operations ops; ++ + #define PSTORE_EFI_ATTRIBUTES \ + (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ +@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = { + .default_attrs = def_attrs, + }; + +-static struct pstore_info efi_pstore_info; +- + static inline void + efivar_unregister(struct efivar_entry *var) + { + kobject_put(&var->kobj); + } + ++static int efivarfs_file_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static ssize_t efivarfs_file_write(struct file *file, ++ const char __user *userbuf, size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars; ++ efi_status_t status; ++ void *data; ++ u32 attributes; ++ struct inode *inode = file->f_mapping->host; ++ int datasize = count - sizeof(attributes); ++ ++ if (count < sizeof(attributes)) ++ return -EINVAL; ++ ++ data = kmalloc(datasize, GFP_KERNEL); ++ ++ if (!data) ++ return -ENOMEM; ++ ++ efivars = var->efivars; ++ ++ if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (attributes & ~(EFI_VARIABLE_MASK)) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { ++ count = -EFAULT; ++ goto out; ++ } ++ ++ if (validate_var(&var->var, data, datasize) == false) { ++ count = -EINVAL; ++ goto out; ++ } ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ attributes, datasize, ++ data); ++ ++ switch (status) { ++ case EFI_SUCCESS: ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, count); ++ mutex_unlock(&inode->i_mutex); ++ break; ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ break; ++ } ++out: ++ kfree(data); ++ ++ return count; ++} ++ ++static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct efivar_entry *var = file->private_data; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ unsigned long datasize = 0; ++ u32 attributes; ++ void *data; ++ ssize_t size; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, NULL); ++ ++ if (status != EFI_BUFFER_TOO_SMALL) ++ return 0; ++ ++ data = kmalloc(datasize + 4, GFP_KERNEL); ++ ++ if (!data) ++ return 0; ++ ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ &attributes, &datasize, ++ (data + 4)); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ memcpy(data, &attributes, 4); ++ size = simple_read_from_buffer(userbuf, count, ppos, ++ data, datasize + 4); ++ kfree(data); ++ ++ return size; ++} ++ ++static void efivarfs_evict_inode(struct inode *inode) ++{ ++ clear_inode(inode); ++} ++ ++static const struct super_operations efivarfs_ops = { ++ .statfs = simple_statfs, ++ .drop_inode = generic_delete_inode, ++ .evict_inode = efivarfs_evict_inode, ++ .show_options = generic_show_options, ++}; ++ ++static struct super_block *efivarfs_sb; ++ ++static const struct inode_operations efivarfs_dir_inode_operations; ++ ++static const struct file_operations efivarfs_file_operations = { ++ .open = efivarfs_file_open, ++ .read = efivarfs_file_read, ++ .write = efivarfs_file_write, ++ .llseek = no_llseek, ++}; ++ ++static struct inode *efivarfs_get_inode(struct super_block *sb, ++ const struct inode *dir, int mode, dev_t dev) ++{ ++ struct inode *inode = new_inode(sb); ++ ++ if (inode) { ++ inode->i_ino = get_next_ino(); ++ inode->i_uid = inode->i_gid = 0; ++ inode->i_mode = mode; ++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ inode->i_fop = &efivarfs_file_operations; ++ break; ++ case S_IFDIR: ++ inode->i_op = &efivarfs_dir_inode_operations; ++ inode->i_fop = &simple_dir_operations; ++ inc_nlink(inode); ++ break; ++ } ++ } ++ return inode; ++} ++ ++static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) ++{ ++ guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); ++ guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]); ++ guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]); ++ guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]); ++ guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]); ++ guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]); ++ guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]); ++ guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]); ++ guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]); ++ guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]); ++ guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]); ++ guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]); ++ guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]); ++ guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]); ++ guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]); ++ guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]); ++} ++ ++static int efivarfs_create(struct inode *dir, struct dentry *dentry, ++ umode_t mode, bool excl) ++{ ++ struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct efivars *efivars = &__efivars; ++ struct efivar_entry *var; ++ int namelen, i = 0, err = 0; ++ ++ if (dentry->d_name.len < 38) ++ return -EINVAL; ++ ++ if (!inode) ++ return -ENOSPC; ++ ++ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); ++ ++ if (!var) ++ return -ENOMEM; ++ ++ namelen = dentry->d_name.len - GUID_LEN; ++ ++ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, ++ &var->var.VendorGuid); ++ ++ for (i = 0; i < namelen; i++) ++ var->var.VariableName[i] = dentry->d_name.name[i]; ++ ++ var->var.VariableName[i] = '\0'; ++ ++ inode->i_private = var; ++ var->efivars = efivars; ++ var->kobj.kset = efivars->kset; ++ ++ err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", ++ dentry->d_name.name); ++ if (err) ++ goto out; ++ ++ kobject_uevent(&var->kobj, KOBJ_ADD); ++ spin_lock(&efivars->lock); ++ list_add(&var->list, &efivars->list); ++ spin_unlock(&efivars->lock); ++ d_instantiate(dentry, inode); ++ dget(dentry); ++out: ++ if (err) ++ kfree(var); ++ return err; ++} ++ ++static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ struct efivar_entry *var = dentry->d_inode->i_private; ++ struct efivars *efivars = var->efivars; ++ efi_status_t status; ++ ++ spin_lock(&efivars->lock); ++ ++ status = efivars->ops->set_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ 0, 0, NULL); ++ ++ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(dir); ++ dput(dentry); ++ return 0; ++ } ++ ++ spin_unlock(&efivars->lock); ++ return -EINVAL; ++}; ++ ++int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct inode *inode = NULL; ++ struct dentry *root; ++ struct efivar_entry *entry, *n; ++ struct efivars *efivars = &__efivars; ++ int err; ++ ++ efivarfs_sb = sb; ++ ++ sb->s_maxbytes = MAX_LFS_FILESIZE; ++ sb->s_blocksize = PAGE_CACHE_SIZE; ++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_op = &efivarfs_ops; ++ sb->s_time_gran = 1; ++ ++ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); ++ if (!inode) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ inode->i_op = &efivarfs_dir_inode_operations; ++ ++ root = d_make_root(inode); ++ sb->s_root = root; ++ if (!root) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ list_for_each_entry_safe(entry, n, &efivars->list, list) { ++ struct inode *inode; ++ struct dentry *dentry, *root = efivarfs_sb->s_root; ++ char *name; ++ unsigned long size = 0; ++ int len, i; ++ ++ len = utf16_strlen(entry->var.VariableName); ++ ++ /* GUID plus trailing NULL */ ++ name = kmalloc(len + 38, GFP_ATOMIC); ++ ++ for (i = 0; i < len; i++) ++ name[i] = entry->var.VariableName[i] & 0xFF; ++ ++ name[len] = '-'; ++ ++ efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); ++ ++ name[len+GUID_LEN] = '\0'; ++ ++ inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, ++ S_IFREG | 0644, 0); ++ dentry = d_alloc_name(root, name); ++ ++ efivars->ops->get_variable(entry->var.VariableName, ++ &entry->var.VendorGuid, ++ &entry->var.Attributes, ++ &size, ++ NULL); ++ ++ mutex_lock(&inode->i_mutex); ++ inode->i_private = entry; ++ i_size_write(inode, size+4); ++ mutex_unlock(&inode->i_mutex); ++ d_add(dentry, inode); ++ } ++ ++ return 0; ++fail: ++ iput(inode); ++ return err; ++} ++ ++static struct dentry *efivarfs_mount(struct file_system_type *fs_type, ++ int flags, const char *dev_name, void *data) ++{ ++ return mount_single(fs_type, flags, data, efivarfs_fill_super); ++} ++ ++static void efivarfs_kill_sb(struct super_block *sb) ++{ ++ kill_litter_super(sb); ++ efivarfs_sb = NULL; ++} ++ ++static struct file_system_type efivarfs_type = { ++ .name = "efivarfs", ++ .mount = efivarfs_mount, ++ .kill_sb = efivarfs_kill_sb, ++}; ++ ++static const struct inode_operations efivarfs_dir_inode_operations = { ++ .lookup = simple_lookup, ++ .unlink = efivarfs_unlink, ++ .create = efivarfs_create, ++}; ++ ++static struct pstore_info efi_pstore_info; ++ + #ifdef CONFIG_PSTORE + + static int efi_pstore_open(struct pstore_info *psi) +@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars, + pstore_register(&efivars->efi_pstore_info); + } + ++ register_filesystem(&efivarfs_type); ++ + out: + kfree(variable_name); + +@@ -1205,9 +1580,6 @@ out: + } + EXPORT_SYMBOL_GPL(register_efivars); + +-static struct efivars __efivars; +-static struct efivar_operations ops; +- + /* + * For now we register the efi subsystem with the firmware subsystem + * and the vars subsystem with the efi subsystem. In the future, it +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 8670eb1..b2af157 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -29,7 +29,12 @@ + #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) + #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) + #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) ++#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) + + typedef unsigned long efi_status_t; + typedef u8 efi_bool_t; +-- +1.7.12.1 + + +From 2fc1dc88e97665c70f203f0132232ea55e8dd7eb Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 02/17] efi: Handle deletions and size changes in + efivarfs_write_file + +A write to an efivarfs file will not always result in a variable of +'count' size after the EFI SetVariable() call. We may have appended to +the existing data (ie, with the EFI_VARIABLE_APPEND_WRITE attribute), or +even have deleted the variable (with an authenticated variable update, +with a zero datasize). + +This change re-reads the updated variable from firmware, to check for +size changes and deletions. In the latter case, we need to drop the +dentry. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 49 ++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b605c48..d7658b4 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file, + u32 attributes; + struct inode *inode = file->f_mapping->host; + int datasize = count - sizeof(attributes); ++ unsigned long newdatasize; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file, + + switch (status) { + case EFI_SUCCESS: +- mutex_lock(&inode->i_mutex); +- i_size_write(inode, count); +- mutex_unlock(&inode->i_mutex); + break; + case EFI_INVALID_PARAMETER: + count = -EINVAL; +- break; ++ goto out; + case EFI_OUT_OF_RESOURCES: + count = -ENOSPC; +- break; ++ goto out; + case EFI_DEVICE_ERROR: + count = -EIO; +- break; ++ goto out; + case EFI_WRITE_PROTECTED: + count = -EROFS; +- break; ++ goto out; + case EFI_SECURITY_VIOLATION: + count = -EACCES; +- break; ++ goto out; + case EFI_NOT_FOUND: + count = -ENOENT; +- break; ++ goto out; + default: + count = -EINVAL; +- break; ++ goto out; + } ++ ++ /* ++ * Writing to the variable may have caused a change in size (which ++ * could either be an append or an overwrite), or the variable to be ++ * deleted. Perform a GetVariable() so we can tell what actually ++ * happened. ++ */ ++ newdatasize = 0; ++ status = efivars->ops->get_variable(var->var.VariableName, ++ &var->var.VendorGuid, ++ NULL, &newdatasize, ++ NULL); ++ ++ if (status == EFI_BUFFER_TOO_SMALL) { ++ mutex_lock(&inode->i_mutex); ++ i_size_write(inode, newdatasize + sizeof(attributes)); ++ mutex_unlock(&inode->i_mutex); ++ ++ } else if (status == EFI_NOT_FOUND) { ++ spin_lock(&efivars->lock); ++ list_del(&var->list); ++ spin_unlock(&efivars->lock); ++ efivar_unregister(var); ++ drop_nlink(inode); ++ dput(file->f_dentry); ++ ++ } else { ++ pr_warn("efivarfs: inconsistent EFI variable implementation? " ++ "status = %lx\n", status); ++ } ++ + out: + kfree(data); + +-- +1.7.12.1 + + +From c98611fc95672862950c9bc4d6a3a4c4453a3c3e Mon Sep 17 00:00:00 2001 +From: "Lee, Chun-Yi" +Date: Fri, 5 Oct 2012 13:54:56 +0800 +Subject: [PATCH 03/17] efi: add efivars kobject to efi sysfs folder + +UEFI variable filesystem need a new mount point, so this patch add +efivars kobject to efi_kobj for create a /sys/firmware/efi/efivars +folder. + +Cc: Matthew Garrett +Cc: H. Peter Anvin +Signed-off-by: Lee, Chun-Yi +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 9 +++++++++ + include/linux/efi.h | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d7658b4..6793965 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -1527,6 +1527,7 @@ void unregister_efivars(struct efivars *efivars) + sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); + kfree(efivars->new_var); + kfree(efivars->del_var); ++ kobject_put(efivars->kobject); + kset_unregister(efivars->kset); + } + EXPORT_SYMBOL_GPL(unregister_efivars); +@@ -1558,6 +1559,14 @@ int register_efivars(struct efivars *efivars, + goto out; + } + ++ efivars->kobject = kobject_create_and_add("efivars", parent_kobj); ++ if (!efivars->kobject) { ++ pr_err("efivars: Subsystem registration failed.\n"); ++ error = -ENOMEM; ++ kset_unregister(efivars->kset); ++ goto out; ++ } ++ + /* + * Per EFI spec, the maximum storage allocated for both + * the variable name and variable data is 1024 bytes. +diff --git a/include/linux/efi.h b/include/linux/efi.h +index b2af157..337aefb 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -662,6 +662,7 @@ struct efivars { + spinlock_t lock; + struct list_head list; + struct kset *kset; ++ struct kobject *kobject; + struct bin_attribute *new_var, *del_var; + const struct efivar_operations *ops; + struct efivar_entry *walk_entry; +-- +1.7.12.1 + + +From 8ef5f49da57087022f2031820ceb3b1c6101d76c Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Thu, 4 Oct 2012 09:57:31 +0100 +Subject: [PATCH 04/17] efivarfs: Add documentation for the EFI variable + filesystem + +Signed-off-by: Matt Fleming +--- + Documentation/filesystems/00-INDEX | 2 ++ + Documentation/filesystems/efivarfs.txt | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 Documentation/filesystems/efivarfs.txt + +diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX +index 8c624a1..7b52ba7 100644 +--- a/Documentation/filesystems/00-INDEX ++++ b/Documentation/filesystems/00-INDEX +@@ -38,6 +38,8 @@ dnotify_test.c + - example program for dnotify + ecryptfs.txt + - docs on eCryptfs: stacked cryptographic filesystem for Linux. ++efivarfs.txt ++ - info for the efivarfs filesystem. + exofs.txt + - info, usage, mount options, design about EXOFS. + ext2.txt +diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt +new file mode 100644 +index 0000000..c477af0 +--- /dev/null ++++ b/Documentation/filesystems/efivarfs.txt +@@ -0,0 +1,16 @@ ++ ++efivarfs - a (U)EFI variable filesystem ++ ++The efivarfs filesystem was created to address the shortcomings of ++using entries in sysfs to maintain EFI variables. The old sysfs EFI ++variables code only supported variables of up to 1024 bytes. This ++limitation existed in version 0.99 of the EFI specification, but was ++removed before any full releases. Since variables can now be larger ++than a single page, sysfs isn't the best interface for this. ++ ++Variables can be created, deleted and modified with the efivarfs ++filesystem. ++ ++efivarfs is typically mounted like this, ++ ++ mount -t efivarfs none /sys/firmware/efi/efivars +-- +1.7.12.1 + + +From f69c39248e2f1eebf24f5ee55139602c56d15aec Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:17 +0100 +Subject: [PATCH 05/17] efivarfs: efivarfs_file_read ensure we free data in + error paths + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6793965..b7c9a32 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -766,7 +766,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + unsigned long datasize = 0; + u32 attributes; + void *data; +- ssize_t size; ++ ssize_t size = 0; + + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, +@@ -784,13 +784,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); +- + if (status != EFI_SUCCESS) +- return 0; ++ goto out_free; + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, + data, datasize + 4); ++out_free: + kfree(data); + + return size; +-- +1.7.12.1 + + +From 429136e16c7c43bbebb8b8030203161a2d3fc3ce Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:18 +0100 +Subject: [PATCH 06/17] efivarfs: efivarfs_create() ensure we drop our + reference on inode on error + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index b7c9a32..6e5f367 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -866,7 +866,7 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) + static int efivarfs_create(struct inode *dir, struct dentry *dentry, + umode_t mode, bool excl) + { +- struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); ++ struct inode *inode; + struct efivars *efivars = &__efivars; + struct efivar_entry *var; + int namelen, i = 0, err = 0; +@@ -874,13 +874,15 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + if (dentry->d_name.len < 38) + return -EINVAL; + ++ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) + return -ENOSPC; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); +- +- if (!var) +- return -ENOMEM; ++ if (!var) { ++ err = -ENOMEM; ++ goto out; ++ } + + namelen = dentry->d_name.len - GUID_LEN; + +@@ -908,8 +910,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + d_instantiate(dentry, inode); + dget(dentry); + out: +- if (err) ++ if (err) { + kfree(var); ++ iput(inode); ++ } + return err; + } + +-- +1.7.12.1 + + +From 1a19268e8a4bae43c1feb3f71ee468c6bc70aca6 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:19 +0100 +Subject: [PATCH 07/17] efivarfs: efivarfs_fill_super() fix inode reference + counts + +When d_make_root() fails it will automatically drop the reference +on the root inode. We should not be doing so as well. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6e5f367..adfc486 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,7 +948,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; +- int err; + + efivarfs_sb = sb; + +@@ -960,18 +959,14 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_time_gran = 1; + + inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); +- if (!inode) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!inode) ++ return -ENOMEM; + inode->i_op = &efivarfs_dir_inode_operations; + + root = d_make_root(inode); + sb->s_root = root; +- if (!root) { +- err = -ENOMEM; +- goto fail; +- } ++ if (!root) ++ return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { + struct inode *inode; +@@ -1012,9 +1007,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; +-fail: +- iput(inode); +- return err; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From f0d90a4024493aed6fc77ce5cd3b93f278fed9c0 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:20 +0100 +Subject: [PATCH 08/17] efivarfs: efivarfs_fill_super() ensure we free our + temporary name + +d_alloc_name() copies the passed name to new storage, once complete we +no longer need our name. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index adfc486..36b3dd6 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -992,6 +992,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); + dentry = d_alloc_name(root, name); ++ /* copied by the above to local storage in the dentry. */ ++ kfree(name); + + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, +-- +1.7.12.1 + + +From c4cf244c318218153200d0011d8ef0ebcf3146ea Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 11 Oct 2012 11:32:21 +0100 +Subject: [PATCH 09/17] efivarfs: efivarfs_fill_super() ensure we clean up + correctly on error + +Ensure we free both the name and inode on error when building the +individual variables. + +Signed-off-by: Andy Whitcroft +Acked-by: Matthew Garrett +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 36b3dd6..216086d 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct dentry *root; + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; ++ char *name; + + efivarfs_sb = sb; + +@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + return -ENOMEM; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { +- struct inode *inode; + struct dentry *dentry, *root = efivarfs_sb->s_root; +- char *name; + unsigned long size = 0; + int len, i; + ++ inode = NULL; ++ + len = utf16_strlen(entry->var.VariableName); + + /* GUID plus trailing NULL */ + name = kmalloc(len + 38, GFP_ATOMIC); ++ if (!name) ++ goto fail; + + for (i = 0; i < len; i++) + name[i] = entry->var.VariableName[i] & 0xFF; +@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); ++ if (!inode) ++ goto fail_name; ++ + dentry = d_alloc_name(root, name); ++ if (!dentry) ++ goto fail_inode; ++ + /* copied by the above to local storage in the dentry. */ + kfree(name); + +@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + } + + return 0; ++ ++fail_inode: ++ iput(inode); ++fail_name: ++ kfree(name); ++fail: ++ return -ENOMEM; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.7.12.1 + + +From d3b7165568bcb50e4526c3dadda59e43f6681bc0 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Thu, 11 Oct 2012 21:19:11 +0800 +Subject: [PATCH 10/17] efivarfs: Implement exclusive access for + {get,set}_variable + +Currently, efivarfs does not enforce exclusion over the get_variable and +set_variable operations. Section 7.1 of UEFI requires us to only allow a +single processor to enter {get,set}_variable services at once. + +This change acquires the efivars->lock over calls to these operations +from the efivarfs paths. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 68 +++++++++++++++++++++++++++++----------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 216086d..d478c56 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -690,35 +690,45 @@ static ssize_t efivarfs_file_write(struct file *file, + goto out; + } + ++ /* ++ * The lock here protects the get_variable call, the conditional ++ * set_variable call, and removal of the variable from the efivars ++ * list (in the case of an authenticated delete). ++ */ ++ spin_lock(&efivars->lock); ++ + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, + attributes, datasize, + data); + +- switch (status) { +- case EFI_SUCCESS: +- break; +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- goto out; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- goto out; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- goto out; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- goto out; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- goto out; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- goto out; +- default: +- count = -EINVAL; +- goto out; ++ if (status != EFI_SUCCESS) { ++ spin_unlock(&efivars->lock); ++ kfree(data); ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ count = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ count = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ count = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ count = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ count = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ count = -ENOENT; ++ break; ++ default: ++ count = -EINVAL; ++ } ++ return count; + } + + /* +@@ -734,12 +744,12 @@ static ssize_t efivarfs_file_write(struct file *file, + NULL); + + if (status == EFI_BUFFER_TOO_SMALL) { ++ spin_unlock(&efivars->lock); + mutex_lock(&inode->i_mutex); + i_size_write(inode, newdatasize + sizeof(attributes)); + mutex_unlock(&inode->i_mutex); + + } else if (status == EFI_NOT_FOUND) { +- spin_lock(&efivars->lock); + list_del(&var->list); + spin_unlock(&efivars->lock); + efivar_unregister(var); +@@ -747,6 +757,7 @@ static ssize_t efivarfs_file_write(struct file *file, + dput(file->f_dentry); + + } else { ++ spin_unlock(&efivars->lock); + pr_warn("efivarfs: inconsistent EFI variable implementation? " + "status = %lx\n", status); + } +@@ -768,9 +779,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + void *data; + ssize_t size = 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, NULL); ++ spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) + return 0; +@@ -780,10 +793,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (!data) + return 0; + ++ spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, + (data + 4)); ++ spin_unlock(&efivars->lock); ++ + if (status != EFI_SUCCESS) + goto out_free; + +@@ -1004,11 +1020,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + /* copied by the above to local storage in the dentry. */ + kfree(name); + ++ spin_lock(&efivars->lock); + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, + &entry->var.Attributes, + &size, + NULL); ++ spin_unlock(&efivars->lock); + + mutex_lock(&inode->i_mutex); + inode->i_private = entry; +-- +1.7.12.1 + + +From 90a462e9cf439a1987e0f9434d1f615addcc1970 Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Fri, 19 Oct 2012 15:16:45 +0800 +Subject: [PATCH 11/17] efi: Clarify GUID length calculations + +At present, the handling of GUIDs in efivar file names isn't consistent. +We use GUID_LEN in some places, and 38 in others (GUID_LEN plus +separator), and implicitly use the presence of the trailing NUL. + +This change removes the trailing NUL from GUID_LEN, so that we're +explicitly adding it when required. We also replace magic numbers +with GUID_LEN, and clarify the comments where appropriate. + +We also fix the allocation size in efivar_create_sysfs_entry, where +we're allocating one byte too much, due to counting the trailing NUL +twice - once when calculating short_name_size, and once in the kzalloc. + +Signed-off-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 33 +++++++++++++++++++++++++-------- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d478c56..a93e401 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -95,7 +95,12 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(EFIVARS_VERSION); + + #define DUMP_NAME_LEN 52 +-#define GUID_LEN 37 ++ ++/* ++ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) ++ * not including trailing NUL ++ */ ++#define GUID_LEN 36 + + /* + * The maximum size of VariableName + Data = 1024 +@@ -887,7 +892,11 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + struct efivar_entry *var; + int namelen, i = 0, err = 0; + +- if (dentry->d_name.len < 38) ++ /* ++ * We need a GUID, plus at least one letter for the variable name, ++ * plus the '-' separator ++ */ ++ if (dentry->d_name.len < GUID_LEN + 2) + return -EINVAL; + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); +@@ -900,7 +909,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + goto out; + } + +- namelen = dentry->d_name.len - GUID_LEN; ++ /* length of the variable name itself: remove GUID and separator */ ++ namelen = dentry->d_name.len - GUID_LEN - 1; + + efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, + &var->var.VendorGuid); +@@ -994,8 +1004,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + len = utf16_strlen(entry->var.VariableName); + +- /* GUID plus trailing NULL */ +- name = kmalloc(len + 38, GFP_ATOMIC); ++ /* name, plus '-', plus GUID, plus NUL*/ ++ name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); + if (!name) + goto fail; + +@@ -1006,7 +1016,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + + efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); + +- name[len+GUID_LEN] = '\0'; ++ name[len+GUID_LEN+1] = '\0'; + + inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, + S_IFREG | 0644, 0); +@@ -1435,11 +1445,18 @@ efivar_create_sysfs_entry(struct efivars *efivars, + efi_char16_t *variable_name, + efi_guid_t *vendor_guid) + { +- int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; ++ int i, short_name_size; + char *short_name; + struct efivar_entry *new_efivar; + +- short_name = kzalloc(short_name_size + 1, GFP_KERNEL); ++ /* ++ * Length of the variable bytes in ASCII, plus the '-' separator, ++ * plus the GUID, plus trailing NUL ++ */ ++ short_name_size = variable_name_size / sizeof(efi_char16_t) ++ + 1 + GUID_LEN + 1; ++ ++ short_name = kzalloc(short_name_size, GFP_KERNEL); + new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + + if (!short_name || !new_efivar) { +-- +1.7.12.1 + + +From ecbf90823d85ebb41e68e6be01f476862d184825 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 16 Oct 2012 15:58:07 +0100 +Subject: [PATCH 12/17] efivarfs: Return an error if we fail to read a + variable + +Instead of always returning 0 in efivarfs_file_read(), even when we +fail to successfully read the variable, convert the EFI status to +something meaningful and return that to the caller. This way the user +will have some hint as to why the read failed. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 62 +++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 26 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index a93e401..277e426 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -653,6 +653,36 @@ static int efivarfs_file_open(struct inode *inode, struct file *file) + return 0; + } + ++static int efi_status_to_err(efi_status_t status) ++{ ++ int err; ++ ++ switch (status) { ++ case EFI_INVALID_PARAMETER: ++ err = -EINVAL; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ err = -ENOSPC; ++ break; ++ case EFI_DEVICE_ERROR: ++ err = -EIO; ++ break; ++ case EFI_WRITE_PROTECTED: ++ err = -EROFS; ++ break; ++ case EFI_SECURITY_VIOLATION: ++ err = -EACCES; ++ break; ++ case EFI_NOT_FOUND: ++ err = -ENOENT; ++ break; ++ default: ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ + static ssize_t efivarfs_file_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) + { +@@ -711,29 +741,7 @@ static ssize_t efivarfs_file_write(struct file *file, + spin_unlock(&efivars->lock); + kfree(data); + +- switch (status) { +- case EFI_INVALID_PARAMETER: +- count = -EINVAL; +- break; +- case EFI_OUT_OF_RESOURCES: +- count = -ENOSPC; +- break; +- case EFI_DEVICE_ERROR: +- count = -EIO; +- break; +- case EFI_WRITE_PROTECTED: +- count = -EROFS; +- break; +- case EFI_SECURITY_VIOLATION: +- count = -EACCES; +- break; +- case EFI_NOT_FOUND: +- count = -ENOENT; +- break; +- default: +- count = -EINVAL; +- } +- return count; ++ return efi_status_to_err(status); + } + + /* +@@ -791,12 +799,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + spin_unlock(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) +- return 0; ++ return efi_status_to_err(status); + + data = kmalloc(datasize + 4, GFP_KERNEL); + + if (!data) +- return 0; ++ return -ENOMEM; + + spin_lock(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, +@@ -805,8 +813,10 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + (data + 4)); + spin_unlock(&efivars->lock); + +- if (status != EFI_SUCCESS) ++ if (status != EFI_SUCCESS) { ++ size = efi_status_to_err(status); + goto out_free; ++ } + + memcpy(data, &attributes, 4); + size = simple_read_from_buffer(userbuf, count, ppos, +-- +1.7.12.1 + + +From 39210330739b943856ff21b29b4a0804f4e8349f Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Mon, 22 Oct 2012 15:23:29 +0100 +Subject: [PATCH 13/17] efivarfs: Replace magic number with sizeof(attributes) + +Seeing "+ 4" littered throughout the functions gets a bit +confusing. Use "sizeof(attributes)" which clearly explains what +quantity we're adding. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 277e426..2c04434 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -801,7 +801,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (status != EFI_BUFFER_TOO_SMALL) + return efi_status_to_err(status); + +- data = kmalloc(datasize + 4, GFP_KERNEL); ++ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); + + if (!data) + return -ENOMEM; +@@ -810,7 +810,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, +- (data + 4)); ++ (data + sizeof(attributes))); + spin_unlock(&efivars->lock); + + if (status != EFI_SUCCESS) { +@@ -818,9 +818,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + goto out_free; + } + +- memcpy(data, &attributes, 4); ++ memcpy(data, &attributes, sizeof(attributes)); + size = simple_read_from_buffer(userbuf, count, ppos, +- data, datasize + 4); ++ data, datasize + sizeof(attributes)); + out_free: + kfree(data); + +-- +1.7.12.1 + + +From 5555f0af6294b3675a95a06da23101150644936d Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Mon, 22 Oct 2012 15:51:45 +0100 +Subject: [PATCH 14/17] efivarfs: Add unique magic number + +Using pstore's superblock magic number is no doubt going to cause +problems in the future. Give efivarfs its own magic number. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + include/uapi/linux/magic.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 2c04434..3b0cf9a 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -991,7 +991,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; +- sb->s_magic = PSTOREFS_MAGIC; ++ sb->s_magic = EFIVARFS_MAGIC; + sb->s_op = &efivarfs_ops; + sb->s_time_gran = 1; + +diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h +index e15192c..12f68c7 100644 +--- a/include/uapi/linux/magic.h ++++ b/include/uapi/linux/magic.h +@@ -27,6 +27,7 @@ + #define ISOFS_SUPER_MAGIC 0x9660 + #define JFFS2_SUPER_MAGIC 0x72b6 + #define PSTOREFS_MAGIC 0x6165676C ++#define EFIVARFS_MAGIC 0xde5e81e4 + + #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ + #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ +-- +1.7.12.1 + + +From a42845c67f2386b164d0c5d8220838d7faf5a409 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 23 Oct 2012 12:35:43 +0100 +Subject: [PATCH 15/17] efivarfs: Make 'datasize' unsigned long + +There's no reason to declare 'datasize' as an int, since the majority +of the functions it's passed to expect an unsigned long anyway. Plus, +this way we avoid any sign problems during arithmetic. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 3b0cf9a..6a858d1 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -692,7 +692,7 @@ static ssize_t efivarfs_file_write(struct file *file, + void *data; + u32 attributes; + struct inode *inode = file->f_mapping->host; +- int datasize = count - sizeof(attributes); ++ unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; + + if (count < sizeof(attributes)) +-- +1.7.12.1 + + +From a268bdf6d7ce623ea4bdfcf39aa52ed3fbfdfd65 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 23 Oct 2012 12:41:03 +0100 +Subject: [PATCH 16/17] efivarfs: Return a consistent error when + efivarfs_get_inode() fails + +Instead of returning -ENOSPC if efivarfs_get_inode() fails we should +be returning -ENOMEM, since running out of memory is the only reason +it can fail. Furthermore, that's the error value used everywhere else +in this file. It's also less likely to confuse users that hit this +error case. + +Acked-by: Jeremy Kerr +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 6a858d1..58cec62 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -911,7 +911,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + + inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); + if (!inode) +- return -ENOSPC; ++ return -ENOMEM; + + var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); + if (!var) { +-- +1.7.12.1 + + +From 9c3136c987175b179c0aa725d76cda156894f918 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Fri, 26 Oct 2012 12:18:53 +0100 +Subject: [PATCH 17/17] efivarfs: Fix return value of efivarfs_file_write() + +We're stuffing a variable of type size_t (unsigned) into a ssize_t +(signed) which, even though both types should be the same number of +bits, it's just asking for sign issues to be introduced. + +Cc: Jeremy Kerr +Reported-by: Alan Cox +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 58cec62..9ac9340 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -694,6 +694,7 @@ static ssize_t efivarfs_file_write(struct file *file, + struct inode *inode = file->f_mapping->host; + unsigned long datasize = count - sizeof(attributes); + unsigned long newdatasize; ++ ssize_t bytes = 0; + + if (count < sizeof(attributes)) + return -EINVAL; +@@ -706,22 +707,22 @@ static ssize_t efivarfs_file_write(struct file *file, + efivars = var->efivars; + + if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (attributes & ~(EFI_VARIABLE_MASK)) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + + if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { +- count = -EFAULT; ++ bytes = -EFAULT; + goto out; + } + + if (validate_var(&var->var, data, datasize) == false) { +- count = -EINVAL; ++ bytes = -EINVAL; + goto out; + } + +@@ -744,6 +745,8 @@ static ssize_t efivarfs_file_write(struct file *file, + return efi_status_to_err(status); + } + ++ bytes = count; ++ + /* + * Writing to the variable may have caused a change in size (which + * could either be an append or an overwrite), or the variable to be +@@ -778,7 +781,7 @@ static ssize_t efivarfs_file_write(struct file *file, + out: + kfree(data); + +- return count; ++ return bytes; + } + + static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, +-- +1.7.12.1 + diff --git a/exec-do-not-leave-bprm-interp-on-stack.patch b/exec-do-not-leave-bprm-interp-on-stack.patch index 2a4b2dd28..5198824ed 100644 --- a/exec-do-not-leave-bprm-interp-on-stack.patch +++ b/exec-do-not-leave-bprm-interp-on-stack.patch @@ -1,6 +1,6 @@ -From 20ae2081584450e552735a3df968ce5b5946a607 Mon Sep 17 00:00:00 2001 +From 6752ab4cb863fc63ed85f1ca78a42235c09fad83 Mon Sep 17 00:00:00 2001 From: Kees Cook -Date: Mon, 26 Nov 2012 08:56:37 -0500 +Date: Mon, 26 Nov 2012 09:07:50 -0500 Subject: [PATCH 1/2] exec: do not leave bprm->interp on stack If a series of scripts are executed, each triggering module loading via @@ -73,10 +73,10 @@ index d3b8c1f..df49d48 100644 /* * OK, now restart the process with the interpreter's dentry. diff --git a/fs/exec.c b/fs/exec.c -index fab2c6d..59896ae 100644 +index 0039055..c6e6de4 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1202,9 +1202,24 @@ void free_bprm(struct linux_binprm *bprm) +@@ -1175,9 +1175,24 @@ void free_bprm(struct linux_binprm *bprm) mutex_unlock(¤t->signal->cred_guard_mutex); abort_creds(bprm->cred); } @@ -102,10 +102,10 @@ index fab2c6d..59896ae 100644 * install the new credentials for this executable */ diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index 366422b..eb53e15 100644 +index cfcc6bf..de0628e 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h -@@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, +@@ -114,6 +114,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); extern int bprm_mm_init(struct linux_binprm *bprm); diff --git a/exec-use-eloop-for-max-recursion-depth.patch b/exec-use-eloop-for-max-recursion-depth.patch index cbaff2f7a..a3c48884f 100644 --- a/exec-use-eloop-for-max-recursion-depth.patch +++ b/exec-use-eloop-for-max-recursion-depth.patch @@ -1,4 +1,4 @@ -From 4ae8186cd77835b45f1b35edb4ce70309287bfc3 Mon Sep 17 00:00:00 2001 +From ba1b23d05259e31d30a78017cdfbc010dcb08aa6 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 26 Nov 2012 09:02:11 -0500 Subject: [PATCH 2/2] exec: use -ELOOP for max recursion depth @@ -98,10 +98,10 @@ index df49d48..8ae4be1 100644 fput(bprm->file); bprm->file = NULL; diff --git a/fs/exec.c b/fs/exec.c -index 59896ae..541cc51 100644 +index c6e6de4..85c1f9e 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1398,6 +1398,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1371,6 +1371,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) struct linux_binfmt *fmt; pid_t old_pid, old_vpid; @@ -112,7 +112,7 @@ index 59896ae..541cc51 100644 retval = security_bprm_check(bprm); if (retval) return retval; -@@ -1422,12 +1426,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1395,12 +1399,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); @@ -127,10 +127,10 @@ index 59896ae..541cc51 100644 if (retval >= 0) { if (depth == 0) { diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index eb53e15..5bab59b 100644 +index de0628e..54135f6 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h -@@ -68,8 +68,6 @@ struct linux_binprm { +@@ -54,8 +54,6 @@ struct linux_binprm { #define BINPRM_FLAGS_EXECFD_BIT 1 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) @@ -138,7 +138,7 @@ index eb53e15..5bab59b 100644 - /* Function parameter for binfmt->coredump */ struct coredump_params { - long signr; + siginfo_t *siginfo; -- 1.8.0 diff --git a/fs-lock-splice_read-and-splice_write-functions.patch b/fs-lock-splice_read-and-splice_write-functions.patch deleted file mode 100644 index 938cbd9f5..000000000 --- a/fs-lock-splice_read-and-splice_write-functions.patch +++ /dev/null @@ -1,74 +0,0 @@ -Lock splice_read and splice_write functions - -commit 1a25b1c4ce189e3926f2981f3302352a930086db -Author: Mikulas Patocka -Date: Mon Oct 15 17:20:17 2012 -0400 - - Lock splice_read and splice_write functions - - Functions generic_file_splice_read and generic_file_splice_write access - the pagecache directly. For block devices these functions must be locked - so that block size is not changed while they are in progress. - - This patch is an additional fix for commit b87570f5d349 ("Fix a crash - when block device is read and block size is changed at the same time") - that locked aio_read, aio_write and mmap against block size change. - - Signed-off-by: Mikulas Patocka - Signed-off-by: Linus Torvalds - -Index: linux-3.6.x86_64/fs/block_dev.c -=================================================================== ---- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:57.352936580 -0500 -+++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:13:11.908887989 -0500 -@@ -1662,6 +1662,39 @@ - return ret; - } - -+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ percpu_down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_splice_read(file, ppos, pipe, len, flags); -+ -+ percpu_up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ -+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, -+ struct file *file, loff_t *ppos, size_t len, -+ unsigned int flags) -+{ -+ ssize_t ret; -+ struct block_device *bdev = I_BDEV(file->f_mapping->host); -+ -+ percpu_down_read(&bdev->bd_block_size_semaphore); -+ -+ ret = generic_file_splice_write(pipe, file, ppos, len, flags); -+ -+ percpu_up_read(&bdev->bd_block_size_semaphore); -+ -+ return ret; -+} -+ -+ - /* - * Try to release a page associated with block device when the system - * is under memory pressure. -@@ -1700,8 +1733,8 @@ - #ifdef CONFIG_COMPAT - .compat_ioctl = compat_blkdev_ioctl, - #endif -- .splice_read = generic_file_splice_read, -- .splice_write = generic_file_splice_write, -+ .splice_read = blkdev_splice_read, -+ .splice_write = blkdev_splice_write, - }; - - int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/handle-efi-roms.patch b/handle-efi-roms.patch index 3002b1f89..bc080542b 100644 --- a/handle-efi-roms.patch +++ b/handle-efi-roms.patch @@ -131,62 +131,6 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c . /* * See if we have Graphics Output Protocol */ -@@ -276,8 +392,9 @@ - nr_gops = size / sizeof(void *); - for (i = 0; i < nr_gops; i++) { - struct efi_graphics_output_mode_info *info; -- efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; -- void *pciio; -+ efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; -+ bool conout_found = false; -+ void *dummy; - void *h = gop_handle[i]; - - status = efi_call_phys3(sys_table->boottime->handle_protocol, -@@ -285,19 +402,21 @@ - if (status != EFI_SUCCESS) - continue; - -- efi_call_phys3(sys_table->boottime->handle_protocol, -- h, &pciio_proto, &pciio); -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ h, &conout_proto, &dummy); -+ -+ if (status == EFI_SUCCESS) -+ conout_found = true; - - status = efi_call_phys4(gop->query_mode, gop, - gop->mode->mode, &size, &info); -- if (status == EFI_SUCCESS && (!first_gop || pciio)) { -+ if (status == EFI_SUCCESS && (!first_gop || conout_found)) { - /* -- * Apple provide GOPs that are not backed by -- * real hardware (they're used to handle -- * multiple displays). The workaround is to -- * search for a GOP implementing the PCIIO -- * protocol, and if one isn't found, to just -- * fallback to the first GOP. -+ * Systems that use the UEFI Console Splitter may -+ * provide multiple GOP devices, not all of which are -+ * backed by real hardware. The workaround is to search -+ * for a GOP implementing the ConOut protocol, and if -+ * one isn't found, to just fall back to the first GOP. - */ - width = info->horizontal_resolution; - height = info->vertical_resolution; -@@ -308,10 +427,10 @@ - pixels_per_scan_line = info->pixels_per_scan_line; - - /* -- * Once we've found a GOP supporting PCIIO, -+ * Once we've found a GOP supporting ConOut, - * don't bother looking any further. - */ -- if (pciio) -+ if (conout_found) - break; - - first_gop = gop; @@ -1052,6 +1171,8 @@ setup_graphics(boot_params); @@ -196,20 +140,6 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c . status = efi_call_phys3(sys_table->boottime->allocate_pool, EFI_LOADER_DATA, sizeof(*gdt), (void **)&gdt); -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-07-21 16:58:29.000000000 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h 2012-08-22 15:25:40.530244882 -0400 -@@ -14,6 +14,10 @@ - #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) - #define EFI_READ_CHUNK_SIZE (1024 * 1024) - -+#define EFI_CONSOLE_OUT_DEVICE_GUID \ -+ EFI_GUID( 0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ -+ 0x3f, 0xc1, 0x4d ) -+ - #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 - #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 - #define PIXEL_BIT_MASK 2 diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h --- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:26:32.485522068 -0400 +++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:25:40.530244882 -0400 @@ -332,25 +262,19 @@ diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c --- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-07-21 16:58:29.000000000 -0400 +++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-08-22 15:25:40.531244893 -0400 -@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) - void __iomem *rom; - - /* -+ * Some devices may provide ROMs via a source other than the BAR -+ */ -+ if (pdev->rom && pdev->romlen) { -+ *size = pdev->romlen; -+ return phys_to_virt(pdev->rom); -+ /* - * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy - * memory map if the VGA enable bit of the Bridge Control register is - * set for embedded VGA. - */ -- if (res->flags & IORESOURCE_ROM_SHADOW) { -+ } else if (res->flags & IORESOURCE_ROM_SHADOW) { +@@ -126,6 +126,12 @@ /* primary video rom always starts here */ start = (loff_t)0xC0000; *size = 0x20000; /* cover C000:0 through E000:0 */ ++ /* ++ * Some devices may provide ROMs via a source other than the BAR ++ */ ++ } else if (pdev->rom && pdev->romlen) { ++ *size = pdev->romlen; ++ return phys_to_virt(pdev->rom); + } else { + if (res->flags & + (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { @@ -219,7 +225,8 @@ if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) return; diff --git a/kernel.spec b/kernel.spec index 57af99470..b6f407309 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,19 +62,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 6 +%define base_sublevel 7 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -426,6 +426,14 @@ Summary: The Linux kernel %endif %endif +# Should make listnewconfig fail if there's config options +# printed out? +%if %{nopatches}%{using_upstream_branch} +%define listnewconfig_fail 0 +%else +%define listnewconfig_fail 1 +%endif + # To temporarily exclude an architecture from being built, add it to # %%nobuildarches. Do _NOT_ use the ExclusiveArch: line, because if we # don't build kernel-headers then the new build system will no longer let @@ -662,10 +670,6 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch -Patch150: team-net-next-20120808.patch -Patch151: team-net-next-update-20120927.patch -Patch152: team-net-next-20121205.patch - Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch @@ -687,12 +691,11 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-upstream-3.7.patch Patch901: modsign-post-KS-jwb.patch # secure boot Patch1000: secure-boot-20121212.patch -Patch1001: efivarfs-3.6.patch +Patch1001: efivarfs-3.7.patch # Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -741,7 +744,6 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-read_current_timer.patch Patch21001: arm-fix-omapdrm.patch -Patch21002: arm-fix_radio_shark.patch Patch21003: arm-alignment-faults.patch # OMAP @@ -751,7 +753,6 @@ Patch21005: arm-tegra-usb-no-reset-linux33.patch Patch21006: arm-tegra-sdhci-module-fix.patch # ARM highbank patches -Patch21010: arm-highbank-sata-fix.patch # ARM exynos4 Patch21020: arm-smdk310-regulator-fix.patch @@ -765,33 +766,9 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 869904 869909 CVE-2012-4508 -Patch22080: 0001-ext4-ext4_inode_info-diet.patch -Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch -Patch22082: 0003-ext4-fix-unwritten-counter-leakage.patch -Patch22083: 0004-ext4-completed_io-locking-cleanup.patch -Patch22084: 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch -Patch22085: 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch -Patch22086: 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch -Patch22087: 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch -Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch -Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch -Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch -Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch - -Patch22100: uprobes-upstream-backport.patch - #rhbz 871078 Patch22112: USB-report-submission-of-active-URBs.patch -#rhbz 869341 -Patch22113: smp_irq_move_cleanup_interrupt.patch - -#rhbz 812129 -Patch22120: block-fix-a-crash-when-block-device-is.patch -Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch -Patch22122: fs-lock-splice_read-and-splice_write-functions.patch - #rhbz 874791 Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch @@ -802,9 +779,6 @@ Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch -#rhbz 869629 -Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch - #rhbz 851278 Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch @@ -816,9 +790,6 @@ Patch21234: mac80211-fix-ibss-scanning.patch #rhbz 873107 Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch -#rhbz 874372 -Patch21238: don-t-do-blind-d_drop-in-nfs_prime_dcache.patch - # END OF PATCH DEFINITIONS %endif @@ -1386,23 +1357,17 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch -ApplyPatch team-net-next-20120808.patch -ApplyPatch team-net-next-update-20120927.patch -ApplyPatch team-net-next-20121205.patch - # Architecture patches # x86(-64) # # ARM # -ApplyPatch arm-read_current_timer.patch -ApplyPatch arm-fix-omapdrm.patch -ApplyPatch arm-fix_radio_shark.patch +#ApplyPatch arm-read_current_timer.patch +#ApplyPatch arm-fix-omapdrm.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch -ApplyPatch arm-highbank-sata-fix.patch ApplyPatch arm-alignment-faults.patch ApplyPatch arm-smdk310-regulator-fix.patch ApplyPatch arm-origen-regulator-fix.patch @@ -1473,12 +1438,11 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ -ApplyPatch modsign-upstream-3.7.patch ApplyPatch modsign-post-KS-jwb.patch # secure boot -ApplyPatch efivarfs-3.6.patch -ApplyPatch secure-boot-20121212.patch +ApplyPatch efivarfs-3.7.patch +#ApplyPatch secure-boot-20121212.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1520,8 +1484,8 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch lis3-improve-handling-of-null-rate.patch -ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch -ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch +#ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch +#ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1531,33 +1495,9 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 869904 869909 CVE-2012-4508 -ApplyPatch 0001-ext4-ext4_inode_info-diet.patch -ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch -ApplyPatch 0003-ext4-fix-unwritten-counter-leakage.patch -ApplyPatch 0004-ext4-completed_io-locking-cleanup.patch -ApplyPatch 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch -ApplyPatch 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch -ApplyPatch 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch -ApplyPatch 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch -ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch -ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch -ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch -ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch - -ApplyPatch uprobes-upstream-backport.patch - #rhbz 871078 ApplyPatch USB-report-submission-of-active-URBs.patch -#rhbz 869341 -ApplyPatch smp_irq_move_cleanup_interrupt.patch - -#rhbz 812129 -ApplyPatch block-fix-a-crash-when-block-device-is.patch -ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch -ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch - #rhbz 874791 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch @@ -1568,9 +1508,6 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch -#rhbz 869629 -ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch - #rhbz 851278 ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch @@ -1582,9 +1519,6 @@ ApplyPatch mac80211-fix-ibss-scanning.patch #rhbz 873107 ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch -#rhbz 874372 -ApplyPatch don-t-do-blind-d_drop-in-nfs_prime_dcache.patch - # END OF PATCH APPLICATIONS @@ -1613,17 +1547,23 @@ done rm -f kernel-%{version}-*debug.config %endif -# run oldconfig over the config files (except when noarch) -if [ "%{_target_cpu}" != "noarch" ]; then - for i in kernel-*-%{_target_cpu}*.config - do - mv $i .config - Arch=`head -1 .config | cut -b 3-` - make ARCH=$Arch oldnoconfig - echo "# $Arch" > configs/$i - cat .config >> configs/$i - done -fi +# now run oldconfig over all the config files +for i in *.config +do + mv $i .config + Arch=`head -1 .config | cut -b 3-` + make ARCH=$Arch listnewconfig | grep -E '^CONFIG_' >.newoptions || true +%if %{listnewconfig_fail} + if [ -s .newoptions ]; then + cat .newoptions + exit 1 + fi +%endif + rm -f .newoptions + make ARCH=$Arch oldnoconfig + echo "# $Arch" > configs/$i + cat .config >> configs/$i +done # end of kernel config %endif @@ -2451,6 +2391,9 @@ fi # ||----w | # || || %changelog +* Thu Jan 03 2013 Dave Jones +- Rebase to 3.7.1 + * Wed Jan 02 2013 Josh Boyer - Fix autofs issue in 3.6 (rhbz 874372) - BR the hostname package (rhbz 886113) @@ -2640,2023 +2583,6 @@ fi - Linux 3.6.0 - Disable debugging options. -* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git3.1 -- Linux v3.6-rc7-103-g6672d90 - -* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.2 -- Split out kernel-tools-libs (rhbz 859943) - -* Fri Sep 28 2012 Josh Boyer - 3.6.0-0.rc7.git2.1 -- Linux v3.6-rc7-71-g6399413 - -* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.4 -- Move the modules-extra processing to a script -- Prep mod-extra.sh for signed modules -- Switch to using modsign-post-KS upstream with x509 certs - -* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.2 -- Update team driver from net-next from Jiri Pirko - -* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 -- Linux v3.6-rc7-10-g56d27ad - -* Tue Sep 25 2012 Josh Boyer - 3.6.0-0.rc7.git0.2 -- Reenable debugging options. - -* Mon Sep 24 2012 Josh Boyer - 3.6.0-0.rc7.git1.1 -- Linux v3.6-rc7 -- Disable debugging options. - -* Thu Sep 20 2012 Josh Boyer - 3.6.0-0.rc6.git2.1 -- Linux v3.6-rc6-52-gc46de22 - -* Tue Sep 18 2012 Josh Boyer - 3.6.0-0.rc6.git1.1 -- Linux v3.6-rc6-25-g4651afb -- Enable POWER7+ crypto modules (rhbz 857971) - -* Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.2 -- Reenable debugging options. - -* Mon Sep 17 2012 Josh Boyer - 3.6.0-0.rc6.git0.1 -- Linux v3.6-rc6 -- Disable debugging options. - -* Sun Sep 16 2012 Josh Boyer - 3.6.0-0.rc5.git3.1 -- Linux v3.6-rc5-315-g3f0c3c8 - -* Fri Sep 14 2012 Dave Jones -- Enable CONFIG_DRM_LOAD_EDID_FIRMWARE (rhbz 857511) - -* Fri Sep 14 2012 Dave Jones -- Reenable UBIFS (rhbz 823238) - -* Fri Sep 14 2012 Dave Jones -- Fix license tag. (rhbz 450492) - -* Wed Sep 12 2012 Josh Boyer - 3.6.0-0.rc5.git2.1 -- Linux v3.6-rc5-44-g0bd1189 - -* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.2 -- Drop old Xen EC2 patch. It is no longer needed per Matt Wilson - -* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git1.1 -- Linux v3.6-rc5-32-g1a95620 -- Reenable debugging options. - -* Tue Sep 11 2012 Josh Boyer - 3.6.0-0.rc5.git0.1 -- Linux v3.6-rc5 -- Disable debugging options. - -* Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.2 -- Re-enable BTRFS on ppc. Brent Baude says it works now. - -* Fri Sep 07 2012 Josh Boyer - 3.6.0-0.rc4.git2.1 -- Linux v3.6-rc4-128-geeea3ac - -* Wed Sep 05 2012 Dave Jones -- Don't create empty include/linux/autoconf.h in kernel-devel (rhbz 854689) - -* Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git1.1 -- Linux v3.6-rc4-53-g5b716ac -- Add patch to fix ibmveth issue from Santiago Leon (rhbz 852842) - -* Wed Sep 05 2012 Josh Boyer - 3.6.0-0.rc4.git0.2 -- Reenable debugging options. - -* Tue Sep 4 2012 Matthew Garrett -- handle-efi-roms.patch: Improve PCI support on UEFI systems - -* Tue Sep 4 2012 Peter Robinson -- Tweak OMAP options - -* Mon Sep 03 2012 Josh Boyer - 3.6.0-0.rc4.git0.1 -- Linux v3.6-rc4 -- Disable debugging options. - -* Thu Aug 30 2012 Josh Boyer - 3.6.0-0.rc3.git4.1 -- Linux v3.6-rc3-230-g155e36d - -* Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.2 -- Add patch to fix USB audio regression (rhbz 851619) - -* Wed Aug 29 2012 Josh Boyer - 3.6.0-0.rc3.git3.1 -- Linux v3.6-rc3-207-g318e151 - -* Tue Aug 28 2012 Peter Robinson -- Add patches to fix OMAP drm, radio shark -- Tweak ARM config - -* Mon Aug 27 2012 Josh Boyer - 3.6.0-0.rc3.git2.1 -- Linux v3.6-rc3-177-gc182ae4 - -* Sat Aug 25 2012 Peter Robinson -- Add patch to fix build on ARM -- Enable USB ULPI driver to fix some USB ports - -* Fri Aug 24 2012 Josh Boyer - 3.6.0-0.rc3.git1.1 -- Linux v3.6-rc3-37-g2d809dc - -* Thu Aug 23 2012 Josh Boyer - 3.6.0-0.rc3.git0.2 -- Reenable debugging options. - -* Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc3.git0.1 -- Linux v3.6-rc3 -- Disable debugging options. - -* Wed Aug 22 2012 Josh Boyer - 3.6.0-0.rc2.git2.1 -- Linux v3.6-rc2-400-g23dcfa6 -- CVE-2012-3520: af_netlink: invalid handling of SCM_CREDENTIALS passing - -* Tue Aug 21 2012 Josh Boyer -- Add patch from Dave Jones to fix suspicious RCU usage in SELinux (rhbz 846037) -- Add patch from Richard W.M. Jones to fix virtio scsi oops (rhbz 847548) -- Add patch from Dave Airlie to fix fb cursor vs grub2 gfxterm hang - -* Mon Aug 20 2012 Josh Boyer - 3.6.0-0.rc2.git1.1 -- Linux v3.6-rc2-206-g10c63c9 - -* Mon Aug 20 2012 Dave Jones -- Reenable W1 drivers. (rhbz 849430) - -* Fri Aug 17 2012 Josh Boyer - 3.6.0-0.rc2.git0.2 -- Reenable debugging options. - -* Thu Aug 16 2012 Josh Boyer - 3.6.0-0.rc2.git0.1 -- Linux v3.6-rc2 -- Disable debugging options. - -* Tue Aug 14 2012 Josh Boyer - 3.6.0-0.rc1.git6.1 -- Linux v3.6-rc1-355-gddf343f - -* Mon Aug 13 2012 Josh Boyer - 3.6.0-0.rc1.git5.2 -- Fix VFS file creation bugs (rhbz 844485) - -* Mon Aug 13 2012 Josh Boyer - 3.6.0-0.rc1.git5.1 -- Linux v3.6-rc1-312-g3bf671a - -* Sun Aug 12 2012 Josh Boyer - 3.6.0-0.rc1.git4.1 -- Linux v3.6-rc1-268-g21d2f8d - -* Fri Aug 10 2012 Dennis Gilmore -- disable some options on highbank at calxeda's request -- enable the PL011 serial console on highbank -- enable ARM architected timer on all arm arches - -* Thu Aug 09 2012 Josh Boyer - 3.6.0-0.rc1.git3.2 -- Update secure-boot patch to pass correct CFLAGS to EFI stub - -* Thu Aug 09 2012 Josh Boyer - 3.6.0-0.rc1.git3.1 -- Linux v3.6-rc1-207-gf4ba394 - -* Wed Aug 08 2012 Josh Boyer - 3.6.0-0.rc1.git2.2 -- Update team driver from net-next from Jiri Pirko - -* Tue Aug 07 2012 Josh Boyer -- Add support for ppc64p7 subarch - -* Mon Aug 06 2012 Josh Boyer - 3.6.0-0.rc1.git2.1 -- Linux v3.6-rc1-133-g42a579a - -* Sat Aug 04 2012 Josh Boyer - 3.6.0-0.rc1.git1.2 -- Reenable debugging options. - -* Sat Aug 04 2012 Josh Boyer - 3.6.0-0.rc1.git1.1 -- Linux v3.6-rc1-112-ge7882d6 - -* Fri Aug 03 2012 Josh Boyer - 3.6.0-0.rc1.git0.2 -- CVE-2012-3412 sfc: potential rDOS through TCP MSS option (rhbz 844714 845558) - -* Fri Aug 03 2012 Josh Boyer - 3.6.0-0.rc1.git0.1 -- Linux v3.6-rc1 -- Disable debugging options. - -* Thu Aug 02 2012 Josh Boyer - 3.6.0-0.rc0.git9.3 -- Update modsign and secure-boot patch sets - -* Thu Aug 02 2012 Josh Boyer -- Reenable cgroups memory controller (rhbz 845285) -- Add two patches from Seth Forshee to fix brcmsmac backtrace - -* Thu Aug 02 2012 Josh Boyer - 3.6.0-0.rc0.git9.1 -- Linux v3.5-9139-g1a9b499 - -* Wed Aug 01 2012 Josh Boyer - 3.6.0-0.rc0.git8.1 -- Linux v3.5-8833-g2d53492 - -* Wed Aug 01 2012 Josh Boyer - 3.6.0-0.rc0.git7.1 -- Linux v3.5-8367-g08843b7 - -* Tue Jul 31 2012 Josh Boyer - 3.6.0-0.rc0.git6.1 -- Linux v3.5-8197-g2e3ee61 - -* Wed Jul 31 2012 John W. Linville -- Enable batman-adv and add it to the list of "extra" modules - -* Tue Jul 31 2012 Dave Jones -- Change VM_BUG_ON's to be WARN_ONs instead. - -* Tue Jul 31 2012 Josh Boyer -- Move modules needed by Shorewall back to main kernel package (rhbz 844436) - -* Mon Jul 30 2012 Josh Boyer - 3.6.0-0.rc0.git5.2 -- Update config options - -* Mon Jul 30 2012 Josh Boyer - 3.6.0-0.rc0.git5.1 -- Linux v3.5-7815-g37cd960 - -* Mon Jul 30 2012 Josh Boyer - 3.6.0-0.rc0.git4.1 -- Linux v3.5-7078-gf7da9cd - -* Mon Jul 30 2012 Josh Boyer -- Fixup patches - -* Fri Jul 27 2012 Justin M. Forbes - 3.6.0-0.rc0.git3.1 -- Linux v3.5-6982-gb387e41 - -* Thu Jul 26 2012 Josh Boyer -- Apply patch to fix uvcvideo crash (rhbz 836742) -- Enable Intel MEI driver (rhbz 842444) - -* Wed Jul 25 2012 Justin M. Forbes - 3.6.0-0.rc0.git2.1 -- Linux v3.5-4773-gbdc0077 - -* Tue Jul 24 2012 Josh Boyer -- Update modsign patch to latest upstream -- Add initial UEFI Secure Boot patchset. Work in progress. - -* Tue Jul 24 2012 Justin M. Forbes - 3.6.0-0.rc0.git1.1 -- Linux v3.5-1643-gf0a08fc - -* Mon Jul 23 2012 Justin M. Forbes - 3.5.0-2 -- Reenable debugging options. - -* Mon Jul 23 2012 Justin M. Forbes - 3.5.0-1 -- Linux v3.5 -- Disable debugging options. - -* Fri Jul 20 2012 John W. Linville -- Enable NFC subsystem and drivers - -* Fri Jul 20 2012 Justin M. Forbes - 3.5.0-0.rc7.git4.1 -- Linux v3.5-rc7-141-g85efc72 - -* Thu Jul 19 2012 Justin M. Forbes - 3.5.0-0.rc7.git3.1 -- Linux v3.5-rc7-124-g8a7298b - -* Wed Jul 18 2012 Josh Boyer -- Update modsign patch to latest upstream - -* Wed Jul 18 2012 Justin M. Forbes - 3.5.0-0.rc7.git2.1 -- Linux v3.5-rc7-81-ga018540 - -* Wed Jul 18 2012 Josh Boyer -- check return value of power_supply_register from Lan Tianyu (rhbz 772730) - -* Tue Jul 17 2012 Justin M. Forbes - 3.5.0-0.rc7.git1.2 -- Reenable debugging options. - -* Tue Jul 17 2012 Justin M. Forbes - 3.5.0-0.rc7.git1.1 -- Linux v3.5-rc7-25-ge5254a6 - -* Mon Jul 16 2012 Justin M. Forbes - 3.5.0-0.rc7.git0.1 -- Linux v3.5-rc7 -- Disable debugging options. - -* Fri Jul 13 2012 Justin M. Forbes - 3.5.0-0.rc6.git4.1 -- Linux v3.5-rc6-186-gac7d181 - -* Fri Jul 13 2012 Josh Boyer -- Build CONFIG_HID and CONFIG_HID_GENERIC in - -* Thu Jul 12 2012 Justin M. Forbes - 3.5.0-0.rc6.git3.1 -- Linux v3.5-rc6-117-g918227b - -* Wed Jul 11 2012 Justin M. Forbes - 3.5.0-0.rc6.git2.1 -- Linux v3.5-rc6-40-g055c9fa -- Fix FIPS for aesni hardware (rhbz 839239) - -* Tue Jul 10 2012 Justin M. Forbes - 3.5.0-0.rc6.git1.1 -- Linux v3.5-rc6-22-g2437fcc - -* Mon Jul 09 2012 Justin M. Forbes - 3.5.0-0.rc6.git0.3 -- Reenable debugging options. - -* Mon Jul 09 2012 Justin M. Forbes - 3.5.0-0.rc6.git0.2 -- Linux v3.5-rc6 -- Disable debugging options. - -* Fri Jul 06 2012 Justin M. Forbes - 3.5.0-0.rc5.git3.1 -- Linux v3.5-rc5-149-gc4aed35 - -* Thu Jul 05 2012 Josh Boyer -- Move sch_htb module into main kernel package (rhbz 836185) - -* Thu Jul 05 2012 Dennis Gilmore -- enable cpu frequency scaling on omap systems - -* Thu Jul 05 2012 Justin M. Forbes - 3.5.0-0.rc5.git2.1 -- Linux v3.5-rc5-98-g9e85a6f - -* Wed Jul 4 2012 Josh Boyer -- Patch from Stanislaw Gruszka to fix rt2x00 USB access point (rhbz 828824) - -* Tue Jul 03 2012 Justin M. Forbes - 3.5.0-0.rc5.git1.1 -- Linux v3.5-rc5-6-g9d4056a - -* Tue Jul 03 2012 Justin M. Forbes - 3.5.0-0.rc5.git0.3 -- Reenable debugging options. - -* Mon Jul 02 2012 Justin M. Forbes - 3.5.0-0.rc5.git0.2 -- Linux 3.5-rc5 -- Disable debugging options. - -* Fri Jun 29 2012 Justin M. Forbes - 3.5.0-0.rc4.git4.1 -- Linux v3.5-rc4-211-g9acc7bd - -* Thu Jun 28 2012 Dennis Gilmore -- include the mach- headers on arm arches if they are available - -* Thu Jun 28 2012 Justin M. Forbes - 3.5.0-0.rc4.git3.1 -- Linux v3.5-rc4-98-g47b514c -- Team driver update - -* Wed Jun 27 2012 Justin M. Forbes - 3.5.0-0.rc4.git2.1 -- Linux v3.5-rc4-59-gd1346a6 - -* Tue Jun 26 2012 Justin M. Forbes - 3.5.0-0.rc4.git1.2 -- Reenable debugging options. - -* Tue Jun 26 2012 Justin M. Forbes - 3.5.0-0.rc4.git1.1 -- Linux v3.5-rc4-52-gaace99e - -* Mon Jun 25 2012 Peter Robinson -- Add patch to fix ARM OMAP build -- re-enable IMX kernel now it builds again - -* Mon Jun 25 2012 Justin M. Forbes - 3.5.0-0.rc4.git0.1 -- Disable debugging options. - -* Mon Jun 25 2012 Justin M. Forbes -- Linux 3.5-rc4 - -* Fri Jun 22 2012 Josh Boyer -- Add uprobe backports from -tip from Anton Arapov - -* Wed Jun 20 2012 Josh Boyer -- Fix incorrect logic in irqpoll patch - -* Mon Jun 18 2012 Josh Boyer - 3.5.0-0.rc3.git0.2 -- Disable debugging options. - -* Mon Jun 18 2012 Josh Boyer - -3.5.0-0.rc3.git0.1 -- Linux v3.5-rc3 - -* Tue Jun 12 2012 Peter Robinson -- ARM: build in rtc modules so time gets set right on boot - -* Mon Jun 11 2012 Josh Boyer -- Add virtual provides for kernel-module to kernel-modules-extra (rhbz 770444) - -* Mon Jun 11 2012 Josh Boyer - 3.5.0-0.rc2.git0.3 -- Add patch to fix xen domU 32bit (rhbz 829016) -- Reenable debugging options. - -* Mon Jun 11 2012 Josh Boyer -- Add two upstream commits to fix flaky iwlwifi (rhbz 825491) - -* Sun Jun 10 2012 Peter Robinson -- Temporarily disable ARM imx kernel due to missing clk patches -- Add patch to fix OMAP build -- Drop DTB mac patches as rejected upstream -- General ARM cleanups - -* Sat Jun 09 2012 Josh Boyer - 3.5.0-0.rc2.git0.1 -- Linux v3.5-rc2 - -* Fri Jun 08 2012 Josh Boyer -- Enable HV assisted KVM on ppc64 - -* Tue Jun 05 2012 Josh Boyer -- Disable MV643XX on ppc32 because ARM broke it (rhbz 828776) - -* Tue Jun 05 2012 Peter Robinson -- Update ARM config options for 3.5 -- Enable MTD/UBI/JFFS2 on ARM platforms - -* Mon Jun 04 2012 Dave Jones -- Remove 32bit NX emulation. - -* Mon Jun 04 2012 Josh Boyer -- Remove modules.{devname,softdep} to prevent RPM verify errors (rhbz 650807) - -* Sun Jun 03 2012 Josh Boyer - 3.5.0-0.rc1.git0.1 -- Linux v3.5-rc1 -- Disable debugging options. - -* Sat Jun 02 2012 Peter Robinson -- ARM OMAP updates - -* Sat Jun 02 2012 Josh Boyer - 3.5.0-0.rc0.git12.1 -- Linux v3.4-10115-g829f51d - -* Fri Jun 01 2012 Josh Boyer - 3.5.0-0.rc0.git11.1 -- Linux v3.4-9547-gfb21aff - -* Thu May 31 2012 Josh Boyer -- Per Adam Jackson, drop linux-2.6-intel-iommu-igfx.patch - -* Thu May 31 2012 Josh Boyer - 3.5.0-0.rc0.git10.2 -- Fix crash in cirrus qemu driver from Dave Airlie (rhbz 826983) - -* Thu May 31 2012 Josh Boyer - 3.5.0-0.rc0.git10.1 -- Linux v3.4-9208-gaf56e0a - -* Wed May 30 2012 Josh Boyer -- modsign: Fix 32bit ELF table interpretation from David Howells (rhbz 825944) - -* Tue May 29 2012 Josh Boyer - 3.5.0-0.rc0.git9.1 -- Linux v3.4-8261-ga01ee16 - -* Sun May 27 2012 Josh Boyer - 3.5.0-0.rc0.git8.1 -- Linux v3.4-8215-g1e2aec8 - -* Fri May 25 2012 Josh Boyer - 3.5.0-0.rc0.git7.1 -- Linux v3.4-7644-g07acfc2 - -* Fri May 25 2012 Mauro Carvalho Chehab -- Don't manually customise tuners/frontends (rhbz 825203) - -* Thu May 24 2012 Dennis Gilmore -- enable XGI_FB on kirkwood for openrd -- enable DeviceTree support on kirkwood -- enable dreamplug support on kerkwood - -* Thu May 24 2012 Josh Boyer - 3.5.0-0.rc0.git6.1 -- Linux v3.4-5722-gf936991 - -* Thu May 24 2012 Josh Boyer -- CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) - -* Thu May 24 2012 Peter Robinson -- Don't build Nokia ARM device support - -* Wed May 23 2012 Josh Boyer - 3.5.0-0.rc0.git5.1 -- Linux v3.4-5161-g56edab3 - -* Wed May 23 2012 Adam Jackson -- drm-i915-lvds-dual-channel.patch: Scrape LVDS dual-channel-ness from the - VBT instead of just making things up. (#819343) - -* Wed May 23 2012 Josh Boyer - 3.5.0-0.rc0.git4.1 -- Add patch to fix perf build -- Linux v3.4-4842-g61011677 - -* Wed May 23 2012 Dennis Gilmore -- add patch to fix ftbfs on tegra due to sdhci MODULE_DEVICE_TABLE mismatch -- dont make a arm config file we do not use it anywhere - -* Tue May 22 2012 Josh Boyer - 3.5.0-0.rc0.git3.1 -- Linux v3.4-2580-g72c04af - -* Tue May 22 2012 Josh Boyer - 3.5.0-0.rc0.git2.1 -- Linux v3.4-2285-g2e32180 - -* Mon May 21 2012 Josh Boyer -- Update the modsign patchset to the most recent version - -* Mon May 21 2012 Josh Boyer - 3.5.0-0.rc0.git1.2 -- Linux v3.4-1622-g31a6710 - -* Mon May 21 2012 Josh Boyer - 3.4.0-2 -- Reenable debugging options. - -* Mon May 21 2012 Josh Boyer - 3.4.0-1 -- Linux v3.4 - -* Mon May 21 2012 Josh Boyer - 3.4.0-0.rc7.git6.2 -- Disable debugging options. - -* Mon May 21 2012 Josh Boyer -- Bump NR_CPUS to 128 on x86_64 - -* Sun May 20 2012 Josh Boyer - 3.4.0-0.rc7.git6.1 -- Linux v3.4-rc7-124-gd6c77973 - -* Sat May 19 2012 Josh Boyer - 3.4.0-0.rc7.git5.1 -- Linux v3.4-rc7-106-gb1dab2f - -* Fri May 18 2012 Josh Boyer - 3.4.0-0.rc7.git4.1 -- Linux v3.4-rc7-92-g42ea7d7 - -* Thu May 17 2012 Josh Boyer - 3.4.0-0.rc7.git3.1 -- Linux v3.4-rc7-53-g0e93b4b - -* Thu May 17 2012 Josh Boyer -- Enable cpu_idle drivers for ppc64/pseries (requested by Ben Herrenschmidt) - -* Wed May 16 2012 Josh Boyer -- Update the vgaarb patches to pick up a small switcheroo fix from airlied - -* Wed May 16 2012 Josh Boyer - 3.4.0-0.rc7.git2.1 -- Linux v3.4-rc7-24-g568b445 - -* Tue May 15 2012 Josh Boyer -- Enable Nilfs2 and put it in modules-extra (rhbz 821702) - -* Tue May 15 2012 Dennis Gilmore -- dont build a up kernel on armv5tel - -* Tue May 15 2012 Josh Boyer - 3.4.0-0.rc7.git1.1 -- Fixup atl1c register programming (rhbz 749276) -- Linux v3.4-rc7-21-gb6255ee - -* Tue May 15 2012 Dennis Gilmore -- make sure smp is on in generic arm config -- tweak vexpress config - -* Mon May 14 2012 Josh Boyer -- Enable DRM_VIA again per Adam Jackson - -* Mon May 14 2012 Josh Boyer - 3.4.0-0.rc7.git0.2 -- Reenable debugging options. - -* Sun May 13 2012 Josh Boyer - 3.4.0-0.rc7.git0.1 -- Linux v3.4-rc7 -- Disable debugging options. - -* Fri May 11 2012 Josh Boyer -- Enable CONFIG_NFSD_FAULT_INJECTION on debug builds (suggested by Jeff Layton) -- Enable CONFIG_SUNRPC_DEBUG (pointed out by Jeff Layton) - -* Fri May 11 2012 Josh Boyer - 3.4.0-0.rc6.git3.1 -- Linux v3.4-rc6-76-gd60b9c1 - -* Thu May 10 2012 Josh Boyer - 3.4.0-0.rc6.git2.2 -- Fix normal kernel builds - -* Thu May 10 2012 Josh Boyer - 3.4.0-0.rc6.git2.1 -- Linux v3.4-rc6-41-g7ee94d9 - -* Thu May 10 2012 Peter Robinson -- Build in MMC on VExpress so we can boot using qemu - -* Tue May 8 2012 Peter Robinson -- Restructure ARM configs to minimise duplication and pull all generic options -- Spilt Versatile config and use Express chip into dedicated config for qemu - -* Tue May 08 2012 Josh Boyer - 3.4.0-0.rc6.git1.1 -- Linux v3.4-rc6-20-g789505b - -* Tue May 08 2012 Josh Boyer - 3.4.0-0.rc6.git0.2 -- Reenable debugging options. - -* Mon May 07 2012 Dave Jones -- Remove /proc/device-tree when openfirmware init fails. (rhbz 818378) - -* Mon May 07 2012 Josh Boyer - 3.4.0-0.rc6.git0.1 -- Linux v3.4-rc6 -- Disable debugging options. - -* Sat May 05 2012 Josh Boyer - 3.4.0-0.rc5.git5.1 -- Linux v3.4-rc5-208-g6f24f89 - -* Fri May 04 2012 Josh Boyer - 3.4.0-0.rc5.git4.1 -- Linux v3.4-rc5-183-g0a6ba09 - -* Thu May 03 2012 Dennis Gilmore -- enable omap KMS driver - -* Thu May 3 2012 Peter Robinson -- Patch for disconnect issues with storage attached to a tegra-ehci controller - -* Thu May 03 2012 Justin M. Forbes -- Reenable slip and add to module-extras (rhbz 818308) - -* Wed May 02 2012 Josh Boyer -- Disable PCIEPORTBUS on ppc64 per IBM request - -* Wed May 02 2012 Josh Boyer - 3.4.0-0.rc5.git3.1 -- Linux v3.4-rc5-62-g529acf5 - -* Tue May 01 2012 Josh Boyer - 3.4.0-0.rc5.git2.1 -- Drop merged patch. Drink coffee before doing build. -- Linux v3.4-rc5-34-g655861e - -* Mon Apr 30 2012 Josh Boyer - 3.4.0-0.rc5.git1.1 -- Linux v3.4-rc5-8-g8a7dc4b - -* Mon Apr 30 2012 Josh Boyer -- Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) - -* Mon Apr 30 2012 Josh Boyer - 3.4.0-0.rc5.git0.3 -- Reenable debugging options. - -* Mon Apr 30 2012 Josh Boyer - 3.4.0-0.rc5.git0.2 -- Linux v3.4-rc5 -- Disable debugging options. - -* Sat Apr 28 2012 Josh Boyer - 3.4.0-0.rc4.git4.1 -- Linux v3.4-rc4-308-gf7b0069 - -* Fri Apr 27 2012 Josh Boyer - 3.4.0-0.rc4.git3.1 -- Linux v3.4-rc4-180-g82b7690 - -* Thu Apr 26 2012 Josh Boyer - 3.4.0-0.rc4.git2.1 -- Linux v3.4-rc4-135-g2300fd6 - -* Tue Apr 24 2012 Josh Boyer - 3.4.0-0.rc4.git1.1 -- Linux v3.4-rc4-95-g95f7147 - -* Tue Apr 24 2012 Josh Boyer -- Add patch to fix ipw2200 (rhbz 802106) - -* Mon Apr 23 2012 Peter Hutterer -- Fix regression on clickpads - -* Mon Apr 23 2012 Josh Boyer - 3.4.0-0.rc4.git0.2 -- Add GMA3600 (Cedarview) support (rhbz 810686) -- Reenable debugging options. - -* Mon Apr 23 2012 Josh Boyer - 3.4.0-0.rc4.git0.1 -- Disable debugging options. -- Linux v3.4-rc4 - -* Fri Apr 20 2012 Josh Boyer -- Move the dlm module to modules-extra and do additional cleanup (rhbz 811547) - -* Fri Apr 20 2012 Justin M. Forbes - 3.4.0-0.rc3.git4.1 -- Linux v3.4-rc3-89-gc6f5c93 - -* Thu Apr 19 2012 Justin M. Forbes - 3.4.0-0.rc3.git3.1 -- Linux v3.4-rc3-65-g9b7f43a - -* Thu Apr 19 2012 Justin M. Forbes -- CVE-2012-2119 macvtap: zerocopy: vector length is not validated before - pinning user pages (rhbz 814278 814289) - -* Thu Apr 19 2012 Justin M. Forbes -- CVE-2012-2121: Fix KVM device assignment page leak (rhbz 814149 814155) - -* Wed Apr 18 2012 Justin M. Forbes - 3.4.0-0.rc3.git2.1 -- Linux v3.4-rc3-36-g592fe89 - -* Wed Apr 18 2012 Josh Boyer -- Fix hfsplus bless ioctl with hardlinks (from Matthew Garrett) -- Change patch to resolve libata hotplug (rhbz 807632) - -* Tue Apr 17 2012 Josh Boyer -- Move the dlm module to modules-extra (rhbz 811547) - -* Tue Apr 17 2012 Justin M. Forbes - 3.4.0-0.rc3.git1.1 -- Linux v3.4-rc3-17-g4643b05 - -* Tue Apr 17 2012 Josh Boyer -- Fix oops on invalid AMD microcode load (rhbz 797559) - -* Mon Apr 16 2012 Josh Boyer -- Add and use vga_default_device patches (requested by Matthew Garrett) -- Enable Apple gmux driver - -* Mon Apr 16 2012 Justin M. Forbes - 3.4.0-0.rc3.git0.2 -- Reenable debugging options. - -* Mon Apr 16 2012 John W. Linville -- Disable CONFIG_WIRELESS_EXT_SYSFS (long deprecated upstream) - -* Mon Apr 16 2012 Justin M. Forbes - 3.4.0-0.rc3.git0.1 -- Linux v3.4-rc3 -- Disable debugging options. - -* Fri Apr 13 2012 Justin M. Forbes - 3.4.0-0.rc2.git3.1 -- Linux v3.4-rc2-269-g4166fb6 - -* Thu Apr 12 2012 Justin M. Forbes - 3.4.0-0.rc2.git2.1 -- Linux v3.4-rc2-174-gecca5c3 - -* Thu Apr 12 2012 Dennis Gilmore -- KALLSYMS_EXTRA_PASS=1 has to be passed in on the command line so do so only for arm - -* Wed Apr 11 2012 Peter Robinson -- update ARM configs, rename arm-omap - -* Wed Apr 11 2012 Dennis Gilmore -- set KALLSYMS_EXTRA_PASS=1 on arm arches - -* Wed Apr 11 2012 Justin M. Forbes -- enable HyperV drivers - -* Wed Apr 11 2012 Justin M. Forbes - 3.4.0-0.rc2.git1.1 -- Linux v3.4-rc2-23-g923e9a1 - -* Tue Apr 10 2012 Josh Boyer -- Disable the PMAC ide driver. PATA_MACIO seems to work (rhbz 810579) -- Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) - -* Mon Apr 09 2012 Justin M. Forbes - 3.4.0-0.rc2.git0.3 -- Reenable debugging options. - -* Mon Apr 09 2012 Justin M. Forbes -- SELinux apply a different permission to ptrace a child vs non-child - -* Mon Apr 09 2012 Justin M. Forbes - 3.4.0-0.rc2.git0.2 -- Disable debugging options. - -* Mon Apr 09 2012 Justin M. Forbes - 3.4.0-0.rc2 -- Linux v3.4-rc2 - -* Fri Apr 06 2012 Justin M. Forbes - 3.4.0-0.rc1.git3.1 -- Linux v3.4-rc1-349-g314489b - -* Thu Apr 05 2012 Justin M. Forbes - 3.4.0-0.rc1.git2.1 -- Linux v3.4-rc1-246-g6c216ec -- Turn off CONFIG_RCU_FAST_NO_HZ until it is fixed upstream - -* Thu Apr 05 2012 Dave Jones -- Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) - -* Wed Apr 04 2012 Josh Boyer -- Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - -* Tue Apr 03 2012 Justin M. Forbes - 3.4.0-0.rc1.git1.2 -- BTRFS use after free patch - -* Tue Apr 03 2012 Justin M. Forbes - 3.4.0-0.rc1.git1.2 -- Reenable debugging options. - -* Tue Apr 03 2012 Justin M. Forbes - 3.4.0-0.rc1.git1.1 -- Linux v3.4-rc1-144-g01627d9 - -* Tue Apr 03 2012 Josh Boyer -- Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) - -* Mon Apr 02 2012 Justin M. Forbes - 3.4.0-0.rc1.git0.2 -- Fix config since koji preps as noarch - -* Mon Apr 02 2012 Justin M. Forbes - 3.4.0-0.rc1.git0.2 -- Disable debugging options. - -* Mon Apr 02 2012 Justin M. Forbes - 3.4.0-0.rc1 -- Linux v3.4-rc1 - -* Fri Mar 30 2012 Justin M. Forbes - 3.4.0-0.rc0.git5.1 -- Linux v3.3-9295-gf52b69f - -* Fri Mar 30 2012 Dave Jones -- Change config parsing to use {_target_cpu} (From Niels de Vos) - -* Thu Mar 29 2012 Justin M. Forbes - 3.4.0-0.rc0.git4.1 -- Linux v3.3-8839-gb5174fa - -* Thu Mar 29 2012 Josh Boyer -- Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) - -* Wed Mar 28 2012 Josh Boyer -- Move 9p modules back to main package for KVM (rhbz 807733) - -* Wed Mar 28 2012 Justin M. Forbes - 3.4.0-0.rc0.git3.1 -- Linux v3.3-7919-g6658a69 - -* Mon Mar 26 2012 Justin M. Forbes - 3.4.0-0.rc0.git2.1 -- Linux v3.3-6972-ge22057c - -* Thu Mar 22 2012 Dave Jones 3.4.0-0.rc0.git1.2 -- Fix occasional EBADMSG from signed modules. (rhbz 804345) - -* Thu Mar 22 2012 Dave Jones -- Fix dentry hash collisions that prevented boot with selinux enabled (rhbz 805371) - -* Thu Mar 22 2012 Dave Jones 3.4.0-0.rc0.git1.1 -- Linux v3.3-4074-g5375871 - -* Wed Mar 21 2012 Josh Boyer -- Ship hmac file for vmlinuz for FIPS-140 (rhbz 805538) - -* Tue Mar 20 2012 Josh Boyer -- CVE-2012-1568: execshield: predictable ascii armour base address (rhbz 804957) -- mac80211: fix possible tid_rx->reorder_timer use after free - from Stanislaw Gruska (rhbz 804007) - -* Mon Mar 19 2012 Dave Jones - 3.3.0-3 -- Reenable debugging options. - -* Mon Mar 19 2012 Dave Jones - 3.3.0-2 -- Disable debugging options. - -* Sun Mar 18 2012 Dave Jones -- Linux 3.3 - -* Fri Mar 16 2012 Adam Jackson -- drm-i915-dp-stfu.patch: Muzzle a bunch of DP WARN()s. They're not wrong, - but they're not helpful at this point. - -* Fri Mar 16 2012 Dave Jones - 3.3.0-0.rc7.git2.1 -- Linux v3.3-rc7-103-g0c4d067 - -* Fri Mar 16 2012 Justin M. Forbes -- re-enable threading on hibernate compression/decompression - -* Fri Mar 16 2012 Josh Boyer -- Fix irqpoll patch to really only apply for ASM108x machines (rhbz 800520) - -* Thu Mar 15 2012 Justin M. Forbes -- CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode (rhbz 803809) - -* Wed Mar 14 2012 Josh Boyer -- Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge - -* Tue Mar 13 2012 John W. Linville -- Remove infrastructure related to compat-wireless integration - -* Mon Mar 12 2012 Mark Langsdorf -- Re-enable highbank config option and add new config file to support it - -* Mon Mar 12 2012 Dave Jones - 3.3.0-0.rc7.git0.5 -- Reenable debugging options. - -* Mon Mar 12 2012 Dave Jones - 3.3.0-0.rc7.git0.4 -- Disable debugging options. - -* Mon Mar 12 2012 Dave Jones -- Linux 3.3-rc7 - -* Wed Mar 07 2012 Dave Jones -- Add debug patch for bugs 787171/766277 - -* Wed Mar 07 2012 Josh Boyer -- Add modsign for x86 builds - -* Wed Mar 07 2012 Dave Jones - 3.3.0-0.rc6.git2.2 -- Disable debugging options. - -* Wed Mar 07 2012 Dave Jones - 3.3.0-0.rc6.git2.1 -- Linux v3.3-rc6-132-g55062d0 - -* Wed Mar 07 2012 Dave Jones - 3.3.0-0.rc6.git1.1 -- Linux v3.3-rc6-131-g097d591 - -* Mon Mar 05 2012 Dave Jones -- Linux 3.3-rc6 - -* Mon Mar 05 2012 John W. Linville -- Turn-off CONFIG_B43_BCMA_EXTRA to avoid b43/brcmsmac overlap - -* Mon Mar 05 2012 Mark Wielaard -- Add -r to debuginfo_args to invoke eu-strip --reloc-debug-sections. - -* Fri Mar 02 2012 Justin M. Forbes -- Disable threading in hibernate compression/decompression - -* Fri Mar 02 2012 Adam Jackson -- drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) - -* Thu Mar 01 2012 Dave Jones -- temporarily switch to low-performance polling IRQ mode when - unexpected IRQs occur. - -* Wed Feb 29 2012 Dave Jones - 3.3.0-0.rc5.git3.1 -- Linux v3.3-rc5-101-g88ebdda - -* Wed Feb 29 2012 John W. Linville -- Disable with_backports (pending removal) -- Disable a number of drivers for ancient wireless LAN cards -- Disable iwm3200-related drivers (hardware never released) -- Disable "thin firmware" version of libertas driver (libertas_tf) - -* Tue Feb 28 2012 Josh Boyer -- Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) - -* Tue Feb 28 2012 Dave Jones -- Disable CONFIG_USB_DEVICEFS (Deprecated). - -* Tue Feb 28 2012 Justin M. Forbes -- CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) - -* Tue Feb 28 2012 Dave Jones - 3.3.0-0.rc5.git2.1 -- Linux v3.3-rc5-88-g586c6e7 - -* Mon Feb 27 2012 Josh Boyer -- Add patch to fix regression in FADT revision checks (rhbz 730007 727865) - -* Mon Feb 27 2012 Josh Boyer - 3.3.0-0.rc5.git1.1 -- Linux 3.3-rc5-git1 (upstream 500dd2370e77c9551ba298bdeeb91b02d8402199) -- Reenable debugging options. - -* Sun Feb 26 2012 Josh Boyer - 3.3.0-0.rc5.git0.3 -- Add patch from Linus Torvalds to fix 32-bit autofs4 build - -* Sat Feb 25 2012 Josh Boyer - 3.3.0-0.rc5.git0.2 -- Disable debugging options. - -* Sat Feb 25 2012 Josh Boyer - 3.3.0-0.rc5.git0.1 -- Linux 3.3-rc5 - -* Sat Feb 25 2012 Josh Boyer - 3.3.0-0.rc4.git5.1 -- Linux 3.3-rc4-git5 (upstream b52b80023f262ce8a0ffdcb490acb23e8678377a) - -* Fri Feb 24 2012 Josh Boyer -- Linux 3.3-rc4-git4 (upstream bb4c7e9a9908548b458f34afb2fee74dc0d49f90) - -* Thu Feb 23 2012 Peter Robinson -- Further ARM config updates - -* Wed Feb 22 2012 Josh Boyer - 3.3.0-0.rc4.git3.1 -- Linux 3.3-rc4-git3 (upstream 45196cee28a5bcfb6ddbe2bffa4270cbed66ae4b) - -* Wed Feb 22 2012 Josh Boyer - 3.3.0-0.rc4.git2.1 -- Linux 3.3-rc4-git2 (upstream 719741d9986572d64b47c35c09f5e7bb8d389400) - -* Tue Feb 21 2012 Josh Boyer - 3.3.0-0.rc4.git1.4 -- Drop x86-Avoid-invoking-RCU-when-CPU-is-idle.patch (rhbz 795050) - -* Tue Feb 21 2012 Peter Robinson -- update ARM configs to F-17 branch - -* Tue Feb 21 2012 Josh Boyer -- ext4: fix resize when resizing within single group (rhbz 786454) -- imon: don't wedge hardware after early callbacks (rhbz 781832) - -* Tue Feb 21 2012 Josh Boyer - 3.3.0-0.rc4.git1.2 -- Enable rtl8712 driver (rhbz 699618) -- Linux 3.3-rc4-git1 (upstream 27e74da9800289e69ba907777df1e2085231eff7) - -* Mon Feb 20 2012 Dave Jones -- Do not call drivers when invalidating partitions for -ENOMEDIUM - -* Mon Feb 20 2012 Josh Boyer -- Avoid using stack variables in ums_realtek (again) (rhbz 795544) - -* Mon Feb 20 2012 Dave Jones -- NFSv4: Fix an Oops in the NFSv4 getacl code - -* Mon Feb 20 2012 Josh Boyer - 3.3.0-0.rc4.git0.2 -- Reenable debugging options. - -* Sun Feb 19 2012 Josh Boyer - 3.3.0-0.rc4.git0.1 -- Linux 3.3-rc4 -- Disable debugging options. - -* Sun Feb 19 2012 Peter Robinson -- Further updates to ARM config -- Fix and re-enable Tegra NVEC patch - -* Fri Feb 17 2012 Dave Jones -- improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) - -* Fri Feb 17 2012 Dave Jones -- Reenable radio drivers. (rhbz 784824) - -* Fri Feb 17 2012 Josh Boyer - 3.3.0-0.rc3.git7.2 -- Freeze all filesystems during system suspend/hibernate. - -* Fri Feb 17 2012 Josh Boyer - 3.3.0-0.rc3.git7.1 -- Linux 3.3-rc3-git7 (upstream 4903062b5485f0e2c286a23b44c9b59d9b017d53) - -* Wed Feb 15 2012 Peter Robinson -- Update ARM configs to 3.3 kernel -- use mainline cpu freq options - -* Wed Feb 15 2012 Josh Boyer - 3.3.0-0.rc3.git6.2 -- Linux 3.3-rc3-git6 (upstream c38e23456278e967f094b08247ffc3711b1029b2) -- Require newer linux-firmware package for updated bnx2/bnx2x drivers - -* Wed Feb 15 2012 Adam Jackson -- Add patch and config change for vgem.ko - -* Tue Feb 14 2012 Josh Boyer -- Add patch to fix RCU usage during cpu idle (rhbz 789641) -- Add patch to fix mce rcu splat (rhbz 789644) -- Patch to enable CONFIG_KEYS_COMPAT on s390 from David Howells (rhbz 790367) -- Modify sd_revalidate_disk patch to do a WARN_ONCE instead of silently skip -- Install perf examples as suggested by Jason Baron - -* Tue Feb 14 2012 Josh Boyer - 3.3.0-0.rc3.git5.1 -- Linux 3.3-rc3-git5 (upstream ce5afed937f0a823d3b00c9459409c3f5f2fbd5d) - -* Tue Feb 14 2012 Peter Robinson -- Update ARM components in Makefile.config - -* Mon Feb 13 2012 Josh Boyer -- Apply patch to fix autofs4 lockdep splat (rhbz 714828) - -* Mon Feb 13 2012 Josh Boyer - 3.3.0-0.rc3.git4.1 -- Linux 3.3-rc3-git4 (upstream 3ec1e88b33a3bdd852ce8e014052acec7a9da8b5) - -* Sat Feb 11 2012 Josh Boyer - 3.3.0-0.rc3.git3.1 -- Linux 3.3-rc3-git3 (upstream 8df54d622a120058ee8bec38743c9b8f091c8e58) - -* Fri Feb 10 2012 Josh Boyer -- Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) - -* Fri Feb 10 2012 Josh Boyer - 3.3.0-0.rc3.git2.1 -- Linux 3.3-rc3-git2 (upstream 612b8507c5d545feed2437b3d2239929cac7688d) - -* Fri Feb 10 2012 Josh Boyer - 3.3.0-0.rc3.git1.2 -- Reenable debugging options. - -* Fri Feb 10 2012 Josh Boyer -- Linux 3.3-rc3-git1 (upstream 19e00f2f1d5273dbc52eab0ebc315cae3aa44b2a) - -* Thu Feb 09 2012 Dave Jones -- bsg: fix sysfs link remove warning (#787281) - -* Thu Feb 09 2012 Josh Boyer - 3.3.0-0.rc3.git0.2 -- Disable debugging options. - -* Thu Feb 09 2012 Josh Boyer -- Linux 3.3-rc3 - -* Wed Feb 08 2012 Josh Boyer -- Remove a bogus inline declaration that broke ARM and ppc builds (rhbz 787373) -- CVE-2011-4086 jbd2: unmapped buffer with _Unwritten or _Delay flags set can - lead to DoS (rhbz 788260) -- Add new upstream NFS id mapping patches from Steve Dickson - -* Tue Feb 07 2012 Josh Boyer -- Linux 3.3-rc2-git6 (upstream 6bd113f1f4a8c0d05c4dbadb300319e0e3526db4) - -* Tue Feb 07 2012 Chris Wright -- Enable Open vSwitch - -* Tue Feb 07 2012 Justin M. Forbes -- Add virtio-scsi support - -* Tue Feb 07 2012 Josh Boyer -- Make build/ point to /usr/src/kernels instead of being relative (rhbz 788125) - -* Tue Feb 07 2012 Josh Boyer -- Linux 3.3-rc2-git5 (upstream 8597559a78e1cde158b999212bc9543682638eb1) -- Add hfsplus file blessing patches from Matthew Garrett - -* Mon Feb 6 2012 Peter Robinson -- Build an ARM hardfp base versatile/qemu kernel - -* Mon Feb 06 2012 Josh Boyer - 3.3.0-0.rc2.git4.1 -- Linux 3.3-rc2-git4 (upstream 23783f817bceedd6d4e549385e3f400ea64059e5) -- Build and ship turbostat and x86_energy_perf_policy in kernel-tools - -* Mon Feb 06 2012 John W. Linville -- Update compat-wireless snapshot from 2012-02-05 - -* Fri Feb 03 2012 Josh Boyer -- Goodbye iSeries. Only sfr loved you and even he's moved on - -* Fri Feb 03 2012 Josh Boyer - 3.3.0-0.rc2.git3.2 -- Drop patch that was NAKed upstream (rhbz 783211) - -* Fri Feb 03 2012 Josh Boyer - 3.3.0-0.rc2.git3.1 -- Linux 3.3-rc2-git3 (upstream 7f06db34e55af8fc33cf3d6d46d869cb7a372b5d) -- Patch from Jakub Kicinski to fix rt2x00 MCU requests (rhbz 772772) - -* Thu Feb 02 2012 Dennis Gilmore -- disable TOUCHSCREEN_EGALAX on arm arches -- build in CACHE_L2X0 on the imx kernel -- dont build the module for imx21 usb since its not something we support - -* Thu Feb 02 2012 Josh Boyer - 3.3.0-0.rc2.git2.1 -- Linux 3.3-rc2-git2 (upstream 24b36da33c64368775f4ef9386d44dce1d2bc8cf) - -* Thu Feb 02 2012 Dennis Gilmore -- disable compat-wireless on arm arches - -* Wed Feb 01 2012 Josh Boyer - 3.3.0-0.rc2.git1.1 -- Linux 3.3-rc2-git1 (upstream ce106ad31016b5da1168496cd0454a6290555f84) - -* Wed Feb 01 2012 Josh Boyer - 3.3.0-0.rc2.git0.3 -- Reenable debugging options. - -* Tue Jan 31 2012 Josh Boyer - 3.3.0-0.rc2.git0.2 -- Disable debugging options. - -* Tue Jan 31 2012 Josh Boyer -- Linux 3.3-rc2 - -* Tue Jan 31 2012 Dave Jones -- Distributed switch architecture & drivers can be modular in 3.3. - -* Mon Jan 30 2012 Josh Boyer - 3.3.0-0.rc1.git6.1 -- Linux 3.3-rc1-git6 (upstream 6bc2b95ee602659c1be6fac0f6aadeb0c5c29a5d) -- Add patch from Kay Sievers for udlfb device removal -- utrace patch to allow calling internal functions from atomic context from - Oleg Nesterov - -* Mon Jan 30 2012 John W. Linville -- ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix - -* Sun Jan 29 2012 Josh Boyer - 3.3.0-0.rc1.git5.1 -- Linux 3.3-rc1-git5 (upstream 0a9626575400879d1d5e6bc8768188b938d7c501) - -* Fri Jan 27 2012 John W. Linville -- Update compat-wireless with snapshot from 2012-01-26 -- Drop brcmfmac GCC 4.7 compatibility patch (included in above) -- Include config.mk from compat-wireless build in files for installation - -* Fri Jan 27 2012 Josh Boyer - 3.3.0-0.rc1.git4.1 -- Linux 3.3-rc1-git4 (upstream 74ea15d909b31158f9b63190a95b52bc05586d4b) -- Enable the non-staging GMA500 driver (rhbz 785053) - -* Thu Jan 26 2012 Josh Boyer -- Drop revert-efi-rtclock.patch. Issue was fixed by upstream commit 47997d75 -- Enable CONFIG_EFI_STUB per Matthew Garrett - -* Wed Jan 25 2012 Peter Robinson -- Build perf/tools on ARM sfp/hfp not just sfp - -* Wed Jan 25 2012 Josh Boyer - 3.3.0-0.rc1.git3.1 -- Linux 3.3-rc1-git3 (upstream aaad641eadfd3e74b0fbb68fcf539b9cef0415d0) -- Update utrace.patch from Oleg Nesterov -- Add patch to invalidate parent cache when fsync is called on a partition - (rhbz 783211) - -* Wed Jan 25 2012 Josh Boyer - 3.3.0-0.rc1.git2.1 -- Linux 3.3-rc1-git2 (upstream f8275f9694b8adf9f3498e747ea4c3e8b984499b) - -* Tue Jan 24 2012 Josh Boyer -- Re-enable the ARCMSR module (rhbz 784287) -- Re-enable the LIRC_STAGING drivers (rhbz 784398) - -* Tue Jan 24 2012 Josh Boyer - 3.3.0-0.rc1.git1.1 -- Linux 3.3-rc1-git1 (upstream c1aab02dac690af7ff634d8e1cb3be6a04387eef) - -* Mon Jan 23 2012 Josh Boyer - 3.3.0-0.rc1.git0.4 -- Reenable debugging options. - -* Mon Jan 23 2012 Josh Boyer -- Add mac80211 deauth fix pointed out by Stanislaw Gruszka -- Add arch guards in files section for kernel-tools subpackage - -* Sun Jan 22 2012 Josh Boyer - 3.3.0-0.rc1.git0.3 -- Disable NVME as it doesn't build on 32-bit - -* Fri Jan 20 2012 Josh Boyer - 3.3.0-0.rc1.git0.2 -- Disable debugging options. - -* Fri Jan 20 2012 Josh Boyer -- Rebase to Linux 3.3-rc1 - -* Thu Jan 19 2012 John W. Linville -- Pass the same make options to compat-wireless as to the base kernel - -* Thu Jan 19 2012 Dennis Gilmore -- dont build TOUCHSCREEN_EETI on arm - -* Wed Jan 18 2012 Josh Boyer 3.2.1-8 -- Fix broken procfs backport (rhbz 782961) - -* Wed Jan 18 2012 Josh Boyer 3.2.1-7 -- /proc/pid/* information leak (rhbz 782686) -- CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) -- CVE-2012-0058 Unused iocbs in a batch should not be accounted as active - (rhbz 782696) - -* Tue Jan 17 2012 Dave Jones -- Rawhide builds now use MAXSMP on x86. -- For release builds, set x86-64 to support 64 CPUs. - If larger systems become widespread, we can increase in an update. - -* Tue Jan 17 2012 Dave Jones 3.2.1-5 -- Give KMEMLEAK a try again. - -* Mon Jan 16 2012 Dave Jones -- Disable ISA - -* Mon Jan 16 2012 John W. Linville -- Re-enable CONFIG_BRCMFMAC builds (found work-around for GCC 4.7 builds) - -* Sun Jan 15 2012 Josh Boyer -- Avoid packaging symlinks for kernel-doc files (rhbz 767351) -- Apply mac80211 NULL ptr deref fix to compat-wireless too (rhbz 769766) - -* Fri Jan 13 2012 Dave Jones -- Disable NFC drivers. - -* Fri Jan 13 2012 Dave Jones -- Enable CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK - (On by default in rawhide/-debug) - -* Fri Jan 13 2012 Dave Jones -- Disable memory hotplug on x86-64 - -* Fri Jan 13 2012 Dave Jones -- Disable Calgary IOMMU - -* Fri Jan 13 2012 Dave Jones -- Disable MTD - -* Fri Jan 13 2012 Dave Jones -- Flannel shirts, Grunge music, IOMega ZIP drives, PCMCIA & ISA SCSI - controllers. The 90s were _awesome_. But it's time to move on. - -* Fri Jan 13 2012 Dave Jones -- Disable PLIP, Enable PPP BSDCOMP, Disable SLIP - -* Fri Jan 13 2012 Josh Boyer -- Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) - -* Fri Jan 13 2012 Josh Boyer 3.2.1-2 -- CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) - -* Fri Jan 13 2012 Josh Boyer 3.2.1-1 -- Linux 3.2.1 -- Change stable patch compression format to xz - -* Wed Jan 11 2012 Josh Boyer -- Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) - -* Tue Jan 10 2012 John W. Linville -- Update compat-wireless snapshot with version from 2012-01-09 - -* Tue Jan 10 2012 Josh Boyer -- Add patch to fix ext4 compatibility with ext2 mount option (rhbz 770172) -- Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) - -* Thu Jan 05 2012 Adam Jackson -- Disable unsupported DRI1-only DRM drivers: i810, r128, tdfx - -* Thu Jan 05 2012 John W. Linville -- Patch compat-wireless build to avoid "pr_fmt redefined" warnings -- Disable CONFIG_BRCMFMAC builds (needs unknown symbol __bad_udelay) -- Include compat-wireless in removal of files resulting from patch fuzz - -* Thu Jan 05 2012 Josh Boyer -- Move the depmod file removal below the compat-wireless build to make sure we - clean them all out - -* Thu Jan 05 2012 Dave Jones -- CONFIG_DEBUG_SET_MODULE_RONX should always be set. - -* Thu Jan 05 2012 Dave Jones - 3.2.0-3 -- Reenable debugging options. - -* Thu Jan 05 2012 Dave Jones - 3.2.0-2 -- Disable debugging options. - -* Wed Jan 04 2012 Dave Jones 3.2.0-1 -- Linux 3.2 - -* Wed Jan 04 2012 Dave Jones 3.2.0-0.rc7.git5.1 -- Linux 3.2-rc7-git5 (157e8bf8b4823bfcdefa6c1548002374b61f61df) - -* Tue Jan 03 2012 John W. Linville -- Avoid unnecessary modprobe invocations during compat-wireless build - -* Tue Jan 03 2012 Josh Boyer -- Add bluetooth support for BCM20102A0 21e3 (rhbz 770233) - -* Tue Jan 03 2012 John W. Linville -- Re-enable CONFIG_RT2800PCI_RT53XX in compat-wireless build (rhbz #720594) - -* Mon Jan 02 2012 Dave Jones - 3.2.0-0.rc7.git4.1 -- Linux 3.2-rc7-git4 (115e8e705e4be071b9e06ff72578e3b603f2ba65) - -* Sat Dec 31 2011 Dave Jones - 3.2.0-0.rc7.git3.1 -- Linux 3.2-rc7-git3 (06867fbb8abc936192195e5dcc4b63e12cc78f72) - -* Fri Dec 30 2011 Dave Jones - 3.2.0-0.rc7.git2.1 -- Linux 3.2-rc7-git2 (89307babf966165171547f105e2253dec261cfa5) - -* Wed Dec 28 2011 Dave Jones -- Disable unnecessary CONFIG_NET_DCCPPROBE - -* Wed Dec 28 2011 Dave Jones - 3.2.0-0.rc7.git1.1 -- Linux 3.2-rc7-git1 (371de6e4e0042adf4f9b54c414154f57414ddd37) - -* Sat Dec 24 2011 Kyle McMartin - 3.2.0-0.rc7.git0.1 -- Linux 3.2-rc7 - -* Fri Dec 23 2011 Dennis Gilmore -- build imx highbank and kirkwood kernels on arm -- clean up arm config options - -* Thu Dec 22 2011 Dave Jones - 3.2.0-0.rc6.git3.1 -- Linux 3.2-rc6-git3 (ecefc36b41ac0fe92d76273a23faf27b2da13411) - -* Tue Dec 20 2011 Dave Jones - 3.2.0-0.rc6.git2.1 -- Linux 3.2-rc6-git2 (a4a4923919f2d43583789b1f3603f4e5600d8321) - -* Tue Dec 20 2011 Josh Boyer -- Include crtsaves.o for ppc64 as well (rhbz #769415) -- Drop EDID headers patch from 751589 for now (rhbz #769103) - -* Mon Dec 19 2011 John W. Linville -- modpost: add option to allow external modules to avoid taint -- Make integrated compat-wireless take advantage of the above -- Turn-on backports again, since TAINT_OOT_MODULE issue is resolved -- Update compat-wireless snapshot from 2011-12-18 - -* Mon Dec 19 2011 Dave Jones -- Switch x86-code-dump-fix-truncation.patch to use the pending upstream fix. - -* Mon Dec 19 2011 Dave Jones -- Disable IMA. (Forces TPM on, which may be undesirable: See 733964, 746097) - Move TPM modules to modules-extra - -* Mon Dec 19 2011 Dave Jones - 3.2.0-0.rc6.git1.1 -- Linux 3.2-rc6-git1 (390f998509bf049019df0b078c0a6606e0d57fb4) - -* Sat Dec 17 2011 Josh Boyer - 3.2.0-0.rc6.git0.1 -- Linux 3.2-rc6 - -* Fri Dec 16 2011 Dave Jones - 3.2.0-0.rc5.git4.1 -- Linux 3.2-rc5-git4 (6f12d2ee52dcf97dcefdadbd500e7650311eaa6a) - -* Fri Dec 16 2011 Ben Skeggs -- Add patch to do a better job of dealing with busted EDID headers (rhbz#751589) - -* Thu Dec 15 2011 Josh Boyer - 3.2.0-0.rc5.git3.1 -- Linux 3.2-rc5-git3 (55b02d2f4445ad625213817a1736bf2884d32547) - -* Thu Dec 15 2011 Dave Jones - 3.2.0-0.rc5.git2.4 -- Disable Intel IOMMU by default. - -* Thu Dec 15 2011 Dave Jones - 3.2.0-0.rc5.git2.3 -- Change configfs to be built-in. (rhbz 767432) - -* Wed Dec 14 2011 Steve Dickson 3.2.0-0.rc5.git2.2.fc17 -- Enabled the in-kernel idmapper. -- keyring: allow special keyrings to be cleared - -* Wed Dec 14 2011 Dave Jones - 3.2.0-0.rc5.git2.1 -- Linux 3.2-rc5-git2 (373da0a2a33018d560afcb2c77f8842985d79594) - -* Tue Dec 13 2011 Dave Jones - 3.2.0-0.rc5.git1.1 -- Linux 3.2-rc5-git1 (442ee5a942834431ccf0b412e3cf7bb9ae97ff4e) - -* Tue Dec 13 2011 Dave Jones -- Disable FDDI/SKFP. - -* Tue Dec 13 2011 Josh Boyer -- mod-extras: Don't fail the build if a module is listed that isn't built -- Remove extraneous settings and enable Radeon KMS for powerpc (via Will Woods) - -* Mon Dec 12 2011 John W. Linville -- Turn-off backports until TAINT_OOT_MODULE issue is resolved - -* Mon Dec 12 2011 Josh Boyer -- Disable backports on arches where we don't actually build a kernel (or config) - -* Sun Dec 11 2011 Kyle McMartin - 3.0.0-0.rc5.git0.1 -- Linux 3.2-rc5 - -* Fri Dec 09 2011 John W. Linville -- Do a better job of cleaning-up compat-wireless between builds - -* Fri Dec 09 2011 Dave Jones - 3.2.0-0.rc4.git6.1 -- Linux 3.2-rc4-git6 (09d9673d53005fdf40de4c759425893904292236) - -* Thu Dec 08 2011 Josh Boyer -- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) - -* Wed Dec 07 2011 Dave Jones - 3.2.0-0.rc4.git5.2 -- Linux 3.2-rc4-git5 (77a7300abad7fe01891b400e88d746f97307ee5a) - -* Wed Dec 07 2011 Dave Jones -- Turn DEBUG_PAGEALLOC back off. - -* Wed Dec 07 2011 Chuck Ebbert -- Attempt to fix rhbz #736815 by printing spaces before the brackets - -* Tue Dec 06 2011 Dave Jones 3.2.0-0.rc4.git4.2.fc17 -- Linux 3.2-rc4-git2 (b835c0f47f725d864bf2545f10c733b754bb6d51) - -* Tue Dec 06 2011 Dave Jones -- Turn on DEBUG_PAGEALLOC for a day. - -* Tue Dec 06 2011 Dave Jones -- Linux 3.2-rc4-git2 (45e713efe2fa574b6662e7fb63fae9497c5e03d4) - -* Tue Dec 06 2011 Josh Boyer -- Move 802.1q and yenta_socket back into the main kernel package - -* Mon Dec 05 2011 Josh Boyer -- Only print the apm_cpu_idle message once (rhbz #760341) - -* Mon Dec 05 2011 Dave Jones -- Enable CONFIG_BSD_ACCT_V3. Should be safe since psacct-6.5.4-4.fc14. - -* Mon Dec 05 2011 Dave Jones 3.2.0-0.rc4.git2.1.fc17 -- Linux 3.2-rc4-git2 (8e8da023f5af71662867729db5547dc54786093c) - -* Sat Dec 03 2011 John W. Linville -- Add compat-wireless patch to define module_usb_driver - -* Fri Dec 02 2011 John W. Linville -- Revise compat-wireless configuration -- Update compat-wireless snapshot -- Enable with-backports by default - -* Fri Dec 02 2011 Josh Boyer 3.2.0-0.rc4.git1.4.fc17 -- Backport ALPS touchpad patches from input/next branch (rhbz #590880) -- Apply patch from John Linville to reverse modules-extra dependency order -- Put ssb.ko back in the main kernel package - -* Fri Dec 02 2011 Dave Jones 3.2.0-0.rc4.git1.3.fc17 -- Enable Poulsbo DRM. - -* Fri Dec 02 2011 Dave Jones -- Linux 3.2-rc4-git1 (5983fe2b29df5885880d7fa3b91aca306c7564ef) - dropped: rtlwifi-fix-lps_lock-deadlock.patch (applied upstream) - -* Fri Dec 02 2011 Josh Boyer -- Adjust Requires for modules-extra pacakge to rely on kernel-uname-r - -* Thu Dec 01 2011 Dave Jones -- Linux 3.2-rc4 - -* Thu Dec 01 2011 Dave Jones -- Linux 3.2-rc3-git2 (b930c26416c4ea6855726fd977145ccea9afbdda) - -* Tue Nov 29 2011 Josh Boyer -- Add modules-extra subpackage -- Drop drm-intel-make-lvds-work.patch (rhbz #731296) -- Add patch to fix deadlock in rtlwifi (rhbz #755154) - -* Tue Nov 29 2011 Josh Boyer 3.2.0-0.rc3.git1.1 -- Linux 3.2-rc3-git1 - -* Thu Nov 24 2011 Josh Boyer 3.2.0-0.rc3.git0.1 -- Linux 3.2-rc3. Gobble. - -* Wed Nov 23 2011 Josh Boyer 3.2.0-0.rc2.git8.1 -- Linux 3.2-rc2-git8 - -* Tue Nov 22 2011 Josh Boyer 3.2.0-0.rc2.git7.1 -- Linux 3.2-rc2-git7 - -* Mon Nov 21 2011 Josh Boyer 3.2.0-0.rc2.git6.1 -- Linux 3.2-rc2-git6 -- Update utrace.patch from Oleg Nesterov - -* Mon Nov 21 2011 Josh Boyer 3.2.0-0.rc2.git5.1 -- Linux 3.2-rc2-git5 - -* Sun Nov 20 2011 Josh Boyer 3.2.0-0.rc2.git4.1 -- Linux 3.2-rc2-git4 - -* Fri Nov 18 2011 Josh Boyer 3.2.0-0.rc2.git3.1 -- Linux 3.2-rc2-git3 -- Disable various fb and drm drivers that don't have xorg equivalents per ajax -- Other minor config cleanup - -* Thu Nov 17 2011 Josh Boyer -- Linux 3.2-rc2-git2 - -* Thu Nov 17 2011 Kyle McMartin -- Drop Obsoletes/Provides from kernel-tools onto perf. - -* Wed Nov 16 2011 John W. Linville -- Add compat-wireless as an option for kernel build - -* Wed Nov 16 2011 Kyle McMartin -- Work around #663080 and restore building 'perf' on s390x (we don't need - kernel-tools since cpuspeed isn't needed on s390...) -- Restore %{perf_make} to ensure CFLAGS doesn't change across building - perf. - -* Wed Nov 16 2011 Josh Boyer -- Linux 3.2-rc2-git1 - -* Mon Nov 14 2011 Josh Boyer -- Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) -- Add patch to fix ip6_tunnel naming (rhbz 751165) -- Quite warning in apm_cpu_idle (rhbz 753776) - -* Mon Nov 14 2011 Josh Boyer -- CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) -- Linux 3.2-rc1-git4 - -* Sat Nov 12 2011 Josh Boyer -- Linux 3.2-rc1-git3 - -* Fri Nov 11 2011 Chuck Ebbert -- Use the same naming scheme as rawhide for -stable RC kernels - (e.g. 3.1.1-0.rc1.1 instead of 3.1.1-1.rc1) - -* Fri Nov 11 2011 Josh Boyer -- Add reworked pci ASPM patch from Matthew Garrett - -* Fri Nov 11 2011 John W. Linville -- Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 - -* Thu Nov 10 2011 Josh Boyer -- Linux 3.2-rc1-git2 - -* Wed Nov 09 2011 Josh Boyer -- Linux 3.2-rc1-git1 -- Enable the brcm80211 modules now that they have left staging - -* Tue Nov 08 2011 Josh Boyer -- Add python-perf-debuginfo package (rhbz 752140) - -* Tue Nov 08 2011 Neil Horman -- Add msi irq ennumeration per dev in sysfs (bz 744012) - -* Tue Nov 08 2011 Josh Boyer -- Linux 3.2-rc1 - -* Mon Nov 07 2011 Josh Boyer -- Linux 3.1-git7 -- Drop override for XEN_MAX_DOMAIN_MEMORY (rhbz 751789) -- Add fixes from git://openlinux.windriver.com/people/paulg/modsplit-post-merge -- Add two patches to fix mac80211 issues (rhbz 731365) - -* Fri Nov 04 2011 Josh Boyer -- Linux 3.1-git6 - -* Thu Nov 03 2011 Josh Boyer -- Linux 3.1-git5 - -* Tue Nov 01 2011 Josh Boyer -- Linux 3.1-git4 - -* Tue Nov 01 2011 Dave Jones -- allow building the perf rpm for ARM (rhbz 741325) - -* Tue Nov 01 2011 Dave Jones -- Add another Sony laptop to the nonvs blacklist. (rhbz 641789) - -* Tue Nov 01 2011 Kyle McMartin -- Restore perf sub-package so that sparc64 and s390x get their - perf back. - -* Mon Oct 31 2011 Josh Boyer --CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) - -* Mon Oct 31 2011 Kyle McMartin -- Build a python-perf subpackage. - -* Mon Oct 31 2011 Josh Boyer -- Linux 3.1-git3. Happy Halloween. - -* Fri Oct 28 2011 Josh Boyer -- Linux 3.1-git2 - -* Thu Oct 27 2011 Josh Boyer -- Drop ia64 -- Drop alpha - -* Wed Oct 26 2011 Kyle McMartin -- Make some config changes caught during a review: - - CONFIG_SOC_CAMERA: disable, it's only for some ARM boards - - CONFIG_MEDIA_ALTERA_CI=m: needed for some DVB boards - - CONFIG_DEBUG_BLK_CGROUP: stop setting it twice... - -* Wed Oct 26 2011 Chuck Ebbert -- Add build option "--with=release" to build a non-debug kernel in rawhide. - -* Wed Oct 26 2011 Josh Boyer -- Linux 3.1-git1 - -* Wed Oct 26 2011 Fedora Release Engineering - 3.1.0-5 -- Rebuilt for glibc bug#747377 - -* Wed Oct 26 2011 Kyle McMartin -- Drop kernel-firmware subpackage. We've had linux-firmware around for - enough releases now. -- ppc64/ppc vdso patches have been upstream for ages. -- Install vdso on s390/s390x. -- Fedora 8 was a very long time ago... fancy_debuginfo turns into - with_debuginfo in the glorious future. -- Disable CONFIG_CC_OPTIMIZE_FOR_SIZE, upstream consensus is -O2 has - generated better code than -Os for a while - (https://lkml.org/lkml/2009/11/26/57) -- Drop vanilla-% targets, and other Makefile cruft which has been bit - rotting for years. -- Dump %rhel config bits which are not used in Fedora. -- Drop dead Source0 hacks from the 2.6->3.0 transition. - -* Wed Oct 26 2011 Josh Boyer -- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) - -* Tue Oct 25 2011 Josh Boyer -- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) -- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) - -* Mon Oct 24 2011 Josh Boyer -- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) - -* Mon Oct 24 2011 Chuck Ebbert 3.1.0-1 -- Linux 3.1 - -* Sun Oct 23 2011 Chuck Ebbert -- Make rpmbuild option "without_debug" work properly on rawhide. - -* Fri Oct 21 2011 Chuck Ebbert 3.1.0-0.rc10.git1.1 -- Require grubby >= 8.3-1 like F16 does. -- Update to upstream HEAD (v3.1-rc10-42-g2efd7c0). - -* Fri Oct 21 2011 Dave Jones -- Lower severity of Radeon lockup messages. - -* Wed Oct 19 2011 Dave Jones -- Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) - -* Wed Oct 19 2011 Chuck Ebbert -- Sync with F16 -- Linux 3.1-rc10 -- Copy nouveau updates patch from F16 -- Fix deadlock in POSIX cputimer code (rhbz #746485) - -* Tue Oct 18 2011 Josh Boyer -- Add patch to fix invalid EFI remap calls from Matt Fleming - -* Mon Oct 17 2011 Josh Boyer -- Add two patches to fix stalls in khugepaged (rhbz 735946) - -* Fri Oct 14 2011 Dave Jones -- Disable CONFIG_ACPI_PROCFS_POWER which is supposed to be going away soon. - -* Thu Oct 13 2011 Josh Boyer -- Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) - -* Thu Oct 13 2011 Adam Jackson -- drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) - -* Thu Oct 13 2011 Josh Boyer -- Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) - -* Tue Oct 11 2011 Josh Boyer -- Disable CONFIG_XEN_BALLOON_MEMORY_HOTPLUG (rhbz 744408) - -* Thu Oct 06 2011 Josh Boyer -- Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) - -* Thu Oct 06 2011 Dave Jones -- Taint if virtualbox modules have been loaded. - -* Wed Oct 05 2011 Josh Boyer -- Linux 3.1-rc9 - -* Thu Sep 29 2011 Josh Boyer -- Update logitech USB quirk patch - -* Tue Sep 27 2011 Chuck Ebbert -- Linux 3.1-rc8 -- New option: CONFIG_ARM_ERRATA_764369 is not set -- Fix up utrace.patch to apply after commit f9d81f61c - -* Thu Sep 22 2011 Dave Jones -- Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) - -* Thu Sep 22 2011 Dennis Gilmore -- build a vmlinux image on sparc64 - -* Wed Sep 21 2011 Josh Boyer -- Linux 3.1-rc7 - -* Tue Sep 20 2011 Dave Jones -- Limit 32-bit x86 kernels to 32 processors. - -* Mon Sep 19 2011 Dave Jones -- Merge some improvements to the 32bit mmap randomisation from Kees Cook. - -* Wed Sep 14 2011 Josh Boyer -- Add patch to fix deadlock in ppc64 icswx (rhbz 737984) - -* Wed Sep 14 2011 Neil Horman -- Enable CONFIG_IP_VS_IPV6 (bz 738194) - -* Wed Sep 14 2011 Josh Boyer -- Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth -- Add patch to fix HVCS on ppc64 (rhbz 738096) -- Add various ibmveth driver fixes (rhbz 733766) - -* Mon Sep 12 2011 Josh Boyer -- Linux 3.1-rc6 -- Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) - -* Fri Sep 09 2011 Josh Boyer -- Change to 64K page size for ppc64 kernels (rhbz 736751) - -* Wed Sep 07 2011 Josh Boyer -- Linux 3.1-rc5 (locally generated patch from git as kernel.org is down) -- Add patch to fix oops when linking entities in ucvideo (rhbz 735437) - -* Fri Sep 02 2011 Dave Jones -- utrace: s390: fix the compile problem with traps.c (rhbz 735118) - -* Tue Aug 30 2011 Dave Jones -- Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) - -* Tue Aug 30 2011 Josh Boyer -- Add patch to fix rhbz 606017 - -* Mon Aug 29 2011 Josh Boyer -- Linux 3.1-rc4 - -* Sat Aug 27 2011 Dave Jones -- Fix get_gate_vma usage in i386 NX emulation -- Bring back the 32bit mmap randomization patch for now. - NX emulation is still too dependant upon it. - -* Sat Aug 27 2011 Josh Boyer -- Linux 3.1-rc3-git6 - -* Fri Aug 26 2011 Dave Jones -- Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. - -* Fri Aug 26 2011 Dave Jones -- Drop linux-2.6-debug-vm-would-have-oomkilled.patch - The oom-killer heuristics have improved enough that this should - never be necessary (and it probably doesn't dtrt any more) - -* Fri Aug 26 2011 Dave Jones -- Drop linux-2.6-32bit-mmap-exec-randomization.patch - Outlived it's usefulness (and made of ugly) - -* Fri Aug 26 2011 Dave Jones -- Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) - -* Fri Aug 26 2011 Josh Boyer -- Linux 3.1-rc3-git5 - -* Thu Aug 25 2011 Josh Boyer -- Linux 3.1-rc3-git3 - -* Wed Aug 24 2011 Josh Boyer -- Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) - -* Mon Aug 22 2011 Josh Boyer -- Linux 3.1-rc3 -- Add patch to fix duplicate backlight registration (rhbz 732202) - -* Mon Aug 22 2011 Josh Boyer -- Linux 3.1-rc2-git9 - -* Sat Aug 20 2011 Josh Boyer -- Linux 3.1-rc2-git8 - -* Sat Aug 20 2011 Josh Boyer -- Linux 3.1-rc2-git7 -- Add a provides/obsoletes for cpupowerutils-devel - -* Fri Aug 19 2011 Josh Boyer -- Add patch from upstream to fix 64-bit divide error in btrfs - -* Fri Aug 19 2011 Josh Boyer -- Linux 3.1-rc2-git5 -- Change XHCI to builtin (rhbz 731706) -- Add patch to fix race between cryptd and aesni (rhbz 721002) - -* Thu Aug 18 2011 Josh Boyer -- Adjust provides/obsoletes to replace the cpupowerutils package - -* Thu Aug 18 2011 Josh Boyer -- Add patch to fix perf build against rawhide glibc -- Add BR for gettext for cpupower translations - -* Wed Aug 17 2011 Josh Boyer -- Linux 3.1-rc2-git4 -- Create the kernel-tools subpackages based on a start by davej - -* Tue Aug 16 2011 Dave Jones -- Prepare for packaging more of tools/ by renaming 'perf' subpackage - to kernel-tools - -* Tue Aug 16 2011 Dennis Gilmore -+- add config for arm tegra devices -+- setup kernel to build omap image (patch from David Marlin) -+- setup kernel to build tegra image based on omap work -+- add arm device tree patches - -* Tue Aug 16 2011 Josh Boyer -- Bring ARM config changes from David Marlin forward -- Sync a handful of patches from f16 - -* Mon Aug 15 2011 Josh Boyer -- Linux-3.1-rc2 -- Replace trial patch for rhbz 726877 with a better fix - -* Thu Aug 11 2011 Josh Boyer -- Linux-3.1-rc1-git6 -- Make ide_pmac a module (rhbz 730039) - -* Thu Aug 11 2011 Josh Boyer -- Linux-3.1-rc1-git3 - -* Wed Aug 10 2011 Josh Boyer -- Make sure all the config-* files are in Sources - -* Wed Aug 10 2011 Josh Boyer -- Linux-3.1-rc1-git2 - -* Tue Aug 09 2011 Dave Jones -- ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined - -* Tue Aug 09 2011 Dave Jones -- Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) - -* Mon Aug 08 2011 Josh Boyer -- Linux-3.1-rc1-git1 - -* Mon Aug 08 2011 Josh Boyer -- Linux-3.1-rc1 -- Adjust Makefile munging for new 3.x numbering scheme - -* Fri Aug 05 2011 Dave Jones -- Deselect CONFIG_DECNET. Unmaintained, and rubbish. - -* Fri Aug 05 2011 Josh Boyer -- Linux-3.0-git21 - -* Thu Aug 04 2011 Dave Jones -- Drop neuter_intel_microcode_load.patch (rhbz 690930) - -* Thu Aug 04 2011 Josh Boyer -- Linux 3.0-git19 -- Add patch to fix epoll backtrace (rhbz 722472) -- Add trial patch to fix rhbz 726877 - -* Wed Aug 03 2011 Dave Jones -- Re-apply the rebased utrace - -* Wed Aug 03 2011 John W. Linville -- Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) - -* Tue Aug 02 2011 Dave Jones -- Change USB_SERIAL_OPTION back to modular. (rhbz 727680) - -* Tue Aug 02 2011 Josh Boyer -- Linux 3.0-git17 -- Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) -- Add patch to fix backtrace in usm-realtek driver (rhbz 720054) -- Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking - (rhbz 708314) - -* Tue Aug 02 2011 Josh Boyer -- Linux 3.0-git16 - -* Mon Aug 01 2011 Josh Boyer -- Linux 3.0-git14 - -* Sat Jul 30 2011 Josh Boyer -- Linux 3.0-git12 - -* Fri Jul 29 2011 Josh Boyer -- Adjust Makefile sedding to account for 3.x release style - -* Fri Jul 29 2011 Josh Boyer -- Linux 3.0-git11 -- Backport patch to correct udlfb removal events (rhbz 726163) - -* Thu Jul 28 2011 Dave Jones -- module-init-tools needs to be a prereq not a conflict. - -* Wed Jul 27 2011 Josh Boyer -- Linux 3.0-git9 -- Move CONFIG_JUMP_LABEL to config-generic now that powerpc has it too - -* Mon Jul 25 2011 Kyle McMartin -- Linux 3.0-git3 -- Drop hda_intel-prealloc-4mb-dmabuffer.patch, set new - CONFIG_SND_HDA_PREALLOC_SIZE=4096 for similar effect. - -* Fri Jul 22 2011 Dave Jones -- bootwrapper needs objcopy. Add it to requires: (wwoods) - -* Fri Jul 22 2011 Kyle McMartin 3.0.0-1 -- Linux 3.0, but really 3.0.0 (sigh) - -* Thu Jul 21 2011 Chuck Ebbert 3.0-0.rc7.git10.1 -- 3.0-rc7-git10 -- Use ext4 for ext2 and ext3 filesystems (CONFIG_EXT4_USE_FOR_EXT23=y) - -* Thu Jul 21 2011 Dave Jones -- Switch BLK_DEV_RAM to be modular (rhbz 720833) - -* Wed Jul 20 2011 Chuck Ebbert 3.0-0.rc7.git8.1 -- 3.0-rc7-git8 - -* Fri Jul 15 2011 Dave Jones 3.0-0.rc7.git3.1 -- 3.0-rc7-git3 - -* Fri Jul 15 2011 Dave Jones -- Bring back utrace until uprobes gets merged upstream. - -* Wed Jul 13 2011 Kyle McMartin 3.0-0.rc7.git1.1 -- Update to snapshot 3.0-rc7-git1 for intel drm fixes. - -* Tue Jul 12 2011 John W. Linville -- zd1211rw: fix invalid signal values from device (rhbz 720093) - -* Tue Jul 12 2011 John W. Linville -- rt2x00: Add device ID for RT539F device. (rhbz 720594) - -* Tue Jul 12 2011 Kyle McMartin 3.0-0.rc7.git0.1 -- Linux 3.0-rc7, hopefully the last before the Great Renumbering becomes - official. - -* Mon Jul 11 2011 Dave Jones -- Change BINFMT_MISC to be modular. (rhbz 695415) - -* Sun Jul 10 2011 Kyle McMartin 3.0-0.rc6.git6.1 -- Linux 3.0-rc6-git6 -- iwlagn-fix-dma-direction.patch: drop. -- Revert CONFIG_X86_RESERVE_LOW=640, it breaks booting on x86_64. - -* Thu Jul 07 2011 Dave Jones -- Centralise CPU_FREQ options into config-generic. - Switch to using ondemand by default. (rhbz 713572) - -* Wed Jul 06 2011 Chuck Ebbert -- Set CONFIG_X86_RESERVE_LOW=640 as requested by mjg - -* Mon Jul 04 2011 Kyle McMartin 3.0-0.rc6.git0.1 -- Linux 3.0-rc6 -- [generic] SCSI_ISCI=m, because why not - -* Sat Jul 02 2011 Kyle McMartin 3.0-0.rc5.git5.1 -- Linux 3.0-rc5-git5 - -* Mon Jun 27 2011 Kyle McMartin 3.0-0.rc5.git0.1 -- Linux 3.0-rc5 - -* Mon Jun 27 2011 Dave Jones -- Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) - -* Thu Jun 23 2011 Kyle McMartin 3.0-0.rc4.git3.1 -- Linux 3.0-rc4-git3 -- Drop linux-3.0-fix-uts-release.patch, and instead just perl the Makefile -- linux-2.6-silence-noise.patch: fix context -- iwlagn-fix-dma-direction.patch: fix DMAR errors (for me at least) - -* Wed Jun 22 2011 Kyle McMartin 3.0-0.rc4.git0.2 -- Re-enable debuginfo generation. Thanks to Richard Jones for noticing... no - wonder builds had been so quick lately. - -* Tue Jun 21 2011 Kyle McMartin 3.0-0.rc4.git0.1 -- Linux 3.0-rc4 (getting closer...) - -* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git6.1 -- Update to 3.0-rc3-git6 - -* Fri Jun 17 2011 Dave Jones -- drop qcserial 'compile fix' that was just duplicating an include. -- drop struct sizeof debug patch. (no real value. not upstreamable) -- drop linux-2.6-debug-always-inline-kzalloc.patch. - Can't recall why this was added. Can easily re-add if deemed necessary. - -* Fri Jun 17 2011 Kyle McMartin -- linux-2.6-defaults-pci_no_msi.patch: drop, haven't toggled the default - in many moons. -- linux-2.6-defaults-pci_use_crs.patch: ditto. -- linux-2.6-selinux-mprotect-checks.patch: upstream a while ago. -- drm-i915-gen4-has-non-power-of-two-strides.patch: drop buggy bugfix -- drop some more unapplied crud. -- We haven't applied firewire patches in a dogs age. - -* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git5.1 -- Try updating to a git snapshot for the first time in 3.0-rc, - update to 3.0-rc3-git5 -- Fix a subtle bug I introduced in 3.0-rc1, "patch-3." is 9 letters, not 10. - -* Thu Jun 16 2011 Kyle McMartin -- Disable mm patches which had been submitted against 2.6.39, as Rik reports - they seem to aggravate a VM_BUG_ON. More investigation is necessary. - -* Wed Jun 15 2011 Kyle McMartin -- Conflict with pre-3.2.1-5 versions of mdadm. (#710646) - -* Wed Jun 15 2011 Kyle McMartin -- Build in aesni-intel on i686 for symmetry with 64-bit. - -* Tue Jun 14 2011 Kyle McMartin 3.0-0.rc3.git0.3 -- Fix libdm conflict (whose bright idea was it to give subpackages differing - version numbers?) - -* Tue Jun 14 2011 Kyle McMartin -- Update to 3.0-rc3, add another conflicts to deal with 2 digit - versions (libdm.) -- Simplify linux-3.0-fix-uts-release.patch now that SUBLEVEL is optional. -- revert-ftrace-remove-unnecessary-disabling-of-irqs.patch: drop upstreamed - patch. -- drm-intel-eeebox-eb1007-quirk.patch: ditto. -- ath5k-disable-fast-channel-switching-by-default.patch: ditto. - -* Thu Jun 09 2011 Kyle McMartin -- ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) - (korgbz#34992) [a99168ee in wireless-next] - -* Thu Jun 09 2011 Kyle McMartin 3.0-0.rc2.git0.2 -- rhbz#710921: revert-ftrace-remove-unnecessary-disabling-of-irqs.patch - -* Wed Jun 08 2011 Kyle McMartin 3.0-0.rc2.git0.1 -- Update to 3.0-rc2, rebase utsname fix. -- Build IPv6 into the kernel for a variety of reasons - (http://lists.fedoraproject.org/pipermail/kernel/2011-June/003105.html) - -* Mon Jun 06 2011 Kyle McMartin 3.0-0.rc1.git0.3 -- Conflict with module-init-tools older than 3.13 to ensure the - 3.0 transition is handled correctly. - -* Wed Jun 01 2011 Kyle McMartin 3.0-0.rc1.git0.2 -- Fix utsname for 3.0-rc1 - -* Mon May 30 2011 Kyle McMartin 3.0-0.rc1.git0.1 -- Linux 3.0-rc1 (won't build until module-init-tools gets an update.) - -* Mon May 30 2011 Kyle McMartin -- Trimmed changelog, see fedpkg git for earlier history. - ### # The following Emacs magic makes C-c C-e use UTC dates. # Local Variables: diff --git a/linux-2.6-serial-460800.patch b/linux-2.6-serial-460800.patch index 979b248d5..0e68378e7 100644 --- a/linux-2.6-serial-460800.patch +++ b/linux-2.6-serial-460800.patch @@ -28,14 +28,14 @@ index 2209620..659c1bb 100644 quot = uart_get_divisor(port, baud); @@ -2240,7 +2251,7 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - struct uart_8250_port *up = (struct uart_8250_port *)port; + container_of(port, struct uart_8250_port, port); unsigned char cval, fcr = 0; unsigned long flags; - unsigned int baud, quot; + unsigned int baud, quot, max_baud; + int fifo_bug = 0; switch (termios->c_cflag & CSIZE) { - case CS5: @@ -2272,9 +2283,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ask the core to calculate the divisor for us. diff --git a/lis3-improve-handling-of-null-rate.patch b/lis3-improve-handling-of-null-rate.patch index 98512564a..30ed26d80 100644 --- a/lis3-improve-handling-of-null-rate.patch +++ b/lis3-improve-handling-of-null-rate.patch @@ -28,9 +28,9 @@ index 35c67e0..42dce2a 100644 -static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; +/* LIS3DC: 0 = power off, above 9 = undefined */ +static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000, -1, -1, -1, -1, -1, -1}; + static int lis3_3dlh_rates[4] = {50, 100, 400, 1000}; /* ODR is Output Data Rate */ - static int lis3lv02d_get_odr(struct lis3lv02d *lis3) @@ -202,12 +203,11 @@ static int lis3lv02d_get_odr(struct lis3lv02d *lis3) return lis3->odrs[(ctrl >> shift)]; } diff --git a/modsign-upstream-3.7.patch b/modsign-upstream-3.7.patch deleted file mode 100644 index 33fd0592f..000000000 --- a/modsign-upstream-3.7.patch +++ /dev/null @@ -1,10997 +0,0 @@ -From 9d501208ff48eb3ecc0d1ac8d897c38e99d18161 Mon Sep 17 00:00:00 2001 -From: Rusty Russell -Date: Wed, 26 Sep 2012 10:09:40 +0100 -Subject: [PATCH 01/37] module: signature checking hook - -We do a very simple search for a particular string appended to the module -(which is cache-hot and about to be SHA'd anyway). There's both a config -option and a boot parameter which control whether we accept or fail with -unsigned modules and modules that are signed with an unknown key. - -If module signing is enabled, the kernel will be tainted if a module is -loaded that is unsigned or has a signature for which we don't have the -key. - -(Useful feedback and tweaks by David Howells ) - -Signed-off-by: Rusty Russell -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - Documentation/kernel-parameters.txt | 6 +++ - include/linux/module.h | 8 ++++ - init/Kconfig | 14 ++++++ - kernel/Makefile | 1 + - kernel/module-internal.h | 13 ++++++ - kernel/module.c | 93 ++++++++++++++++++++++++++++++++++++- - kernel/module_signing.c | 23 +++++++++ - 7 files changed, 157 insertions(+), 1 deletion(-) - create mode 100644 kernel/module-internal.h - create mode 100644 kernel/module_signing.c - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index ad7e2e5..9b2b8d3 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - log everything. Information is printed at KERN_DEBUG - so loglevel=8 may also need to be specified. - -+ module.sig_enforce -+ [KNL] When CONFIG_MODULE_SIG is set, this means that -+ modules without (valid) signatures will fail to load. -+ Note that if CONFIG_MODULE_SIG_ENFORCE is set, that -+ is always true, so this option does nothing. -+ - mousedev.tap_time= - [MOUSE] Maximum time between finger touching and - leaving touchpad surface for touch to be considered -diff --git a/include/linux/module.h b/include/linux/module.h -index fbcafe2..7760c6d 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -21,6 +21,9 @@ - #include - #include - -+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ -+#define MODULE_SIG_STRING "~Module signature appended~\n" -+ - /* Not Yet Implemented */ - #define MODULE_SUPPORTED_DEVICE(name) - -@@ -260,6 +263,11 @@ struct module - const unsigned long *unused_gpl_crcs; - #endif - -+#ifdef CONFIG_MODULE_SIG -+ /* Signature was verified. */ -+ bool sig_ok; -+#endif -+ - /* symbols that will be GPL-only in the near future. */ - const struct kernel_symbol *gpl_future_syms; - const unsigned long *gpl_future_crcs; -diff --git a/init/Kconfig b/init/Kconfig -index af6c7f8..7452e19 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL - the version). With this option, such a "srcversion" field - will be created for all modules. If unsure, say N. - -+config MODULE_SIG -+ bool "Module signature verification" -+ depends on MODULES -+ help -+ Check modules for valid signatures upon load: the signature -+ is simply appended to the module. For more information see -+ Documentation/module-signing.txt. -+ -+config MODULE_SIG_FORCE -+ bool "Require modules to be validly signed" -+ depends on MODULE_SIG -+ help -+ Reject unsigned modules or signed modules for which we don't have a -+ key. Without this, such modules will simply taint the kernel. - endif # MODULES - - config INIT_ALL_POSSIBLE -diff --git a/kernel/Makefile b/kernel/Makefile -index c0cc67a..08ba8a6 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -new file mode 100644 -index 0000000..033c17f ---- /dev/null -+++ b/kernel/module-internal.h -@@ -0,0 +1,13 @@ -+/* Module internals -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+extern int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen); -diff --git a/kernel/module.c b/kernel/module.c -index 9ad9ee9..7efb415 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include "module-internal.h" - - #define CREATE_TRACE_POINTS - #include -@@ -102,6 +103,43 @@ static LIST_HEAD(modules); - struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - #endif /* CONFIG_KGDB_KDB */ - -+#ifdef CONFIG_MODULE_SIG -+#ifdef CONFIG_MODULE_SIG_FORCE -+static bool sig_enforce = true; -+#else -+static bool sig_enforce = false; -+ -+static int param_set_bool_enable_only(const char *val, -+ const struct kernel_param *kp) -+{ -+ int err; -+ bool test; -+ struct kernel_param dummy_kp = *kp; -+ -+ dummy_kp.arg = &test; -+ -+ err = param_set_bool(val, &dummy_kp); -+ if (err) -+ return err; -+ -+ /* Don't let them unset it once it's set! */ -+ if (!test && sig_enforce) -+ return -EROFS; -+ -+ if (test) -+ sig_enforce = true; -+ return 0; -+} -+ -+static const struct kernel_param_ops param_ops_bool_enable_only = { -+ .set = param_set_bool_enable_only, -+ .get = param_get_bool, -+}; -+#define param_check_bool_enable_only param_check_bool -+ -+module_param(sig_enforce, bool_enable_only, 0644); -+#endif /* !CONFIG_MODULE_SIG_FORCE */ -+#endif /* CONFIG_MODULE_SIG */ - - /* Block module loading/unloading? */ - int modules_disabled = 0; -@@ -136,6 +174,7 @@ struct load_info { - unsigned long symoffs, stroffs; - struct _ddebug *debug; - unsigned int num_debug; -+ bool sig_ok; - struct { - unsigned int sym, str, mod, vers, info, pcpu; - } index; -@@ -2399,7 +2438,49 @@ static inline void kmemleak_load_module(const struct module *mod, - } - #endif - --/* Sets info->hdr and info->len. */ -+#ifdef CONFIG_MODULE_SIG -+static int module_sig_check(struct load_info *info, -+ const void *mod, unsigned long *len) -+{ -+ int err = -ENOKEY; -+ const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -+ const void *p = mod, *end = mod + *len; -+ -+ /* Poor man's memmem. */ -+ while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -+ if (p + markerlen > end) -+ break; -+ -+ if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -+ const void *sig = p + markerlen; -+ /* Truncate module up to signature. */ -+ *len = p - mod; -+ err = mod_verify_sig(mod, *len, sig, end - sig); -+ break; -+ } -+ p++; -+ } -+ -+ if (!err) { -+ info->sig_ok = true; -+ return 0; -+ } -+ -+ /* Not having a signature is only an error if we're strict. */ -+ if (err == -ENOKEY && !sig_enforce) -+ err = 0; -+ -+ return err; -+} -+#else /* !CONFIG_MODULE_SIG */ -+static int module_sig_check(struct load_info *info, -+ void *mod, unsigned long *len) -+{ -+ return 0; -+} -+#endif /* !CONFIG_MODULE_SIG */ -+ -+/* Sets info->hdr, info->len and info->sig_ok. */ - static int copy_and_check(struct load_info *info, - const void __user *umod, unsigned long len, - const char __user *uargs) -@@ -2419,6 +2500,10 @@ static int copy_and_check(struct load_info *info, - goto free_hdr; - } - -+ err = module_sig_check(info, hdr, &len); -+ if (err) -+ goto free_hdr; -+ - /* Sanity checks against insmoding binaries or wrong arch, - weird elf version */ - if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 -@@ -2890,6 +2975,12 @@ static struct module *load_module(void __user *umod, - goto free_copy; - } - -+#ifdef CONFIG_MODULE_SIG -+ mod->sig_ok = info.sig_ok; -+ if (!mod->sig_ok) -+ add_taint_module(mod, TAINT_FORCED_MODULE); -+#endif -+ - /* Now module is in final location, initialize linked lists, etc. */ - err = module_unload_init(mod); - if (err) -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -new file mode 100644 -index 0000000..499728a ---- /dev/null -+++ b/kernel/module_signing.c -@@ -0,0 +1,23 @@ -+/* Module signature checker -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include "module-internal.h" -+ -+/* -+ * Verify the signature on a module. -+ */ -+int mod_verify_sig(const void *mod, unsigned long modlen, -+ const void *sig, unsigned long siglen) -+{ -+ return -ENOKEY; -+} --- -1.7.12.1 - - -From 82400c211d81ea36338fb8266b5c41710101a013 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 13:06:29 +0100 -Subject: [PATCH 02/37] KEYS: Add payload preparsing opportunity prior to key - instantiate or update - -Give the key type the opportunity to preparse the payload prior to the -instantiation and update routines being called. This is done with the -provision of two new key type operations: - - int (*preparse)(struct key_preparsed_payload *prep); - void (*free_preparse)(struct key_preparsed_payload *prep); - -If the first operation is present, then it is called before key creation (in -the add/update case) or before the key semaphore is taken (in the update and -instantiate cases). The second operation is called to clean up if the first -was called. - -preparse() is given the opportunity to fill in the following structure: - - struct key_preparsed_payload { - char *description; - void *type_data[2]; - void *payload; - const void *data; - size_t datalen; - size_t quotalen; - }; - -Before the preparser is called, the first three fields will have been cleared, -the payload pointer and size will be stored in data and datalen and the default -quota size from the key_type struct will be stored into quotalen. - -The preparser may parse the payload in any way it likes and may store data in -the type_data[] and payload fields for use by the instantiate() and update() -ops. - -The preparser may also propose a description for the key by attaching it as a -string to the description field. This can be used by passing a NULL or "" -description to the add_key() system call or the key_create_or_update() -function. This cannot work with request_key() as that required the description -to tell the upcall about the key to be created. - -This, for example permits keys that store PGP public keys to generate their own -name from the user ID and public key fingerprint in the key. - -The instantiate() and update() operations are then modified to look like this: - - int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - int (*update)(struct key *key, struct key_preparsed_payload *prep); - -and the new payload data is passed in *prep, whether or not it was preparsed. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - Documentation/security/keys.txt | 50 +++++++++++++- - fs/cifs/cifs_spnego.c | 6 +- - fs/cifs/cifsacl.c | 8 +-- - include/keys/user-type.h | 6 +- - include/linux/key-type.h | 35 +++++++++- - net/ceph/crypto.c | 9 +-- - net/dns_resolver/dns_key.c | 6 +- - net/rxrpc/ar-key.c | 40 +++++------ - security/keys/encrypted-keys/encrypted.c | 16 +++-- - security/keys/key.c | 114 ++++++++++++++++++++++--------- - security/keys/keyctl.c | 18 +++-- - security/keys/keyring.c | 6 +- - security/keys/request_key_auth.c | 8 +-- - security/keys/trusted.c | 16 +++-- - security/keys/user_defined.c | 14 ++-- - 15 files changed, 250 insertions(+), 102 deletions(-) - -diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt -index aa0dbd7..7d9ca92 100644 ---- a/Documentation/security/keys.txt -+++ b/Documentation/security/keys.txt -@@ -412,6 +412,10 @@ The main syscalls are: - to the keyring. In this case, an error will be generated if the process - does not have permission to write to the keyring. - -+ If the key type supports it, if the description is NULL or an empty -+ string, the key type will try and generate a description from the content -+ of the payload. -+ - The payload is optional, and the pointer can be NULL if not required by - the type. The payload is plen in size, and plen can be zero for an empty - payload. -@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: - it should return 0. - - -- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ (*) int (*preparse)(struct key_preparsed_payload *prep); -+ -+ This optional method permits the key type to attempt to parse payload -+ before a key is created (add key) or the key semaphore is taken (update or -+ instantiate key). The structure pointed to by prep looks like: -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ Before calling the method, the caller will fill in data and datalen with -+ the payload blob parameters; quotalen will be filled in with the default -+ quota size from the key type and the rest will be cleared. -+ -+ If a description can be proposed from the payload contents, that should be -+ attached as a string to the description field. This will be used for the -+ key description if the caller of add_key() passes NULL or "". -+ -+ The method can attach anything it likes to type_data[] and payload. These -+ are merely passed along to the instantiate() or update() operations. -+ -+ The method should return 0 if success ful or a negative error code -+ otherwise. -+ -+ -+ (*) void (*free_preparse)(struct key_preparsed_payload *prep); -+ -+ This method is only required if the preparse() method is provided, -+ otherwise it is unused. It cleans up anything attached to the -+ description, type_data and payload fields of the key_preparsed_payload -+ struct as filled in by the preparse() method. -+ -+ -+ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - This method is called to attach a payload to a key during construction. - The payload attached need not bear any relation to the data passed to this - function. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - If the amount of data attached to the key differs from the size in - keytype->def_datalen, then key_payload_reserve() should be called. - -@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: - If this type of key can be updated, then this method should be provided. - It is called to update a key's payload from the blob of data provided. - -+ The prep->data and prep->datalen fields will define the original payload -+ blob. If preparse() was supplied then other fields may be filled in also. -+ - key_payload_reserve() should be called if the data length might change - before any changes are actually made. Note that if this succeeds, the type - is committed to changing the key because it's already been altered, so all -diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c -index e622863..086f381 100644 ---- a/fs/cifs/cifs_spnego.c -+++ b/fs/cifs/cifs_spnego.c -@@ -31,18 +31,18 @@ - - /* create a new cifs key */ - static int --cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - int ret; - - ret = -ENOMEM; -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - goto error; - - /* attach the data */ -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; - ret = 0; - -diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c -index 05f4dc2..f3c60e2 100644 ---- a/fs/cifs/cifsacl.c -+++ b/fs/cifs/cifsacl.c -@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { - }; - - static int --cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) -+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - char *payload; - -- payload = kmalloc(datalen, GFP_KERNEL); -+ payload = kmalloc(prep->datalen, GFP_KERNEL); - if (!payload) - return -ENOMEM; - -- memcpy(payload, data, datalen); -+ memcpy(payload, prep->data, prep->datalen); - key->payload.data = payload; -- key->datalen = datalen; -+ key->datalen = prep->datalen; - return 0; - } - -diff --git a/include/keys/user-type.h b/include/keys/user-type.h -index bc9ec1d..5e452c8 100644 ---- a/include/keys/user-type.h -+++ b/include/keys/user-type.h -@@ -35,8 +35,10 @@ struct user_key_payload { - extern struct key_type key_type_user; - extern struct key_type key_type_logon; - --extern int user_instantiate(struct key *key, const void *data, size_t datalen); --extern int user_update(struct key *key, const void *data, size_t datalen); -+struct key_preparsed_payload; -+ -+extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); -+extern int user_update(struct key *key, struct key_preparsed_payload *prep); - extern int user_match(const struct key *key, const void *criterion); - extern void user_revoke(struct key *key); - extern void user_destroy(struct key *key); -diff --git a/include/linux/key-type.h b/include/linux/key-type.h -index f0c651c..518a53a 100644 ---- a/include/linux/key-type.h -+++ b/include/linux/key-type.h -@@ -26,6 +26,27 @@ struct key_construction { - struct key *authkey;/* authorisation for key being constructed */ - }; - -+/* -+ * Pre-parsed payload, used by key add, update and instantiate. -+ * -+ * This struct will be cleared and data and datalen will be set with the data -+ * and length parameters from the caller and quotalen will be set from -+ * def_datalen from the key type. Then if the preparse() op is provided by the -+ * key type, that will be called. Then the struct will be passed to the -+ * instantiate() or the update() op. -+ * -+ * If the preparse() op is given, the free_preparse() op will be called to -+ * clear the contents. -+ */ -+struct key_preparsed_payload { -+ char *description; /* Proposed key description (or NULL) */ -+ void *type_data[2]; /* Private key-type data */ -+ void *payload; /* Proposed payload */ -+ const void *data; /* Raw data */ -+ size_t datalen; /* Raw datalen */ -+ size_t quotalen; /* Quota length for proposed payload */ -+}; -+ - typedef int (*request_key_actor_t)(struct key_construction *key, - const char *op, void *aux); - -@@ -45,18 +66,28 @@ struct key_type { - /* vet a description */ - int (*vet_description)(const char *description); - -+ /* Preparse the data blob from userspace that is to be the payload, -+ * generating a proposed description and payload that will be handed to -+ * the instantiate() and update() ops. -+ */ -+ int (*preparse)(struct key_preparsed_payload *prep); -+ -+ /* Free a preparse data structure. -+ */ -+ void (*free_preparse)(struct key_preparsed_payload *prep); -+ - /* instantiate a key of this type - * - this method should call key_payload_reserve() to determine if the - * user's quota will hold the payload - */ -- int (*instantiate)(struct key *key, const void *data, size_t datalen); -+ int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); - - /* update a key of this type (optional) - * - this method should call key_payload_reserve() to recalculate the - * quota consumption - * - the key must be locked against read when modifying - */ -- int (*update)(struct key *key, const void *data, size_t datalen); -+ int (*update)(struct key *key, struct key_preparsed_payload *prep); - - /* match a key against a description */ - int (*match)(const struct key *key, const void *desc); -diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c -index 9da7fdd..af14cb4 100644 ---- a/net/ceph/crypto.c -+++ b/net/ceph/crypto.c -@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, - } - } - --int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) -+int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct ceph_crypto_key *ckey; -+ size_t datalen = prep->datalen; - int ret; - void *p; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto err; - - ret = key_payload_reserve(key, datalen); -@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) - goto err; - - /* TODO ceph_crypto_key_decode should really take const input */ -- p = (void *)data; -- ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); -+ p = (void *)prep->data; -+ ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); - if (ret < 0) - goto err_ckey; - -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index d9507dd..859ab8b 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; - * "ip1,ip2,...#foo=bar" - */ - static int --dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) -+dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; - unsigned long derrno; - int ret; -- size_t result_len = 0; -- const char *data = _data, *end, *opt; -+ size_t datalen = prep->datalen, result_len = 0; -+ const char *data = prep->data, *end, *opt; - - kenter("%%%d,%s,'%*.*s',%zu", - key->serial, key->description, -diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c -index 8b1f9f4..106c5a6 100644 ---- a/net/rxrpc/ar-key.c -+++ b/net/rxrpc/ar-key.c -@@ -26,8 +26,8 @@ - #include "ar-internal.h" - - static int rxrpc_vet_description_s(const char *); --static int rxrpc_instantiate(struct key *, const void *, size_t); --static int rxrpc_instantiate_s(struct key *, const void *, size_t); -+static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); -+static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); - static void rxrpc_destroy(struct key *); - static void rxrpc_destroy_s(struct key *); - static void rxrpc_describe(const struct key *, struct seq_file *); -@@ -678,7 +678,7 @@ error: - * - * if no data is provided, then a no-security key is made - */ --static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) -+static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - const struct rxrpc_key_data_v1 *v1; - struct rxrpc_key_token *token, **pp; -@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - u32 kver; - int ret; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - - /* handle a no-security key */ -- if (!data && datalen == 0) -+ if (!prep->data && prep->datalen == 0) - return 0; - - /* determine if the XDR payload format is being used */ -- if (datalen > 7 * 4) { -- ret = rxrpc_instantiate_xdr(key, data, datalen); -+ if (prep->datalen > 7 * 4) { -+ ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); - if (ret != -EPROTO) - return ret; - } - - /* get the key interface version number */ - ret = -EINVAL; -- if (datalen <= 4 || !data) -+ if (prep->datalen <= 4 || !prep->data) - goto error; -- memcpy(&kver, data, sizeof(kver)); -- data += sizeof(kver); -- datalen -= sizeof(kver); -+ memcpy(&kver, prep->data, sizeof(kver)); -+ prep->data += sizeof(kver); -+ prep->datalen -= sizeof(kver); - - _debug("KEY I/F VERSION: %u", kver); - -@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) - - /* deal with a version 1 key */ - ret = -EINVAL; -- if (datalen < sizeof(*v1)) -+ if (prep->datalen < sizeof(*v1)) - goto error; - -- v1 = data; -- if (datalen != sizeof(*v1) + v1->ticket_length) -+ v1 = prep->data; -+ if (prep->datalen != sizeof(*v1) + v1->ticket_length) - goto error; - - _debug("SCIX: %u", v1->security_index); -@@ -784,17 +784,17 @@ error: - * instantiate a server secret key - * data should be a pointer to the 8-byte secret key - */ --static int rxrpc_instantiate_s(struct key *key, const void *data, -- size_t datalen) -+static int rxrpc_instantiate_s(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct crypto_blkcipher *ci; - -- _enter("{%x},,%zu", key_serial(key), datalen); -+ _enter("{%x},,%zu", key_serial(key), prep->datalen); - -- if (datalen != 8) -+ if (prep->datalen != 8) - return -EINVAL; - -- memcpy(&key->type_data, data, 8); -+ memcpy(&key->type_data, prep->data, 8); - - ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(ci)) { -@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, - return PTR_ERR(ci); - } - -- if (crypto_blkcipher_setkey(ci, data, 8) < 0) -+ if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) - BUG(); - - key->payload.data = ci; -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 2d1bb8a..9e1e005 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int encrypted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = NULL; - char *datablob = NULL; -@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, - char *master_desc = NULL; - char *decrypted_datalen = NULL; - char *hex_encoded_iv = NULL; -+ size_t datalen = prep->datalen; - int ret; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; - datablob[datalen] = 0; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - ret = datablob_parse(datablob, &format, &master_desc, - &decrypted_datalen, &hex_encoded_iv); - if (ret < 0) -@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) - * - * On success, return 0. Otherwise return errno. - */ --static int encrypted_update(struct key *key, const void *data, size_t datalen) -+static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct encrypted_key_payload *epayload = key->payload.data; - struct encrypted_key_payload *new_epayload; - char *buf; - char *new_master_desc = NULL; - const char *format = NULL; -+ size_t datalen = prep->datalen; - int ret = 0; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - buf = kmalloc(datalen + 1, GFP_KERNEL); -@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) - return -ENOMEM; - - buf[datalen] = 0; -- memcpy(buf, data, datalen); -+ memcpy(buf, prep->data, datalen); - ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); - if (ret < 0) - goto out; -diff --git a/security/keys/key.c b/security/keys/key.c -index 50d96d4..1d039af 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); - * key_construction_mutex. - */ - static int __key_instantiate_and_link(struct key *key, -- const void *data, -- size_t datalen, -+ struct key_preparsed_payload *prep, - struct key *keyring, - struct key *authkey, - unsigned long *_prealloc) -@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, - /* can't instantiate twice */ - if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { - /* instantiate the key */ -- ret = key->type->instantiate(key, data, datalen); -+ ret = key->type->instantiate(key, prep); - - if (ret == 0) { - /* mark the key as being instantiated */ -@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, - struct key *keyring, - struct key *authkey) - { -+ struct key_preparsed_payload prep; - unsigned long prealloc; - int ret; - -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = data; -+ prep.datalen = datalen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; -+ } -+ - if (keyring) { - ret = __key_link_begin(keyring, key->type, key->description, - &prealloc); - if (ret < 0) -- return ret; -+ goto error_free_preparse; - } - -- ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, -+ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, - &prealloc); - - if (keyring) - __key_link_end(keyring, key->type, prealloc); - -+error_free_preparse: -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - -@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) - * if we get an error. - */ - static inline key_ref_t __key_update(key_ref_t key_ref, -- const void *payload, size_t plen) -+ struct key_preparsed_payload *prep) - { - struct key *key = key_ref_to_ptr(key_ref); - int ret; -@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, - - down_write(&key->sem); - -- ret = key->type->update(key, payload, plen); -+ ret = key->type->update(key, prep); - if (ret == 0) - /* updating a negative key instantiates it */ - clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - unsigned long flags) - { - unsigned long prealloc; -+ struct key_preparsed_payload prep; - const struct cred *cred = current_cred(); - struct key_type *ktype; - struct key *keyring, *key = NULL; -@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - } - - key_ref = ERR_PTR(-EINVAL); -- if (!ktype->match || !ktype->instantiate) -- goto error_2; -+ if (!ktype->match || !ktype->instantiate || -+ (!description && !ktype->preparse)) -+ goto error_put_type; - - keyring = key_ref_to_ptr(keyring_ref); - -@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - - key_ref = ERR_PTR(-ENOTDIR); - if (keyring->type != &key_type_keyring) -- goto error_2; -+ goto error_put_type; -+ -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = ktype->def_datalen; -+ if (ktype->preparse) { -+ ret = ktype->preparse(&prep); -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_put_type; -+ } -+ if (!description) -+ description = prep.description; -+ key_ref = ERR_PTR(-EINVAL); -+ if (!description) -+ goto error_free_prep; -+ } - - ret = __key_link_begin(keyring, ktype, description, &prealloc); -- if (ret < 0) -- goto error_2; -+ if (ret < 0) { -+ key_ref = ERR_PTR(ret); -+ goto error_free_prep; -+ } - - /* if we're going to allocate a new key, we're going to have - * to modify the keyring */ - ret = key_permission(keyring_ref, KEY_WRITE); - if (ret < 0) { - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - /* if it's possible to update this type of key, search for an existing -@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - perm, flags); - if (IS_ERR(key)) { - key_ref = ERR_CAST(key); -- goto error_3; -+ goto error_link_end; - } - - /* instantiate it and link it into the target keyring */ -- ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, -- &prealloc); -+ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); - if (ret < 0) { - key_put(key); - key_ref = ERR_PTR(ret); -- goto error_3; -+ goto error_link_end; - } - - key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); - -- error_3: -+error_link_end: - __key_link_end(keyring, ktype, prealloc); -- error_2: -+error_free_prep: -+ if (ktype->preparse) -+ ktype->free_preparse(&prep); -+error_put_type: - key_type_put(ktype); -- error: -+error: - return key_ref; - - found_matching_key: -@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - * - we can drop the locks first as we have the key pinned - */ - __key_link_end(keyring, ktype, prealloc); -- key_type_put(ktype); - -- key_ref = __key_update(key_ref, payload, plen); -- goto error; -+ key_ref = __key_update(key_ref, &prep); -+ goto error_free_prep; - } - EXPORT_SYMBOL(key_create_or_update); - -@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); - */ - int key_update(key_ref_t key_ref, const void *payload, size_t plen) - { -+ struct key_preparsed_payload prep; - struct key *key = key_ref_to_ptr(key_ref); - int ret; - -@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - - /* attempt to update it if supported */ - ret = -EOPNOTSUPP; -- if (key->type->update) { -- down_write(&key->sem); -- -- ret = key->type->update(key, payload, plen); -- if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ if (!key->type->update) -+ goto error; - -- up_write(&key->sem); -+ memset(&prep, 0, sizeof(prep)); -+ prep.data = payload; -+ prep.datalen = plen; -+ prep.quotalen = key->type->def_datalen; -+ if (key->type->preparse) { -+ ret = key->type->preparse(&prep); -+ if (ret < 0) -+ goto error; - } - -- error: -+ down_write(&key->sem); -+ -+ ret = key->type->update(key, &prep); -+ if (ret == 0) -+ /* updating a negative key instantiates it */ -+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ -+ up_write(&key->sem); -+ -+ if (key->type->preparse) -+ key->type->free_preparse(&prep); -+error: - return ret; - } - EXPORT_SYMBOL(key_update); -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 3364fbf..505d40b 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, - * Extract the description of a new key from userspace and either add it as a - * new key to the specified keyring or update a matching key in that keyring. - * -+ * If the description is NULL or an empty string, the key type is asked to -+ * generate one from the payload. -+ * - * The keyring must be writable so that we can attach the key to it. - * - * If successful, the new key's serial number is returned, otherwise an error -@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, - if (ret < 0) - goto error; - -- description = strndup_user(_description, PAGE_SIZE); -- if (IS_ERR(description)) { -- ret = PTR_ERR(description); -- goto error; -+ description = NULL; -+ if (_description) { -+ description = strndup_user(_description, PAGE_SIZE); -+ if (IS_ERR(description)) { -+ ret = PTR_ERR(description); -+ goto error; -+ } -+ if (!*description) { -+ kfree(description); -+ description = NULL; -+ } - } - - /* pull the payload in if one was supplied */ -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index 81e7852..f04d8cf 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) - * operations. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen); -+ struct key_preparsed_payload *prep); - static int keyring_match(const struct key *keyring, const void *criterion); - static void keyring_revoke(struct key *keyring); - static void keyring_destroy(struct key *keyring); -@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) - * Returns 0 on success, -EINVAL if given any data. - */ - static int keyring_instantiate(struct key *keyring, -- const void *data, size_t datalen) -+ struct key_preparsed_payload *prep) - { - int ret; - - ret = -EINVAL; -- if (datalen == 0) { -+ if (prep->datalen == 0) { - /* make the keyring available by name if it has one */ - keyring_publish_name(keyring); - ret = 0; -diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c -index 60d4e3f..85730d5 100644 ---- a/security/keys/request_key_auth.c -+++ b/security/keys/request_key_auth.c -@@ -19,7 +19,8 @@ - #include - #include "internal.h" - --static int request_key_auth_instantiate(struct key *, const void *, size_t); -+static int request_key_auth_instantiate(struct key *, -+ struct key_preparsed_payload *); - static void request_key_auth_describe(const struct key *, struct seq_file *); - static void request_key_auth_revoke(struct key *); - static void request_key_auth_destroy(struct key *); -@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { - * Instantiate a request-key authorisation key. - */ - static int request_key_auth_instantiate(struct key *key, -- const void *data, -- size_t datalen) -+ struct key_preparsed_payload *prep) - { -- key->payload.data = (struct request_key_auth *) data; -+ key->payload.data = (struct request_key_auth *)prep->data; - return 0; - } - -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 2d5d041..42036c7 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) - * - * On success, return 0. Otherwise return errno. - */ --static int trusted_instantiate(struct key *key, const void *data, -- size_t datalen) -+static int trusted_instantiate(struct key *key, -+ struct key_preparsed_payload *prep) - { - struct trusted_key_payload *payload = NULL; - struct trusted_key_options *options = NULL; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - int key_cmd; - -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - - options = trusted_options_alloc(); -@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) - /* - * trusted_update - reseal an existing key with new PCR values - */ --static int trusted_update(struct key *key, const void *data, size_t datalen) -+static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - { - struct trusted_key_payload *p = key->payload.data; - struct trusted_key_payload *new_p; - struct trusted_key_options *new_o; -+ size_t datalen = prep->datalen; - char *datablob; - int ret = 0; - - if (!p->migratable) - return -EPERM; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); -@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) - goto out; - } - -- memcpy(datablob, data, datalen); -+ memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { -diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c -index c7660a2..55dc889 100644 ---- a/security/keys/user_defined.c -+++ b/security/keys/user_defined.c -@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); - /* - * instantiate a user defined key - */ --int user_instantiate(struct key *key, const void *data, size_t datalen) -+int user_instantiate(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - ret = key_payload_reserve(key, datalen); -@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) - - /* attach the data */ - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - rcu_assign_keypointer(key, upayload); - ret = 0; - -@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); - * update a user defined key - * - the key's semaphore is write-locked - */ --int user_update(struct key *key, const void *data, size_t datalen) -+int user_update(struct key *key, struct key_preparsed_payload *prep) - { - struct user_key_payload *upayload, *zap; -+ size_t datalen = prep->datalen; - int ret; - - ret = -EINVAL; -- if (datalen <= 0 || datalen > 32767 || !data) -+ if (datalen <= 0 || datalen > 32767 || !prep->data) - goto error; - - /* construct a replacement payload */ -@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) - goto error; - - upayload->datalen = datalen; -- memcpy(upayload->data, data, datalen); -+ memcpy(upayload->data, prep->data, datalen); - - /* check the quota and attach the new data */ - zap = upayload; --- -1.7.12.1 - - -From 162ce9c1b0f28d36598975f8931f216245b7e778 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 13:09:33 +0100 -Subject: [PATCH 03/37] MPILIB: Provide count_leading/trailing_zeros() based - on arch functions - -Provide count_leading/trailing_zeros() macros based on extant arch bit scanning -functions rather than reimplementing from scratch in MPILIB. - -Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x). - -Also move the definition to asm-generic as other people may be interested in -using it. - -Signed-off-by: David Howells -Cc: David S. Miller -Cc: Dmitry Kasatkin -Cc: Arnd Bergmann -Signed-off-by: Rusty Russell ---- - include/asm-generic/bitops/count_zeros.h | 57 +++++++++++++ - lib/mpi/longlong.h | 138 +------------------------------ - lib/mpi/mpi-bit.c | 2 +- - lib/mpi/mpi-pow.c | 4 +- - 4 files changed, 62 insertions(+), 139 deletions(-) - create mode 100644 include/asm-generic/bitops/count_zeros.h - -diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h -new file mode 100644 -index 0000000..97520d2 ---- /dev/null -+++ b/include/asm-generic/bitops/count_zeros.h -@@ -0,0 +1,57 @@ -+/* Count leading and trailing zeros functions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ -+ -+#include -+ -+/** -+ * count_leading_zeros - Count the number of zeros from the MSB back -+ * @x: The value -+ * -+ * Count the number of leading zeros from the MSB going towards the LSB in @x. -+ * -+ * If the MSB of @x is set, the result is 0. -+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. -+ */ -+static inline int count_leading_zeros(unsigned long x) -+{ -+ if (sizeof(x) == 4) -+ return BITS_PER_LONG - fls(x); -+ else -+ return BITS_PER_LONG - fls64(x); -+} -+ -+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG -+ -+/** -+ * count_trailing_zeros - Count the number of zeros from the LSB forwards -+ * @x: The value -+ * -+ * Count the number of trailing zeros from the LSB going towards the MSB in @x. -+ * -+ * If the LSB of @x is set, the result is 0. -+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. -+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. -+ */ -+static inline int count_trailing_zeros(unsigned long x) -+{ -+#define COUNT_TRAILING_ZEROS_0 (-1) -+ -+ if (sizeof(x) == 4) -+ return ffs(x); -+ else -+ return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; -+} -+ -+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ -diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h -index 29f9862..678ce4f 100644 ---- a/lib/mpi/longlong.h -+++ b/lib/mpi/longlong.h -@@ -19,6 +19,8 @@ - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. */ - -+#include -+ - /* You have to define the following before including this file: - * - * UWtype -- An unsigned type, default type for operations (typically a "word") -@@ -146,12 +148,6 @@ do { \ - : "1" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))) -- --#define count_leading_zeros(count, x) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #endif /* __a29k__ */ - - #if defined(__alpha) && W_TYPE_SIZE == 64 -@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); - : "1" ((USItype)(nh)), \ - "0" ((USItype)(nl)), \ - "g" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bsch/1 %1,%0" \ -- : "=g" (count) \ -- : "g" ((USItype)(x)), \ -- "0" ((USItype)0)) - #endif - - /*************************************** -@@ -354,27 +345,6 @@ do { USItype __r; \ - } while (0) - extern USItype __udiv_qrnnd(); - #endif /* LONGLONG_STANDALONE */ --#define count_leading_zeros(count, x) \ --do { \ -- USItype __tmp; \ -- __asm__ ( \ -- "ldi 1,%0\n" \ -- "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ -- "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ -- "ldo 16(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ -- "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ -- "ldo 8(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ -- "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ -- "ldo 4(%0),%0 ; Yes. Perform add.\n" \ -- "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ -- "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ -- "ldo 2(%0),%0 ; Yes. Perform add.\n" \ -- "extru %1,30,1,%1 ; Extract bit 1.\n" \ -- "sub %0,%1,%0 ; Subtract it. " \ -- : "=r" (count), "=r" (__tmp) : "1" (x)); \ --} while (0) - #endif /* hppa */ - - /*************************************** -@@ -457,15 +427,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "rm" ((USItype)(d))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("bsrl %1,%0" \ -- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define count_trailing_zeros(count, x) \ -- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) - #ifndef UMUL_TIME - #define UMUL_TIME 40 - #endif -@@ -536,15 +497,6 @@ do { \ - "dI" ((USItype)(d))); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("scanbit %1,%0" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ - #if defined(__i960mx) /* what is the proper symbol to test??? */ - #define rshift_rhlc(r, h, l, c) \ - do { \ -@@ -603,11 +555,6 @@ do { \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) --#define count_leading_zeros(count, x) \ -- __asm__ ("bfffo %1{%b2:%b2},%0" \ -- : "=d" ((USItype)(count)) \ -- : "od" ((USItype)(x)), "n" (0)) --#define COUNT_LEADING_ZEROS_0 32 - #else /* not mc68020 */ - #define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ -@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ - "rJ" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) --#define count_leading_zeros(count, x) \ --do { \ -- USItype __cbtmp; \ -- __asm__ ("ff1 %0,%1" \ -- : "=r" (__cbtmp) \ -- : "r" ((USItype)(x))); \ -- (count) = __cbtmp ^ 31; \ --} while (0) --#define COUNT_LEADING_ZEROS_0 63 /* sic */ - #if defined(__m88110__) - #define umul_ppmm(wh, wl, u, v) \ - do { \ -@@ -779,12 +717,6 @@ do { \ - : "0" (__xx.__ll), \ - "g" ((USItype)(d))); \ - (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) --#define count_trailing_zeros(count, x) \ --do { \ -- __asm__("ffsd %2,%0" \ -- : "=r"((USItype) (count)) \ -- : "0"((USItype) 0), "r"((USItype) (x))); \ -- } while (0) - #endif /* __ns32000__ */ - - /*************************************** -@@ -855,11 +787,6 @@ do { \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - } while (0) --#define count_leading_zeros(count, x) \ -- __asm__ ("{cntlz|cntlzw} %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))) --#define COUNT_LEADING_ZEROS_0 32 - #if defined(_ARCH_PPC) - #define umul_ppmm(ph, pl, m0, m1) \ - do { \ -@@ -1001,19 +928,6 @@ do { \ - } while (0) - #define UMUL_TIME 20 - #define UDIV_TIME 200 --#define count_leading_zeros(count, x) \ --do { \ -- if ((x) >= 0x10000) \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x) >> 16)); \ -- else { \ -- __asm__ ("clz %0,%1" \ -- : "=r" ((USItype)(count)) \ -- : "r" ((USItype)(x))); \ -- (count) += 16; \ -- } \ --} while (0) - #endif /* RT/ROMP */ - - /*************************************** -@@ -1142,13 +1056,6 @@ do { \ - "rI" ((USItype)(d)) \ - : "%g1" __AND_CLOBBER_CC) - #define UDIV_TIME 37 --#define count_leading_zeros(count, x) \ -- __asm__ ("scan %1,0,%0" \ -- : "=r" ((USItype)(x)) \ -- : "r" ((USItype)(count))) --/* Early sparclites return 63 for an argument of 0, but they warn that future -- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 -- undefined. */ - #endif /* __sparclite__ */ - #endif /* __sparc_v8__ */ - /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -@@ -1454,47 +1361,6 @@ do { \ - #define udiv_qrnnd __udiv_qrnnd_c - #endif - --#undef count_leading_zeros --#if !defined(count_leading_zeros) -- extern --#ifdef __STDC__ -- const --#endif -- unsigned char __clz_tab[]; --#define count_leading_zeros(count, x) \ --do { \ -- UWtype __xr = (x); \ -- UWtype __a; \ -- \ -- if (W_TYPE_SIZE <= 32) { \ -- __a = __xr < ((UWtype) 1 << 2*__BITS4) \ -- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ -- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ -- } \ -- else { \ -- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ -- if (((__xr >> __a) & 0xff) != 0) \ -- break; \ -- } \ -- \ -- (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ --} while (0) -- /* This version gives a well-defined value for zero. */ --#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE --#endif -- --#if !defined(count_trailing_zeros) --/* Define count_trailing_zeros using count_leading_zeros. The latter might be -- defined in asm, but if it is not, the C version above is good enough. */ --#define count_trailing_zeros(count, x) \ --do { \ -- UWtype __ctz_x = (x); \ -- UWtype __ctz_c; \ -- count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ -- (count) = W_TYPE_SIZE - 1 - __ctz_c; \ --} while (0) --#endif -- - #ifndef UDIV_NEEDS_NORMALIZATION - #define UDIV_NEEDS_NORMALIZATION 0 - #endif -diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c -index 5687248..503537e 100644 ---- a/lib/mpi/mpi-bit.c -+++ b/lib/mpi/mpi-bit.c -@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) - if (a->nlimbs) { - mpi_limb_t alimb = a->d[a->nlimbs - 1]; - if (alimb) -- count_leading_zeros(n, alimb); -+ n = count_leading_zeros(alimb); - else - n = BITS_PER_MPI_LIMB; - n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index 67f3e79..5464c87 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - mp = mp_marker = mpi_alloc_limb_space(msize); - if (!mp) - goto enomem; -- count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); -+ mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); - if (mod_shift_cnt) - mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); - else -@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - - i = esize - 1; - e = ep[i]; -- count_leading_zeros(c, e); -+ c = count_leading_zeros(e); - e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ - c = BITS_PER_MPI_LIMB - 1 - c; - --- -1.7.12.1 - - -From ef184bcab1e58dafae2f02ae30824365bec1d27a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 04/37] KEYS: Document asymmetric key type - -In-source documentation for the asymmetric key type. This will be located in: - - Documentation/crypto/asymmetric-keys.txt - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++ - 1 file changed, 312 insertions(+) - create mode 100644 Documentation/crypto/asymmetric-keys.txt - -diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt -new file mode 100644 -index 0000000..b767590 ---- /dev/null -+++ b/Documentation/crypto/asymmetric-keys.txt -@@ -0,0 +1,312 @@ -+ ============================================= -+ ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE -+ ============================================= -+ -+Contents: -+ -+ - Overview. -+ - Key identification. -+ - Accessing asymmetric keys. -+ - Signature verification. -+ - Asymmetric key subtypes. -+ - Instantiation data parsers. -+ -+ -+======== -+OVERVIEW -+======== -+ -+The "asymmetric" key type is designed to be a container for the keys used in -+public-key cryptography, without imposing any particular restrictions on the -+form or mechanism of the cryptography or form of the key. -+ -+The asymmetric key is given a subtype that defines what sort of data is -+associated with the key and provides operations to describe and destroy it. -+However, no requirement is made that the key data actually be stored in the -+key. -+ -+A completely in-kernel key retention and operation subtype can be defined, but -+it would also be possible to provide access to cryptographic hardware (such as -+a TPM) that might be used to both retain the relevant key and perform -+operations using that key. In such a case, the asymmetric key would then -+merely be an interface to the TPM driver. -+ -+Also provided is the concept of a data parser. Data parsers are responsible -+for extracting information from the blobs of data passed to the instantiation -+function. The first data parser that recognises the blob gets to set the -+subtype of the key and define the operations that can be done on that key. -+ -+A data parser may interpret the data blob as containing the bits representing a -+key, or it may interpret it as a reference to a key held somewhere else in the -+system (for example, a TPM). -+ -+ -+================== -+KEY IDENTIFICATION -+================== -+ -+If a key is added with an empty name, the instantiation data parsers are given -+the opportunity to pre-parse a key and to determine the description the key -+should be given from the content of the key. -+ -+This can then be used to refer to the key, either by complete match or by -+partial match. The key type may also use other criteria to refer to a key. -+ -+The asymmetric key type's match function can then perform a wider range of -+comparisons than just the straightforward comparison of the description with -+the criterion string: -+ -+ (1) If the criterion string is of the form "id:" then the match -+ function will examine a key's fingerprint to see if the hex digits given -+ after the "id:" match the tail. For instance: -+ -+ keyctl search @s asymmetric id:5acc2142 -+ -+ will match a key with fingerprint: -+ -+ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 -+ -+ (2) If the criterion string is of the form ":" then the -+ match will match the ID as in (1), but with the added restriction that -+ only keys of the specified subtype (e.g. tpm) will be matched. For -+ instance: -+ -+ keyctl search @s asymmetric tpm:5acc2142 -+ -+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are -+displayed, along with the subtype: -+ -+ 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] -+ -+ -+========================= -+ACCESSING ASYMMETRIC KEYS -+========================= -+ -+For general access to asymmetric keys from within the kernel, the following -+inclusion is required: -+ -+ #include -+ -+This gives access to functions for dealing with asymmetric / public keys. -+Three enums are defined there for representing public-key cryptography -+algorithms: -+ -+ enum pkey_algo -+ -+digest algorithms used by those: -+ -+ enum pkey_hash_algo -+ -+and key identifier representations: -+ -+ enum pkey_id_type -+ -+Note that the key type representation types are required because key -+identifiers from different standards aren't necessarily compatible. For -+instance, PGP generates key identifiers by hashing the key data plus some -+PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. -+ -+The operations defined upon a key are: -+ -+ (1) Signature verification. -+ -+Other operations are possible (such as encryption) with the same key data -+required for verification, but not currently supported, and others -+(eg. decryption and signature generation) require extra key data. -+ -+ -+SIGNATURE VERIFICATION -+---------------------- -+ -+An operation is provided to perform cryptographic signature verification, using -+an asymmetric key to provide or to provide access to the public key. -+ -+ int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ -+The caller must have already obtained the key from some source and can then use -+it to check the signature. The caller must have parsed the signature and -+transferred the relevant bits to the structure pointed to by sig. -+ -+ struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ u8 nr_mpi; -+ union { -+ MPI mpi[2]; -+ ... -+ }; -+ }; -+ -+The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that -+make up the actual signature must be stored in sig->mpi[] and the count of MPIs -+placed in sig->nr_mpi. -+ -+In addition, the data must have been digested by the caller and the resulting -+hash must be pointed to by sig->digest and the size of the hash be placed in -+sig->digest_size. -+ -+The function will return 0 upon success or -EKEYREJECTED if the signature -+doesn't match. -+ -+The function may also return -ENOTSUPP if an unsupported public-key algorithm -+or public-key/hash algorithm combination is specified or the key doesn't -+support the operation; -EBADMSG or -ERANGE if some of the parameters have weird -+data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned -+if the key argument is the wrong type or is incompletely set up. -+ -+ -+======================= -+ASYMMETRIC KEY SUBTYPES -+======================= -+ -+Asymmetric keys have a subtype that defines the set of operations that can be -+performed on that key and that determines what data is attached as the key -+payload. The payload format is entirely at the whim of the subtype. -+ -+The subtype is selected by the key data parser and the parser must initialise -+the data required for it. The asymmetric key retains a reference on the -+subtype module. -+ -+The subtype definition structure can be found in: -+ -+ #include -+ -+and looks like the following: -+ -+ struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ void (*destroy)(void *payload); -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+ }; -+ -+Asymmetric keys point to this with their type_data[0] member. -+ -+The owner and name fields should be set to the owning module and the name of -+the subtype. Currently, the name is only used for print statements. -+ -+There are a number of operations defined by the subtype: -+ -+ (1) describe(). -+ -+ Mandatory. This allows the subtype to display something in /proc/keys -+ against the key. For instance the name of the public key algorithm type -+ could be displayed. The key type will display the tail of the key -+ identity string after this. -+ -+ (2) destroy(). -+ -+ Mandatory. This should free the memory associated with the key. The -+ asymmetric key will look after freeing the fingerprint and releasing the -+ reference on the subtype module. -+ -+ (3) verify_signature(). -+ -+ Optional. These are the entry points for the key usage operations. -+ Currently there is only the one defined. If not set, the caller will be -+ given -ENOTSUPP. The subtype may do anything it likes to implement an -+ operation, including offloading to hardware. -+ -+ -+========================== -+INSTANTIATION DATA PARSERS -+========================== -+ -+The asymmetric key type doesn't generally want to store or to deal with a raw -+blob of data that holds the key data. It would have to parse it and error -+check it each time it wanted to use it. Further, the contents of the blob may -+have various checks that can be performed on it (eg. self-signatures, validity -+dates) and may contain useful data about the key (identifiers, capabilities). -+ -+Also, the blob may represent a pointer to some hardware containing the key -+rather than the key itself. -+ -+Examples of blob formats for which parsers could be implemented include: -+ -+ - OpenPGP packet stream [RFC 4880]. -+ - X.509 ASN.1 stream. -+ - Pointer to TPM key. -+ - Pointer to UEFI key. -+ -+During key instantiation each parser in the list is tried until one doesn't -+return -EBADMSG. -+ -+The parser definition structure can be found in: -+ -+ #include -+ -+and looks like the following: -+ -+ struct asymmetric_key_parser { -+ struct module *owner; -+ const char *name; -+ -+ int (*parse)(struct key_preparsed_payload *prep); -+ }; -+ -+The owner and name fields should be set to the owning module and the name of -+the parser. -+ -+There is currently only a single operation defined by the parser, and it is -+mandatory: -+ -+ (1) parse(). -+ -+ This is called to preparse the key from the key creation and update paths. -+ In particular, it is called during the key creation _before_ a key is -+ allocated, and as such, is permitted to provide the key's description in -+ the case that the caller declines to do so. -+ -+ The caller passes a pointer to the following struct with all of the fields -+ cleared, except for data, datalen and quotalen [see -+ Documentation/security/keys.txt]. -+ -+ struct key_preparsed_payload { -+ char *description; -+ void *type_data[2]; -+ void *payload; -+ const void *data; -+ size_t datalen; -+ size_t quotalen; -+ }; -+ -+ The instantiation data is in a blob pointed to by data and is datalen in -+ size. The parse() function is not permitted to change these two values at -+ all, and shouldn't change any of the other values _unless_ they are -+ recognise the blob format and will not return -EBADMSG to indicate it is -+ not theirs. -+ -+ If the parser is happy with the blob, it should propose a description for -+ the key and attach it to ->description, ->type_data[0] should be set to -+ point to the subtype to be used, ->payload should be set to point to the -+ initialised data for that subtype, ->type_data[1] should point to a hex -+ fingerprint and quotalen should be updated to indicate how much quota this -+ key should account for. -+ -+ When clearing up, the data attached to ->type_data[1] and ->description -+ will be kfree()'d and the data attached to ->payload will be passed to the -+ subtype's ->destroy() method to be disposed of. A module reference for -+ the subtype pointed to by ->type_data[0] will be put. -+ -+ -+ If the data format is not recognised, -EBADMSG should be returned. If it -+ is recognised, but the key cannot for some reason be set up, some other -+ negative error code should be returned. On success, 0 should be returned. -+ -+ The key's fingerprint string may be partially matched upon. For a -+ public-key algorithm such as RSA and DSA this will likely be a printable -+ hex version of the key's fingerprint. -+ -+Functions are provided to register and unregister parsers: -+ -+ int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); -+ void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); -+ -+Parsers may not have the same name. The names are otherwise only used for -+displaying in debugging messages. --- -1.7.12.1 - - -From 0e450d75d1067b6f45f1f6b58a530a5d95144373 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:21 +0100 -Subject: [PATCH 05/37] KEYS: Implement asymmetric key type - -Create a key type that can be used to represent an asymmetric key type for use -in appropriate cryptographic operations, such as encryption, decryption, -signature generation and signature verification. - -The key type is "asymmetric" and can provide access to a variety of -cryptographic algorithms. - -Possibly, this would be better as "public_key" - but that has the disadvantage -that "public key" is an overloaded term. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/Kconfig | 1 + - crypto/Makefile | 1 + - crypto/asymmetric_keys/Kconfig | 13 +++ - crypto/asymmetric_keys/Makefile | 7 ++ - crypto/asymmetric_keys/asymmetric_keys.h | 15 +++ - crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++ - include/keys/asymmetric-subtype.h | 55 +++++++++++ - include/keys/asymmetric-type.h | 25 +++++ - 8 files changed, 273 insertions(+) - create mode 100644 crypto/asymmetric_keys/Kconfig - create mode 100644 crypto/asymmetric_keys/Makefile - create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h - create mode 100644 crypto/asymmetric_keys/asymmetric_type.c - create mode 100644 include/keys/asymmetric-subtype.h - create mode 100644 include/keys/asymmetric-type.h - -diff --git a/crypto/Kconfig b/crypto/Kconfig -index a323805..1ca0b24 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER - key cipher algorithms. - - source "drivers/crypto/Kconfig" -+source crypto/asymmetric_keys/Kconfig - - endif # if CRYPTO -diff --git a/crypto/Makefile b/crypto/Makefile -index 30f33d6..ced472e 100644 ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o - # - obj-$(CONFIG_XOR_BLOCKS) += xor.o - obj-$(CONFIG_ASYNC_CORE) += async_tx/ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -new file mode 100644 -index 0000000..cad29b3 ---- /dev/null -+++ b/crypto/asymmetric_keys/Kconfig -@@ -0,0 +1,13 @@ -+menuconfig ASYMMETRIC_KEY_TYPE -+ tristate "Asymmetric (public-key cryptographic) key type" -+ depends on KEYS -+ help -+ This option provides support for a key type that holds the data for -+ the asymmetric keys used for public key cryptographic operations such -+ as encryption, decryption, signature generation and signature -+ verification. -+ -+if ASYMMETRIC_KEY_TYPE -+ -+ -+endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -new file mode 100644 -index 0000000..b725bcc ---- /dev/null -+++ b/crypto/asymmetric_keys/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for asymmetric cryptographic keys -+# -+ -+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o -+ -+asymmetric_keys-y := asymmetric_type.o -diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h -new file mode 100644 -index 0000000..515b634 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_keys.h -@@ -0,0 +1,15 @@ -+/* Internal definitions for asymmetric key type -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+static inline const char *asymmetric_key_id(const struct key *key) -+{ -+ return key->type_data.p[1]; -+} -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -new file mode 100644 -index 0000000..bfb0424 ---- /dev/null -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -0,0 +1,156 @@ -+/* Asymmetric public-key cryptography key type -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Match asymmetric keys on (part of) their name -+ * We have some shorthand methods for matching keys. We allow: -+ * -+ * "" - request a key by description -+ * "id:" - request a key matching the ID -+ * ":" - request a key of a subtype -+ */ -+static int asymmetric_key_match(const struct key *key, const void *description) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *spec = description; -+ const char *id, *kid; -+ ptrdiff_t speclen; -+ size_t idlen, kidlen; -+ -+ if (!subtype || !spec || !*spec) -+ return 0; -+ -+ /* See if the full key description matches as is */ -+ if (key->description && strcmp(key->description, description) == 0) -+ return 1; -+ -+ /* All tests from here on break the criterion description into a -+ * specifier, a colon and then an identifier. -+ */ -+ id = strchr(spec, ':'); -+ if (!id) -+ return 0; -+ -+ speclen = id - spec; -+ id++; -+ -+ /* Anything after here requires a partial match on the ID string */ -+ kid = asymmetric_key_id(key); -+ if (!kid) -+ return 0; -+ -+ idlen = strlen(id); -+ kidlen = strlen(kid); -+ if (idlen > kidlen) -+ return 0; -+ -+ kid += kidlen - idlen; -+ if (strcasecmp(id, kid) != 0) -+ return 0; -+ -+ if (speclen == 2 && -+ memcmp(spec, "id", 2) == 0) -+ return 1; -+ -+ if (speclen == subtype->name_len && -+ memcmp(spec, subtype->name, speclen) == 0) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Describe the asymmetric key -+ */ -+static void asymmetric_key_describe(const struct key *key, struct seq_file *m) -+{ -+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ const char *kid = asymmetric_key_id(key); -+ size_t n; -+ -+ seq_puts(m, key->description); -+ -+ if (subtype) { -+ seq_puts(m, ": "); -+ subtype->describe(key, m); -+ -+ if (kid) { -+ seq_putc(m, ' '); -+ n = strlen(kid); -+ if (n <= 8) -+ seq_puts(m, kid); -+ else -+ seq_puts(m, kid + n - 8); -+ } -+ -+ seq_puts(m, " ["); -+ /* put something here to indicate the key's capabilities */ -+ seq_putc(m, ']'); -+ } -+} -+ -+/* -+ * Instantiate a asymmetric_key defined key. The key was preparsed, so we just -+ * have to transfer the data here. -+ */ -+static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) -+{ -+ return -EOPNOTSUPP; -+} -+ -+/* -+ * dispose of the data dangling from the corpse of a asymmetric key -+ */ -+static void asymmetric_key_destroy(struct key *key) -+{ -+ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); -+ if (subtype) { -+ subtype->destroy(key->payload.data); -+ module_put(subtype->owner); -+ key->type_data.p[0] = NULL; -+ } -+ kfree(key->type_data.p[1]); -+ key->type_data.p[1] = NULL; -+} -+ -+struct key_type key_type_asymmetric = { -+ .name = "asymmetric", -+ .instantiate = asymmetric_key_instantiate, -+ .match = asymmetric_key_match, -+ .destroy = asymmetric_key_destroy, -+ .describe = asymmetric_key_describe, -+}; -+EXPORT_SYMBOL_GPL(key_type_asymmetric); -+ -+/* -+ * Module stuff -+ */ -+static int __init asymmetric_key_init(void) -+{ -+ return register_key_type(&key_type_asymmetric); -+} -+ -+static void __exit asymmetric_key_cleanup(void) -+{ -+ unregister_key_type(&key_type_asymmetric); -+} -+ -+module_init(asymmetric_key_init); -+module_exit(asymmetric_key_cleanup); -diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h -new file mode 100644 -index 0000000..4b840e8 ---- /dev/null -+++ b/include/keys/asymmetric-subtype.h -@@ -0,0 +1,55 @@ -+/* Asymmetric public-key cryptography key subtype -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H -+#define _KEYS_ASYMMETRIC_SUBTYPE_H -+ -+#include -+#include -+ -+struct public_key_signature; -+ -+/* -+ * Keys of this type declare a subtype that indicates the handlers and -+ * capabilities. -+ */ -+struct asymmetric_key_subtype { -+ struct module *owner; -+ const char *name; -+ unsigned short name_len; /* length of name */ -+ -+ /* Describe a key of this subtype for /proc/keys */ -+ void (*describe)(const struct key *key, struct seq_file *m); -+ -+ /* Destroy a key of this subtype */ -+ void (*destroy)(void *payload); -+ -+ /* Verify the signature on a key of this subtype (optional) */ -+ int (*verify_signature)(const struct key *key, -+ const struct public_key_signature *sig); -+}; -+ -+/** -+ * asymmetric_key_subtype - Get the subtype from an asymmetric key -+ * @key: The key of interest. -+ * -+ * Retrieves and returns the subtype pointer of the asymmetric key from the -+ * type-specific data attached to the key. -+ */ -+static inline -+struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) -+{ -+ return key->type_data.p[0]; -+} -+ -+#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ -diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h -new file mode 100644 -index 0000000..7dd4734 ---- /dev/null -+++ b/include/keys/asymmetric-type.h -@@ -0,0 +1,25 @@ -+/* Asymmetric Public-key cryptography key type interface -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_TYPE_H -+#define _KEYS_ASYMMETRIC_TYPE_H -+ -+#include -+ -+extern struct key_type key_type_asymmetric; -+ -+/* -+ * The payload is at the discretion of the subtype. -+ */ -+ -+#endif /* _KEYS_ASYMMETRIC_TYPE_H */ --- -1.7.12.1 - - -From 6ec62201b26995d57fbd457469314bfc5653f2a0 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 13 Sep 2012 15:17:32 +0100 -Subject: [PATCH 06/37] KEYS: Asymmetric key pluggable data parsers - -The instantiation data passed to the asymmetric key type are expected to be -formatted in some way, and there are several possible standard ways to format -the data. - -The two obvious standards are OpenPGP keys and X.509 certificates. The latter -is especially useful when dealing with UEFI, and the former might be useful -when dealing with, say, eCryptfs. - -Further, it might be desirable to provide formatted blobs that indicate -hardware is to be accessed to retrieve the keys or that the keys live -unretrievably in a hardware store, but that the keys can be used by means of -the hardware. - -From userspace, the keys can be loaded using the keyctl command, for example, -an X.509 binary certificate: - - keyctl padd asymmetric foo @s -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++- - include/keys/asymmetric-parser.h | 37 ++++++++++ - 2 files changed, 156 insertions(+), 1 deletion(-) - create mode 100644 include/keys/asymmetric-parser.h - -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -index bfb0424..cf80765 100644 ---- a/crypto/asymmetric_keys/asymmetric_type.c -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -11,6 +11,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - #include -+#include - #include - #include - #include -@@ -18,6 +19,9 @@ - - MODULE_LICENSE("GPL"); - -+static LIST_HEAD(asymmetric_key_parsers); -+static DECLARE_RWSEM(asymmetric_key_parsers_sem); -+ - /* - * Match asymmetric keys on (part of) their name - * We have some shorthand methods for matching keys. We allow: -@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) - } - - /* -+ * Preparse a asymmetric payload to get format the contents appropriately for the -+ * internal payload to cut down on the number of scans of the data performed. -+ * -+ * We also generate a proposed description from the contents of the key that -+ * can be used to name the key if the user doesn't want to provide one. -+ */ -+static int asymmetric_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_parser *parser; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (prep->datalen == 0) -+ return -EINVAL; -+ -+ down_read(&asymmetric_key_parsers_sem); -+ -+ ret = -EBADMSG; -+ list_for_each_entry(parser, &asymmetric_key_parsers, link) { -+ pr_debug("Trying parser '%s'\n", parser->name); -+ -+ ret = parser->parse(prep); -+ if (ret != -EBADMSG) { -+ pr_debug("Parser recognised the format (ret %d)\n", -+ ret); -+ break; -+ } -+ } -+ -+ up_read(&asymmetric_key_parsers_sem); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Clean up the preparse data -+ */ -+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) -+{ -+ struct asymmetric_key_subtype *subtype = prep->type_data[0]; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (subtype) { -+ subtype->destroy(prep->payload); -+ module_put(subtype->owner); -+ } -+ kfree(prep->type_data[1]); -+ kfree(prep->description); -+} -+ -+/* - * Instantiate a asymmetric_key defined key. The key was preparsed, so we just - * have to transfer the data here. - */ - static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) - { -- return -EOPNOTSUPP; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ ret = key_payload_reserve(key, prep->quotalen); -+ if (ret == 0) { -+ key->type_data.p[0] = prep->type_data[0]; -+ key->type_data.p[1] = prep->type_data[1]; -+ key->payload.data = prep->payload; -+ prep->type_data[0] = NULL; -+ prep->type_data[1] = NULL; -+ prep->payload = NULL; -+ } -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } - - /* -@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) - - struct key_type key_type_asymmetric = { - .name = "asymmetric", -+ .preparse = asymmetric_key_preparse, -+ .free_preparse = asymmetric_key_free_preparse, - .instantiate = asymmetric_key_instantiate, - .match = asymmetric_key_match, - .destroy = asymmetric_key_destroy, -@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { - }; - EXPORT_SYMBOL_GPL(key_type_asymmetric); - -+/** -+ * register_asymmetric_key_parser - Register a asymmetric key blob parser -+ * @parser: The parser to register -+ */ -+int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ struct asymmetric_key_parser *cursor; -+ int ret; -+ -+ down_write(&asymmetric_key_parsers_sem); -+ -+ list_for_each_entry(cursor, &asymmetric_key_parsers, link) { -+ if (strcmp(cursor->name, parser->name) == 0) { -+ pr_err("Asymmetric key parser '%s' already registered\n", -+ parser->name); -+ ret = -EEXIST; -+ goto out; -+ } -+ } -+ -+ list_add_tail(&parser->link, &asymmetric_key_parsers); -+ -+ pr_notice("Asymmetric key parser '%s' registered\n", parser->name); -+ ret = 0; -+ -+out: -+ up_write(&asymmetric_key_parsers_sem); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); -+ -+/** -+ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser -+ * @parser: The parser to unregister -+ */ -+void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) -+{ -+ down_write(&asymmetric_key_parsers_sem); -+ list_del(&parser->link); -+ up_write(&asymmetric_key_parsers_sem); -+ -+ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); -+} -+EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); -+ - /* - * Module stuff - */ -diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h -new file mode 100644 -index 0000000..09b3b48 ---- /dev/null -+++ b/include/keys/asymmetric-parser.h -@@ -0,0 +1,37 @@ -+/* Asymmetric public-key cryptography data parser -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_ASYMMETRIC_PARSER_H -+#define _KEYS_ASYMMETRIC_PARSER_H -+ -+/* -+ * Key data parser. Called during key instantiation. -+ */ -+struct asymmetric_key_parser { -+ struct list_head link; -+ struct module *owner; -+ const char *name; -+ -+ /* Attempt to parse a key from the data blob passed to add_key() or -+ * keyctl_instantiate(). Should also generate a proposed description -+ * that the caller can optionally use for the key. -+ * -+ * Return EBADMSG if not recognised. -+ */ -+ int (*parse)(struct key_preparsed_payload *prep); -+}; -+ -+extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); -+extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); -+ -+#endif /* _KEYS_ASYMMETRIC_PARSER_H */ --- -1.7.12.1 - - -From 390ad626607322c6e4da8a2e6d2a4094e78b919a Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:24:55 +0100 -Subject: [PATCH 07/37] KEYS: Asymmetric public-key algorithm crypto key - subtype - -Add a subtype for supporting asymmetric public-key encryption algorithms such -as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/Kconfig | 8 +++ - crypto/asymmetric_keys/Makefile | 2 + - crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/public_key.h | 28 ++++++++++ - include/crypto/public_key.h | 104 ++++++++++++++++++++++++++++++++++ - 5 files changed, 250 insertions(+) - create mode 100644 crypto/asymmetric_keys/public_key.c - create mode 100644 crypto/asymmetric_keys/public_key.h - create mode 100644 include/crypto/public_key.h - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index cad29b3..bbfccaa 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE - - if ASYMMETRIC_KEY_TYPE - -+config ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ tristate "Asymmetric public-key crypto algorithm subtype" -+ select MPILIB -+ help -+ This option provides support for asymmetric public key type handling. -+ If signature generation and/or verification are to be used, -+ appropriate hash algorithms (such as SHA-1) must be available. -+ ENOPKG will be reported if the requisite algorithm is unavailable. - - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index b725bcc..5ed46ee 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -5,3 +5,5 @@ - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - - asymmetric_keys-y := asymmetric_type.o -+ -+obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -new file mode 100644 -index 0000000..cb2e291 ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.c -@@ -0,0 +1,108 @@ -+/* In-software asymmetric public-key crypto subtype -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "PKEY: "fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+ -+const char *const pkey_algo[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = "DSA", -+ [PKEY_ALGO_RSA] = "RSA", -+}; -+EXPORT_SYMBOL_GPL(pkey_algo); -+ -+const char *const pkey_hash_algo[PKEY_HASH__LAST] = { -+ [PKEY_HASH_MD4] = "md4", -+ [PKEY_HASH_MD5] = "md5", -+ [PKEY_HASH_SHA1] = "sha1", -+ [PKEY_HASH_RIPE_MD_160] = "rmd160", -+ [PKEY_HASH_SHA256] = "sha256", -+ [PKEY_HASH_SHA384] = "sha384", -+ [PKEY_HASH_SHA512] = "sha512", -+ [PKEY_HASH_SHA224] = "sha224", -+}; -+EXPORT_SYMBOL_GPL(pkey_hash_algo); -+ -+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { -+ [PKEY_ID_PGP] = "PGP", -+ [PKEY_ID_X509] = "X509", -+}; -+EXPORT_SYMBOL_GPL(pkey_id_type); -+ -+/* -+ * Provide a part of a description of the key for /proc/keys. -+ */ -+static void public_key_describe(const struct key *asymmetric_key, -+ struct seq_file *m) -+{ -+ struct public_key *key = asymmetric_key->payload.data; -+ -+ if (key) -+ seq_printf(m, "%s.%s", -+ pkey_id_type[key->id_type], key->algo->name); -+} -+ -+/* -+ * Destroy a public key algorithm key. -+ */ -+void public_key_destroy(void *payload) -+{ -+ struct public_key *key = payload; -+ int i; -+ -+ if (key) { -+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++) -+ mpi_free(key->mpi[i]); -+ kfree(key); -+ } -+} -+EXPORT_SYMBOL_GPL(public_key_destroy); -+ -+/* -+ * Verify a signature using a public key. -+ */ -+static int public_key_verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct public_key *pk = key->payload.data; -+ -+ if (!pk->algo->verify_signature) -+ return -ENOTSUPP; -+ -+ if (sig->nr_mpi != pk->algo->n_sig_mpi) { -+ pr_debug("Signature has %u MPI not %u\n", -+ sig->nr_mpi, pk->algo->n_sig_mpi); -+ return -EINVAL; -+ } -+ -+ return pk->algo->verify_signature(pk, sig); -+} -+ -+/* -+ * Public key algorithm asymmetric key subtype -+ */ -+struct asymmetric_key_subtype public_key_subtype = { -+ .owner = THIS_MODULE, -+ .name = "public_key", -+ .describe = public_key_describe, -+ .destroy = public_key_destroy, -+ .verify_signature = public_key_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(public_key_subtype); -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -new file mode 100644 -index 0000000..1f86aad ---- /dev/null -+++ b/crypto/asymmetric_keys/public_key.h -@@ -0,0 +1,28 @@ -+/* Public key algorithm internals -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+ -+extern struct asymmetric_key_subtype public_key_subtype; -+ -+/* -+ * Public key algorithm definition. -+ */ -+struct public_key_algorithm { -+ const char *name; -+ u8 n_pub_mpi; /* Number of MPIs in public key */ -+ u8 n_sec_mpi; /* Number of MPIs in secret key */ -+ u8 n_sig_mpi; /* Number of MPIs in a signature */ -+ int (*verify_signature)(const struct public_key *key, -+ const struct public_key_signature *sig); -+}; -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -new file mode 100644 -index 0000000..4b8b6c1 ---- /dev/null -+++ b/include/crypto/public_key.h -@@ -0,0 +1,104 @@ -+/* Asymmetric public-key algorithm definitions -+ * -+ * See Documentation/crypto/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_PUBLIC_KEY_H -+#define _LINUX_PUBLIC_KEY_H -+ -+#include -+ -+enum pkey_algo { -+ PKEY_ALGO_DSA, -+ PKEY_ALGO_RSA, -+ PKEY_ALGO__LAST -+}; -+ -+extern const char *const pkey_algo[PKEY_ALGO__LAST]; -+ -+enum pkey_hash_algo { -+ PKEY_HASH_MD4, -+ PKEY_HASH_MD5, -+ PKEY_HASH_SHA1, -+ PKEY_HASH_RIPE_MD_160, -+ PKEY_HASH_SHA256, -+ PKEY_HASH_SHA384, -+ PKEY_HASH_SHA512, -+ PKEY_HASH_SHA224, -+ PKEY_HASH__LAST -+}; -+ -+extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; -+ -+enum pkey_id_type { -+ PKEY_ID_PGP, /* OpenPGP generated key ID */ -+ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ -+ PKEY_ID_TYPE__LAST -+}; -+ -+extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; -+ -+/* -+ * Cryptographic data for the public-key subtype of the asymmetric key type. -+ * -+ * Note that this may include private part of the key as well as the public -+ * part. -+ */ -+struct public_key { -+ const struct public_key_algorithm *algo; -+ u8 capabilities; -+#define PKEY_CAN_ENCRYPT 0x01 -+#define PKEY_CAN_DECRYPT 0x02 -+#define PKEY_CAN_SIGN 0x04 -+#define PKEY_CAN_VERIFY 0x08 -+ enum pkey_id_type id_type : 8; -+ union { -+ MPI mpi[5]; -+ struct { -+ MPI p; /* DSA prime */ -+ MPI q; /* DSA group order */ -+ MPI g; /* DSA group generator */ -+ MPI y; /* DSA public-key value = g^x mod p */ -+ MPI x; /* DSA secret exponent (if present) */ -+ } dsa; -+ struct { -+ MPI n; /* RSA public modulus */ -+ MPI e; /* RSA public encryption exponent */ -+ MPI d; /* RSA secret encryption exponent (if present) */ -+ MPI p; /* RSA secret prime (if present) */ -+ MPI q; /* RSA secret prime (if present) */ -+ } rsa; -+ }; -+}; -+ -+extern void public_key_destroy(void *payload); -+ -+/* -+ * Public key cryptography signature data -+ */ -+struct public_key_signature { -+ u8 *digest; -+ u8 digest_size; /* Number of bytes in digest */ -+ u8 nr_mpi; /* Occupancy of mpi[] */ -+ enum pkey_hash_algo pkey_hash_algo : 8; -+ union { -+ MPI mpi[2]; -+ struct { -+ MPI s; /* m^d mod n */ -+ } rsa; -+ struct { -+ MPI r; -+ MPI s; -+ } dsa; -+ }; -+}; -+ -+#endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.12.1 - - -From 13d9a26663043faaa37dbe6c2f214ceef5f00b05 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:04 +0100 -Subject: [PATCH 08/37] KEYS: Provide signature verification with an - asymmetric key - -Provide signature verification using an asymmetric-type key to indicate the -public key to be used. - -The API is a single function that can be found in crypto/public_key.h: - - int verify_signature(const struct key *key, - const struct public_key_signature *sig) - -The first argument is the appropriate key to be used and the second argument -is the parsed signature data: - - struct public_key_signature { - u8 *digest; - u16 digest_size; - enum pkey_hash_algo pkey_hash_algo : 8; - union { - MPI mpi[2]; - struct { - MPI s; /* m^d mod n */ - } rsa; - struct { - MPI r; - MPI s; - } dsa; - }; - }; - -This should be filled in prior to calling the function. The hash algorithm -should already have been called and the hash finalised and the output should -be in a buffer pointed to by the 'digest' member. - -Any extra data to be added to the hash by the hash format (eg. PGP) should -have been added by the caller prior to finalising the hash. - -It is assumed that the signature is made up of a number of MPI values. If an -algorithm becomes available for which this is not the case, the above structure -will have to change. - -It is also assumed that it will have been checked that the signature algorithm -matches the key algorithm. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/Makefile | 2 +- - crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++ - include/crypto/public_key.h | 4 ++++ - 3 files changed, 54 insertions(+), 1 deletion(-) - create mode 100644 crypto/asymmetric_keys/signature.c - -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 5ed46ee..8dcdf0c 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -4,6 +4,6 @@ - - obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - --asymmetric_keys-y := asymmetric_type.o -+asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c -new file mode 100644 -index 0000000..50b3f88 ---- /dev/null -+++ b/crypto/asymmetric_keys/signature.c -@@ -0,0 +1,49 @@ -+/* Signature verification with an asymmetric key -+ * -+ * See Documentation/security/asymmetric-keys.txt -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+ -+/** -+ * verify_signature - Initiate the use of an asymmetric key to verify a signature -+ * @key: The asymmetric key to verify against -+ * @sig: The signature to check -+ * -+ * Returns 0 if successful or else an error. -+ */ -+int verify_signature(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct asymmetric_key_subtype *subtype; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ if (key->type != &key_type_asymmetric) -+ return -EINVAL; -+ subtype = asymmetric_key_subtype(key); -+ if (!subtype || -+ !key->payload.data) -+ return -EINVAL; -+ if (!subtype->verify_signature) -+ return -ENOTSUPP; -+ -+ ret = subtype->verify_signature(key, sig); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(verify_signature); -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 4b8b6c1..f5b0224 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -101,4 +101,8 @@ struct public_key_signature { - }; - }; - -+struct key; -+extern int verify_signature(const struct key *key, -+ const struct public_key_signature *sig); -+ - #endif /* _LINUX_PUBLIC_KEY_H */ --- -1.7.12.1 - - -From 3d379de76f21782c611b7d409d7374b82bc90220 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:22 +0100 -Subject: [PATCH 09/37] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA - signature verification - -Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by -RSA signature verification as per RFC3447 section 5.2.2 step 1. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - lib/mpi/Makefile | 1 + - lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) - create mode 100644 lib/mpi/mpi-cmp.c - -diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile -index 45ca90a..019a68c 100644 ---- a/lib/mpi/Makefile -+++ b/lib/mpi/Makefile -@@ -14,6 +14,7 @@ mpi-y = \ - generic_mpih-add1.o \ - mpicoder.o \ - mpi-bit.o \ -+ mpi-cmp.o \ - mpih-cmp.o \ - mpih-div.o \ - mpih-mul.o \ -diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c -new file mode 100644 -index 0000000..1871e7b ---- /dev/null -+++ b/lib/mpi/mpi-cmp.c -@@ -0,0 +1,70 @@ -+/* mpi-cmp.c - MPI functions -+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc. -+ * -+ * This file is part of GnuPG. -+ * -+ * GnuPG is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * GnuPG 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ */ -+ -+#include "mpi-internal.h" -+ -+int mpi_cmp_ui(MPI u, unsigned long v) -+{ -+ mpi_limb_t limb = v; -+ -+ mpi_normalize(u); -+ if (!u->nlimbs && !limb) -+ return 0; -+ if (u->sign) -+ return -1; -+ if (u->nlimbs > 1) -+ return 1; -+ -+ if (u->d[0] == limb) -+ return 0; -+ else if (u->d[0] > limb) -+ return 1; -+ else -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp_ui); -+ -+int mpi_cmp(MPI u, MPI v) -+{ -+ mpi_size_t usize, vsize; -+ int cmp; -+ -+ mpi_normalize(u); -+ mpi_normalize(v); -+ usize = u->nlimbs; -+ vsize = v->nlimbs; -+ if (!u->sign && v->sign) -+ return 1; -+ if (u->sign && !v->sign) -+ return -1; -+ if (usize != vsize && !u->sign && !v->sign) -+ return usize - vsize; -+ if (usize != vsize && u->sign && v->sign) -+ return vsize + usize; -+ if (!usize) -+ return 0; -+ cmp = mpihelp_cmp(u->d, v->d, usize); -+ if (!cmp) -+ return 0; -+ if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) -+ return 1; -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mpi_cmp); --- -1.7.12.1 - - -From b872c7db2ce34b5f051d1c38216843a1f796aa86 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:25:40 +0100 -Subject: [PATCH 10/37] RSA: Implement signature verification algorithm - [PKCS#1 / RFC3447] - -Implement RSA public key cryptography [PKCS#1 / RFC3447]. At this time, only -the signature verification algorithm is supported. This uses the asymmetric -public key subtype to hold its key data. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/Kconfig | 7 + - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/public_key.h | 2 + - crypto/asymmetric_keys/rsa.c | 269 ++++++++++++++++++++++++++++++++++++ - 4 files changed, 279 insertions(+) - create mode 100644 crypto/asymmetric_keys/rsa.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index bbfccaa..561759d 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE - appropriate hash algorithms (such as SHA-1) must be available. - ENOPKG will be reported if the requisite algorithm is unavailable. - -+config PUBLIC_KEY_ALGO_RSA -+ tristate "RSA public-key algorithm" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select MPILIB_EXTRA -+ help -+ This option enables support for the RSA algorithm (PKCS#1, RFC3447). -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 8dcdf0c..7c92691 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o - asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -+obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -index 1f86aad..5e5e356 100644 ---- a/crypto/asymmetric_keys/public_key.h -+++ b/crypto/asymmetric_keys/public_key.h -@@ -26,3 +26,5 @@ struct public_key_algorithm { - int (*verify_signature)(const struct public_key *key, - const struct public_key_signature *sig); - }; -+ -+extern const struct public_key_algorithm RSA_public_key_algorithm; -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -new file mode 100644 -index 0000000..9b31ee2 ---- /dev/null -+++ b/crypto/asymmetric_keys/rsa.c -@@ -0,0 +1,269 @@ -+/* RSA asymmetric public-key algorithm [RFC3447] -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "RSA: "fmt -+#include -+#include -+#include -+#include "public_key.h" -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("RSA Public Key Algorithm"); -+ -+#define kenter(FMT, ...) \ -+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -+#define kleave(FMT, ...) \ -+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) -+ -+/* -+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. -+ */ -+static const u8 RSA_digest_info_MD5[] = { -+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, -+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ -+ 0x05, 0x00, 0x04, 0x10 -+}; -+ -+static const u8 RSA_digest_info_SHA1[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_RIPE_MD_160[] = { -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x24, 0x03, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x14 -+}; -+ -+static const u8 RSA_digest_info_SHA224[] = { -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C -+}; -+ -+static const u8 RSA_digest_info_SHA256[] = { -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20 -+}; -+ -+static const u8 RSA_digest_info_SHA384[] = { -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30 -+}; -+ -+static const u8 RSA_digest_info_SHA512[] = { -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40 -+}; -+ -+static const struct { -+ const u8 *data; -+ size_t size; -+} RSA_ASN1_templates[PKEY_HASH__LAST] = { -+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } -+ [PKEY_HASH_MD5] = _(MD5), -+ [PKEY_HASH_SHA1] = _(SHA1), -+ [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), -+ [PKEY_HASH_SHA256] = _(SHA256), -+ [PKEY_HASH_SHA384] = _(SHA384), -+ [PKEY_HASH_SHA512] = _(SHA512), -+ [PKEY_HASH_SHA224] = _(SHA224), -+#undef _ -+}; -+ -+/* -+ * RSAVP1() function [RFC3447 sec 5.2.2] -+ */ -+static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) -+{ -+ MPI m; -+ int ret; -+ -+ /* (1) Validate 0 <= s < n */ -+ if (mpi_cmp_ui(s, 0) < 0) { -+ kleave(" = -EBADMSG [s < 0]"); -+ return -EBADMSG; -+ } -+ if (mpi_cmp(s, key->rsa.n) >= 0) { -+ kleave(" = -EBADMSG [s >= n]"); -+ return -EBADMSG; -+ } -+ -+ m = mpi_alloc(0); -+ if (!m) -+ return -ENOMEM; -+ -+ /* (2) m = s^e mod n */ -+ ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); -+ if (ret < 0) { -+ mpi_free(m); -+ return ret; -+ } -+ -+ *_m = m; -+ return 0; -+} -+ -+/* -+ * Integer to Octet String conversion [RFC3447 sec 4.1] -+ */ -+static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) -+{ -+ unsigned X_size, x_size; -+ int X_sign; -+ u8 *X; -+ -+ /* Make sure the string is the right length. The number should begin -+ * with { 0x00, 0x01, ... } so we have to account for 15 leading zero -+ * bits not being reported by MPI. -+ */ -+ x_size = mpi_get_nbits(x); -+ pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); -+ if (x_size != xLen * 8 - 15) -+ return -ERANGE; -+ -+ X = mpi_get_buffer(x, &X_size, &X_sign); -+ if (!X) -+ return -ENOMEM; -+ if (X_sign < 0) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ if (X_size != xLen - 1) { -+ kfree(X); -+ return -EBADMSG; -+ } -+ -+ *_X = X; -+ return 0; -+} -+ -+/* -+ * Perform the RSA signature verification. -+ * @H: Value of hash of data and metadata -+ * @EM: The computed signature value -+ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) -+ * @hash_size: The size of H -+ * @asn1_template: The DigestInfo ASN.1 template -+ * @asn1_size: Size of asm1_template[] -+ */ -+static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, -+ const u8 *asn1_template, size_t asn1_size) -+{ -+ unsigned PS_end, T_offset, i; -+ -+ kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); -+ -+ if (k < 2 + 1 + asn1_size + hash_size) -+ return -EBADMSG; -+ -+ /* Decode the EMSA-PKCS1-v1_5 */ -+ if (EM[1] != 0x01) { -+ kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); -+ return -EBADMSG; -+ } -+ -+ T_offset = k - (asn1_size + hash_size); -+ PS_end = T_offset - 1; -+ if (EM[PS_end] != 0x00) { -+ kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); -+ return -EBADMSG; -+ } -+ -+ for (i = 2; i < PS_end; i++) { -+ if (EM[i] != 0xff) { -+ kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); -+ return -EBADMSG; -+ } -+ } -+ -+ if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { -+ kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); -+ return -EBADMSG; -+ } -+ -+ if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { -+ kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); -+ return -EKEYREJECTED; -+ } -+ -+ kleave(" = 0"); -+ return 0; -+} -+ -+/* -+ * Perform the verification step [RFC3447 sec 8.2.2]. -+ */ -+static int RSA_verify_signature(const struct public_key *key, -+ const struct public_key_signature *sig) -+{ -+ size_t tsize; -+ int ret; -+ -+ /* Variables as per RFC3447 sec 8.2.2 */ -+ const u8 *H = sig->digest; -+ u8 *EM = NULL; -+ MPI m = NULL; -+ size_t k; -+ -+ kenter(""); -+ -+ if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) -+ return -ENOTSUPP; -+ -+ /* (1) Check the signature size against the public key modulus size */ -+ k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ -+ tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -+ if (tsize != k) { -+ ret = -EBADMSG; -+ goto error; -+ } -+ -+ /* (2b) Apply the RSAVP1 verification primitive to the public key */ -+ ret = RSAVP1(key, sig->rsa.s, &m); -+ if (ret < 0) -+ goto error; -+ -+ /* (2c) Convert the message representative (m) to an encoded message -+ * (EM) of length k octets. -+ * -+ * NOTE! The leading zero byte is suppressed by MPI, so we pass a -+ * pointer to the _preceding_ byte to RSA_verify()! -+ */ -+ ret = RSA_I2OSP(m, k, &EM); -+ if (ret < 0) -+ goto error; -+ -+ ret = RSA_verify(H, EM - 1, k, sig->digest_size, -+ RSA_ASN1_templates[sig->pkey_hash_algo].data, -+ RSA_ASN1_templates[sig->pkey_hash_algo].size); -+ -+error: -+ kfree(EM); -+ mpi_free(m); -+ kleave(" = %d", ret); -+ return ret; -+} -+ -+const struct public_key_algorithm RSA_public_key_algorithm = { -+ .name = "RSA", -+ .n_pub_mpi = 2, -+ .n_sec_mpi = 3, -+ .n_sig_mpi = 1, -+ .verify_signature = RSA_verify_signature, -+}; -+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); --- -1.7.12.1 - - -From 362af238a35e095094b3f5a228cf2c0f60c10cd9 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:28:05 +0100 -Subject: [PATCH 11/37] RSA: Fix signature verification for shorter signatures - -gpg can produce a signature file where length of signature is less than the -modulus size because the amount of space an MPI takes up is kept as low as -possible by discarding leading zeros. This regularly happens for several -modules during the build. - -Fix it by relaxing check in RSA verification code. - -Thanks to Tomas Mraz and Miloslav Trmac for help. - -Signed-off-by: Milan Broz -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/rsa.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c -index 9b31ee2..4a6a069 100644 ---- a/crypto/asymmetric_keys/rsa.c -+++ b/crypto/asymmetric_keys/rsa.c -@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key, - return -ENOTSUPP; - - /* (1) Check the signature size against the public key modulus size */ -- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ k = mpi_get_nbits(key->rsa.n); -+ tsize = mpi_get_nbits(sig->rsa.s); - -- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ /* According to RFC 4880 sec 3.2, length of MPI is computed starting -+ * from most significant bit. So the RFC 3447 sec 8.2.2 size check -+ * must be relaxed to conform with shorter signatures - so we fail here -+ * only if signature length is longer than modulus size. -+ */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -- if (tsize != k) { -+ if (k < tsize) { - ret = -EBADMSG; - goto error; - } - -+ /* Round up and convert to octets */ -+ k = (k + 7) / 8; -+ - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); - if (ret < 0) --- -1.7.12.1 - - -From 81451f08c7db892e06144cf3bc89746e68269624 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:30:46 +0100 -Subject: [PATCH 12/37] X.509: Implement simple static OID registry - -Implement a simple static OID registry that allows the mapping of an encoded -OID to an enum value for ease of use. - -The OID registry index enum appears in the: - - linux/oid_registry.h - -header file. A script generates the registry from lines in the header file -that look like: - - OID_foo,/*1.2.3.4*/ - -The actual OID is taken to be represented by the numbers with interpolated -dots in the comment. - -All other lines in the header are ignored. - -The registry is queries by calling: - - OID look_up_oid(const void *data, size_t datasize); - -This returns a number from the registry enum representing the OID if found or -OID__NR if not. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - include/linux/oid_registry.h | 90 +++++++++++++++++++ - lib/.gitignore | 2 +- - lib/Kconfig | 5 ++ - lib/Makefile | 16 ++++ - lib/build_OID_registry | 209 +++++++++++++++++++++++++++++++++++++++++++ - lib/oid_registry.c | 89 ++++++++++++++++++ - 6 files changed, 410 insertions(+), 1 deletion(-) - create mode 100644 include/linux/oid_registry.h - create mode 100755 lib/build_OID_registry - create mode 100644 lib/oid_registry.c - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -new file mode 100644 -index 0000000..5928546 ---- /dev/null -+++ b/include/linux/oid_registry.h -@@ -0,0 +1,90 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_OID_REGISTRY_H -+#define _LINUX_OID_REGISTRY_H -+ -+#include -+ -+/* -+ * OIDs are turned into these values if possible, or OID__NR if not held here. -+ * -+ * NOTE! Do not mess with the format of each line as this is read by -+ * build_OID_registry.pl to generate the data for look_up_OID(). -+ */ -+enum OID { -+ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ -+ OID_id_dsa, /* 1.2.840.10040.4.1 */ -+ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ -+ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ -+ -+ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ -+ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ -+ OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ -+ OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ -+ OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ -+ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ -+ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ -+ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ -+ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ -+ OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ -+ /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ -+ OID_data, /* 1.2.840.113549.1.7.1 */ -+ OID_signed_data, /* 1.2.840.113549.1.7.2 */ -+ /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ -+ OID_email_address, /* 1.2.840.113549.1.9.1 */ -+ OID_content_type, /* 1.2.840.113549.1.9.3 */ -+ OID_messageDigest, /* 1.2.840.113549.1.9.4 */ -+ OID_signingTime, /* 1.2.840.113549.1.9.5 */ -+ OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ -+ OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ -+ -+ /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ -+ OID_md2, /* 1.2.840.113549.2.2 */ -+ OID_md4, /* 1.2.840.113549.2.4 */ -+ OID_md5, /* 1.2.840.113549.2.5 */ -+ -+ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ -+ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ -+ OID_sha1, /* 1.3.14.3.2.26 */ -+ -+ /* Distinguished Name attribute IDs [RFC 2256] */ -+ OID_commonName, /* 2.5.4.3 */ -+ OID_surname, /* 2.5.4.4 */ -+ OID_countryName, /* 2.5.4.6 */ -+ OID_locality, /* 2.5.4.7 */ -+ OID_stateOrProvinceName, /* 2.5.4.8 */ -+ OID_organizationName, /* 2.5.4.10 */ -+ OID_organizationUnitName, /* 2.5.4.11 */ -+ OID_title, /* 2.5.4.12 */ -+ OID_description, /* 2.5.4.13 */ -+ OID_name, /* 2.5.4.41 */ -+ OID_givenName, /* 2.5.4.42 */ -+ OID_initials, /* 2.5.4.43 */ -+ OID_generationalQualifier, /* 2.5.4.44 */ -+ -+ /* Certificate extension IDs */ -+ OID_subjectKeyIdentifier, /* 2.5.29.14 */ -+ OID_keyUsage, /* 2.5.29.15 */ -+ OID_subjectAltName, /* 2.5.29.17 */ -+ OID_issuerAltName, /* 2.5.29.18 */ -+ OID_basicConstraints, /* 2.5.29.19 */ -+ OID_crlDistributionPoints, /* 2.5.29.31 */ -+ OID_certPolicies, /* 2.5.29.32 */ -+ OID_authorityKeyIdentifier, /* 2.5.29.35 */ -+ OID_extKeyUsage, /* 2.5.29.37 */ -+ -+ OID__NR -+}; -+ -+extern enum OID look_up_OID(const void *data, size_t datasize); -+ -+#endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/.gitignore b/lib/.gitignore -index 3bef1ea..09aae85 100644 ---- a/lib/.gitignore -+++ b/lib/.gitignore -@@ -3,4 +3,4 @@ - # - gen_crc32table - crc32table.h -- -+oid_registry_data.c -diff --git a/lib/Kconfig b/lib/Kconfig -index bb94c1b..4b31a46 100644 ---- a/lib/Kconfig -+++ b/lib/Kconfig -@@ -396,4 +396,9 @@ config SIGNATURE - config LIBFDT - bool - -+config OID_REGISTRY -+ tristate -+ help -+ Enable fast lookup object identifier registry. -+ - endmenu -diff --git a/lib/Makefile b/lib/Makefile -index 42d283e..b042896 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN $@ - - $(obj)/crc32table.h: $(obj)/gen_crc32table - $(call cmd,crc32) -+ -+# -+# Build a fast OID lookip registry from include/linux/oid_registry.h -+# -+obj-$(CONFIG_OID_REGISTRY) += oid_registry.o -+ -+$(obj)/oid_registry.c: $(obj)/oid_registry_data.c -+ -+$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ -+ $(src)/build_OID_registry -+ $(call cmd,build_OID_registry) -+ -+quiet_cmd_build_OID_registry = GEN $@ -+ cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ -+ -+clean-files += oid_registry_data.c -diff --git a/lib/build_OID_registry b/lib/build_OID_registry -new file mode 100755 -index 0000000..dfbdaab ---- /dev/null -+++ b/lib/build_OID_registry -@@ -0,0 +1,209 @@ -+#!/usr/bin/perl -w -+# -+# Build a static ASN.1 Object Identified (OID) registry -+# -+# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+# Written by David Howells (dhowells@redhat.com) -+# -+# This program is free software; you can redistribute it and/or -+# modify it under the terms of the GNU General Public Licence -+# as published by the Free Software Foundation; either version -+# 2 of the Licence, or (at your option) any later version. -+# -+ -+use strict; -+ -+my @names = (); -+my @oids = (); -+ -+if ($#ARGV != 1) { -+ print STDERR "Format: ", $0, " \n"; -+ exit(2); -+} -+ -+# -+# Open the file to read from -+# -+open IN_FILE, "<$ARGV[0]" || die; -+while () { -+ chomp; -+ if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { -+ push @names, $1; -+ push @oids, $2; -+ } -+} -+close IN_FILE || die; -+ -+# -+# Open the files to write into -+# -+open C_FILE, ">$ARGV[1]" or die; -+print C_FILE "/*\n"; -+print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; -+print C_FILE " */\n"; -+ -+# -+# Split the data up into separate lists and also determine the lengths of the -+# encoded data arrays. -+# -+my @indices = (); -+my @lengths = (); -+my $total_length = 0; -+ -+print "Compiling ", $#names + 1, " OIDs\n"; -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my $name = $names[$i]; -+ my $oid = $oids[$i]; -+ -+ my @components = split(/[.]/, $oid); -+ -+ # Determine the encoded length of this OID -+ my $size = $#components; -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # We will base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ $size += $tmp; -+ } -+ push @lengths, $size; -+ push @indices, $total_length; -+ $total_length += $size; -+} -+ -+# -+# Emit the look-up-by-OID index table -+# -+print C_FILE "\n"; -+if ($total_length <= 255) { -+ print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; -+} else { -+ print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; -+} -+for (my $i = 0; $i <= $#names; $i++) { -+ print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" -+} -+print C_FILE "\t[OID__NR] = ", $total_length, "\n"; -+print C_FILE "};\n"; -+ -+# -+# Encode the OIDs -+# -+my @encoded_oids = (); -+ -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = (); -+ -+ my @components = split(/[.]/, $oids[$i]); -+ -+ push @octets, $components[0] * 40 + $components[1]; -+ -+ for (my $loop = 2; $loop <= $#components; $loop++) { -+ my $c = $components[$loop]; -+ -+ # Base128 encode the number -+ my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); -+ $tmp = int($tmp / 7); -+ -+ for (; $tmp > 0; $tmp--) { -+ push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; -+ } -+ push @octets, $c & 0x7f; -+ } -+ -+ push @encoded_oids, \@octets; -+} -+ -+# -+# Create a hash value for each OID -+# -+my @hash_values = (); -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ -+ my $hash = $#octets; -+ foreach (@octets) { -+ $hash += $_ * 33; -+ } -+ -+ $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); -+ -+ push @hash_values, $hash & 0xff; -+} -+ -+# -+# Emit the OID data -+# -+print C_FILE "\n"; -+print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$i]}; -+ print C_FILE "\t"; -+ print C_FILE $_, ", " foreach (@octets); -+ print C_FILE "\t// ", $names[$i]; -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Build the search index table (ordered by length then hash then content) -+# -+my @index_table = ( 0 .. $#names ); -+ -+@index_table = sort { -+ my @octets_a = @{$encoded_oids[$a]}; -+ my @octets_b = @{$encoded_oids[$b]}; -+ -+ return $hash_values[$a] <=> $hash_values[$b] -+ if ($hash_values[$a] != $hash_values[$b]); -+ return $#octets_a <=> $#octets_b -+ if ($#octets_a != $#octets_b); -+ for (my $i = $#octets_a; $i >= 0; $i--) { -+ return $octets_a[$i] <=> $octets_b[$i] -+ if ($octets_a[$i] != $octets_b[$i]); -+ } -+ return 0; -+ -+} @index_table; -+ -+# -+# Emit the search index and hash value table -+# -+print C_FILE "\n"; -+print C_FILE "static const struct {\n"; -+print C_FILE "\tunsigned char hash;\n"; -+if ($#names <= 255) { -+ print C_FILE "\tenum OID oid : 8;\n"; -+} else { -+ print C_FILE "\tenum OID oid : 16;\n"; -+} -+print C_FILE "} oid_search_table[OID__NR] = {\n"; -+for (my $i = 0; $i <= $#names; $i++) { -+ my @octets = @{$encoded_oids[$index_table[$i]]}; -+ printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", -+ $i, -+ $hash_values[$index_table[$i]], -+ $names[$index_table[$i]]); -+ printf C_FILE "%02x", $_ foreach (@octets); -+ print C_FILE "\n"; -+} -+print C_FILE "};\n"; -+ -+# -+# Emit the OID debugging name table -+# -+#print C_FILE "\n"; -+#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; -+# -+#for (my $i = 0; $i <= $#names; $i++) { -+# print C_FILE "\t\"", $names[$i], "\",\n" -+#} -+#print C_FILE "\t\"Unknown-OID\"\n"; -+#print C_FILE "};\n"; -+ -+# -+# Polish off -+# -+close C_FILE or die; -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -new file mode 100644 -index 0000000..33cfd17 ---- /dev/null -+++ b/lib/oid_registry.c -@@ -0,0 +1,89 @@ -+/* ASN.1 Object identifier (OID) registry -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include "oid_registry_data.c" -+ -+/** -+ * look_up_OID - Find an OID registration for the specified data -+ * @data: Binary representation of the OID -+ * @datasize: Size of the binary representation -+ */ -+enum OID look_up_OID(const void *data, size_t datasize) -+{ -+ const unsigned char *octets = data; -+ enum OID oid; -+ unsigned char xhash; -+ unsigned i, j, k, hash; -+ size_t len; -+ -+ /* Hash the OID data */ -+ hash = datasize - 1; -+ -+ for (i = 0; i < datasize; i++) -+ hash += octets[i] * 33; -+ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; -+ hash &= 0xff; -+ -+ /* Binary search the OID registry. OIDs are stored in ascending order -+ * of hash value then ascending order of size and then in ascending -+ * order of reverse value. -+ */ -+ i = 0; -+ k = OID__NR; -+ while (i < k) { -+ j = (i + k) / 2; -+ -+ xhash = oid_search_table[j].hash; -+ if (xhash > hash) { -+ k = j; -+ continue; -+ } -+ if (xhash < hash) { -+ i = j + 1; -+ continue; -+ } -+ -+ oid = oid_search_table[j].oid; -+ len = oid_index[oid + 1] - oid_index[oid]; -+ if (len > datasize) { -+ k = j; -+ continue; -+ } -+ if (len < datasize) { -+ i = j + 1; -+ continue; -+ } -+ -+ /* Variation is most likely to be at the tail end of the -+ * OID, so do the comparison in reverse. -+ */ -+ while (len > 0) { -+ unsigned char a = oid_data[oid_index[oid] + --len]; -+ unsigned char b = octets[len]; -+ if (a > b) { -+ k = j; -+ goto next; -+ } -+ if (a < b) { -+ i = j + 1; -+ goto next; -+ } -+ } -+ return oid; -+ next: -+ ; -+ } -+ -+ return OID__NR; -+} -+EXPORT_SYMBOL_GPL(look_up_OID); --- -1.7.12.1 - - -From 3e1b30d7c67fd5419d4f6eb5d10b557dda4bc4fd Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:30:51 +0100 -Subject: [PATCH 13/37] X.509: Add utility functions to render OIDs as strings - -Add a pair of utility functions to render OIDs as strings. The first takes an -encoded OID and turns it into a "a.b.c.d" form string: - - int sprint_oid(const void *data, size_t datasize, - char *buffer, size_t bufsize); - -The second takes an OID enum index and calls the first on the data held -therein: - - int sprint_OID(enum OID oid, char *buffer, size_t bufsize); - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - include/linux/oid_registry.h | 2 ++ - lib/oid_registry.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 83 insertions(+) - -diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h -index 5928546..6926db7 100644 ---- a/include/linux/oid_registry.h -+++ b/include/linux/oid_registry.h -@@ -86,5 +86,7 @@ enum OID { - }; - - extern enum OID look_up_OID(const void *data, size_t datasize); -+extern int sprint_oid(const void *, size_t, char *, size_t); -+extern int sprint_OID(enum OID, char *, size_t); - - #endif /* _LINUX_OID_REGISTRY_H */ -diff --git a/lib/oid_registry.c b/lib/oid_registry.c -index 33cfd17..d8de11f 100644 ---- a/lib/oid_registry.c -+++ b/lib/oid_registry.c -@@ -11,6 +11,9 @@ - - #include - #include -+#include -+#include -+#include - #include "oid_registry_data.c" - - /** -@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize) - return OID__NR; - } - EXPORT_SYMBOL_GPL(look_up_OID); -+ -+/* -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @data: The encoded OID to print -+ * @datasize: The size of the encoded OID -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -EBADMSG is returned if the data could not be intepreted -+ * and -ENOBUFS if the buffer was too small. -+ */ -+int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) -+{ -+ const unsigned char *v = data, *end = v + datasize; -+ unsigned long num; -+ unsigned char n; -+ size_t ret; -+ int count; -+ -+ if (v >= end) -+ return -EBADMSG; -+ -+ n = *v++; -+ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ -+ while (v < end) { -+ num = 0; -+ n = *v++; -+ if (!(n & 0x80)) { -+ num = n; -+ } else { -+ num = n & 0x7f; -+ do { -+ if (v >= end) -+ return -EBADMSG; -+ n = *v++; -+ num <<= 7; -+ num |= n & 0x7f; -+ } while (n & 0x80); -+ } -+ ret += count = snprintf(buffer, bufsize, ".%lu", num); -+ buffer += count; -+ bufsize -= count; -+ if (bufsize == 0) -+ return -ENOBUFS; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_oid); -+ -+/** -+ * sprint_OID - Print an Object Identifier into a buffer -+ * @oid: The OID to print -+ * @buffer: The buffer to render into -+ * @bufsize: The size of the buffer -+ * -+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of -+ * bytes is returned. -+ */ -+int sprint_OID(enum OID oid, char *buffer, size_t bufsize) -+{ -+ int ret; -+ -+ BUG_ON(oid >= OID__NR); -+ -+ ret = sprint_oid(oid_data + oid_index[oid], -+ oid_index[oid + 1] - oid_index[oid], -+ buffer, bufsize); -+ BUG_ON(ret == -EBADMSG); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(sprint_OID); --- -1.7.12.1 - - -From 978cd19071f71ae6a0e622bb2521f88ea633a326 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 21 Sep 2012 23:31:13 +0100 -Subject: [PATCH 14/37] X.509: Add simple ASN.1 grammar compiler - -Add a simple ASN.1 grammar compiler. This produces a bytecode output that can -be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it -is trying to parse. - -Action functions can be specified in the grammar by interpolating: - - ({ foo }) - -after a type, for example: - - SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - subjectPublicKey BIT STRING ({ do_key_data }) - } - -The decoder is expected to call these after matching this type and parsing the -contents if it is a constructed type. - -The grammar compiler does not currently support the SET type (though it does -support SET OF) as I can't see a good way of tracking which members have been -encountered yet without using up extra stack space. - -Currently, the grammar compiler will fail if more than 256 bytes of bytecode -would be produced or more than 256 actions have been specified as it uses -8-bit jump values and action indices to keep space usage down. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - include/linux/asn1.h | 67 ++ - include/linux/asn1_ber_bytecode.h | 87 +++ - init/Kconfig | 8 + - scripts/.gitignore | 1 + - scripts/Makefile | 2 + - scripts/Makefile.build | 11 + - scripts/asn1_compiler.c | 1545 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 1721 insertions(+) - create mode 100644 include/linux/asn1.h - create mode 100644 include/linux/asn1_ber_bytecode.h - create mode 100644 scripts/asn1_compiler.c - -diff --git a/include/linux/asn1.h b/include/linux/asn1.h -new file mode 100644 -index 0000000..5c3f4e4 ---- /dev/null -+++ b/include/linux/asn1.h -@@ -0,0 +1,67 @@ -+/* ASN.1 BER/DER/CER encoding definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_H -+#define _LINUX_ASN1_H -+ -+/* Class */ -+enum asn1_class { -+ ASN1_UNIV = 0, /* Universal */ -+ ASN1_APPL = 1, /* Application */ -+ ASN1_CONT = 2, /* Context */ -+ ASN1_PRIV = 3 /* Private */ -+}; -+#define ASN1_CLASS_BITS 0xc0 -+ -+ -+enum asn1_method { -+ ASN1_PRIM = 0, /* Primitive */ -+ ASN1_CONS = 1 /* Constructed */ -+}; -+#define ASN1_CONS_BIT 0x20 -+ -+/* Tag */ -+enum asn1_tag { -+ ASN1_EOC = 0, /* End Of Contents or N/A */ -+ ASN1_BOOL = 1, /* Boolean */ -+ ASN1_INT = 2, /* Integer */ -+ ASN1_BTS = 3, /* Bit String */ -+ ASN1_OTS = 4, /* Octet String */ -+ ASN1_NULL = 5, /* Null */ -+ ASN1_OID = 6, /* Object Identifier */ -+ ASN1_ODE = 7, /* Object Description */ -+ ASN1_EXT = 8, /* External */ -+ ASN1_REAL = 9, /* Real float */ -+ ASN1_ENUM = 10, /* Enumerated */ -+ ASN1_EPDV = 11, /* Embedded PDV */ -+ ASN1_UTF8STR = 12, /* UTF8 String */ -+ ASN1_RELOID = 13, /* Relative OID */ -+ /* 14 - Reserved */ -+ /* 15 - Reserved */ -+ ASN1_SEQ = 16, /* Sequence and Sequence of */ -+ ASN1_SET = 17, /* Set and Set of */ -+ ASN1_NUMSTR = 18, /* Numerical String */ -+ ASN1_PRNSTR = 19, /* Printable String */ -+ ASN1_TEXSTR = 20, /* T61 String / Teletext String */ -+ ASN1_VIDSTR = 21, /* Videotex String */ -+ ASN1_IA5STR = 22, /* IA5 String */ -+ ASN1_UNITIM = 23, /* Universal Time */ -+ ASN1_GENTIM = 24, /* General Time */ -+ ASN1_GRASTR = 25, /* Graphic String */ -+ ASN1_VISSTR = 26, /* Visible String */ -+ ASN1_GENSTR = 27, /* General String */ -+ ASN1_UNISTR = 28, /* Universal String */ -+ ASN1_CHRSTR = 29, /* Character String */ -+ ASN1_BMPSTR = 30, /* BMP String */ -+ ASN1_LONG_TAG = 31 /* Long form tag */ -+}; -+ -+#endif /* _LINUX_ASN1_H */ -diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h -new file mode 100644 -index 0000000..945d44a ---- /dev/null -+++ b/include/linux/asn1_ber_bytecode.h -@@ -0,0 +1,87 @@ -+/* ASN.1 BER/DER/CER parsing state machine internal definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_BER_BYTECODE_H -+#define _LINUX_ASN1_BER_BYTECODE_H -+ -+#ifdef __KERNEL__ -+#include -+#endif -+#include -+ -+typedef int (*asn1_action_t)(void *context, -+ size_t hdrlen, /* In case of ANY type */ -+ unsigned char tag, /* In case of ANY type */ -+ const void *value, size_t vlen); -+ -+struct asn1_decoder { -+ const unsigned char *machine; -+ size_t machlen; -+ const asn1_action_t *actions; -+}; -+ -+enum asn1_opcode { -+ /* The tag-matching ops come first and the odd-numbered slots -+ * are for OR_SKIP ops. -+ */ -+#define ASN1_OP_MATCH__SKIP 0x01 -+#define ASN1_OP_MATCH__ACT 0x02 -+#define ASN1_OP_MATCH__JUMP 0x04 -+#define ASN1_OP_MATCH__ANY 0x08 -+#define ASN1_OP_MATCH__COND 0x10 -+ -+ ASN1_OP_MATCH = 0x00, -+ ASN1_OP_MATCH_OR_SKIP = 0x01, -+ ASN1_OP_MATCH_ACT = 0x02, -+ ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, -+ ASN1_OP_MATCH_JUMP = 0x04, -+ ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, -+ ASN1_OP_MATCH_ANY = 0x08, -+ ASN1_OP_MATCH_ANY_ACT = 0x0a, -+ /* Everything before here matches unconditionally */ -+ -+ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, -+ ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, -+ ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, -+ ASN1_OP_COND_MATCH_ANY = 0x18, -+ ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, -+ -+ /* Everything before here will want a tag from the data */ -+#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT -+ -+ /* These are here to help fill up space */ -+ ASN1_OP_COND_FAIL = 0x1b, -+ ASN1_OP_COMPLETE = 0x1c, -+ ASN1_OP_ACT = 0x1d, -+ ASN1_OP_RETURN = 0x1e, -+ -+ /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ -+ ASN1_OP_END_SEQ = 0x20, -+ ASN1_OP_END_SET = 0x21, -+ ASN1_OP_END_SEQ_OF = 0x22, -+ ASN1_OP_END_SET_OF = 0x23, -+ ASN1_OP_END_SEQ_ACT = 0x24, -+ ASN1_OP_END_SET_ACT = 0x25, -+ ASN1_OP_END_SEQ_OF_ACT = 0x26, -+ ASN1_OP_END_SET_OF_ACT = 0x27, -+#define ASN1_OP_END__SET 0x01 -+#define ASN1_OP_END__OF 0x02 -+#define ASN1_OP_END__ACT 0x04 -+ -+ ASN1_OP__NR -+}; -+ -+#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) -+#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) -+#define _jump_target(N) (N) -+#define _action(N) (N) -+ -+#endif /* _LINUX_ASN1_BER_BYTECODE_H */ -diff --git a/init/Kconfig b/init/Kconfig -index 7452e19..fa8ccad 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1626,4 +1626,12 @@ config PADATA - depends on SMP - bool - -+config ASN1 -+ tristate -+ help -+ Build a simple ASN.1 grammar compiler that produces a bytecode output -+ that can be interpreted by the ASN.1 stream decoder and used to -+ inform it as to what tags are to be expected in a stream and what -+ functions to call on what tags. -+ - source "kernel/Kconfig.locks" -diff --git a/scripts/.gitignore b/scripts/.gitignore -index 65f362d..fb070fa 100644 ---- a/scripts/.gitignore -+++ b/scripts/.gitignore -@@ -10,3 +10,4 @@ ihex2fw - recordmcount - docproc - sortextable -+asn1_compiler -diff --git a/scripts/Makefile b/scripts/Makefile -index a55b006..01e7adb 100644 ---- a/scripts/Makefile -+++ b/scripts/Makefile -@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash - hostprogs-$(CONFIG_IKCONFIG) += bin2c - hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount - hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable -+hostprogs-$(CONFIG_ASN1) += asn1_compiler - - HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include -+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include - - always := $(hostprogs-y) $(hostprogs-m) - -diff --git a/scripts/Makefile.build b/scripts/Makefile.build -index ff1720d..0e801c3 100644 ---- a/scripts/Makefile.build -+++ b/scripts/Makefile.build -@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ - $(obj)/%.lds: $(src)/%.lds.S FORCE - $(call if_changed_dep,cpp_lds_S) - -+# ASN.1 grammar -+# --------------------------------------------------------------------------- -+quiet_cmd_asn1_compiler = ASN.1 $@ -+ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ -+ $(subst .h,.c,$@) $(subst .c,.h,$@) -+ -+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h -+ -+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler -+ $(call cmd,asn1_compiler) -+ - # Build the compiled-in targets - # --------------------------------------------------------------------------- - -diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c -new file mode 100644 -index 0000000..db0e5cd ---- /dev/null -+++ b/scripts/asn1_compiler.c -@@ -0,0 +1,1545 @@ -+/* Simplified ASN.1 notation parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum token_type { -+ DIRECTIVE_ABSENT, -+ DIRECTIVE_ALL, -+ DIRECTIVE_ANY, -+ DIRECTIVE_APPLICATION, -+ DIRECTIVE_AUTOMATIC, -+ DIRECTIVE_BEGIN, -+ DIRECTIVE_BIT, -+ DIRECTIVE_BMPString, -+ DIRECTIVE_BOOLEAN, -+ DIRECTIVE_BY, -+ DIRECTIVE_CHARACTER, -+ DIRECTIVE_CHOICE, -+ DIRECTIVE_CLASS, -+ DIRECTIVE_COMPONENT, -+ DIRECTIVE_COMPONENTS, -+ DIRECTIVE_CONSTRAINED, -+ DIRECTIVE_CONTAINING, -+ DIRECTIVE_DEFAULT, -+ DIRECTIVE_DEFINED, -+ DIRECTIVE_DEFINITIONS, -+ DIRECTIVE_EMBEDDED, -+ DIRECTIVE_ENCODED, -+ DIRECTIVE_ENCODING_CONTROL, -+ DIRECTIVE_END, -+ DIRECTIVE_ENUMERATED, -+ DIRECTIVE_EXCEPT, -+ DIRECTIVE_EXPLICIT, -+ DIRECTIVE_EXPORTS, -+ DIRECTIVE_EXTENSIBILITY, -+ DIRECTIVE_EXTERNAL, -+ DIRECTIVE_FALSE, -+ DIRECTIVE_FROM, -+ DIRECTIVE_GeneralString, -+ DIRECTIVE_GeneralizedTime, -+ DIRECTIVE_GraphicString, -+ DIRECTIVE_IA5String, -+ DIRECTIVE_IDENTIFIER, -+ DIRECTIVE_IMPLICIT, -+ DIRECTIVE_IMPLIED, -+ DIRECTIVE_IMPORTS, -+ DIRECTIVE_INCLUDES, -+ DIRECTIVE_INSTANCE, -+ DIRECTIVE_INSTRUCTIONS, -+ DIRECTIVE_INTEGER, -+ DIRECTIVE_INTERSECTION, -+ DIRECTIVE_ISO646String, -+ DIRECTIVE_MAX, -+ DIRECTIVE_MIN, -+ DIRECTIVE_MINUS_INFINITY, -+ DIRECTIVE_NULL, -+ DIRECTIVE_NumericString, -+ DIRECTIVE_OBJECT, -+ DIRECTIVE_OCTET, -+ DIRECTIVE_OF, -+ DIRECTIVE_OPTIONAL, -+ DIRECTIVE_ObjectDescriptor, -+ DIRECTIVE_PATTERN, -+ DIRECTIVE_PDV, -+ DIRECTIVE_PLUS_INFINITY, -+ DIRECTIVE_PRESENT, -+ DIRECTIVE_PRIVATE, -+ DIRECTIVE_PrintableString, -+ DIRECTIVE_REAL, -+ DIRECTIVE_RELATIVE_OID, -+ DIRECTIVE_SEQUENCE, -+ DIRECTIVE_SET, -+ DIRECTIVE_SIZE, -+ DIRECTIVE_STRING, -+ DIRECTIVE_SYNTAX, -+ DIRECTIVE_T61String, -+ DIRECTIVE_TAGS, -+ DIRECTIVE_TRUE, -+ DIRECTIVE_TeletexString, -+ DIRECTIVE_UNION, -+ DIRECTIVE_UNIQUE, -+ DIRECTIVE_UNIVERSAL, -+ DIRECTIVE_UTCTime, -+ DIRECTIVE_UTF8String, -+ DIRECTIVE_UniversalString, -+ DIRECTIVE_VideotexString, -+ DIRECTIVE_VisibleString, -+ DIRECTIVE_WITH, -+ NR__DIRECTIVES, -+ TOKEN_ASSIGNMENT = NR__DIRECTIVES, -+ TOKEN_OPEN_CURLY, -+ TOKEN_CLOSE_CURLY, -+ TOKEN_OPEN_SQUARE, -+ TOKEN_CLOSE_SQUARE, -+ TOKEN_OPEN_ACTION, -+ TOKEN_CLOSE_ACTION, -+ TOKEN_COMMA, -+ TOKEN_NUMBER, -+ TOKEN_TYPE_NAME, -+ TOKEN_ELEMENT_NAME, -+ NR__TOKENS -+}; -+ -+static const unsigned char token_to_tag[NR__TOKENS] = { -+ /* EOC goes first */ -+ [DIRECTIVE_BOOLEAN] = ASN1_BOOL, -+ [DIRECTIVE_INTEGER] = ASN1_INT, -+ [DIRECTIVE_BIT] = ASN1_BTS, -+ [DIRECTIVE_OCTET] = ASN1_OTS, -+ [DIRECTIVE_NULL] = ASN1_NULL, -+ [DIRECTIVE_OBJECT] = ASN1_OID, -+ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, -+ [DIRECTIVE_EXTERNAL] = ASN1_EXT, -+ [DIRECTIVE_REAL] = ASN1_REAL, -+ [DIRECTIVE_ENUMERATED] = ASN1_ENUM, -+ [DIRECTIVE_EMBEDDED] = 0, -+ [DIRECTIVE_UTF8String] = ASN1_UTF8STR, -+ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, -+ /* 14 */ -+ /* 15 */ -+ [DIRECTIVE_SEQUENCE] = ASN1_SEQ, -+ [DIRECTIVE_SET] = ASN1_SET, -+ [DIRECTIVE_NumericString] = ASN1_NUMSTR, -+ [DIRECTIVE_PrintableString] = ASN1_PRNSTR, -+ [DIRECTIVE_T61String] = ASN1_TEXSTR, -+ [DIRECTIVE_TeletexString] = ASN1_TEXSTR, -+ [DIRECTIVE_VideotexString] = ASN1_VIDSTR, -+ [DIRECTIVE_IA5String] = ASN1_IA5STR, -+ [DIRECTIVE_UTCTime] = ASN1_UNITIM, -+ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, -+ [DIRECTIVE_GraphicString] = ASN1_GRASTR, -+ [DIRECTIVE_VisibleString] = ASN1_VISSTR, -+ [DIRECTIVE_GeneralString] = ASN1_GENSTR, -+ [DIRECTIVE_UniversalString] = ASN1_UNITIM, -+ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, -+ [DIRECTIVE_BMPString] = ASN1_BMPSTR, -+}; -+ -+static const char asn1_classes[4][5] = { -+ [ASN1_UNIV] = "UNIV", -+ [ASN1_APPL] = "APPL", -+ [ASN1_CONT] = "CONT", -+ [ASN1_PRIV] = "PRIV" -+}; -+ -+static const char asn1_methods[2][5] = { -+ [ASN1_UNIV] = "PRIM", -+ [ASN1_APPL] = "CONS" -+}; -+ -+static const char *const asn1_universal_tags[32] = { -+ "EOC", -+ "BOOL", -+ "INT", -+ "BTS", -+ "OTS", -+ "NULL", -+ "OID", -+ "ODE", -+ "EXT", -+ "REAL", -+ "ENUM", -+ "EPDV", -+ "UTF8STR", -+ "RELOID", -+ NULL, /* 14 */ -+ NULL, /* 15 */ -+ "SEQ", -+ "SET", -+ "NUMSTR", -+ "PRNSTR", -+ "TEXSTR", -+ "VIDSTR", -+ "IA5STR", -+ "UNITIM", -+ "GENTIM", -+ "GRASTR", -+ "VISSTR", -+ "GENSTR", -+ "UNISTR", -+ "CHRSTR", -+ "BMPSTR", -+ NULL /* 31 */ -+}; -+ -+static const char *filename; -+static const char *grammar_name; -+static const char *outputname; -+static const char *headername; -+ -+static const char *const directives[NR__DIRECTIVES] = { -+#define _(X) [DIRECTIVE_##X] = #X -+ _(ABSENT), -+ _(ALL), -+ _(ANY), -+ _(APPLICATION), -+ _(AUTOMATIC), -+ _(BEGIN), -+ _(BIT), -+ _(BMPString), -+ _(BOOLEAN), -+ _(BY), -+ _(CHARACTER), -+ _(CHOICE), -+ _(CLASS), -+ _(COMPONENT), -+ _(COMPONENTS), -+ _(CONSTRAINED), -+ _(CONTAINING), -+ _(DEFAULT), -+ _(DEFINED), -+ _(DEFINITIONS), -+ _(EMBEDDED), -+ _(ENCODED), -+ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", -+ _(END), -+ _(ENUMERATED), -+ _(EXCEPT), -+ _(EXPLICIT), -+ _(EXPORTS), -+ _(EXTENSIBILITY), -+ _(EXTERNAL), -+ _(FALSE), -+ _(FROM), -+ _(GeneralString), -+ _(GeneralizedTime), -+ _(GraphicString), -+ _(IA5String), -+ _(IDENTIFIER), -+ _(IMPLICIT), -+ _(IMPLIED), -+ _(IMPORTS), -+ _(INCLUDES), -+ _(INSTANCE), -+ _(INSTRUCTIONS), -+ _(INTEGER), -+ _(INTERSECTION), -+ _(ISO646String), -+ _(MAX), -+ _(MIN), -+ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", -+ [DIRECTIVE_NULL] = "NULL", -+ _(NumericString), -+ _(OBJECT), -+ _(OCTET), -+ _(OF), -+ _(OPTIONAL), -+ _(ObjectDescriptor), -+ _(PATTERN), -+ _(PDV), -+ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", -+ _(PRESENT), -+ _(PRIVATE), -+ _(PrintableString), -+ _(REAL), -+ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", -+ _(SEQUENCE), -+ _(SET), -+ _(SIZE), -+ _(STRING), -+ _(SYNTAX), -+ _(T61String), -+ _(TAGS), -+ _(TRUE), -+ _(TeletexString), -+ _(UNION), -+ _(UNIQUE), -+ _(UNIVERSAL), -+ _(UTCTime), -+ _(UTF8String), -+ _(UniversalString), -+ _(VideotexString), -+ _(VisibleString), -+ _(WITH) -+}; -+ -+struct action { -+ struct action *next; -+ unsigned char index; -+ char name[]; -+}; -+ -+static struct action *action_list; -+static unsigned nr_actions; -+ -+struct token { -+ unsigned short line; -+ enum token_type token_type : 8; -+ unsigned char size; -+ struct action *action; -+ const char *value; -+ struct type *type; -+}; -+ -+static struct token *token_list; -+static unsigned nr_tokens; -+ -+static int directive_compare(const void *_key, const void *_pdir) -+{ -+ const struct token *token = _key; -+ const char *const *pdir = _pdir, *dir = *pdir; -+ size_t dlen, clen; -+ int val; -+ -+ dlen = strlen(dir); -+ clen = (dlen < token->size) ? dlen : token->size; -+ -+ //printf("cmp(%*.*s,%s) = ", -+ // (int)token->size, (int)token->size, token->value, -+ // dir); -+ -+ val = memcmp(token->value, dir, clen); -+ if (val != 0) { -+ //printf("%d [cmp]\n", val); -+ return val; -+ } -+ -+ if (dlen == token->size) { -+ //printf("0\n"); -+ return 0; -+ } -+ //printf("%d\n", (int)dlen - (int)token->size); -+ return dlen - token->size; /* shorter -> negative */ -+} -+ -+/* -+ * Tokenise an ASN.1 grammar -+ */ -+static void tokenise(char *buffer, char *end) -+{ -+ struct token *tokens; -+ char *line, *nl, *p, *q; -+ unsigned tix, lineno; -+ -+ /* Assume we're going to have half as many tokens as we have -+ * characters -+ */ -+ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); -+ if (!tokens) { -+ perror(NULL); -+ exit(1); -+ } -+ tix = 0; -+ -+ lineno = 0; -+ while (buffer < end) { -+ /* First of all, break out a line */ -+ lineno++; -+ line = buffer; -+ nl = memchr(line, '\n', end - buffer); -+ if (!nl) { -+ buffer = nl = end; -+ } else { -+ buffer = nl + 1; -+ *nl = '\0'; -+ } -+ -+ /* Remove "--" comments */ -+ p = line; -+ next_comment: -+ while ((p = memchr(p, '-', nl - p))) { -+ if (p[1] == '-') { -+ /* Found a comment; see if there's a terminator */ -+ q = p + 2; -+ while ((q = memchr(q, '-', nl - q))) { -+ if (q[1] == '-') { -+ /* There is - excise the comment */ -+ q += 2; -+ memmove(p, q, nl - q); -+ goto next_comment; -+ } -+ q++; -+ } -+ *p = '\0'; -+ nl = p; -+ break; -+ } else { -+ p++; -+ } -+ } -+ -+ p = line; -+ while (p < nl) { -+ /* Skip white space */ -+ while (p < nl && isspace(*p)) -+ *(p++) = 0; -+ if (p >= nl) -+ break; -+ -+ tokens[tix].line = lineno; -+ tokens[tix].value = p; -+ -+ /* Handle string tokens */ -+ if (isalpha(*p)) { -+ const char **dir; -+ -+ /* Can be a directive, type name or element -+ * name. Find the end of the name. -+ */ -+ q = p + 1; -+ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ -+ /* If it begins with a lowercase letter then -+ * it's an element name -+ */ -+ if (islower(tokens[tix].value[0])) { -+ tokens[tix++].token_type = TOKEN_ELEMENT_NAME; -+ continue; -+ } -+ -+ /* Otherwise we need to search the directive -+ * table -+ */ -+ dir = bsearch(&tokens[tix], directives, -+ sizeof(directives) / sizeof(directives[1]), -+ sizeof(directives[1]), -+ directive_compare); -+ if (dir) { -+ tokens[tix++].token_type = dir - directives; -+ continue; -+ } -+ -+ tokens[tix++].token_type = TOKEN_TYPE_NAME; -+ continue; -+ } -+ -+ /* Handle numbers */ -+ if (isdigit(*p)) { -+ /* Find the end of the number */ -+ q = p + 1; -+ while (q < nl && (isdigit(*q))) -+ q++; -+ tokens[tix].size = q - p; -+ p = q; -+ tokens[tix++].token_type = TOKEN_NUMBER; -+ continue; -+ } -+ -+ if (nl - p >= 3) { -+ if (memcmp(p, "::=", 3) == 0) { -+ p += 3; -+ tokens[tix].size = 3; -+ tokens[tix++].token_type = TOKEN_ASSIGNMENT; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 2) { -+ if (memcmp(p, "({", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_OPEN_ACTION; -+ continue; -+ } -+ if (memcmp(p, "})", 2) == 0) { -+ p += 2; -+ tokens[tix].size = 2; -+ tokens[tix++].token_type = TOKEN_CLOSE_ACTION; -+ continue; -+ } -+ } -+ -+ if (nl - p >= 1) { -+ tokens[tix].size = 1; -+ switch (*p) { -+ case '{': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_CURLY; -+ continue; -+ case '}': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_CURLY; -+ continue; -+ case '[': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_OPEN_SQUARE; -+ continue; -+ case ']': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; -+ continue; -+ case ',': -+ p += 1; -+ tokens[tix++].token_type = TOKEN_COMMA; -+ continue; -+ default: -+ break; -+ } -+ } -+ -+ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", -+ filename, lineno, *p); -+ exit(1); -+ } -+ } -+ -+ nr_tokens = tix; -+ printf("Extracted %u tokens\n", nr_tokens); -+ -+#if 0 -+ { -+ int n; -+ for (n = 0; n < nr_tokens; n++) -+ printf("Token %3u: '%*.*s'\n", -+ n, -+ (int)token_list[n].size, (int)token_list[n].size, -+ token_list[n].value); -+ } -+#endif -+} -+ -+static void build_type_list(void); -+static void parse(void); -+static void render(FILE *out, FILE *hdr); -+ -+/* -+ * -+ */ -+int main(int argc, char **argv) -+{ -+ struct stat st; -+ ssize_t readlen; -+ FILE *out, *hdr; -+ char *buffer, *p; -+ int fd; -+ -+ if (argc != 4) { -+ fprintf(stderr, "Format: %s \n", -+ argv[0]); -+ exit(2); -+ } -+ -+ filename = argv[1]; -+ outputname = argv[2]; -+ headername = argv[3]; -+ -+ fd = open(filename, O_RDONLY); -+ if (fd < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (fstat(fd, &st) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (!(buffer = malloc(st.st_size + 1))) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ if ((readlen = read(fd, buffer, st.st_size)) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (close(fd) < 0) { -+ perror(filename); -+ exit(1); -+ } -+ -+ if (readlen != st.st_size) { -+ fprintf(stderr, "%s: Short read\n", filename); -+ exit(1); -+ } -+ -+ p = strrchr(argv[1], '/'); -+ p = p ? p + 1 : argv[1]; -+ grammar_name = strdup(p); -+ if (!p) { -+ perror(NULL); -+ exit(1); -+ } -+ p = strchr(grammar_name, '.'); -+ if (p) -+ *p = '\0'; -+ -+ buffer[readlen] = 0; -+ tokenise(buffer, buffer + readlen); -+ build_type_list(); -+ parse(); -+ -+ out = fopen(outputname, "w"); -+ if (!out) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ hdr = fopen(headername, "w"); -+ if (!out) { -+ perror(headername); -+ exit(1); -+ } -+ -+ render(out, hdr); -+ -+ if (fclose(out) < 0) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ if (fclose(hdr) < 0) { -+ perror(headername); -+ exit(1); -+ } -+ -+ return 0; -+} -+ -+enum compound { -+ NOT_COMPOUND, -+ SET, -+ SET_OF, -+ SEQUENCE, -+ SEQUENCE_OF, -+ CHOICE, -+ ANY, -+ TYPE_REF, -+ TAG_OVERRIDE -+}; -+ -+struct element { -+ struct type *type_def; -+ struct token *name; -+ struct token *type; -+ struct action *action; -+ struct element *children; -+ struct element *next; -+ struct element *render_next; -+ struct element *list_next; -+ uint8_t n_elements; -+ enum compound compound : 8; -+ enum asn1_class class : 8; -+ enum asn1_method method : 8; -+ uint8_t tag; -+ unsigned entry_index; -+ unsigned flags; -+#define ELEMENT_IMPLICIT 0x0001 -+#define ELEMENT_EXPLICIT 0x0002 -+#define ELEMENT_MARKED 0x0004 -+#define ELEMENT_RENDERED 0x0008 -+#define ELEMENT_SKIPPABLE 0x0010 -+#define ELEMENT_CONDITIONAL 0x0020 -+}; -+ -+struct type { -+ struct token *name; -+ struct token *def; -+ struct element *element; -+ unsigned ref_count; -+ unsigned flags; -+#define TYPE_STOP_MARKER 0x0001 -+#define TYPE_BEGIN 0x0002 -+}; -+ -+static struct type *type_list; -+static struct type **type_index; -+static unsigned nr_types; -+ -+static int type_index_compare(const void *_a, const void *_b) -+{ -+ const struct type *const *a = _a, *const *b = _b; -+ -+ if ((*a)->name->size != (*b)->name->size) -+ return (*a)->name->size - (*b)->name->size; -+ else -+ return memcmp((*a)->name->value, (*b)->name->value, -+ (*a)->name->size); -+} -+ -+static int type_finder(const void *_key, const void *_ti) -+{ -+ const struct token *token = _key; -+ const struct type *const *ti = _ti; -+ const struct type *type = *ti; -+ -+ if (token->size != type->name->size) -+ return token->size - type->name->size; -+ else -+ return memcmp(token->value, type->name->value, -+ token->size); -+} -+ -+/* -+ * Build up a list of types and a sorted index to that list. -+ */ -+static void build_type_list(void) -+{ -+ struct type *types; -+ unsigned nr, t, n; -+ -+ nr = 0; -+ for (n = 0; n < nr_tokens - 1; n++) -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) -+ nr++; -+ -+ if (nr == 0) { -+ fprintf(stderr, "%s: No defined types\n", filename); -+ exit(1); -+ } -+ -+ nr_types = nr; -+ types = type_list = calloc(nr + 1, sizeof(type_list[0])); -+ if (!type_list) { -+ perror(NULL); -+ exit(1); -+ } -+ type_index = calloc(nr, sizeof(type_index[0])); -+ if (!type_index) { -+ perror(NULL); -+ exit(1); -+ } -+ -+ t = 0; -+ types[t].flags |= TYPE_BEGIN; -+ for (n = 0; n < nr_tokens - 1; n++) { -+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && -+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { -+ types[t].name = &token_list[n]; -+ type_index[t] = &types[t]; -+ t++; -+ } -+ } -+ types[t].name = &token_list[n + 1]; -+ types[t].flags |= TYPE_STOP_MARKER; -+ -+ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); -+ -+ printf("Extracted %u types\n", nr_types); -+#if 0 -+ for (n = 0; n < nr_types; n++) { -+ struct type *type = type_index[n]; -+ printf("- %*.*s\n", -+ (int)type->name->size, -+ (int)type->name->size, -+ type->name->value); -+ } -+#endif -+} -+ -+static struct element *parse_type(struct token **_cursor, struct token *stop, -+ struct token *name); -+ -+/* -+ * Parse the token stream -+ */ -+static void parse(void) -+{ -+ struct token *cursor; -+ struct type *type; -+ -+ /* Parse one type definition statement at a time */ -+ type = type_list; -+ do { -+ cursor = type->name; -+ -+ if (cursor[0].token_type != TOKEN_TYPE_NAME || -+ cursor[1].token_type != TOKEN_ASSIGNMENT) -+ abort(); -+ cursor += 2; -+ -+ type->element = parse_type(&cursor, type[1].name, NULL); -+ type->element->type_def = type; -+ -+ if (cursor != type[1].name) { -+ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ } while (type++, !(type->flags & TYPE_STOP_MARKER)); -+ -+ printf("Extracted %u actions\n", nr_actions); -+} -+ -+static struct element *element_list; -+ -+static struct element *alloc_elem(struct token *type) -+{ -+ struct element *e = calloc(1, sizeof(*e)); -+ if (!e) { -+ perror(NULL); -+ exit(1); -+ } -+ e->list_next = element_list; -+ element_list = e; -+ return e; -+} -+ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates); -+ -+/* -+ * Parse one type definition statement -+ */ -+static struct element *parse_type(struct token **_cursor, struct token *end, -+ struct token *name) -+{ -+ struct element *top, *element; -+ struct action *action, **ppaction; -+ struct token *cursor = *_cursor; -+ struct type **ref; -+ char *p; -+ int labelled = 0, implicit = 0; -+ -+ top = element = alloc_elem(cursor); -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ -+ /* Extract the tag value if one given */ -+ if (cursor->token_type == TOKEN_OPEN_SQUARE) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ switch (cursor->token_type) { -+ case DIRECTIVE_UNIVERSAL: -+ element->class = ASN1_UNIV; -+ cursor++; -+ break; -+ case DIRECTIVE_APPLICATION: -+ element->class = ASN1_APPL; -+ cursor++; -+ break; -+ case TOKEN_NUMBER: -+ element->class = ASN1_CONT; -+ break; -+ case DIRECTIVE_PRIVATE: -+ element->class = ASN1_PRIV; -+ cursor++; -+ break; -+ default: -+ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_NUMBER) { -+ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ element->tag &= ~0x1f; -+ element->tag |= strtoul(cursor->value, &p, 10); -+ if (p - cursor->value != cursor->size) -+ abort(); -+ cursor++; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_SQUARE) { -+ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ labelled = 1; -+ } -+ -+ /* Handle implicit and explicit markers */ -+ if (cursor->token_type == DIRECTIVE_IMPLICIT) { -+ element->flags |= ELEMENT_IMPLICIT; -+ implicit = 1; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { -+ element->flags |= ELEMENT_EXPLICIT; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ if (labelled) { -+ if (!implicit) -+ element->method |= ASN1_CONS; -+ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; -+ element->children = alloc_elem(cursor); -+ element = element->children; -+ element->class = ASN1_UNIV; -+ element->method = ASN1_PRIM; -+ element->tag = token_to_tag[cursor->token_type]; -+ element->name = name; -+ } -+ -+ /* Extract the type we're expecting here */ -+ element->type = cursor; -+ switch (cursor->token_type) { -+ case DIRECTIVE_ANY: -+ element->compound = ANY; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_NULL: -+ case DIRECTIVE_BOOLEAN: -+ case DIRECTIVE_ENUMERATED: -+ case DIRECTIVE_INTEGER: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_EXTERNAL: -+ element->method = ASN1_CONS; -+ -+ case DIRECTIVE_BMPString: -+ case DIRECTIVE_GeneralString: -+ case DIRECTIVE_GraphicString: -+ case DIRECTIVE_IA5String: -+ case DIRECTIVE_ISO646String: -+ case DIRECTIVE_NumericString: -+ case DIRECTIVE_PrintableString: -+ case DIRECTIVE_T61String: -+ case DIRECTIVE_TeletexString: -+ case DIRECTIVE_UniversalString: -+ case DIRECTIVE_UTF8String: -+ case DIRECTIVE_VideotexString: -+ case DIRECTIVE_VisibleString: -+ case DIRECTIVE_ObjectDescriptor: -+ case DIRECTIVE_GeneralizedTime: -+ case DIRECTIVE_UTCTime: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_BIT: -+ case DIRECTIVE_OCTET: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_STRING) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_OBJECT: -+ element->compound = NOT_COMPOUND; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != DIRECTIVE_IDENTIFIER) -+ goto parse_error; -+ cursor++; -+ break; -+ -+ case TOKEN_TYPE_NAME: -+ element->compound = TYPE_REF; -+ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), -+ type_finder); -+ if (!ref) { -+ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor->type = *ref; -+ (*ref)->ref_count++; -+ cursor++; -+ break; -+ -+ case DIRECTIVE_CHOICE: -+ element->compound = CHOICE; -+ cursor++; -+ element->children = parse_compound(&cursor, end, 1); -+ break; -+ -+ case DIRECTIVE_SEQUENCE: -+ element->compound = SEQUENCE; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SEQUENCE_OF; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 0); -+ } -+ break; -+ -+ case DIRECTIVE_SET: -+ element->compound = SET; -+ element->method = ASN1_CONS; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type == DIRECTIVE_OF) { -+ element->compound = SET_OF; -+ cursor++; -+ if (cursor >= end) -+ goto parse_error; -+ element->children = parse_type(&cursor, end, NULL); -+ } else { -+ element->children = parse_compound(&cursor, end, 1); -+ } -+ break; -+ -+ default: -+ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ /* Handle elements that are optional */ -+ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || -+ cursor->token_type == DIRECTIVE_DEFAULT) -+ ) { -+ cursor++; -+ top->flags |= ELEMENT_SKIPPABLE; -+ } -+ -+ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_ELEMENT_NAME) { -+ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ -+ action = malloc(sizeof(struct action) + cursor->size + 1); -+ if (!action) { -+ perror(NULL); -+ exit(1); -+ } -+ action->index = 0; -+ memcpy(action->name, cursor->value, cursor->size); -+ action->name[cursor->size] = 0; -+ -+ for (ppaction = &action_list; -+ *ppaction; -+ ppaction = &(*ppaction)->next -+ ) { -+ int cmp = strcmp(action->name, (*ppaction)->name); -+ if (cmp == 0) { -+ free(action); -+ action = *ppaction; -+ goto found; -+ } -+ if (cmp < 0) { -+ action->next = *ppaction; -+ *ppaction = action; -+ nr_actions++; -+ goto found; -+ } -+ } -+ action->next = NULL; -+ *ppaction = action; -+ nr_actions++; -+ found: -+ -+ element->action = action; -+ cursor->action = action; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_CLOSE_ACTION) { -+ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ } -+ -+ *_cursor = cursor; -+ return top; -+ -+parse_error: -+ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+/* -+ * Parse a compound type list -+ */ -+static struct element *parse_compound(struct token **_cursor, struct token *end, -+ int alternates) -+{ -+ struct element *children, **child_p = &children, *element; -+ struct token *cursor = *_cursor, *name; -+ -+ if (cursor->token_type != TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ -+ if (cursor->token_type == TOKEN_OPEN_CURLY) { -+ fprintf(stderr, "%s:%d: Empty compound\n", -+ filename, cursor->line); -+ exit(1); -+ } -+ -+ for (;;) { -+ name = NULL; -+ if (cursor->token_type == TOKEN_ELEMENT_NAME) { -+ name = cursor; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ element = parse_type(&cursor, end, name); -+ if (alternates) -+ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; -+ -+ *child_p = element; -+ child_p = &element->next; -+ -+ if (cursor >= end) -+ goto overrun_error; -+ if (cursor->token_type != TOKEN_COMMA) -+ break; -+ cursor++; -+ if (cursor >= end) -+ goto overrun_error; -+ } -+ -+ children->flags &= ~ELEMENT_CONDITIONAL; -+ -+ if (cursor->token_type != TOKEN_CLOSE_CURLY) { -+ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", -+ filename, cursor->line, -+ (int)cursor->size, (int)cursor->size, cursor->value); -+ exit(1); -+ } -+ cursor++; -+ -+ *_cursor = cursor; -+ return children; -+ -+overrun_error: -+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); -+ exit(1); -+} -+ -+static void render_element(FILE *out, struct element *e, struct element *tag); -+static void render_out_of_line_list(FILE *out); -+ -+static int nr_entries; -+static int render_depth = 1; -+static struct element *render_list, **render_list_p = &render_list; -+ -+__attribute__((format(printf, 2, 3))) -+static void render_opcode(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+ nr_entries++; -+} -+ -+__attribute__((format(printf, 2, 3))) -+static void render_more(FILE *out, const char *fmt, ...) -+{ -+ va_list va; -+ -+ if (out) { -+ va_start(va, fmt); -+ vfprintf(out, fmt, va); -+ va_end(va); -+ } -+} -+ -+/* -+ * Render the grammar into a state machine definition. -+ */ -+static void render(FILE *out, FILE *hdr) -+{ -+ struct element *e; -+ struct action *action; -+ struct type *root; -+ int index; -+ -+ fprintf(hdr, "/*\n"); -+ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(hdr, " *\n"); -+ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(hdr, " */\n"); -+ fprintf(hdr, "#include \n"); -+ fprintf(hdr, "\n"); -+ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); -+ if (ferror(hdr)) { -+ perror(headername); -+ exit(1); -+ } -+ -+ fprintf(out, "/*\n"); -+ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); -+ fprintf(out, " *\n"); -+ fprintf(out, " * ASN.1 parser for %s\n", grammar_name); -+ fprintf(out, " */\n"); -+ fprintf(out, "#include \n"); -+ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); -+ fprintf(out, "\n"); -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* Tabulate the action functions we might have to call */ -+ fprintf(hdr, "\n"); -+ index = 0; -+ for (action = action_list; action; action = action->next) { -+ action->index = index++; -+ fprintf(hdr, -+ "extern int %s(void *, size_t, unsigned char," -+ " const void *, size_t);\n", -+ action->name); -+ } -+ fprintf(hdr, "\n"); -+ -+ fprintf(out, "enum %s_actions {\n", grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\tACT_%s = %u,\n", -+ action->name, action->index); -+ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", -+ grammar_name, grammar_name); -+ for (action = action_list; action; action = action->next) -+ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); -+ fprintf(out, "};\n"); -+ -+ if (ferror(out)) { -+ perror(outputname); -+ exit(1); -+ } -+ -+ /* We do two passes - the first one calculates all the offsets */ -+ printf("Pass 1\n"); -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(NULL, root->element, NULL); -+ render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(NULL); -+ -+ for (e = element_list; e; e = e->list_next) -+ e->flags &= ~ELEMENT_RENDERED; -+ -+ /* And then we actually render */ -+ printf("Pass 2\n"); -+ fprintf(out, "\n"); -+ fprintf(out, "static const unsigned char %s_machine[] = {\n", -+ grammar_name); -+ -+ nr_entries = 0; -+ root = &type_list[0]; -+ render_element(out, root->element, NULL); -+ render_opcode(out, "ASN1_OP_COMPLETE,\n"); -+ render_out_of_line_list(out); -+ -+ fprintf(out, "};\n"); -+ -+ fprintf(out, "\n"); -+ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); -+ fprintf(out, "\t.machine = %s_machine,\n", grammar_name); -+ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); -+ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); -+ fprintf(out, "};\n"); -+} -+ -+/* -+ * Render the out-of-line elements -+ */ -+static void render_out_of_line_list(FILE *out) -+{ -+ struct element *e, *ce; -+ const char *act; -+ int entry; -+ -+ while ((e = render_list)) { -+ render_list = e->render_next; -+ if (!render_list) -+ render_list_p = &render_list; -+ -+ render_more(out, "\n"); -+ e->entry_index = entry = nr_entries; -+ render_depth++; -+ for (ce = e->children; ce; ce = ce->next) -+ render_element(out, ce, NULL); -+ render_depth--; -+ -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case SEQUENCE: -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ break; -+ case SEQUENCE_OF: -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ case SET: -+ render_opcode(out, "ASN1_OP_END_SET%s,\n", act); -+ break; -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ break; -+ } -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", -+ e->action->name); -+ render_opcode(out, "ASN1_OP_RETURN,\n"); -+ } -+} -+ -+/* -+ * Render an element. -+ */ -+static void render_element(FILE *out, struct element *e, struct element *tag) -+{ -+ struct element *ec; -+ const char *cond, *act; -+ int entry, skippable = 0, outofline = 0; -+ -+ if (e->flags & ELEMENT_SKIPPABLE || -+ (tag && tag->flags & ELEMENT_SKIPPABLE)) -+ skippable = 1; -+ -+ if ((e->type_def && e->type_def->ref_count > 1) || -+ skippable) -+ outofline = 1; -+ -+ if (e->type_def && out) { -+ render_more(out, "\t// %*.*s\n", -+ (int)e->type_def->name->size, (int)e->type_def->name->size, -+ e->type_def->name->value); -+ } -+ -+ /* Render the operation */ -+ cond = (e->flags & ELEMENT_CONDITIONAL || -+ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; -+ act = e->action ? "_ACT" : ""; -+ switch (e->compound) { -+ case ANY: -+ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ goto dont_render_tag; -+ -+ case TAG_OVERRIDE: -+ render_element(out, e->children, e); -+ return; -+ -+ case SEQUENCE: -+ case SEQUENCE_OF: -+ case SET: -+ case SET_OF: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, -+ outofline ? "_JUMP" : "", -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ -+ case CHOICE: -+ goto dont_render_tag; -+ -+ case TYPE_REF: -+ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) -+ goto dont_render_tag; -+ default: -+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,", -+ cond, act, -+ skippable ? "_OR_SKIP" : ""); -+ break; -+ } -+ -+ if (e->name) -+ render_more(out, "\t\t// %*.*s", -+ (int)e->name->size, (int)e->name->size, -+ e->name->value); -+ render_more(out, "\n"); -+ -+ /* Render the tag */ -+ if (!tag) -+ tag = e; -+ if (tag->class == ASN1_UNIV && -+ tag->tag != 14 && -+ tag->tag != 15 && -+ tag->tag != 31) -+ render_opcode(out, "_tag(%s, %s, %s),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ asn1_universal_tags[tag->tag]); -+ else -+ render_opcode(out, "_tagn(%s, %s, %2u),\n", -+ asn1_classes[tag->class], -+ asn1_methods[tag->method | e->method], -+ tag->tag); -+ tag = NULL; -+dont_render_tag: -+ -+ /* Deal with compound types */ -+ switch (e->compound) { -+ case TYPE_REF: -+ render_element(out, e->type->type->element, tag); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ case SEQUENCE: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ render_depth++; -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ render_depth--; -+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); -+ } -+ break; -+ -+ case SEQUENCE_OF: -+ case SET_OF: -+ if (outofline) { -+ /* Render out-of-line for multiple use or -+ * skipability */ -+ render_opcode(out, "_jump_target(%u),", e->entry_index); -+ if (e->type_def && e->type_def->name) -+ render_more(out, "\t\t// --> %*.*s", -+ (int)e->type_def->name->size, -+ (int)e->type_def->name->size, -+ e->type_def->name->value); -+ render_more(out, "\n"); -+ if (!(e->flags & ELEMENT_RENDERED)) { -+ e->flags |= ELEMENT_RENDERED; -+ *render_list_p = e; -+ render_list_p = &e->render_next; -+ } -+ return; -+ } else { -+ /* Render inline for single use */ -+ entry = nr_entries; -+ render_depth++; -+ render_element(out, e->children, NULL); -+ render_depth--; -+ if (e->compound == SEQUENCE_OF) -+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); -+ else -+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); -+ render_opcode(out, "_jump_target(%u),\n", entry); -+ } -+ break; -+ -+ case SET: -+ /* I can't think of a nice way to do SET support without having -+ * a stack of bitmasks to make sure no element is repeated. -+ * The bitmask has also to be checked that no non-optional -+ * elements are left out whilst not preventing optional -+ * elements from being left out. -+ */ -+ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); -+ exit(1); -+ -+ case CHOICE: -+ for (ec = e->children; ec; ec = ec->next) -+ render_element(out, ec, NULL); -+ if (!skippable) -+ render_opcode(out, "ASN1_OP_COND_FAIL,\n"); -+ if (e->action) -+ render_opcode(out, "ASN1_OP_ACT,\n"); -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (e->action) -+ render_opcode(out, "_action(ACT_%s),\n", e->action->name); -+} --- -1.7.12.1 - - -From 650c728e4b8d58d72b19973e97c3c765178e81b8 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:16 +0100 -Subject: [PATCH 15/37] X.509: Add an ASN.1 decoder - -Add an ASN.1 BER/DER/CER decoder. This uses the bytecode from the ASN.1 -compiler in the previous patch to inform it as to what to expect to find in the -encoded byte stream. The output from the compiler also tells it what functions -to call on what tags, thus allowing the caller to retrieve information. - -The decoder is called as follows: - - int asn1_decoder(const struct asn1_decoder *decoder, - void *context, - const unsigned char *data, - size_t datalen); - -The decoder argument points to the bytecode from the ASN.1 compiler. context -is the caller's context and is passed to the action functions. data and -datalen define the byte stream to be decoded. - -Note that the decoder is currently limited to datalen being less than 64K. -This reduces the amount of stack space used by the decoder because ASN.1 is a -nested construct. Similarly, the decoder is limited to a maximum of 10 levels -of constructed data outside of a leaf node also in an effort to keep stack -usage down. - -These restrictions can be raised if necessary. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - include/linux/asn1_decoder.h | 24 +++ - lib/Makefile | 2 + - lib/asn1_decoder.c | 477 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 503 insertions(+) - create mode 100644 include/linux/asn1_decoder.h - create mode 100644 lib/asn1_decoder.c - -diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h -new file mode 100644 -index 0000000..fa2ff5b ---- /dev/null -+++ b/include/linux/asn1_decoder.h -@@ -0,0 +1,24 @@ -+/* ASN.1 decoder -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _LINUX_ASN1_DECODER_H -+#define _LINUX_ASN1_DECODER_H -+ -+#include -+ -+struct asn1_decoder; -+ -+extern int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen); -+ -+#endif /* _LINUX_ASN1_DECODER_H */ -diff --git a/lib/Makefile b/lib/Makefile -index b042896..ca856b6 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \ - $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) - lib-$(CONFIG_LIBFDT) += $(libfdt_files) - -+obj-$(CONFIG_ASN1) += asn1_decoder.o -+ - hostprogs-y := gen_crc32table - clean-files := crc32table.h - -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -new file mode 100644 -index 0000000..2e4196d ---- /dev/null -+++ b/lib/asn1_decoder.c -@@ -0,0 +1,477 @@ -+/* Decoder for ASN.1 BER/DER/CER encoded bytestream -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { -+ /* OPC TAG JMP ACT */ -+ [ASN1_OP_MATCH] = 1 + 1, -+ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_MATCH_ANY] = 1, -+ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, -+ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, -+ [ASN1_OP_COND_MATCH_ANY] = 1, -+ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, -+ [ASN1_OP_COND_FAIL] = 1, -+ [ASN1_OP_COMPLETE] = 1, -+ [ASN1_OP_ACT] = 1 + 1, -+ [ASN1_OP_RETURN] = 1, -+ [ASN1_OP_END_SEQ] = 1, -+ [ASN1_OP_END_SEQ_OF] = 1 + 1, -+ [ASN1_OP_END_SET] = 1, -+ [ASN1_OP_END_SET_OF] = 1 + 1, -+ [ASN1_OP_END_SEQ_ACT] = 1 + 1, -+ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, -+ [ASN1_OP_END_SET_ACT] = 1 + 1, -+ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, -+}; -+ -+/* -+ * Find the length of an indefinite length object -+ */ -+static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, -+ const char **_errmsg, size_t *_err_dp) -+{ -+ unsigned char tag, tmp; -+ size_t dp = 0, len, n; -+ int indef_level = 1; -+ -+next_tag: -+ if (unlikely(datalen - dp < 2)) { -+ if (datalen == dp) -+ goto missing_eoc; -+ goto data_overrun_error; -+ } -+ -+ /* Extract a tag from the data */ -+ tag = data[dp++]; -+ if (tag == 0) { -+ /* It appears to be an EOC. */ -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ if (--indef_level <= 0) -+ return dp; -+ goto next_tag; -+ } -+ -+ if (unlikely((tag & 0x1f) == 0x1f)) { -+ do { -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ tmp = data[dp++]; -+ } while (tmp & 0x80); -+ } -+ -+ /* Extract the length */ -+ len = data[dp++]; -+ if (len < 0x7f) { -+ dp += len; -+ goto next_tag; -+ } -+ -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) -+ goto indefinite_len_primitive; -+ indef_level++; -+ goto next_tag; -+ } -+ -+ n = len - 0x80; -+ if (unlikely(n > sizeof(size_t) - 1)) -+ goto length_too_long; -+ if (unlikely(n > datalen - dp)) -+ goto data_overrun_error; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ dp += len; -+ goto next_tag; -+ -+length_too_long: -+ *_errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ *_errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+invalid_eoc: -+ *_errmsg = "Invalid length EOC"; -+ goto error; -+data_overrun_error: -+ *_errmsg = "Data overrun error"; -+ goto error; -+missing_eoc: -+ *_errmsg = "Missing EOC in indefinite len cons"; -+error: -+ *_err_dp = dp; -+ return -1; -+} -+ -+/** -+ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern -+ * @decoder: The decoder definition (produced by asn1_compiler) -+ * @context: The caller's context (to be passed to the action functions) -+ * @data: The encoded data -+ * @datasize: The size of the encoded data -+ * -+ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern -+ * produced by asn1_compiler. Action functions are called on marked tags to -+ * allow the caller to retrieve significant data. -+ * -+ * LIMITATIONS: -+ * -+ * To keep down the amount of stack used by this function, the following limits -+ * have been imposed: -+ * -+ * (1) This won't handle datalen > 65535 without increasing the size of the -+ * cons stack elements and length_too_long checking. -+ * -+ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf -+ * constructed types exceeds this, the decode will fail. -+ * -+ * (3) The SET type (not the SET OF type) isn't really supported as tracking -+ * what members of the set have been seen is a pain. -+ */ -+int asn1_ber_decoder(const struct asn1_decoder *decoder, -+ void *context, -+ const unsigned char *data, -+ size_t datalen) -+{ -+ const unsigned char *machine = decoder->machine; -+ const asn1_action_t *actions = decoder->actions; -+ size_t machlen = decoder->machlen; -+ enum asn1_opcode op; -+ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; -+ const char *errmsg; -+ size_t pc = 0, dp = 0, tdp = 0, len = 0; -+ int ret; -+ -+ unsigned char flags = 0; -+#define FLAG_INDEFINITE_LENGTH 0x01 -+#define FLAG_MATCHED 0x02 -+#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag -+ * - ie. whether or not we are going to parse -+ * a compound type. -+ */ -+ -+#define NR_CONS_STACK 10 -+ unsigned short cons_dp_stack[NR_CONS_STACK]; -+ unsigned short cons_datalen_stack[NR_CONS_STACK]; -+ unsigned char cons_hdrlen_stack[NR_CONS_STACK]; -+#define NR_JUMP_STACK 10 -+ unsigned char jump_stack[NR_JUMP_STACK]; -+ -+ if (datalen > 65535) -+ return -EMSGSIZE; -+ -+next_op: -+ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", -+ pc, machlen, dp, datalen, csp, jsp); -+ if (unlikely(pc >= machlen)) -+ goto machine_overrun_error; -+ op = machine[pc]; -+ if (unlikely(pc + asn1_op_lengths[op] > machlen)) -+ goto machine_overrun_error; -+ -+ /* If this command is meant to match a tag, then do that before -+ * evaluating the command. -+ */ -+ if (op <= ASN1_OP__MATCHES_TAG) { -+ unsigned char tmp; -+ -+ /* Skip conditional matches if possible */ -+ if ((op & ASN1_OP_MATCH__COND && -+ flags & FLAG_MATCHED) || -+ dp == datalen) { -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ } -+ -+ flags = 0; -+ hdr = 2; -+ -+ /* Extract a tag from the data */ -+ if (unlikely(dp >= datalen - 1)) -+ goto data_overrun_error; -+ tag = data[dp++]; -+ if (unlikely((tag & 0x1f) == 0x1f)) -+ goto long_tag_not_supported; -+ -+ if (op & ASN1_OP_MATCH__ANY) { -+ pr_debug("- any %02x\n", tag); -+ } else { -+ /* Extract the tag from the machine -+ * - Either CONS or PRIM are permitted in the data if -+ * CONS is not set in the op stream, otherwise CONS -+ * is mandatory. -+ */ -+ optag = machine[pc + 1]; -+ flags |= optag & FLAG_CONS; -+ -+ /* Determine whether the tag matched */ -+ tmp = optag ^ tag; -+ tmp &= ~(optag & ASN1_CONS_BIT); -+ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); -+ if (tmp != 0) { -+ /* All odd-numbered tags are MATCH_OR_SKIP. */ -+ if (op & ASN1_OP_MATCH__SKIP) { -+ pc += asn1_op_lengths[op]; -+ dp--; -+ goto next_op; -+ } -+ goto tag_mismatch; -+ } -+ } -+ flags |= FLAG_MATCHED; -+ -+ len = data[dp++]; -+ if (len > 0x7f) { -+ if (unlikely(len == 0x80)) { -+ /* Indefinite length */ -+ if (unlikely(!(tag & ASN1_CONS_BIT))) -+ goto indefinite_len_primitive; -+ flags |= FLAG_INDEFINITE_LENGTH; -+ if (unlikely(2 > datalen - dp)) -+ goto data_overrun_error; -+ } else { -+ int n = len - 0x80; -+ if (unlikely(n > 2)) -+ goto length_too_long; -+ if (unlikely(dp >= datalen - n)) -+ goto data_overrun_error; -+ hdr += n; -+ for (len = 0; n > 0; n--) { -+ len <<= 8; -+ len |= data[dp++]; -+ } -+ if (unlikely(len > datalen - dp)) -+ goto data_overrun_error; -+ } -+ } -+ -+ if (flags & FLAG_CONS) { -+ /* For expected compound forms, we stack the positions -+ * of the start and end of the data. -+ */ -+ if (unlikely(csp >= NR_CONS_STACK)) -+ goto cons_stack_overflow; -+ cons_dp_stack[csp] = dp; -+ cons_hdrlen_stack[csp] = hdr; -+ if (!(flags & FLAG_INDEFINITE_LENGTH)) { -+ cons_datalen_stack[csp] = datalen; -+ datalen = dp + len; -+ } else { -+ cons_datalen_stack[csp] = 0; -+ } -+ csp++; -+ } -+ -+ pr_debug("- TAG: %02x %zu%s\n", -+ tag, len, flags & FLAG_CONS ? " CONS" : ""); -+ tdp = dp; -+ } -+ -+ /* Decide how to handle the operation */ -+ switch (op) { -+ case ASN1_OP_MATCH_ANY_ACT: -+ case ASN1_OP_COND_MATCH_ANY_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH_ACT: -+ case ASN1_OP_MATCH_ACT_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: -+ ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); -+ if (ret < 0) -+ return ret; -+ goto skip_data; -+ -+ case ASN1_OP_MATCH: -+ case ASN1_OP_MATCH_OR_SKIP: -+ case ASN1_OP_MATCH_ANY: -+ case ASN1_OP_COND_MATCH_OR_SKIP: -+ case ASN1_OP_COND_MATCH_ANY: -+ skip_data: -+ if (!(flags & FLAG_CONS)) { -+ if (flags & FLAG_INDEFINITE_LENGTH) { -+ len = asn1_find_indefinite_length( -+ data + dp, datalen - dp, &errmsg, &dp); -+ if (len < 0) -+ goto error; -+ } -+ pr_debug("- LEAF: %zu\n", len); -+ dp += len; -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_MATCH_JUMP: -+ case ASN1_OP_MATCH_JUMP_OR_SKIP: -+ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: -+ pr_debug("- MATCH_JUMP\n"); -+ if (unlikely(jsp == NR_JUMP_STACK)) -+ goto jump_stack_overflow; -+ jump_stack[jsp++] = pc + asn1_op_lengths[op]; -+ pc = machine[pc + 2]; -+ goto next_op; -+ -+ case ASN1_OP_COND_FAIL: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_COMPLETE: -+ if (unlikely(jsp != 0 || csp != 0)) { -+ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", -+ jsp, csp); -+ return -EBADMSG; -+ } -+ return 0; -+ -+ case ASN1_OP_END_SET: -+ case ASN1_OP_END_SET_ACT: -+ if (unlikely(!(flags & FLAG_MATCHED))) -+ goto tag_mismatch; -+ case ASN1_OP_END_SEQ: -+ case ASN1_OP_END_SET_OF: -+ case ASN1_OP_END_SEQ_OF: -+ case ASN1_OP_END_SEQ_ACT: -+ case ASN1_OP_END_SET_OF_ACT: -+ case ASN1_OP_END_SEQ_OF_ACT: -+ if (unlikely(csp <= 0)) -+ goto cons_stack_underflow; -+ csp--; -+ tdp = cons_dp_stack[csp]; -+ hdr = cons_hdrlen_stack[csp]; -+ len = datalen; -+ datalen = cons_datalen_stack[csp]; -+ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", -+ tdp, dp, len, datalen); -+ if (datalen == 0) { -+ /* Indefinite length - check for the EOC. */ -+ datalen = len; -+ if (unlikely(datalen - dp < 2)) -+ goto data_overrun_error; -+ if (data[dp++] != 0) { -+ if (op & ASN1_OP_END__OF) { -+ dp--; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ goto missing_eoc; -+ } -+ if (data[dp++] != 0) -+ goto invalid_eoc; -+ len = dp - tdp - 2; -+ } else { -+ if (dp < len && (op & ASN1_OP_END__OF)) { -+ datalen = len; -+ csp++; -+ pc = machine[pc + 1]; -+ pr_debug("- continue\n"); -+ goto next_op; -+ } -+ if (dp != len) -+ goto cons_length_error; -+ len -= tdp; -+ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); -+ } -+ -+ if (op & ASN1_OP_END__ACT) { -+ unsigned char act; -+ if (op & ASN1_OP_END__OF) -+ act = machine[pc + 2]; -+ else -+ act = machine[pc + 1]; -+ ret = actions[act](context, hdr, 0, data + tdp, len); -+ } -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_ACT: -+ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); -+ pc += asn1_op_lengths[op]; -+ goto next_op; -+ -+ case ASN1_OP_RETURN: -+ if (unlikely(jsp <= 0)) -+ goto jump_stack_underflow; -+ pc = jump_stack[--jsp]; -+ goto next_op; -+ -+ default: -+ break; -+ } -+ -+ /* Shouldn't reach here */ -+ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); -+ return -EBADMSG; -+ -+data_overrun_error: -+ errmsg = "Data overrun error"; -+ goto error; -+machine_overrun_error: -+ errmsg = "Machine overrun error"; -+ goto error; -+jump_stack_underflow: -+ errmsg = "Jump stack underflow"; -+ goto error; -+jump_stack_overflow: -+ errmsg = "Jump stack overflow"; -+ goto error; -+cons_stack_underflow: -+ errmsg = "Cons stack underflow"; -+ goto error; -+cons_stack_overflow: -+ errmsg = "Cons stack overflow"; -+ goto error; -+cons_length_error: -+ errmsg = "Cons length error"; -+ goto error; -+missing_eoc: -+ errmsg = "Missing EOC in indefinite len cons"; -+ goto error; -+invalid_eoc: -+ errmsg = "Invalid length EOC"; -+ goto error; -+length_too_long: -+ errmsg = "Unsupported length"; -+ goto error; -+indefinite_len_primitive: -+ errmsg = "Indefinite len primitive not permitted"; -+ goto error; -+tag_mismatch: -+ errmsg = "Unexpected tag"; -+ goto error; -+long_tag_not_supported: -+ errmsg = "Long tag not supported"; -+error: -+ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", -+ errmsg, pc, dp, optag, tag, len); -+ return -EBADMSG; -+} -+EXPORT_SYMBOL_GPL(asn1_ber_decoder); --- -1.7.12.1 - - -From 686b0b5e3549b711c0bcc405d833697ff5e2344d Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:27 +0100 -Subject: [PATCH 16/37] MPILIB: Provide a function to read raw data into an - MPI - -Provide a function to read raw data of a predetermined size into an MPI rather -than expecting the size to be encoded within the data. The data is assumed to -represent an unsigned integer, and the resulting MPI will be positive. - -The function looks like this: - - MPI mpi_read_raw_data(const void *, size_t); - -This is useful for reading ASN.1 integer primitives where the length is encoded -in the ASN.1 metadata. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - include/linux/mpi.h | 1 + - lib/mpi/mpicoder.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 56 insertions(+) - -diff --git a/include/linux/mpi.h b/include/linux/mpi.h -index d02cca6..5af1b81 100644 ---- a/include/linux/mpi.h -+++ b/include/linux/mpi.h -@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); - - /*-- mpicoder.c --*/ - MPI do_encode_md(const void *sha_buffer, unsigned nbits); -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); - MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); - int mpi_fromstr(MPI val, const char *str); - u32 mpi_get_keyid(MPI a, u32 *keyid); -diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c -index f0fa659..3962b7f 100644 ---- a/lib/mpi/mpicoder.c -+++ b/lib/mpi/mpicoder.c -@@ -18,10 +18,65 @@ - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -+#include -+#include - #include "mpi-internal.h" - - #define MAX_EXTERN_MPI_BITS 16384 - -+/** -+ * mpi_read_raw_data - Read a raw byte stream as a positive integer -+ * @xbuffer: The data to read -+ * @nbytes: The amount of data to read -+ */ -+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) -+{ -+ const uint8_t *buffer = xbuffer; -+ int i, j; -+ unsigned nbits, nlimbs; -+ mpi_limb_t a; -+ MPI val = NULL; -+ -+ while (nbytes >= 0 && buffer[0] == 0) { -+ buffer++; -+ nbytes--; -+ } -+ -+ nbits = nbytes * 8; -+ if (nbits > MAX_EXTERN_MPI_BITS) { -+ pr_info("MPI: mpi too large (%u bits)\n", nbits); -+ return NULL; -+ } -+ if (nbytes > 0) -+ nbits -= count_leading_zeros(buffer[0]); -+ else -+ nbits = 0; -+ -+ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; -+ val = mpi_alloc(nlimbs); -+ if (!val) -+ return NULL; -+ val->nbits = nbits; -+ val->sign = 0; -+ val->nlimbs = nlimbs; -+ -+ if (nbytes > 0) { -+ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; -+ i %= BYTES_PER_MPI_LIMB; -+ for (j = nlimbs; j > 0; j--) { -+ a = 0; -+ for (; i < BYTES_PER_MPI_LIMB; i++) { -+ a <<= 8; -+ a |= *buffer++; -+ } -+ i = 0; -+ val->d[j - 1] = a; -+ } -+ } -+ return val; -+} -+EXPORT_SYMBOL_GPL(mpi_read_raw_data); -+ - MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) - { - const uint8_t *buffer = xbuffer; --- -1.7.12.1 - - -From c6ca1b7770b65d0639fb84a7afead457ff22c8d4 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Mon, 24 Sep 2012 17:11:48 +0100 -Subject: [PATCH 17/37] X.509: Add a crypto key parser for binary (DER) X.509 - certificates - -Add a crypto key parser for binary (DER) encoded X.509 certificates. The -certificate is parsed and, if possible, the signature is verified. - -An X.509 key can be added like this: - - # keyctl padd crypto bar @s -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/.gitignore | 1 + - crypto/asymmetric_keys/Kconfig | 10 + - crypto/asymmetric_keys/Makefile | 17 + - crypto/asymmetric_keys/x509.asn1 | 60 ++++ - crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++ - crypto/asymmetric_keys/x509_parser.h | 36 +++ - crypto/asymmetric_keys/x509_public_key.c | 207 +++++++++++++ - crypto/asymmetric_keys/x509_rsakey.asn1 | 4 + - 8 files changed, 832 insertions(+) - create mode 100644 crypto/asymmetric_keys/.gitignore - create mode 100644 crypto/asymmetric_keys/x509.asn1 - create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c - create mode 100644 crypto/asymmetric_keys/x509_parser.h - create mode 100644 crypto/asymmetric_keys/x509_public_key.c - create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 - -diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore -new file mode 100644 -index 0000000..ee32837 ---- /dev/null -+++ b/crypto/asymmetric_keys/.gitignore -@@ -0,0 +1 @@ -+*-asn1.[ch] -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 561759d..6d2c2ea 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). - -+config X509_CERTIFICATE_PARSER -+ tristate "X.509 certificate parser" -+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select ASN1 -+ select OID_REGISTRY -+ help -+ This option procides support for parsing X.509 format blobs for key -+ data and provides the ability to instantiate a crypto key from a -+ public key packet found inside the certificate. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 7c92691..0727204 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+ -+# -+# X.509 Certificate handling -+# -+obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o -+x509_key_parser-y := \ -+ x509-asn1.o \ -+ x509_rsakey-asn1.o \ -+ x509_cert_parser.o \ -+ x509_public_key.o -+ -+$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h -+$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h -+$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h -+ -+clean-files += x509-asn1.c x509-asn1.h -+clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h -diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 -new file mode 100644 -index 0000000..bf32b3d ---- /dev/null -+++ b/crypto/asymmetric_keys/x509.asn1 -@@ -0,0 +1,60 @@ -+Certificate ::= SEQUENCE { -+ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), -+ signatureAlgorithm AlgorithmIdentifier, -+ signature BIT STRING ({ x509_note_signature }) -+ } -+ -+TBSCertificate ::= SEQUENCE { -+ version [ 0 ] Version DEFAULT, -+ serialNumber CertificateSerialNumber, -+ signature AlgorithmIdentifier ({ x509_note_pkey_algo }), -+ issuer Name ({ x509_note_issuer }), -+ validity Validity, -+ subject Name ({ x509_note_subject }), -+ subjectPublicKeyInfo SubjectPublicKeyInfo, -+ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, -+ extensions [ 3 ] Extensions OPTIONAL -+ } -+ -+Version ::= INTEGER -+CertificateSerialNumber ::= INTEGER -+ -+AlgorithmIdentifier ::= SEQUENCE { -+ algorithm OBJECT IDENTIFIER ({ x509_note_OID }), -+ parameters ANY OPTIONAL -+} -+ -+Name ::= SEQUENCE OF RelativeDistinguishedName -+ -+RelativeDistinguishedName ::= SET OF AttributeValueAssertion -+ -+AttributeValueAssertion ::= SEQUENCE { -+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }), -+ attributeValue ANY ({ x509_extract_name_segment }) -+ } -+ -+Validity ::= SEQUENCE { -+ notBefore Time ({ x509_note_not_before }), -+ notAfter Time ({ x509_note_not_after }) -+ } -+ -+Time ::= CHOICE { -+ utcTime UTCTime, -+ generalTime GeneralizedTime -+ } -+ -+SubjectPublicKeyInfo ::= SEQUENCE { -+ algorithm AlgorithmIdentifier, -+ subjectPublicKey BIT STRING ({ x509_extract_key_data }) -+ } -+ -+UniqueIdentifier ::= BIT STRING -+ -+Extensions ::= SEQUENCE OF Extension -+ -+Extension ::= SEQUENCE { -+ extnid OBJECT IDENTIFIER ({ x509_note_OID }), -+ critical BOOLEAN DEFAULT, -+ extnValue OCTET STRING ({ x509_process_extension }) -+ } -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -new file mode 100644 -index 0000000..8fcac94 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -0,0 +1,497 @@ -+/* X.509 certificate parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "X.509: "fmt -+#include -+#include -+#include -+#include -+#include "public_key.h" -+#include "x509_parser.h" -+#include "x509-asn1.h" -+#include "x509_rsakey-asn1.h" -+ -+struct x509_parse_context { -+ struct x509_certificate *cert; /* Certificate being constructed */ -+ unsigned long data; /* Start of data */ -+ const void *cert_start; /* Start of cert content */ -+ const void *key; /* Key data */ -+ size_t key_size; /* Size of key data */ -+ enum OID last_oid; /* Last OID encountered */ -+ enum OID algo_oid; /* Algorithm OID */ -+ unsigned char nr_mpi; /* Number of MPIs stored */ -+ u8 o_size; /* Size of organizationName (O) */ -+ u8 cn_size; /* Size of commonName (CN) */ -+ u8 email_size; /* Size of emailAddress */ -+ u16 o_offset; /* Offset of organizationName (O) */ -+ u16 cn_offset; /* Offset of commonName (CN) */ -+ u16 email_offset; /* Offset of emailAddress */ -+}; -+ -+/* -+ * Free an X.509 certificate -+ */ -+void x509_free_certificate(struct x509_certificate *cert) -+{ -+ if (cert) { -+ public_key_destroy(cert->pub); -+ kfree(cert->issuer); -+ kfree(cert->subject); -+ kfree(cert->fingerprint); -+ kfree(cert->authority); -+ kfree(cert); -+ } -+} -+ -+/* -+ * Parse an X.509 certificate -+ */ -+struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) -+{ -+ struct x509_certificate *cert; -+ struct x509_parse_context *ctx; -+ long ret; -+ -+ ret = -ENOMEM; -+ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); -+ if (!cert) -+ goto error_no_cert; -+ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); -+ if (!cert->pub) -+ goto error_no_ctx; -+ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); -+ if (!ctx) -+ goto error_no_ctx; -+ -+ ctx->cert = cert; -+ ctx->data = (unsigned long)data; -+ -+ /* Attempt to decode the certificate */ -+ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); -+ if (ret < 0) -+ goto error_decode; -+ -+ /* Decode the public key */ -+ ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, -+ ctx->key, ctx->key_size); -+ if (ret < 0) -+ goto error_decode; -+ -+ kfree(ctx); -+ return cert; -+ -+error_decode: -+ kfree(ctx); -+error_no_ctx: -+ x509_free_certificate(cert); -+error_no_cert: -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Note an OID when we find one for later processing when we know how -+ * to interpret it. -+ */ -+int x509_note_OID(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ ctx->last_oid = look_up_OID(value, vlen); -+ if (ctx->last_oid == OID__NR) { -+ char buffer[50]; -+ sprint_oid(value, vlen, buffer, sizeof(buffer)); -+ pr_debug("Unknown OID: [%zu] %s\n", -+ (unsigned long)value - ctx->data, buffer); -+ } -+ return 0; -+} -+ -+/* -+ * Save the position of the TBS data so that we can check the signature over it -+ * later. -+ */ -+int x509_note_tbs_certificate(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", -+ hdrlen, tag, (unsigned long)value - ctx->data, vlen); -+ -+ ctx->cert->tbs = value - hdrlen; -+ ctx->cert->tbs_size = vlen + hdrlen; -+ return 0; -+} -+ -+/* -+ * Record the public key algorithm -+ */ -+int x509_note_pkey_algo(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("PubKey Algo: %u\n", ctx->last_oid); -+ -+ switch (ctx->last_oid) { -+ case OID_md2WithRSAEncryption: -+ case OID_md3WithRSAEncryption: -+ default: -+ return -ENOPKG; /* Unsupported combination */ -+ -+ case OID_md4WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_MD5; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha1WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha256WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha384WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha512WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ -+ case OID_sha224WithRSAEncryption: -+ ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; -+ ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ break; -+ } -+ -+ ctx->algo_oid = ctx->last_oid; -+ return 0; -+} -+ -+/* -+ * Note the whereabouts and type of the signature. -+ */ -+int x509_note_signature(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); -+ -+ if (ctx->last_oid != ctx->algo_oid) { -+ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", -+ ctx->algo_oid, ctx->last_oid); -+ return -EINVAL; -+ } -+ -+ ctx->cert->sig = value; -+ ctx->cert->sig_size = vlen; -+ return 0; -+} -+ -+/* -+ * Note some of the name segments from which we'll fabricate a name. -+ */ -+int x509_extract_name_segment(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ switch (ctx->last_oid) { -+ case OID_commonName: -+ ctx->cn_size = vlen; -+ ctx->cn_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_organizationName: -+ ctx->o_size = vlen; -+ ctx->o_offset = (unsigned long)value - ctx->data; -+ break; -+ case OID_email_address: -+ ctx->email_size = vlen; -+ ctx->email_offset = (unsigned long)value - ctx->data; -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Fabricate and save the issuer and subject names -+ */ -+static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, -+ unsigned char tag, -+ char **_name, size_t vlen) -+{ -+ const void *name, *data = (const void *)ctx->data; -+ size_t namesize; -+ char *buffer; -+ -+ if (*_name) -+ return -EINVAL; -+ -+ /* Empty name string if no material */ -+ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { -+ buffer = kmalloc(1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ buffer[0] = 0; -+ goto done; -+ } -+ -+ if (ctx->cn_size && ctx->o_size) { -+ /* Consider combining O and CN, but use only the CN if it is -+ * prefixed by the O, or a significant portion thereof. -+ */ -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ if (ctx->cn_size >= ctx->o_size && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, -+ ctx->o_size) == 0) -+ goto single_component; -+ if (ctx->cn_size >= 7 && -+ ctx->o_size >= 7 && -+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) -+ goto single_component; -+ -+ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, -+ GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ -+ memcpy(buffer, -+ data + ctx->o_offset, ctx->o_size); -+ buffer[ctx->o_size + 0] = ':'; -+ buffer[ctx->o_size + 1] = ' '; -+ memcpy(buffer + ctx->o_size + 2, -+ data + ctx->cn_offset, ctx->cn_size); -+ buffer[ctx->o_size + 2 + ctx->cn_size] = 0; -+ goto done; -+ -+ } else if (ctx->cn_size) { -+ namesize = ctx->cn_size; -+ name = data + ctx->cn_offset; -+ } else if (ctx->o_size) { -+ namesize = ctx->o_size; -+ name = data + ctx->o_offset; -+ } else { -+ namesize = ctx->email_size; -+ name = data + ctx->email_offset; -+ } -+ -+single_component: -+ buffer = kmalloc(namesize + 1, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ memcpy(buffer, name, namesize); -+ buffer[namesize] = 0; -+ -+done: -+ *_name = buffer; -+ ctx->cn_size = 0; -+ ctx->o_size = 0; -+ ctx->email_size = 0; -+ return 0; -+} -+ -+int x509_note_issuer(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); -+} -+ -+int x509_note_subject(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); -+} -+ -+/* -+ * Extract the data for the public key algorithm -+ */ -+int x509_extract_key_data(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ -+ if (ctx->last_oid != OID_rsaEncryption) -+ return -ENOPKG; -+ -+ /* There seems to be an extraneous 0 byte on the front of the data */ -+ ctx->cert->pkey_algo = PKEY_ALGO_RSA; -+ ctx->key = value + 1; -+ ctx->key_size = vlen - 1; -+ return 0; -+} -+ -+/* -+ * Extract a RSA public key value -+ */ -+int rsa_extract_mpi(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ MPI mpi; -+ -+ if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { -+ pr_err("Too many public key MPIs in certificate\n"); -+ return -EBADMSG; -+ } -+ -+ mpi = mpi_read_raw_data(value, vlen); -+ if (!mpi) -+ return -ENOMEM; -+ -+ ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; -+ return 0; -+} -+ -+/* -+ * Process certificate extensions that are used to qualify the certificate. -+ */ -+int x509_process_extension(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ const unsigned char *v = value; -+ char *f; -+ int i; -+ -+ pr_debug("Extension: %u\n", ctx->last_oid); -+ -+ if (ctx->last_oid == OID_subjectKeyIdentifier) { -+ /* Get hold of the key fingerprint */ -+ if (vlen < 3) -+ return -EBADMSG; -+ if (v[0] != ASN1_OTS || v[1] != vlen - 2) -+ return -EBADMSG; -+ v += 2; -+ vlen -= 2; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("fingerprint %s\n", f); -+ ctx->cert->fingerprint = f; -+ return 0; -+ } -+ -+ if (ctx->last_oid == OID_authorityKeyIdentifier) { -+ /* Get hold of the CA key fingerprint */ -+ if (vlen < 5) -+ return -EBADMSG; -+ if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || -+ v[1] != vlen - 2 || -+ v[2] != (ASN1_CONT << 6) || -+ v[3] != vlen - 4) -+ return -EBADMSG; -+ v += 4; -+ vlen -= 4; -+ -+ f = kmalloc(vlen * 2 + 1, GFP_KERNEL); -+ if (!f) -+ return -ENOMEM; -+ for (i = 0; i < vlen; i++) -+ sprintf(f + i * 2, "%02x", v[i]); -+ pr_debug("authority %s\n", f); -+ ctx->cert->authority = f; -+ return 0; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Record a certificate time. -+ */ -+static int x509_note_time(time_t *_time, size_t hdrlen, -+ unsigned char tag, -+ const unsigned char *value, size_t vlen) -+{ -+ unsigned YY, MM, DD, hh, mm, ss; -+ const unsigned char *p = value; -+ -+#define dec2bin(X) ((X) - '0') -+#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) -+ -+ if (tag == ASN1_UNITIM) { -+ /* UTCTime: YYMMDDHHMMSSZ */ -+ if (vlen != 13) -+ goto unsupported_time; -+ YY = DD2bin(p); -+ if (YY > 50) -+ YY += 1900; -+ else -+ YY += 2000; -+ } else if (tag == ASN1_GENTIM) { -+ /* GenTime: YYYYMMDDHHMMSSZ */ -+ if (vlen != 15) -+ goto unsupported_time; -+ YY = DD2bin(p) * 100 + DD2bin(p); -+ } else { -+ goto unsupported_time; -+ } -+ -+ MM = DD2bin(p); -+ DD = DD2bin(p); -+ hh = DD2bin(p); -+ mm = DD2bin(p); -+ ss = DD2bin(p); -+ -+ if (*p != 'Z') -+ goto unsupported_time; -+ -+ *_time = mktime(YY, MM, DD, hh, mm, ss); -+ return 0; -+ -+unsupported_time: -+ pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", -+ tag, (int)vlen, (int)vlen, value); -+ return -EBADMSG; -+} -+ -+int x509_note_not_before(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); -+} -+ -+int x509_note_not_after(void *context, size_t hdrlen, -+ unsigned char tag, -+ const void *value, size_t vlen) -+{ -+ struct x509_parse_context *ctx = context; -+ return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); -+} -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -new file mode 100644 -index 0000000..635053f ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -0,0 +1,36 @@ -+/* X.509 certificate parser internal definitions -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+ -+struct x509_certificate { -+ struct x509_certificate *next; -+ struct public_key *pub; /* Public key details */ -+ char *issuer; /* Name of certificate issuer */ -+ char *subject; /* Name of certificate subject */ -+ char *fingerprint; /* Key fingerprint as hex */ -+ char *authority; /* Authority key fingerprint as hex */ -+ time_t valid_from; -+ time_t valid_to; -+ enum pkey_algo pkey_algo : 8; /* Public key algorithm */ -+ enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ -+ enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -+ const void *tbs; /* Signed data */ -+ size_t tbs_size; /* Size of signed data */ -+ const void *sig; /* Signature data */ -+ size_t sig_size; /* Size of sigature */ -+}; -+ -+/* -+ * x509_cert_parser.c -+ */ -+extern void x509_free_certificate(struct x509_certificate *cert); -+extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -new file mode 100644 -index 0000000..716917c ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -0,0 +1,207 @@ -+/* Instantiate a public key crypto key from an X.509 Certificate -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "X.509: "fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "asymmetric_keys.h" -+#include "public_key.h" -+#include "x509_parser.h" -+ -+static const -+struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { -+ [PKEY_ALGO_DSA] = NULL, -+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ -+ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) -+ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -+#endif -+}; -+ -+/* -+ * Check the signature on a certificate using the provided public key -+ */ -+static int x509_check_signature(const struct public_key *pub, -+ const struct x509_certificate *cert) -+{ -+ struct public_key_signature *sig; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data. -+ */ -+ ret = -ENOMEM; -+ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -+ if (!sig) -+ goto error_no_sig; -+ -+ sig->pkey_hash_algo = cert->sig_hash_algo; -+ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; -+ sig->digest_size = digest_size; -+ -+ desc = (void *)sig + sizeof(*sig); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = -ENOMEM; -+ sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); -+ if (!sig->rsa.s) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); -+ if (ret < 0) -+ goto error_mpi; -+ -+ ret = pub->algo->verify_signature(pub, sig); -+ -+ pr_debug("Cert Verification: %d\n", ret); -+ -+error_mpi: -+ mpi_free(sig->rsa.s); -+error: -+ kfree(sig); -+error_no_sig: -+ crypto_free_shash(tfm); -+ -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+ -+/* -+ * Attempt to parse a data blob for a key as an X509 certificate. -+ */ -+static int x509_key_preparse(struct key_preparsed_payload *prep) -+{ -+ struct x509_certificate *cert; -+ time_t now; -+ size_t srlen, sulen; -+ char *desc = NULL; -+ int ret; -+ -+ cert = x509_cert_parse(prep->data, prep->datalen); -+ if (IS_ERR(cert)) -+ return PTR_ERR(cert); -+ -+ pr_devel("Cert Issuer: %s\n", cert->issuer); -+ pr_devel("Cert Subject: %s\n", cert->subject); -+ pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -+ pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ pr_devel("Cert Signature: %s + %s\n", -+ pkey_algo[cert->sig_pkey_algo], -+ pkey_hash_algo[cert->sig_hash_algo]); -+ -+ if (!cert->fingerprint || !cert->authority) { -+ pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", -+ cert->subject); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ -+ now = CURRENT_TIME.tv_sec; -+ if (now < cert->valid_from) { -+ pr_warn("Cert %s is not yet valid\n", cert->fingerprint); -+ ret = -EKEYREJECTED; -+ goto error_free_cert; -+ } -+ if (now >= cert->valid_to) { -+ pr_warn("Cert %s has expired\n", cert->fingerprint); -+ ret = -EKEYEXPIRED; -+ goto error_free_cert; -+ } -+ -+ cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; -+ cert->pub->id_type = PKEY_ID_X509; -+ -+ /* Check the signature on the key */ -+ if (strcmp(cert->fingerprint, cert->authority) == 0) { -+ ret = x509_check_signature(cert->pub, cert); -+ if (ret < 0) -+ goto error_free_cert; -+ } -+ -+ /* Propose a description */ -+ sulen = strlen(cert->subject); -+ srlen = strlen(cert->fingerprint); -+ ret = -ENOMEM; -+ desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); -+ if (!desc) -+ goto error_free_cert; -+ memcpy(desc, cert->subject, sulen); -+ desc[sulen] = ':'; -+ desc[sulen + 1] = ' '; -+ memcpy(desc + sulen + 2, cert->fingerprint, srlen); -+ desc[sulen + 2 + srlen] = 0; -+ -+ /* We're pinning the module by being linked against it */ -+ __module_get(public_key_subtype.owner); -+ prep->type_data[0] = &public_key_subtype; -+ prep->type_data[1] = cert->fingerprint; -+ prep->payload = cert->pub; -+ prep->description = desc; -+ prep->quotalen = 100; -+ -+ /* We've finished with the certificate */ -+ cert->pub = NULL; -+ cert->fingerprint = NULL; -+ desc = NULL; -+ ret = 0; -+ -+error_free_cert: -+ x509_free_certificate(cert); -+ return ret; -+} -+ -+static struct asymmetric_key_parser x509_key_parser = { -+ .owner = THIS_MODULE, -+ .name = "x509", -+ .parse = x509_key_preparse, -+}; -+ -+/* -+ * Module stuff -+ */ -+static int __init x509_key_init(void) -+{ -+ return register_asymmetric_key_parser(&x509_key_parser); -+} -+ -+static void __exit x509_key_exit(void) -+{ -+ unregister_asymmetric_key_parser(&x509_key_parser); -+} -+ -+module_init(x509_key_init); -+module_exit(x509_key_exit); -diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 -new file mode 100644 -index 0000000..4ec7cc6 ---- /dev/null -+++ b/crypto/asymmetric_keys/x509_rsakey.asn1 -@@ -0,0 +1,4 @@ -+RSAPublicKey ::= SEQUENCE { -+ modulus INTEGER ({ rsa_extract_mpi }), -- n -+ publicExponent INTEGER ({ rsa_extract_mpi }) -- e -+ } --- -1.7.12.1 - - -From a4c3000ab42b11536ffc8eb9c1d03a746b424bda Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 18/37] MODSIGN: Add FIPS policy - -If we're in FIPS mode, we should panic if we fail to verify the signature on a -module or we're asked to load an unsigned module in signature enforcing mode. -Possibly FIPS mode should automatically enable enforcing mode. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - kernel/module.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/kernel/module.c b/kernel/module.c -index 7efb415..3e8b1a7 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include - #include "module-internal.h" - - #define CREATE_TRACE_POINTS -@@ -2467,6 +2468,9 @@ static int module_sig_check(struct load_info *info, - } - - /* Not having a signature is only an error if we're strict. */ -+ if (err < 0 && fips_enabled) -+ panic("Module verification failed with error %d in FIPS mode\n", -+ err); - if (err == -ENOKEY && !sig_enforce) - err = 0; - --- -1.7.12.1 - - -From 86342ab6db2c5b10b08bd9d1064b1779070c2a82 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 19/37] MODSIGN: Provide gitignore and make clean rules for - extra files - -Provide gitignore and make clean rules for extra files to hide and clean up the -extra files produced by module signing stuff once it is added. Also add a -clean up rule for the module content extractor program used to extract the data -to be signed. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - .gitignore | 14 ++++++++++++++ - Makefile | 1 + - 2 files changed, 15 insertions(+) - -diff --git a/.gitignore b/.gitignore -index 57af07c..0f2f40f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,6 +14,10 @@ - *.o.* - *.a - *.s -+*.ko.unsigned -+*.ko.stripped -+*.ko.stripped.dig -+*.ko.stripped.sig - *.ko - *.so - *.so.dbg -@@ -84,3 +88,13 @@ GTAGS - *.orig - *~ - \#*# -+ -+# -+# Leavings from module signing -+# -+extra_certificates -+signing_key.priv -+signing_key.x509 -+signing_key.x509.keyid -+signing_key.x509.signer -+x509.genkey -diff --git a/Makefile b/Makefile -index 6cdadf4..b4f9eb5 100644 ---- a/Makefile -+++ b/Makefile -@@ -1239,6 +1239,7 @@ clean: $(clean-dirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -+ -o -name '*.ko.*' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ - -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ --- -1.7.12.1 - - -From c631aa86c295b87aa09188d9313cccf41e5db23f Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:09:50 +0100 -Subject: [PATCH 20/37] MODSIGN: Provide Kconfig options - -Provide kernel configuration options for module signing. - -The following configuration options are added: - - CONFIG_MODULE_SIG_SHA1 - CONFIG_MODULE_SIG_SHA224 - CONFIG_MODULE_SIG_SHA256 - CONFIG_MODULE_SIG_SHA384 - CONFIG_MODULE_SIG_SHA512 - -These select the cryptographic hash used to digest the data prior to signing. -Additionally, the crypto module selected will be built into the kernel as it -won't be possible to load it as a module without incurring a circular -dependency when the kernel tries to check its signature. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/init/Kconfig b/init/Kconfig -index fa8ccad..00d4579 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1593,12 +1593,50 @@ config MODULE_SIG - is simply appended to the module. For more information see - Documentation/module-signing.txt. - -+ !!!WARNING!!! If you enable this option, you MUST make sure that the -+ module DOES NOT get stripped after being signed. This includes the -+ debuginfo strip done by some packagers (such as rpmbuild) and -+ inclusion into an initramfs that wants the module size reduced. -+ - config MODULE_SIG_FORCE - bool "Require modules to be validly signed" - depends on MODULE_SIG - help - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. -+ -+choice -+ prompt "Which hash algorithm should modules be signed with?" -+ depends on MODULE_SIG -+ help -+ This determines which sort of hashing algorithm will be used during -+ signature generation. This algorithm _must_ be built into the kernel -+ directly so that signature verification can take place. It is not -+ possible to load a signed module containing the algorithm to check -+ the signature on that module. -+ -+config MODULE_SIG_SHA1 -+ bool "Sign modules with SHA-1" -+ select CRYPTO_SHA1 -+ -+config MODULE_SIG_SHA224 -+ bool "Sign modules with SHA-224" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA256 -+ bool "Sign modules with SHA-256" -+ select CRYPTO_SHA256 -+ -+config MODULE_SIG_SHA384 -+ bool "Sign modules with SHA-384" -+ select CRYPTO_SHA512 -+ -+config MODULE_SIG_SHA512 -+ bool "Sign modules with SHA-512" -+ select CRYPTO_SHA512 -+ -+endchoice -+ - endif # MODULES - - config INIT_ALL_POSSIBLE --- -1.7.12.1 - - -From 84d1788d1ea47ecfe2d30d0c2081055d7e89441d Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:09:51 +0100 -Subject: [PATCH 21/37] MODSIGN: Automatically generate module signing keys if - missing - -Automatically generate keys for module signing if they're absent so that -allyesconfig doesn't break. The builder should consider generating their own -key and certificate, however, so that the keys are appropriately named. - -The private key for the module signer should be placed in signing_key.priv -(unencrypted!) and the public key in an X.509 certificate as signing_key.x509. - -If a transient key is desired for signing the modules, a config file for -'openssl req' can be placed in x509.genkey, looking something like the -following: - - [ req ] - default_bits = 4096 - distinguished_name = req_distinguished_name - prompt = no - x509_extensions = myexts - - [ req_distinguished_name ] - O = Magarathea - CN = Glacier signing key - emailAddress = slartibartfast@magrathea.h2g2 - - [ myexts ] - basicConstraints=critical,CA:FALSE - keyUsage=digitalSignature - subjectKeyIdentifier=hash - authorityKeyIdentifier=hash - -The build process will use this to configure: - - openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ - -x509 -config x509.genkey \ - -outform DER -out signing_key.x509 \ - -keyout signing_key.priv - -to generate the key. - -Note that it is required that the X.509 certificate have a subjectKeyIdentifier -and an authorityKeyIdentifier. Without those, the certificate will be -rejected. These can be used to check the validity of a certificate. - -Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey, -whether or not they were generated automatically. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 08ba8a6..58c6f11 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -132,3 +132,52 @@ quiet_cmd_timeconst = TIMEC $@ - targets += timeconst.h - $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) -+ -+ifeq ($(CONFIG_MODULE_SIG),y) -+ -+############################################################################### -+# -+# If module signing is requested, say by allyesconfig, but a key has not been -+# supplied, then one will need to be generated to make sure the build does not -+# fail and that the kernel may be used afterwards. -+# -+############################################################################### -+signing_key.priv signing_key.x509: x509.genkey -+ @echo "###" -+ @echo "### Now generating an X.509 key pair to be used for signing modules." -+ @echo "###" -+ @echo "### If this takes a long time, you might wish to run rngd in the" -+ @echo "### background to keep the supply of entropy topped up. It" -+ @echo "### needs to be run as root, and should use a hardware random" -+ @echo "### number generator if one is available, eg:" -+ @echo "###" -+ @echo "### rngd -r /dev/hwrandom" -+ @echo "###" -+ openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ -+ -x509 -config x509.genkey \ -+ -outform DER -out signing_key.x509 \ -+ -keyout signing_key.priv -+ @echo "###" -+ @echo "### Key pair generated." -+ @echo "###" -+ -+x509.genkey: -+ @echo Generating X.509 key generation config -+ @echo >x509.genkey "[ req ]" -+ @echo >>x509.genkey "default_bits = 4096" -+ @echo >>x509.genkey "distinguished_name = req_distinguished_name" -+ @echo >>x509.genkey "prompt = no" -+ @echo >>x509.genkey "x509_extensions = myexts" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ req_distinguished_name ]" -+ @echo >>x509.genkey "O = Magrathea" -+ @echo >>x509.genkey "CN = Glacier signing key" -+ @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" -+ @echo >>x509.genkey -+ @echo >>x509.genkey "[ myexts ]" -+ @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" -+ @echo >>x509.genkey "keyUsage=digitalSignature" -+ @echo >>x509.genkey "subjectKeyIdentifier=hash" -+ @echo >>x509.genkey "authorityKeyIdentifier=keyid" -+endif -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey --- -1.7.12.1 - - -From 51da59e56f0666efe97c376830dffefdfcecd21f Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:09:51 +0100 -Subject: [PATCH 22/37] MODSIGN: Provide module signing public keys to the - kernel - -Include a PGP keyring containing the public keys required to perform module -verification in the kernel image during build and create a special keyring -during boot which is then populated with keys of crypto type holding the public -keys found in the PGP keyring. - -These can be seen by root: - -[root@andromeda ~]# cat /proc/keys -07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] -15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 -... - -It is probably worth permitting root to invalidate these keys, resulting in -their removal and preventing further modules from being loaded with that key. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - kernel/Makefile | 11 ++++- - kernel/modsign_pubkey.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-internal.h | 2 + - 3 files changed, 124 insertions(+), 2 deletions(-) - create mode 100644 kernel/modsign_pubkey.c - -diff --git a/kernel/Makefile b/kernel/Makefile -index 58c6f11..111a845 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,7 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o --obj-$(CONFIG_MODULE_SIG) += module_signing.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE - $(call if_changed,timeconst) - - ifeq ($(CONFIG_MODULE_SIG),y) -+# -+# Pull the signing certificate and any extra certificates into the kernel -+# -+extra_certificates: -+ touch $@ -+ -+kernel/modsign_pubkey.o: signing_key.x509 extra_certificates - - ############################################################################### - # -@@ -180,4 +187,4 @@ x509.genkey: - @echo >>x509.genkey "subjectKeyIdentifier=hash" - @echo >>x509.genkey "authorityKeyIdentifier=keyid" - endif --CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey -+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -new file mode 100644 -index 0000000..4646eb2 ---- /dev/null -+++ b/kernel/modsign_pubkey.c -@@ -0,0 +1,113 @@ -+/* Public keys for module signature verification -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "module-internal.h" -+ -+struct key *modsign_keyring; -+ -+extern __initdata const u8 modsign_certificate_list[]; -+extern __initdata const u8 modsign_certificate_list_end[]; -+asm(".section .init.data,\"aw\"\n" -+ "modsign_certificate_list:\n" -+ ".incbin \"signing_key.x509\"\n" -+ ".incbin \"extra_certificates\"\n" -+ "modsign_certificate_list_end:" -+ ); -+ -+/* -+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice -+ * if modsign.pub changes. -+ */ -+static __initdata const char annoy_ccache[] = __TIME__ "foo"; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int module_verify_init(void) -+{ -+ pr_notice("Initialise module verification\n"); -+ -+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", -+ KUIDT_INIT(0), KGIDT_INIT(0), -+ current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_keyring)) -+ panic("Can't allocate module signing keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(module_verify_init); -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int load_module_signing_keys(void) -+{ -+ key_ref_t key; -+ const u8 *p, *end; -+ size_t plen; -+ -+ pr_notice("Loading module verification certificates\n"); -+ -+ end = modsign_certificate_list_end; -+ p = modsign_certificate_list; -+ while (p < end) { -+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more -+ * than 256 bytes in size. -+ */ -+ if (end - p < 4) -+ goto dodgy_cert; -+ if (p[0] != 0x30 && -+ p[1] != 0x82) -+ goto dodgy_cert; -+ plen = (p[2] << 8) | p[3]; -+ plen += 4; -+ if (plen > end - p) -+ goto dodgy_cert; -+ -+ key = key_create_or_update(make_key_ref(modsign_keyring, 1), -+ "asymmetric", -+ NULL, -+ p, -+ plen, -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(key)) -+ pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("MODSIGN: Loaded cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ p += plen; -+ } -+ -+ return 0; -+ -+dodgy_cert: -+ pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); -+ return 0; -+} -+late_initcall(load_module_signing_keys); -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 033c17f..6114a13 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -9,5 +9,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - -+extern struct key *modsign_keyring; -+ - extern int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen); --- -1.7.12.1 - - -From 81a8def438b252dac4aa9c7eda39ad517bfe51ac Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:11:03 +0100 -Subject: [PATCH 23/37] MODSIGN: Implement module signature checking - -Check the signature on the module against the keys compiled into the kernel or -available in a hardware key store. - -Currently, only RSA keys are supported - though that's easy enough to change, -and the signature is expected to contain raw components (so not a PGP or -PKCS#7 formatted blob). - -The signature blob is expected to consist of the following pieces in order: - - (1) The binary identifier for the key. This is expected to match the - SubjectKeyIdentifier from an X.509 certificate. Only X.509 type - identifiers are currently supported. - - (2) The signature data, consisting of a series of MPIs in which each is in - the format of a 2-byte BE word sizes followed by the content data. - - (3) A 12 byte information block of the form: - - struct module_signature { - enum pkey_algo algo : 8; - enum pkey_hash_algo hash : 8; - enum pkey_id_type id_type : 8; - u8 __pad; - __be32 id_length; - __be32 sig_length; - }; - - The three enums are defined in crypto/public_key.h. - - 'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA). - - 'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1, - etc.). - - 'id_type' contains the public-key identifier type (0->PGP, 1->X.509). - - '__pad' should be 0. - - 'id_length' should contain in the binary identifier length in BE form. - - 'sig_length' should contain in the signature data length in BE form. - - The lengths are in BE order rather than CPU order to make dealing with - cross-compilation easier. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell (minor Kconfig fix) ---- - init/Kconfig | 8 ++ - kernel/module_signing.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 229 insertions(+), 1 deletion(-) - -diff --git a/init/Kconfig b/init/Kconfig -index 00d4579..abc6e63 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL - config MODULE_SIG - bool "Module signature verification" - depends on MODULES -+ select KEYS -+ select CRYPTO -+ select ASYMMETRIC_KEY_TYPE -+ select ASYMMETRIC_PUBLIC_KEY_SUBTYPE -+ select PUBLIC_KEY_ALGO_RSA -+ select ASN1 -+ select OID_REGISTRY -+ select X509_CERTIFICATE_PARSER - help - Check modules for valid signatures upon load: the signature - is simply appended to the module. For more information see -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 499728a..6b09f69 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -11,13 +11,233 @@ - - #include - #include -+#include -+#include -+#include - #include "module-internal.h" - - /* -+ * Module signature information block. -+ * -+ * The constituents of the signature section are, in order: -+ * -+ * - Signer's name -+ * - Key identifier -+ * - Signature data -+ * - Information block -+ */ -+struct module_signature { -+ enum pkey_algo algo : 8; /* Public-key crypto algorithm */ -+ enum pkey_hash_algo hash : 8; /* Digest algorithm */ -+ enum pkey_id_type id_type : 8; /* Key identifier type */ -+ u8 signer_len; /* Length of signer's name */ -+ u8 key_id_len; /* Length of key identifier */ -+ u8 __pad[3]; -+ __be32 sig_len; /* Length of signature data */ -+}; -+ -+/* -+ * Digest the module contents. -+ */ -+static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, -+ const void *mod, -+ unsigned long modlen) -+{ -+ struct public_key_signature *pks; -+ struct crypto_shash *tfm; -+ struct shash_desc *desc; -+ size_t digest_size, desc_size; -+ int ret; -+ -+ pr_devel("==>%s()\n", __func__); -+ -+ /* Allocate the hashing algorithm we're going to need and find out how -+ * big the hash operational data will be. -+ */ -+ tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); -+ if (IS_ERR(tfm)) -+ return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); -+ -+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); -+ digest_size = crypto_shash_digestsize(tfm); -+ -+ /* We allocate the hash operational data storage on the end of our -+ * context data and the digest output buffer on the end of that. -+ */ -+ ret = -ENOMEM; -+ pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); -+ if (!pks) -+ goto error_no_pks; -+ -+ pks->pkey_hash_algo = hash; -+ pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; -+ pks->digest_size = digest_size; -+ -+ desc = (void *)pks + sizeof(*pks); -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ -+ ret = crypto_shash_init(desc); -+ if (ret < 0) -+ goto error; -+ -+ ret = crypto_shash_finup(desc, mod, modlen, pks->digest); -+ if (ret < 0) -+ goto error; -+ -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = ok\n", __func__); -+ return pks; -+ -+error: -+ kfree(pks); -+error_no_pks: -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ERR_PTR(ret); -+} -+ -+/* -+ * Extract an MPI array from the signature data. This represents the actual -+ * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the -+ * size of the MPI in bytes. -+ * -+ * RSA signatures only have one MPI, so currently we only read one. -+ */ -+static int mod_extract_mpi_array(struct public_key_signature *pks, -+ const void *data, size_t len) -+{ -+ size_t nbytes; -+ MPI mpi; -+ -+ if (len < 3) -+ return -EBADMSG; -+ nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; -+ data += 2; -+ len -= 2; -+ if (len != nbytes) -+ return -EBADMSG; -+ -+ mpi = mpi_read_raw_data(data, nbytes); -+ if (!mpi) -+ return -ENOMEM; -+ pks->mpi[0] = mpi; -+ pks->nr_mpi = 1; -+ return 0; -+} -+ -+/* -+ * Request an asymmetric key. -+ */ -+static struct key *request_asymmetric_key(const char *signer, size_t signer_len, -+ const u8 *key_id, size_t key_id_len) -+{ -+ key_ref_t key; -+ size_t i; -+ char *id, *q; -+ -+ pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); -+ -+ /* Construct an identifier. */ -+ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); -+ if (!id) -+ return ERR_PTR(-ENOKEY); -+ -+ memcpy(id, signer, signer_len); -+ -+ q = id + signer_len; -+ *q++ = ':'; -+ *q++ = ' '; -+ for (i = 0; i < key_id_len; i++) { -+ *q++ = hex_asc[*key_id >> 4]; -+ *q++ = hex_asc[*key_id++ & 0x0f]; -+ } -+ -+ *q = 0; -+ -+ pr_debug("Look up: \"%s\"\n", id); -+ -+ key = keyring_search(make_key_ref(modsign_keyring, 1), -+ &key_type_asymmetric, id); -+ if (IS_ERR(key)) -+ pr_warn("Request for unknown module key '%s' err %ld\n", -+ id, PTR_ERR(key)); -+ kfree(id); -+ -+ if (IS_ERR(key)) { -+ switch (PTR_ERR(key)) { -+ /* Hide some search errors */ -+ case -EACCES: -+ case -ENOTDIR: -+ case -EAGAIN: -+ return ERR_PTR(-ENOKEY); -+ default: -+ return ERR_CAST(key); -+ } -+ } -+ -+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); -+ return key_ref_to_ptr(key); -+} -+ -+/* - * Verify the signature on a module. - */ - int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen) - { -- return -ENOKEY; -+ struct public_key_signature *pks; -+ struct module_signature ms; -+ struct key *key; -+ size_t sig_len; -+ int ret; -+ -+ pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); -+ -+ if (siglen <= sizeof(ms)) -+ return -EBADMSG; -+ -+ memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); -+ siglen -= sizeof(ms); -+ -+ sig_len = be32_to_cpu(ms.sig_len); -+ if (sig_len >= siglen || -+ siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) -+ return -EBADMSG; -+ -+ /* For the moment, only support RSA and X.509 identifiers */ -+ if (ms.algo != PKEY_ALGO_RSA || -+ ms.id_type != PKEY_ID_X509) -+ return -ENOPKG; -+ -+ if (ms.hash >= PKEY_HASH__LAST || -+ !pkey_hash_algo[ms.hash]) -+ return -ENOPKG; -+ -+ key = request_asymmetric_key(sig, ms.signer_len, -+ sig + ms.signer_len, ms.key_id_len); -+ if (IS_ERR(key)) -+ return PTR_ERR(key); -+ -+ pks = mod_make_digest(ms.hash, mod, modlen); -+ if (IS_ERR(pks)) { -+ ret = PTR_ERR(pks); -+ goto error_put_key; -+ } -+ -+ ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, -+ sig_len); -+ if (ret < 0) -+ goto error_free_pks; -+ -+ ret = verify_signature(key, pks); -+ pr_devel("verify_signature() = %d\n", ret); -+ -+error_free_pks: -+ mpi_free(pks->rsa.s); -+ kfree(pks); -+error_put_key: -+ key_put(key); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; - } --- -1.7.12.1 - - -From 952f5922dd45a25f7896843df02aec2250c41f42 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:11:06 +0100 -Subject: [PATCH 24/37] MODSIGN: Provide a script for generating a key ID from - an X.509 cert - -Provide a script to parse an X.509 certificate and certain pieces of -information from it in order to generate a key identifier to be included within -a module signature. - -The script takes the Subject Name and extracts (if present) the -organizationName (O), the commonName (CN) and the emailAddress and fabricates -the signer's name from them: - - (1) If both O and CN exist, then the name will be "O: CN", unless: - - (a) CN is prefixed by O, in which case only CN is used. - - (b) CN and O share at least the first 7 characters, in which case only CN - is used. - - (2) Otherwise, CN is used if present. - - (3) Otherwise, O is used if present. - - (4) Otherwise the emailAddress is used, if present. - - (5) Otherwise a blank name is used. - -The script emits a binary encoded identifier in the following form: - - - 2 BE bytes indicating the length of the signer's name. - - - 2 BE bytes indicating the length of the subject key identifier. - - - The characters of the signer's name. - - - The bytes of the subject key identifier. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 268 insertions(+) - create mode 100755 scripts/x509keyid - -diff --git a/scripts/x509keyid b/scripts/x509keyid -new file mode 100755 -index 0000000..c8e91a4 ---- /dev/null -+++ b/scripts/x509keyid -@@ -0,0 +1,268 @@ -+#!/usr/bin/perl -w -+# -+# Generate an identifier from an X.509 certificate that can be placed in a -+# module signature to indentify the key to use. -+# -+# Format: -+# -+# ./scripts/x509keyid -+# -+# We read the DER-encoded X509 certificate and parse it to extract the Subject -+# name and Subject Key Identifier. The provide the data we need to build the -+# certificate identifier. -+# -+# The signer's name part of the identifier is fabricated from the commonName, -+# the organizationName or the emailAddress components of the X.509 subject -+# name and written to the second named file. -+# -+# The subject key ID to select which of that signer's certificates we're -+# intending to use to sign the module is written to the third named file. -+# -+use strict; -+ -+my $raw_data; -+ -+die "Need three filenames\n" if ($#ARGV != 2); -+ -+my $src = $ARGV[0]; -+ -+open(FD, "<$src") || die $src; -+binmode FD; -+my @st = stat(FD); -+die $src if (!@st); -+read(FD, $raw_data, $st[7]) || die $src; -+close(FD); -+ -+my $UNIV = 0 << 6; -+my $APPL = 1 << 6; -+my $CONT = 2 << 6; -+my $PRIV = 3 << 6; -+ -+my $CONS = 0x20; -+ -+my $BOOLEAN = 0x01; -+my $INTEGER = 0x02; -+my $BIT_STRING = 0x03; -+my $OCTET_STRING = 0x04; -+my $NULL = 0x05; -+my $OBJ_ID = 0x06; -+my $UTF8String = 0x0c; -+my $SEQUENCE = 0x10; -+my $SET = 0x11; -+my $UTCTime = 0x17; -+my $GeneralizedTime = 0x18; -+ -+my %OIDs = ( -+ pack("CCC", 85, 4, 3) => "commonName", -+ pack("CCC", 85, 4, 6) => "countryName", -+ pack("CCC", 85, 4, 10) => "organizationName", -+ pack("CCC", 85, 4, 11) => "organizationUnitName", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -+ pack("CCC", 85, 29, 19) => "basicConstraints" -+); -+ -+############################################################################### -+# -+# Extract an ASN.1 element from a string and return information about it. -+# -+############################################################################### -+sub asn1_extract($$@) -+{ -+ my ($cursor, $expected_tag, $optional) = @_; -+ -+ return [ -1 ] -+ if ($cursor->[1] == 0 && $optional); -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -+ if ($cursor->[1] < 2); -+ -+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ -+ if ($expected_tag != -1 && $tag != $expected_tag) { -+ return [ -1 ] -+ if ($optional); -+ die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -+ " not ", $expected_tag, ")\n"; -+ } -+ -+ $cursor->[0] += 2; -+ $cursor->[1] -= 2; -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" -+ if (($tag & 0x1f) == 0x1f); -+ die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -+ if ($len == 0x80); -+ -+ if ($len > 0x80) { -+ my $l = $len - 0x80; -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -+ if ($cursor->[1] < $l); -+ -+ if ($l == 0x1) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -+ } elsif ($l = 0x2) { -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ } elsif ($l = 0x3) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -+ } elsif ($l = 0x4) { -+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -+ } else { -+ die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -+ } -+ -+ $cursor->[0] += $l; -+ $cursor->[1] -= $l; -+ } -+ -+ die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -+ if ($cursor->[1] < $len); -+ -+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -+ $cursor->[0] += $len; -+ $cursor->[1] -= $len; -+ -+ return $ret; -+} -+ -+############################################################################### -+# -+# Retrieve the data referred to by a cursor -+# -+############################################################################### -+sub asn1_retrieve($) -+{ -+ my ($cursor) = @_; -+ my ($offset, $len, $data) = @$cursor; -+ return substr($$data, $offset, $len); -+} -+ -+############################################################################### -+# -+# Roughly parse the X.509 certificate -+# -+############################################################################### -+my $cursor = [ 0, length($raw_data), \$raw_data ]; -+ -+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -+ -+my $subject_key_id = (); -+my $authority_key_id = (); -+ -+# -+# Parse the extension list -+# -+if ($extension_list->[0] != -1) { -+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -+ -+ while ($extensions->[1]->[1] > 0) { -+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -+ -+ my $raw_oid = asn1_retrieve($x_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $x_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($x_val->[1]); -+ -+ if ($x_type eq "subjectKeyIdentifier") { -+ my $vcursor = [ 0, length($raw_value), \$raw_value ]; -+ -+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -+ } -+ } -+} -+ -+############################################################################### -+# -+# Determine what we're going to use as the signer's name. In order of -+# preference, take one of: commonName, organizationName or emailAddress. -+# -+############################################################################### -+my $org = ""; -+my $cn = ""; -+my $email = ""; -+ -+while ($subject->[1]->[1] > 0) { -+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -+ my $n_val = asn1_extract($attr->[1], -1); -+ -+ my $raw_oid = asn1_retrieve($n_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $n_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($n_val->[1]); -+ -+ if ($n_type eq "organizationName") { -+ $org = $raw_value; -+ } elsif ($n_type eq "commonName") { -+ $cn = $raw_value; -+ } elsif ($n_type eq "emailAddress") { -+ $email = $raw_value; -+ } -+} -+ -+my $id_name = $email; -+ -+if ($org && $cn) { -+ # Don't use the organizationName if the commonName repeats it -+ if (length($org) <= length($cn) && -+ substr($cn, 0, length($org)) eq $org) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ # Or a signifcant chunk of it -+ if (length($org) >= 7 && -+ length($cn) >= 7 && -+ substr($cn, 0, 7) eq substr($org, 0, 7)) { -+ $id_name = $cn; -+ goto got_id_name; -+ } -+ -+ $id_name = $org . ": " . $cn; -+} elsif ($org) { -+ $id_name = $org; -+} elsif ($cn) { -+ $id_name = $cn; -+} -+ -+got_id_name: -+ -+############################################################################### -+# -+# Output the signer's name and the key identifier that we're going to include -+# in module signatures. -+# -+############################################################################### -+die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -+ if (!$subject_key_id); -+ -+my $id_key_id = asn1_retrieve($subject_key_id->[1]); -+ -+open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; -+print OUTFD $id_name; -+close OUTFD || die $ARGV[1]; -+ -+open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; -+print OUTFD $id_key_id; -+close OUTFD || die $ARGV[2]; --- -1.7.12.1 - - -From 52a1f2ba9612d689f1a5ed6c1a03bd784f34bf1c Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 26 Sep 2012 10:11:06 +0100 -Subject: [PATCH 25/37] MODSIGN: Sign modules during the build process - -If CONFIG_MODULE_SIG is set, then this patch will cause all modules files to -to have signatures added. The following steps will occur: - - (1) The module will be linked to foo.ko.unsigned instead of foo.ko - - (2) The module will be stripped using both "strip -x -g" and "eu-strip" to - ensure minimal size for inclusion in an initramfs. - - (3) The signature will be generated on the stripped module. - - (4) The signature will be appended to the module, along with some information - about the signature and a magic string that indicates the presence of the - signature. - -Step (3) requires private and public keys to be available. By default these -are expected to be found in files: - - signing_key.priv - signing_key.x509 - -in the base directory of the build. The first is the private key in PEM form -and the second is the X.509 certificate in DER form as can be generated from -openssl: - - openssl req \ - -new -x509 -outform PEM -out signing_key.x509 \ - -keyout signing_key.priv -nodes \ - -subj "/CN=H2G2/O=Magrathea/CN=Slartibartfast" - -If the secret key is not found then signing will be skipped and the unsigned -module from (1) will just be copied to foo.ko. - -If signing occurs, lines like the following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - STRIP [M] fs/foo/foo.ko.stripped - SIGN [M] fs/foo/foo.ko - -will appear in the build log. If the signature step will be skipped and the -following will be seen: - - LD [M] fs/foo/foo.ko.unsigned - STRIP [M] fs/foo/foo.ko.stripped - NO SIGN [M] fs/foo/foo.ko - -NOTE! After the signature step, the signed module _must_not_ be passed through -strip. The unstripped, unsigned module is still available at the name on the -LD [M] line. This restriction may affect packaging tools (such as rpmbuild) -and initramfs composition tools. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - scripts/Makefile.modpost | 77 ++++++++++++++++++++++++++++++- - scripts/sign-file | 115 +++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 191 insertions(+), 1 deletion(-) - create mode 100644 scripts/sign-file - -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 08dce14..2a4d1a1 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -14,7 +14,8 @@ - # 3) create one .mod.c file pr. module - # 4) create one Module.symvers file with CRC for all exported symbols - # 5) compile all .mod.c files --# 6) final link of the module to a file -+# 6) final link of the module to a (or ) file -+# 7) signs the modules to a file - - # Step 3 is used to place certain information in the module's ELF - # section, including information such as: -@@ -32,6 +33,8 @@ - # Step 4 is solely used to allow module versioning in external modules, - # where the CRC of each module is retrieved from the Module.symvers file. - -+# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. -+ - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined - # symbols in the final module linking stage - # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE - targets += $(modules:.ko=.mod.o) - - # Step 6), final link of the modules -+ifneq ($(CONFIG_MODULE_SIG),y) - quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) - - targets += $(modules) -+else -+quiet_cmd_ld_ko_unsigned_o = LD [M] $@ -+ cmd_ld_ko_unsigned_o = \ -+ $(LD) -r $(LDFLAGS) \ -+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -+ -o $@ $(filter-out FORCE,$^) \ -+ $(if $(AFTER_LINK),; $(AFTER_LINK)) -+ -+$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE -+ $(call if_changed,ld_ko_unsigned_o) -+ -+targets += $(modules:.ko=.ko.unsigned) -+ -+# Step 7), sign the modules -+MODSECKEY = ./signing_key.priv -+MODPUBKEY = ./signing_key.x509 -+ -+ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) -+ifeq ($(KBUILD_SRC),) -+ # no O= is being used -+ SCRIPTS_DIR := scripts -+else -+ SCRIPTS_DIR := $(KBUILD_SRC)/scripts -+endif -+SIGN_MODULES := 1 -+else -+SIGN_MODULES := 0 -+endif -+ -+# only sign if it's an in-tree module -+ifneq ($(KBUILD_EXTMOD),) -+SIGN_MODULES := 0 -+endif - -+# We strip the module as best we can - note that using both strip and eu-strip -+# results in a smaller module than using either alone. -+EU_STRIP = $(shell which eu-strip || echo true) -+ -+quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ -+ cmd_sign_ko_stripped_ko_unsigned = \ -+ cp $< $@ && \ -+ strip -x -g $@ && \ -+ $(EU_STRIP) $@ -+ -+ifeq ($(SIGN_MODULES),1) -+ -+quiet_cmd_genkeyid = GENKEYID $@ -+ cmd_genkeyid = \ -+ perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid -+ -+%.signer %.keyid: % -+ $(call if_changed,genkeyid) -+ -+KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid -+quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ -+ cmd_sign_ko_ko_stripped = \ -+ sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ -+else -+KEYRING_DEP := -+quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ -+ cmd_sign_ko_ko_unsigned = \ -+ cp $< $@ -+endif -+ -+$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE -+ $(call if_changed,sign_ko_ko_stripped) -+ -+$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE -+ $(call if_changed,sign_ko_stripped_ko_unsigned) -+ -+targets += $(modules) -+endif - - # Add FORCE to the prequisites of a target to force it to be always rebuilt. - # --------------------------------------------------------------------------- -diff --git a/scripts/sign-file b/scripts/sign-file -new file mode 100644 -index 0000000..e58e34e ---- /dev/null -+++ b/scripts/sign-file -@@ -0,0 +1,115 @@ -+#!/bin/sh -+# -+# Sign a module file using the given key. -+# -+# Format: sign-file -+# -+ -+scripts=`dirname $0` -+ -+CONFIG_MODULE_SIG_SHA512=y -+if [ -r .config ] -+then -+ . ./.config -+fi -+ -+key="$1" -+x509="$2" -+src="$3" -+dst="$4" -+ -+if [ ! -r "$key" ] -+then -+ echo "Can't read private key" >&2 -+ exit 2 -+fi -+ -+if [ ! -r "$x509" ] -+then -+ echo "Can't read X.509 certificate" >&2 -+ exit 2 -+fi -+if [ ! -r "$x509.signer" ] -+then -+ echo "Can't read Signer name" >&2 -+ exit 2; -+fi -+if [ ! -r "$x509.keyid" ] -+then -+ echo "Can't read Key identifier" >&2 -+ exit 2; -+fi -+ -+# -+# Signature parameters -+# -+algo=1 # Public-key crypto algorithm: RSA -+hash= # Digest algorithm -+id_type=1 # Identifier type: X.509 -+ -+# -+# Digest the data -+# -+dgst= -+if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] -+then -+ prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" -+ dgst=-sha1 -+ hash=2 -+elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] -+then -+ prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" -+ dgst=-sha224 -+ hash=7 -+elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] -+then -+ prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" -+ dgst=-sha256 -+ hash=4 -+elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] -+then -+ prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" -+ dgst=-sha384 -+ hash=5 -+elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] -+then -+ prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" -+ dgst=-sha512 -+ hash=6 -+else -+ echo "$0: Can't determine hash algorithm" >&2 -+ exit 2 -+fi -+ -+( -+perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? -+openssl dgst $dgst -binary $src || exit $? -+) >$src.dig || exit $? -+ -+# -+# Generate the binary signature, which will be just the integer that comprises -+# the signature with no metadata attached. -+# -+openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? -+signerlen=`stat -c %s $x509.signer` -+keyidlen=`stat -c %s $x509.keyid` -+siglen=`stat -c %s $src.sig` -+ -+# -+# Build the signed binary -+# -+( -+ cat $src || exit $? -+ echo '~Module signature appended~' || exit $? -+ cat $x509.signer $x509.keyid || exit $? -+ -+ # Preface each signature integer with a 2-byte BE length -+ perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -+ cat $src.sig || exit $? -+ -+ # Generate the information block -+ perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? -+) >$dst~ || exit $? -+ -+# Permit in-place signing -+mv $dst~ $dst || exit $? --- -1.7.12.1 - - -From 1e9ce85a6c40e2c0ba6c589605ceb565b1c83784 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 28 Sep 2012 11:16:57 +0100 -Subject: [PATCH 26/37] MODSIGN: Use the same digest for the autogen key sig - as for the module sig - -Use the same digest type for the autogenerated key signature as for the module -signature so that the hash algorithm is guaranteed to be present in the kernel. - -Without this, the X.509 certificate loader may reject the X.509 certificate so -generated because it was self-signed and the signature will be checked against -itself - but this won't work if the digest algorithm must be loaded as a -module. - -The symptom is that the key fails to load with the following message emitted -into the kernel log: - - MODSIGN: Problem loading in-kernel X.509 certificate (-65) - -the error in brackets being -ENOPKG. What you should see is something like: - - MODSIGN: Loaded cert 'Magarathea: Glacier signing key: 9588321144239a119d3406d4c4cf1fbae1836fa0' - -Note that this doesn't apply to certificates that are not self-signed as we -don't check those currently as they require the parent CA certificate to be -available. - -Reported-by: Rusty Russell -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - kernel/Makefile | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 111a845..a799029 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -149,6 +149,26 @@ kernel/modsign_pubkey.o: signing_key.x509 extra_certificates - # fail and that the kernel may be used afterwards. - # - ############################################################################### -+sign_key_with_hash := -+ifeq ($(CONFIG_MODULE_SIG_SHA1),y) -+sign_key_with_hash := -sha1 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA224),y) -+sign_key_with_hash := -sha224 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA256),y) -+sign_key_with_hash := -sha256 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA384),y) -+sign_key_with_hash := -sha384 -+endif -+ifeq ($(CONFIG_MODULE_SIG_SHA512),y) -+sign_key_with_hash := -sha512 -+endif -+ifeq ($(sign_key_with_hash),) -+$(error Could not determine digest type to use from kernel config) -+endif -+ - signing_key.priv signing_key.x509: x509.genkey - @echo "###" - @echo "### Now generating an X.509 key pair to be used for signing modules." -@@ -160,7 +180,7 @@ signing_key.priv signing_key.x509: x509.genkey - @echo "###" - @echo "### rngd -r /dev/hwrandom" - @echo "###" -- openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ -+ openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \ - -x509 -config x509.genkey \ - -outform DER -out signing_key.x509 \ - -keyout signing_key.priv --- -1.7.12.1 - - -From 4c13d777ecee93ae75dae3184473003acff05a53 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 28 Sep 2012 11:16:57 +0100 -Subject: [PATCH 27/37] MODSIGN: Use utf8 strings in signer's name in - autogenerated X.509 certs - -Place an indication that the certificate should use utf8 strings into the -x509.genkey template generated by kernel/Makefile. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - kernel/Makefile | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/kernel/Makefile b/kernel/Makefile -index a799029..e951adf 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -194,6 +194,7 @@ x509.genkey: - @echo >>x509.genkey "default_bits = 4096" - @echo >>x509.genkey "distinguished_name = req_distinguished_name" - @echo >>x509.genkey "prompt = no" -+ @echo >>x509.genkey "string_mask = utf8only" - @echo >>x509.genkey "x509_extensions = myexts" - @echo >>x509.genkey - @echo >>x509.genkey "[ req_distinguished_name ]" --- -1.7.12.1 - - -From 836513a2dd15675d4ad5fefa585d1b866bec4995 Mon Sep 17 00:00:00 2001 -From: Rusty Russell -Date: Tue, 2 Oct 2012 14:35:24 +0930 -Subject: [PATCH 28/37] MODSIGN: Make mrproper should remove generated files. - -It doesn't, because the clean targets don't include kernel/Makefile, and -because two files were missing from the list. - -Signed-off-by: Rusty Russell ---- - Makefile | 5 ++++- - kernel/Makefile | 1 - - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index b4f9eb5..e4292ea 100644 ---- a/Makefile -+++ b/Makefile -@@ -995,7 +995,10 @@ MRPROPER_DIRS += include/config usr/include include/generated \ - arch/*/include/generated - MRPROPER_FILES += .config .config.old .version .old_version \ - include/linux/version.h \ -- Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS -+ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ -+ signing_key.priv signing_key.x509 x509.genkey \ -+ extra_certificates signing_key.x509.keyid \ -+ signing_key.x509.signer - - # clean - Delete most, but leave enough to build external modules - # -diff --git a/kernel/Makefile b/kernel/Makefile -index e951adf..d3611c8 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -208,4 +208,3 @@ x509.genkey: - @echo >>x509.genkey "subjectKeyIdentifier=hash" - @echo >>x509.genkey "authorityKeyIdentifier=keyid" - endif --CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates --- -1.7.12.1 - - -From 855c92bdf2fb006e4190650b809a6216579395d5 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Tue, 2 Oct 2012 14:36:16 +0100 -Subject: [PATCH 29/37] MODSIGN: Fix 32-bit overflow in X.509 certificate - validity date checking - -The current choice of lifetime for the autogenerated X.509 of 100 years, -putting the validTo date in 2112, causes problems on 32-bit systems where a -32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. - -This can result in something like: - - Loading module verification certificates - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired - MODSIGN: Problem loading in-kernel X.509 certificate (-127) - -Or: - - X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid - MODSIGN: Problem loading in-kernel X.509 certificate (-129) - -Instead of turning the dates into time_t values and comparing, turn the system -clock and the ASN.1 dates into tm structs and compare those piecemeal instead. - -Reported-by: Rusty Russell -Signed-off-by: David Howells -Acked-by: Josh Boyer -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/x509_cert_parser.c | 25 +++++++++--------- - crypto/asymmetric_keys/x509_parser.h | 4 +-- - crypto/asymmetric_keys/x509_public_key.c | 42 +++++++++++++++++++++++++++---- - 3 files changed, 51 insertions(+), 20 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index 8fcac94..db07e8c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, - /* - * Record a certificate time. - */ --static int x509_note_time(time_t *_time, size_t hdrlen, -+static int x509_note_time(struct tm *tm, size_t hdrlen, - unsigned char tag, - const unsigned char *value, size_t vlen) - { -- unsigned YY, MM, DD, hh, mm, ss; - const unsigned char *p = value; - - #define dec2bin(X) ((X) - '0') -@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, - /* UTCTime: YYMMDDHHMMSSZ */ - if (vlen != 13) - goto unsupported_time; -- YY = DD2bin(p); -- if (YY > 50) -- YY += 1900; -+ tm->tm_year = DD2bin(p); -+ if (tm->tm_year >= 50) -+ tm->tm_year += 1900; - else -- YY += 2000; -+ tm->tm_year += 2000; - } else if (tag == ASN1_GENTIM) { - /* GenTime: YYYYMMDDHHMMSSZ */ - if (vlen != 15) - goto unsupported_time; -- YY = DD2bin(p) * 100 + DD2bin(p); -+ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); - } else { - goto unsupported_time; - } - -- MM = DD2bin(p); -- DD = DD2bin(p); -- hh = DD2bin(p); -- mm = DD2bin(p); -- ss = DD2bin(p); -+ tm->tm_year -= 1900; -+ tm->tm_mon = DD2bin(p) - 1; -+ tm->tm_mday = DD2bin(p); -+ tm->tm_hour = DD2bin(p); -+ tm->tm_min = DD2bin(p); -+ tm->tm_sec = DD2bin(p); - - if (*p != 'Z') - goto unsupported_time; - -- *_time = mktime(YY, MM, DD, hh, mm, ss); - return 0; - - unsupported_time: -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index 635053f..f86dc5f 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -18,8 +18,8 @@ struct x509_certificate { - char *subject; /* Name of certificate subject */ - char *fingerprint; /* Key fingerprint as hex */ - char *authority; /* Authority key fingerprint as hex */ -- time_t valid_from; -- time_t valid_to; -+ struct tm valid_from; -+ struct tm valid_to; - enum pkey_algo pkey_algo : 8; /* Public key algorithm */ - enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ - enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 716917c..5ab736d 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -106,7 +106,7 @@ error_no_sig: - static int x509_key_preparse(struct key_preparsed_payload *prep) - { - struct x509_certificate *cert; -- time_t now; -+ struct tm now; - size_t srlen, sulen; - char *desc = NULL; - int ret; -@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); -+ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, -+ cert->valid_from.tm_mday, cert->valid_from.tm_hour, -+ cert->valid_from.tm_min, cert->valid_from.tm_sec); -+ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, -+ cert->valid_to.tm_mday, cert->valid_to.tm_hour, -+ cert->valid_to.tm_min, cert->valid_to.tm_sec); - pr_devel("Cert Signature: %s + %s\n", - pkey_algo[cert->sig_pkey_algo], - pkey_hash_algo[cert->sig_hash_algo]); -@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- now = CURRENT_TIME.tv_sec; -- if (now < cert->valid_from) { -+ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -+ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, -+ now.tm_hour, now.tm_min, now.tm_sec); -+ if (now.tm_year < cert->valid_from.tm_year || -+ (now.tm_year == cert->valid_from.tm_year && -+ (now.tm_mon < cert->valid_from.tm_mon || -+ (now.tm_mon == cert->valid_from.tm_mon && -+ (now.tm_mday < cert->valid_from.tm_mday || -+ (now.tm_mday == cert->valid_from.tm_mday && -+ (now.tm_hour < cert->valid_from.tm_hour || -+ (now.tm_hour == cert->valid_from.tm_hour && -+ (now.tm_min < cert->valid_from.tm_min || -+ (now.tm_min == cert->valid_from.tm_min && -+ (now.tm_sec < cert->valid_from.tm_sec -+ ))))))))))) { - pr_warn("Cert %s is not yet valid\n", cert->fingerprint); - ret = -EKEYREJECTED; - goto error_free_cert; - } -- if (now >= cert->valid_to) { -+ if (now.tm_year > cert->valid_to.tm_year || -+ (now.tm_year == cert->valid_to.tm_year && -+ (now.tm_mon > cert->valid_to.tm_mon || -+ (now.tm_mon == cert->valid_to.tm_mon && -+ (now.tm_mday > cert->valid_to.tm_mday || -+ (now.tm_mday == cert->valid_to.tm_mday && -+ (now.tm_hour > cert->valid_to.tm_hour || -+ (now.tm_hour == cert->valid_to.tm_hour && -+ (now.tm_min > cert->valid_to.tm_min || -+ (now.tm_min == cert->valid_to.tm_min && -+ (now.tm_sec > cert->valid_to.tm_sec -+ ))))))))))) { - pr_warn("Cert %s has expired\n", cert->fingerprint); - ret = -EKEYEXPIRED; - goto error_free_cert; --- -1.7.12.1 - - -From f69bc56c32645bcc0b1a9ee88be662e8246398b4 Mon Sep 17 00:00:00 2001 -From: Randy Dunlap -Date: Wed, 3 Oct 2012 16:04:46 -0700 -Subject: [PATCH 30/37] asymmetric keys: fix printk format warning - -Fix printk format warning in x509_cert_parser.c: - -crypto/asymmetric_keys/x509_cert_parser.c: In function 'x509_note_OID': -crypto/asymmetric_keys/x509_cert_parser.c:113:3: warning: format '%zu' expects type 'size_t', but argument 2 has type 'long unsigned int' - -Builds cleanly on i386 and x86_64. - -Signed-off-by: Randy Dunlap -Cc: David Howells -Cc: Herbert Xu -Cc: linux-crypto@vger.kernel.org -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/x509_cert_parser.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index db07e8c..7fabc4c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -110,7 +110,7 @@ int x509_note_OID(void *context, size_t hdrlen, - if (ctx->last_oid == OID__NR) { - char buffer[50]; - sprint_oid(value, vlen, buffer, sizeof(buffer)); -- pr_debug("Unknown OID: [%zu] %s\n", -+ pr_debug("Unknown OID: [%lu] %s\n", - (unsigned long)value - ctx->data, buffer); - } - return 0; --- -1.7.12.1 - - -From 81338d71c284b7d001004e4a03abfce2d2144087 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 4 Oct 2012 14:21:23 +0100 -Subject: [PATCH 31/37] X.509: Convert some printk calls to pr_devel - -Some debugging printk() calls should've been converted to pr_devel() calls. -Do that now. - -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - crypto/asymmetric_keys/x509_public_key.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 5ab736d..06007f0 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -118,11 +118,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); - pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -- printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, - cert->valid_from.tm_mday, cert->valid_from.tm_hour, - cert->valid_from.tm_min, cert->valid_from.tm_sec); -- printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, - cert->valid_to.tm_mday, cert->valid_to.tm_hour, - cert->valid_to.tm_min, cert->valid_to.tm_sec); -@@ -138,7 +138,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - } - - time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -- printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -+ pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", - now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, - now.tm_hour, now.tm_min, now.tm_sec); - if (now.tm_year < cert->valid_from.tm_year || --- -1.7.12.1 - - -From 1054ea17fe1bf8f2087197c453626153d4649ac5 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Thu, 4 Oct 2012 14:21:23 +0100 -Subject: [PATCH 32/37] X.509: Fix indefinite length element skip error - handling - -asn1_find_indefinite_length() returns an error indicator of -1, which the -caller asn1_ber_decoder() places in a size_t (which is usually unsigned) and -then checks to see whether it is less than 0 (which it can't be). This can -lead to the following warning: - - lib/asn1_decoder.c:320 asn1_ber_decoder() - warn: unsigned 'len' is never less than zero. - -Instead, asn1_find_indefinite_length() update the caller's idea of the data -cursor and length separately from returning the error code. - -Reported-by: Dan Carpenter -Signed-off-by: David Howells -Signed-off-by: Rusty Russell ---- - lib/asn1_decoder.c | 28 +++++++++++++++++++--------- - 1 file changed, 19 insertions(+), 9 deletions(-) - -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -index 2e4196d..de2c8b5 100644 ---- a/lib/asn1_decoder.c -+++ b/lib/asn1_decoder.c -@@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { - - /* - * Find the length of an indefinite length object -+ * @data: The data buffer -+ * @datalen: The end of the innermost containing element in the buffer -+ * @_dp: The data parse cursor (updated before returning) -+ * @_len: Where to return the size of the element. -+ * @_errmsg: Where to return a pointer to an error message on error - */ - static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, -- const char **_errmsg, size_t *_err_dp) -+ size_t *_dp, size_t *_len, -+ const char **_errmsg) - { - unsigned char tag, tmp; -- size_t dp = 0, len, n; -+ size_t dp = *_dp, len, n; - int indef_level = 1; - - next_tag: -@@ -67,8 +73,11 @@ next_tag: - /* It appears to be an EOC. */ - if (data[dp++] != 0) - goto invalid_eoc; -- if (--indef_level <= 0) -- return dp; -+ if (--indef_level <= 0) { -+ *_len = dp - *_dp; -+ *_dp = dp; -+ return 0; -+ } - goto next_tag; - } - -@@ -122,7 +131,7 @@ data_overrun_error: - missing_eoc: - *_errmsg = "Missing EOC in indefinite len cons"; - error: -- *_err_dp = dp; -+ *_dp = dp; - return -1; - } - -@@ -315,13 +324,14 @@ next_op: - skip_data: - if (!(flags & FLAG_CONS)) { - if (flags & FLAG_INDEFINITE_LENGTH) { -- len = asn1_find_indefinite_length( -- data + dp, datalen - dp, &errmsg, &dp); -- if (len < 0) -+ ret = asn1_find_indefinite_length( -+ data, datalen, &dp, &len, &errmsg); -+ if (ret < 0) - goto error; -+ } else { -+ dp += len; - } - pr_debug("- LEAF: %zu\n", len); -- dp += len; - } - pc += asn1_op_lengths[op]; - goto next_op; --- -1.7.12.1 - - -From 4ae37452e7450971072481b98f6e1c29e5165c1e Mon Sep 17 00:00:00 2001 -From: Rusty Russell -Date: Fri, 19 Oct 2012 11:53:15 +1030 -Subject: [PATCH 33/37] kbuild: sign the modules at install time - -Linus deleted the old code and put signing on the install command, -I fixed it to extract the keyid and signer-name within sign-file -and cleaned up that script now it always signs in-place. - -Some enthusiast should convert sign-key to perl and pull -x509keyid into it. - -Signed-off-by: Rusty Russell -Signed-off-by: Linus Torvalds ---- - Makefile | 11 +++++++ - scripts/Makefile.modinst | 2 +- - scripts/Makefile.modpost | 77 +----------------------------------------------- - scripts/sign-file | 44 +++++++++++---------------- - scripts/x509keyid | 16 +++++----- - 5 files changed, 39 insertions(+), 111 deletions(-) - -diff --git a/Makefile b/Makefile -index e4292ea..1cc5de4 100644 ---- a/Makefile -+++ b/Makefile -@@ -714,6 +714,17 @@ endif # INSTALL_MOD_STRIP - export mod_strip_cmd - - -+ifeq ($(CONFIG_MODULE_SIG),y) -+MODSECKEY = ./signing_key.priv -+MODPUBKEY = ./signing_key.x509 -+export MODPUBKEY -+mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid -+else -+mod_sign_cmd = true -+endif -+export mod_sign_cmd -+ -+ - ifeq ($(KBUILD_EXTMOD),) - core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ - -diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst -index efa5d94..38367bd 100644 ---- a/scripts/Makefile.modinst -+++ b/scripts/Makefile.modinst -@@ -17,7 +17,7 @@ __modinst: $(modules) - @: - - quiet_cmd_modules_install = INSTALL $@ -- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) -+ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) - - # Modules built outside the kernel source tree go into extra by default - INSTALL_MOD_DIR ?= extra -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 2a4d1a1..08dce14 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -14,8 +14,7 @@ - # 3) create one .mod.c file pr. module - # 4) create one Module.symvers file with CRC for all exported symbols - # 5) compile all .mod.c files --# 6) final link of the module to a (or ) file --# 7) signs the modules to a file -+# 6) final link of the module to a file - - # Step 3 is used to place certain information in the module's ELF - # section, including information such as: -@@ -33,8 +32,6 @@ - # Step 4 is solely used to allow module versioning in external modules, - # where the CRC of each module is retrieved from the Module.symvers file. - --# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. -- - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined - # symbols in the final module linking stage - # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. -@@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE - targets += $(modules:.ko=.mod.o) - - # Step 6), final link of the modules --ifneq ($(CONFIG_MODULE_SIG),y) - quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) - - targets += $(modules) --else --quiet_cmd_ld_ko_unsigned_o = LD [M] $@ -- cmd_ld_ko_unsigned_o = \ -- $(LD) -r $(LDFLAGS) \ -- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -- -o $@ $(filter-out FORCE,$^) \ -- $(if $(AFTER_LINK),; $(AFTER_LINK)) -- --$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE -- $(call if_changed,ld_ko_unsigned_o) -- --targets += $(modules:.ko=.ko.unsigned) -- --# Step 7), sign the modules --MODSECKEY = ./signing_key.priv --MODPUBKEY = ./signing_key.x509 -- --ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) --ifeq ($(KBUILD_SRC),) -- # no O= is being used -- SCRIPTS_DIR := scripts --else -- SCRIPTS_DIR := $(KBUILD_SRC)/scripts --endif --SIGN_MODULES := 1 --else --SIGN_MODULES := 0 --endif -- --# only sign if it's an in-tree module --ifneq ($(KBUILD_EXTMOD),) --SIGN_MODULES := 0 --endif - --# We strip the module as best we can - note that using both strip and eu-strip --# results in a smaller module than using either alone. --EU_STRIP = $(shell which eu-strip || echo true) -- --quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ -- cmd_sign_ko_stripped_ko_unsigned = \ -- cp $< $@ && \ -- strip -x -g $@ && \ -- $(EU_STRIP) $@ -- --ifeq ($(SIGN_MODULES),1) -- --quiet_cmd_genkeyid = GENKEYID $@ -- cmd_genkeyid = \ -- perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid -- --%.signer %.keyid: % -- $(call if_changed,genkeyid) -- --KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid --quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ -- cmd_sign_ko_ko_stripped = \ -- sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ --else --KEYRING_DEP := --quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ -- cmd_sign_ko_ko_unsigned = \ -- cp $< $@ --endif -- --$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE -- $(call if_changed,sign_ko_ko_stripped) -- --$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE -- $(call if_changed,sign_ko_stripped_ko_unsigned) -- --targets += $(modules) --endif - - # Add FORCE to the prequisites of a target to force it to be always rebuilt. - # --------------------------------------------------------------------------- -diff --git a/scripts/sign-file b/scripts/sign-file -index e58e34e..095a953 100644 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -1,8 +1,8 @@ --#!/bin/sh -+#!/bin/bash - # - # Sign a module file using the given key. - # --# Format: sign-file -+# Format: sign-file - # - - scripts=`dirname $0` -@@ -15,8 +15,8 @@ fi - - key="$1" - x509="$2" --src="$3" --dst="$4" -+keyid_script="$3" -+mod="$4" - - if [ ! -r "$key" ] - then -@@ -29,16 +29,6 @@ then - echo "Can't read X.509 certificate" >&2 - exit 2 - fi --if [ ! -r "$x509.signer" ] --then -- echo "Can't read Signer name" >&2 -- exit 2; --fi --if [ ! -r "$x509.keyid" ] --then -- echo "Can't read Key identifier" >&2 -- exit 2; --fi - - # - # Signature parameters -@@ -83,33 +73,35 @@ fi - - ( - perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? --openssl dgst $dgst -binary $src || exit $? --) >$src.dig || exit $? -+openssl dgst $dgst -binary $mod || exit $? -+) >$mod.dig || exit $? - - # - # Generate the binary signature, which will be just the integer that comprises - # the signature with no metadata attached. - # --openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? --signerlen=`stat -c %s $x509.signer` --keyidlen=`stat -c %s $x509.keyid` --siglen=`stat -c %s $src.sig` -+openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? -+ -+SIGNER="`perl $keyid_script $x509 signer-name`" -+KEYID="`perl $keyid_script $x509 keyid`" -+keyidlen=${#KEYID} -+siglen=${#SIGNER} - - # - # Build the signed binary - # - ( -- cat $src || exit $? -+ cat $mod || exit $? - echo '~Module signature appended~' || exit $? -- cat $x509.signer $x509.keyid || exit $? -+ echo -n "$SIGNER" || exit $? -+ echo -n "$KEYID" || exit $? - - # Preface each signature integer with a 2-byte BE length - perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -- cat $src.sig || exit $? -+ cat $mod.sig || exit $? - - # Generate the information block - perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? --) >$dst~ || exit $? -+) >$mod~ || exit $? - --# Permit in-place signing --mv $dst~ $dst || exit $? -+mv $mod~ $mod || exit $? -diff --git a/scripts/x509keyid b/scripts/x509keyid -index c8e91a4..4241ec6 100755 ---- a/scripts/x509keyid -+++ b/scripts/x509keyid -@@ -22,7 +22,7 @@ use strict; - - my $raw_data; - --die "Need three filenames\n" if ($#ARGV != 2); -+die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); - - my $src = $ARGV[0]; - -@@ -259,10 +259,10 @@ die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" - - my $id_key_id = asn1_retrieve($subject_key_id->[1]); - --open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; --print OUTFD $id_name; --close OUTFD || die $ARGV[1]; -- --open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; --print OUTFD $id_key_id; --close OUTFD || die $ARGV[2]; -+if ($ARGV[1] eq "signer-name") { -+ print $id_name; -+} elsif ($ARGV[1] eq "keyid") { -+ print $id_key_id; -+} else { -+ die "Unknown arg"; -+} --- -1.7.12.1 - - -From 4aa23562520f07f4f27edb5c289bc289438005a0 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Fri, 19 Oct 2012 12:43:19 -0700 -Subject: [PATCH 34/37] kbuild: Fix module signature generation - -Rusty had clearly not actually tested his module signing changes that I -(trustingly) applied as commit e2a666d52b48 ("kbuild: sign the modules -at install time"). That commit had multiple bugs: - - - using "${#VARIABLE}" to get the number of characters in a shell - variable may look clever, but it's locale-dependent: it returns the - number of *characters*, not bytes. And we do need bytes. - - So don't use "${#..}" expansion, do the stupid "wc -c" thing instead - (where "c" stands for "bytes", not "characters", despite the letter. - - - Rusty had confused "siglen" and "signerlen", and his conversion - didn't set "signerlen" at all, and incorrectly set "siglen" to the - size of the signer, not the size of the signature. - -End result: the modified sign-file script did create something that -superficially *looked* like a signature, but didn't actually work at -all, and would fail the signature check. Oops. - -Tssk, tssk, Rusty. - -But Rusty was definitely right that this whole thing should be rewritten -in perl by somebody who has the perl-fu to do so. That is not me, -though - I'm just doing an emergency fix for the shell script. - -Cc: Rusty Russell -Signed-off-by: Linus Torvalds ---- - scripts/sign-file | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/scripts/sign-file b/scripts/sign-file -index 095a953..d014abd 100644 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -81,11 +81,12 @@ openssl dgst $dgst -binary $mod || exit $? - # the signature with no metadata attached. - # - openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? -+siglen=`stat -c %s $mod.sig` - - SIGNER="`perl $keyid_script $x509 signer-name`" - KEYID="`perl $keyid_script $x509 keyid`" --keyidlen=${#KEYID} --siglen=${#SIGNER} -+keyidlen=$(echo -n "$KEYID" | wc -c) -+signerlen=$(echo -n "$SIGNER" | wc -c) - - # - # Build the signed binary --- -1.7.12.1 - - -From f51b71db2cae9539acaa4d64a9e708d7aac1f879 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 19 Oct 2012 23:56:37 +0100 -Subject: [PATCH 35/37] MODSIGN: perlify sign-file and merge in x509keyid - -Turn sign-file into perl and merge in x509keyid. The latter doesn't -need to be a separate script as it doesn't actually need to work out the -SHA1 sum of the X.509 certificate itself, since it can get that from the -X.509 certificate. - -Signed-off-by: David Howells -Signed-off-by: Linus Torvalds ---- - Makefile | 2 +- - scripts/sign-file | 477 +++++++++++++++++++++++++++++++++++++++++++++--------- - scripts/x509keyid | 268 ------------------------------ - 3 files changed, 400 insertions(+), 347 deletions(-) - mode change 100644 => 100755 scripts/sign-file - delete mode 100755 scripts/x509keyid - -diff --git a/Makefile b/Makefile -index 1cc5de4..f4f9cdb 100644 ---- a/Makefile -+++ b/Makefile -@@ -718,7 +718,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) - MODSECKEY = ./signing_key.priv - MODPUBKEY = ./signing_key.x509 - export MODPUBKEY --mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid -+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) - else - mod_sign_cmd = true - endif -diff --git a/scripts/sign-file b/scripts/sign-file -old mode 100644 -new mode 100755 -index d014abd..d37d130 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -1,108 +1,429 @@ --#!/bin/bash -+#!/usr/bin/perl -w - # - # Sign a module file using the given key. - # --# Format: sign-file -+# Format: - # -+# ./scripts/sign-file [-v] [] -+# -+# -+use strict; -+use FileHandle; -+use IPC::Open2; -+ -+my $verbose = 0; -+if ($#ARGV >= 0 && $ARGV[0] eq "-v") { -+ $verbose = 1; -+ shift; -+} -+ -+die "Format: ./scripts/sign-file [-v] []\n" -+ if ($#ARGV != 2 && $#ARGV != 3); -+ -+my $private_key = $ARGV[0]; -+my $x509 = $ARGV[1]; -+my $module = $ARGV[2]; -+my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; -+ -+die "Can't read private key\n" unless (-r $private_key); -+die "Can't read X.509 certificate\n" unless (-r $x509); -+die "Can't read module\n" unless (-r $module); -+ -+# -+# Read the kernel configuration -+# -+my %config = ( -+ CONFIG_MODULE_SIG_SHA512 => 1 -+ ); -+ -+if (-r ".config") { -+ open(FD, "<.config") || die ".config"; -+ while () { -+ if ($_ =~ /^(CONFIG_.*)=[ym]/) { -+ $config{$1} = 1; -+ } -+ } -+ close(FD); -+} - --scripts=`dirname $0` -+# -+# Function to read the contents of a file into a variable. -+# -+sub read_file($) -+{ -+ my ($file) = @_; -+ my $contents; -+ my $len; -+ -+ open(FD, "<$file") || die $file; -+ binmode FD; -+ my @st = stat(FD); -+ die $file if (!@st); -+ $len = read(FD, $contents, $st[7]) || die $file; -+ close(FD) || die $file; -+ die "$file: Wanted length ", $st[7], ", got ", $len, "\n" -+ if ($len != $st[7]); -+ return $contents; -+} -+ -+############################################################################### -+# -+# First of all, we have to parse the X.509 certificate to find certain details -+# about it. -+# -+# We read the DER-encoded X509 certificate and parse it to extract the Subject -+# name and Subject Key Identifier. Theis provides the data we need to build -+# the certificate identifier. -+# -+# The signer's name part of the identifier is fabricated from the commonName, -+# the organizationName or the emailAddress components of the X.509 subject -+# name. -+# -+# The subject key ID is used to select which of that signer's certificates -+# we're intending to use to sign the module. -+# -+############################################################################### -+my $x509_certificate = read_file($x509); - --CONFIG_MODULE_SIG_SHA512=y --if [ -r .config ] --then -- . ./.config --fi -+my $UNIV = 0 << 6; -+my $APPL = 1 << 6; -+my $CONT = 2 << 6; -+my $PRIV = 3 << 6; - --key="$1" --x509="$2" --keyid_script="$3" --mod="$4" -+my $CONS = 0x20; - --if [ ! -r "$key" ] --then -- echo "Can't read private key" >&2 -- exit 2 --fi -+my $BOOLEAN = 0x01; -+my $INTEGER = 0x02; -+my $BIT_STRING = 0x03; -+my $OCTET_STRING = 0x04; -+my $NULL = 0x05; -+my $OBJ_ID = 0x06; -+my $UTF8String = 0x0c; -+my $SEQUENCE = 0x10; -+my $SET = 0x11; -+my $UTCTime = 0x17; -+my $GeneralizedTime = 0x18; - --if [ ! -r "$x509" ] --then -- echo "Can't read X.509 certificate" >&2 -- exit 2 --fi -+my %OIDs = ( -+ pack("CCC", 85, 4, 3) => "commonName", -+ pack("CCC", 85, 4, 6) => "countryName", -+ pack("CCC", 85, 4, 10) => "organizationName", -+ pack("CCC", 85, 4, 11) => "organizationUnitName", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -+ pack("CCC", 85, 29, 19) => "basicConstraints" -+); -+ -+############################################################################### -+# -+# Extract an ASN.1 element from a string and return information about it. -+# -+############################################################################### -+sub asn1_extract($$@) -+{ -+ my ($cursor, $expected_tag, $optional) = @_; -+ -+ return [ -1 ] -+ if ($cursor->[1] == 0 && $optional); -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -+ if ($cursor->[1] < 2); -+ -+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ -+ if ($expected_tag != -1 && $tag != $expected_tag) { -+ return [ -1 ] -+ if ($optional); -+ die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -+ " not ", $expected_tag, ")\n"; -+ } -+ -+ $cursor->[0] += 2; -+ $cursor->[1] -= 2; -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" -+ if (($tag & 0x1f) == 0x1f); -+ die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -+ if ($len == 0x80); -+ -+ if ($len > 0x80) { -+ my $l = $len - 0x80; -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -+ if ($cursor->[1] < $l); -+ -+ if ($l == 0x1) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -+ } elsif ($l = 0x2) { -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -+ } elsif ($l = 0x3) { -+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -+ } elsif ($l = 0x4) { -+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -+ } else { -+ die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -+ } -+ -+ $cursor->[0] += $l; -+ $cursor->[1] -= $l; -+ } -+ -+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -+ if ($cursor->[1] < $len); -+ -+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -+ $cursor->[0] += $len; -+ $cursor->[1] -= $len; -+ -+ return $ret; -+} -+ -+############################################################################### -+# -+# Retrieve the data referred to by a cursor -+# -+############################################################################### -+sub asn1_retrieve($) -+{ -+ my ($cursor) = @_; -+ my ($offset, $len, $data) = @$cursor; -+ return substr($$data, $offset, $len); -+} -+ -+############################################################################### -+# -+# Roughly parse the X.509 certificate -+# -+############################################################################### -+my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; -+ -+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -+ -+my $subject_key_id = (); -+my $authority_key_id = (); -+ -+# -+# Parse the extension list -+# -+if ($extension_list->[0] != -1) { -+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -+ -+ while ($extensions->[1]->[1] > 0) { -+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -+ -+ my $raw_oid = asn1_retrieve($x_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $x_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($x_val->[1]); -+ -+ if ($x_type eq "subjectKeyIdentifier") { -+ my $vcursor = [ 0, length($raw_value), \$raw_value ]; -+ -+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -+ } -+ } -+} -+ -+############################################################################### -+# -+# Determine what we're going to use as the signer's name. In order of -+# preference, take one of: commonName, organizationName or emailAddress. -+# -+############################################################################### -+my $org = ""; -+my $cn = ""; -+my $email = ""; -+ -+while ($subject->[1]->[1] > 0) { -+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -+ my $n_val = asn1_extract($attr->[1], -1); -+ -+ my $raw_oid = asn1_retrieve($n_oid->[1]); -+ next if (!exists($OIDs{$raw_oid})); -+ my $n_type = $OIDs{$raw_oid}; -+ -+ my $raw_value = asn1_retrieve($n_val->[1]); -+ -+ if ($n_type eq "organizationName") { -+ $org = $raw_value; -+ } elsif ($n_type eq "commonName") { -+ $cn = $raw_value; -+ } elsif ($n_type eq "emailAddress") { -+ $email = $raw_value; -+ } -+} -+ -+my $signers_name = $email; -+ -+if ($org && $cn) { -+ # Don't use the organizationName if the commonName repeats it -+ if (length($org) <= length($cn) && -+ substr($cn, 0, length($org)) eq $org) { -+ $signers_name = $cn; -+ goto got_id_name; -+ } -+ -+ # Or a signifcant chunk of it -+ if (length($org) >= 7 && -+ length($cn) >= 7 && -+ substr($cn, 0, 7) eq substr($org, 0, 7)) { -+ $signers_name = $cn; -+ goto got_id_name; -+ } -+ -+ $signers_name = $org . ": " . $cn; -+} elsif ($org) { -+ $signers_name = $org; -+} elsif ($cn) { -+ $signers_name = $cn; -+} -+ -+got_id_name: -+ -+die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -+ if (!$subject_key_id); -+ -+my $key_identifier = asn1_retrieve($subject_key_id->[1]); -+ -+############################################################################### -+# -+# Create and attach the module signature -+# -+############################################################################### - - # - # Signature parameters - # --algo=1 # Public-key crypto algorithm: RSA --hash= # Digest algorithm --id_type=1 # Identifier type: X.509 -+my $algo = 1; # Public-key crypto algorithm: RSA -+my $hash = 0; # Digest algorithm -+my $id_type = 1; # Identifier type: X.509 - - # - # Digest the data - # --dgst= --if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] --then -- prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" -- dgst=-sha1 -- hash=2 --elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] --then -- prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" -- dgst=-sha224 -- hash=7 --elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] --then -- prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" -- dgst=-sha256 -- hash=4 --elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] --then -- prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" -- dgst=-sha384 -- hash=5 --elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] --then -- prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" -- dgst=-sha512 -- hash=6 --else -- echo "$0: Can't determine hash algorithm" >&2 -- exit 2 --fi -- --( --perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? --openssl dgst $dgst -binary $mod || exit $? --) >$mod.dig || exit $? -+my ($dgst, $prologue) = (); -+if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) { -+ $prologue = pack("C*", -+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, -+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, -+ 0x05, 0x00, 0x04, 0x14); -+ $dgst = "-sha1"; -+ $hash = 2; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) { -+ $prologue = pack("C*", -+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, -+ 0x05, 0x00, 0x04, 0x1C); -+ $dgst = "-sha224"; -+ $hash = 7; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) { -+ $prologue = pack("C*", -+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, -+ 0x05, 0x00, 0x04, 0x20); -+ $dgst = "-sha256"; -+ $hash = 4; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) { -+ $prologue = pack("C*", -+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, -+ 0x05, 0x00, 0x04, 0x30); -+ $dgst = "-sha384"; -+ $hash = 5; -+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) { -+ $prologue = pack("C*", -+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, -+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, -+ 0x05, 0x00, 0x04, 0x40); -+ $dgst = "-sha512"; -+ $hash = 6; -+} else { -+ die "Can't determine hash algorithm"; -+} -+ -+# -+# Generate the digest and read from openssl's stdout -+# -+my $digest; -+$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst"; - - # - # Generate the binary signature, which will be just the integer that comprises - # the signature with no metadata attached. - # --openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $? --siglen=`stat -c %s $mod.sig` -+my $pid; -+$pid = open2(*read_from, *write_to, -+ "openssl rsautl -sign -inkey $private_key -keyform PEM") || -+ die "openssl rsautl"; -+binmode write_to; -+print write_to $prologue . $digest || die "pipe to openssl rsautl"; -+close(write_to) || die "pipe to openssl rsautl"; -+ -+binmode read_from; -+my $signature; -+read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; -+close(read_from) || die "pipe from openssl rsautl"; -+$signature = pack("n", length($signature)) . $signature, - --SIGNER="`perl $keyid_script $x509 signer-name`" --KEYID="`perl $keyid_script $x509 keyid`" --keyidlen=$(echo -n "$KEYID" | wc -c) --signerlen=$(echo -n "$SIGNER" | wc -c) -+waitpid($pid, 0) || die; -+die "openssl rsautl died: $?" if ($? >> 8); - - # - # Build the signed binary - # --( -- cat $mod || exit $? -- echo '~Module signature appended~' || exit $? -- echo -n "$SIGNER" || exit $? -- echo -n "$KEYID" || exit $? -+my $unsigned_module = read_file($module); -+ -+my $magic_number = "~Module signature appended~\n"; -+ -+my $info = pack("CCCCCxxxN", -+ $algo, $hash, $id_type, -+ length($signers_name), -+ length($key_identifier), -+ length($signature)); - -- # Preface each signature integer with a 2-byte BE length -- perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? -- cat $mod.sig || exit $? -+if ($verbose) { -+ print "Size of unsigned module: ", length($unsigned_module), "\n"; -+ print "Size of magic number : ", length($magic_number), "\n"; -+ print "Size of signer's name : ", length($signers_name), "\n"; -+ print "Size of key identifier : ", length($key_identifier), "\n"; -+ print "Size of signature : ", length($signature), "\n"; -+ print "Size of informaton : ", length($info), "\n"; -+ print "Signer's name : '", $signers_name, "'\n"; -+ print "Digest : $dgst\n"; -+} - -- # Generate the information block -- perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? --) >$mod~ || exit $? -+open(FD, ">$dest") || die $dest; -+binmode FD; -+print FD -+ $unsigned_module, -+ $magic_number, -+ $signers_name, -+ $key_identifier, -+ $signature, -+ $info -+ ; -+close FD || die $dest; - --mv $mod~ $mod || exit $? -+if ($#ARGV != 3) { -+ rename($dest, $module) || die $module; -+} -diff --git a/scripts/x509keyid b/scripts/x509keyid -deleted file mode 100755 -index 4241ec6..0000000 ---- a/scripts/x509keyid -+++ /dev/null -@@ -1,268 +0,0 @@ --#!/usr/bin/perl -w --# --# Generate an identifier from an X.509 certificate that can be placed in a --# module signature to indentify the key to use. --# --# Format: --# --# ./scripts/x509keyid --# --# We read the DER-encoded X509 certificate and parse it to extract the Subject --# name and Subject Key Identifier. The provide the data we need to build the --# certificate identifier. --# --# The signer's name part of the identifier is fabricated from the commonName, --# the organizationName or the emailAddress components of the X.509 subject --# name and written to the second named file. --# --# The subject key ID to select which of that signer's certificates we're --# intending to use to sign the module is written to the third named file. --# --use strict; -- --my $raw_data; -- --die "Need a filename [keyid|signer-name]\n" if ($#ARGV != 1); -- --my $src = $ARGV[0]; -- --open(FD, "<$src") || die $src; --binmode FD; --my @st = stat(FD); --die $src if (!@st); --read(FD, $raw_data, $st[7]) || die $src; --close(FD); -- --my $UNIV = 0 << 6; --my $APPL = 1 << 6; --my $CONT = 2 << 6; --my $PRIV = 3 << 6; -- --my $CONS = 0x20; -- --my $BOOLEAN = 0x01; --my $INTEGER = 0x02; --my $BIT_STRING = 0x03; --my $OCTET_STRING = 0x04; --my $NULL = 0x05; --my $OBJ_ID = 0x06; --my $UTF8String = 0x0c; --my $SEQUENCE = 0x10; --my $SET = 0x11; --my $UTCTime = 0x17; --my $GeneralizedTime = 0x18; -- --my %OIDs = ( -- pack("CCC", 85, 4, 3) => "commonName", -- pack("CCC", 85, 4, 6) => "countryName", -- pack("CCC", 85, 4, 10) => "organizationName", -- pack("CCC", 85, 4, 11) => "organizationUnitName", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", -- pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", -- pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", -- pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", -- pack("CCC", 85, 29, 19) => "basicConstraints" --); -- --############################################################################### --# --# Extract an ASN.1 element from a string and return information about it. --# --############################################################################### --sub asn1_extract($$@) --{ -- my ($cursor, $expected_tag, $optional) = @_; -- -- return [ -1 ] -- if ($cursor->[1] == 0 && $optional); -- -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" -- if ($cursor->[1] < 2); -- -- my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); -- -- if ($expected_tag != -1 && $tag != $expected_tag) { -- return [ -1 ] -- if ($optional); -- die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, -- " not ", $expected_tag, ")\n"; -- } -- -- $cursor->[0] += 2; -- $cursor->[1] -= 2; -- -- die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" -- if (($tag & 0x1f) == 0x1f); -- die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" -- if ($len == 0x80); -- -- if ($len > 0x80) { -- my $l = $len - 0x80; -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" -- if ($cursor->[1] < $l); -- -- if ($l == 0x1) { -- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); -- } elsif ($l = 0x2) { -- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); -- } elsif ($l = 0x3) { -- $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; -- $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); -- } elsif ($l = 0x4) { -- $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); -- } else { -- die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; -- } -- -- $cursor->[0] += $l; -- $cursor->[1] -= $l; -- } -- -- die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" -- if ($cursor->[1] < $len); -- -- my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; -- $cursor->[0] += $len; -- $cursor->[1] -= $len; -- -- return $ret; --} -- --############################################################################### --# --# Retrieve the data referred to by a cursor --# --############################################################################### --sub asn1_retrieve($) --{ -- my ($cursor) = @_; -- my ($offset, $len, $data) = @$cursor; -- return substr($$data, $offset, $len); --} -- --############################################################################### --# --# Roughly parse the X.509 certificate --# --############################################################################### --my $cursor = [ 0, length($raw_data), \$raw_data ]; -- --my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); --my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); --my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); --my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); --my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); --my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); --my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); --my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); -- --my $subject_key_id = (); --my $authority_key_id = (); -- --# --# Parse the extension list --# --if ($extension_list->[0] != -1) { -- my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); -- -- while ($extensions->[1]->[1] > 0) { -- my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); -- my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); -- my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); -- my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); -- -- my $raw_oid = asn1_retrieve($x_oid->[1]); -- next if (!exists($OIDs{$raw_oid})); -- my $x_type = $OIDs{$raw_oid}; -- -- my $raw_value = asn1_retrieve($x_val->[1]); -- -- if ($x_type eq "subjectKeyIdentifier") { -- my $vcursor = [ 0, length($raw_value), \$raw_value ]; -- -- $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); -- } -- } --} -- --############################################################################### --# --# Determine what we're going to use as the signer's name. In order of --# preference, take one of: commonName, organizationName or emailAddress. --# --############################################################################### --my $org = ""; --my $cn = ""; --my $email = ""; -- --while ($subject->[1]->[1] > 0) { -- my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); -- my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); -- my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); -- my $n_val = asn1_extract($attr->[1], -1); -- -- my $raw_oid = asn1_retrieve($n_oid->[1]); -- next if (!exists($OIDs{$raw_oid})); -- my $n_type = $OIDs{$raw_oid}; -- -- my $raw_value = asn1_retrieve($n_val->[1]); -- -- if ($n_type eq "organizationName") { -- $org = $raw_value; -- } elsif ($n_type eq "commonName") { -- $cn = $raw_value; -- } elsif ($n_type eq "emailAddress") { -- $email = $raw_value; -- } --} -- --my $id_name = $email; -- --if ($org && $cn) { -- # Don't use the organizationName if the commonName repeats it -- if (length($org) <= length($cn) && -- substr($cn, 0, length($org)) eq $org) { -- $id_name = $cn; -- goto got_id_name; -- } -- -- # Or a signifcant chunk of it -- if (length($org) >= 7 && -- length($cn) >= 7 && -- substr($cn, 0, 7) eq substr($org, 0, 7)) { -- $id_name = $cn; -- goto got_id_name; -- } -- -- $id_name = $org . ": " . $cn; --} elsif ($org) { -- $id_name = $org; --} elsif ($cn) { -- $id_name = $cn; --} -- --got_id_name: -- --############################################################################### --# --# Output the signer's name and the key identifier that we're going to include --# in module signatures. --# --############################################################################### --die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" -- if (!$subject_key_id); -- --my $id_key_id = asn1_retrieve($subject_key_id->[1]); -- --if ($ARGV[1] eq "signer-name") { -- print $id_name; --} elsif ($ARGV[1] eq "keyid") { -- print $id_key_id; --} else { -- die "Unknown arg"; --} --- -1.7.12.1 - - -From 02c76d9df8ff5387b9131799750895475f87c351 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Fri, 19 Oct 2012 23:56:45 +0100 -Subject: [PATCH 36/37] MODSIGN: Cleanup .gitignore - -The module build process no longer creates intermediate files for module -signing, so remove them from .gitignore. - -Signed-off-by: David Howells -Signed-off-by: Linus Torvalds ---- - .gitignore | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/.gitignore b/.gitignore -index 0f2f40f..92bd0e4 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,10 +14,6 @@ - *.o.* - *.a - *.s --*.ko.unsigned --*.ko.stripped --*.ko.stripped.dig --*.ko.stripped.sig - *.ko - *.so - *.so.dbg -@@ -95,6 +91,4 @@ GTAGS - extra_certificates - signing_key.priv - signing_key.x509 --signing_key.x509.keyid --signing_key.x509.signer - x509.genkey --- -1.7.12.1 - - -From fd08dfdc1a0022b48b7a5d4599cb4d46bf099882 Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Sat, 20 Oct 2012 01:19:29 +0100 -Subject: [PATCH 37/37] MODSIGN: Move the magic string to the end of a module - and eliminate the search - -Emit the magic string that indicates a module has a signature after the -signature data instead of before it. This allows module_sig_check() to -be made simpler and faster by the elimination of the search for the -magic string. Instead we just need to do a single memcmp(). - -This works because at the end of the signature data there is the -fixed-length signature information block. This block then falls -immediately prior to the magic number. - -From the contents of the information block, it is trivial to calculate -the size of the signature data and thus the size of the actual module -data. - -Signed-off-by: David Howells -Signed-off-by: Linus Torvalds ---- - kernel/module-internal.h | 3 +-- - kernel/module.c | 26 +++++++++----------------- - kernel/module_signing.c | 24 +++++++++++++++--------- - scripts/sign-file | 6 +++--- - 4 files changed, 28 insertions(+), 31 deletions(-) - -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 6114a13..24f9247 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -11,5 +11,4 @@ - - extern struct key *modsign_keyring; - --extern int mod_verify_sig(const void *mod, unsigned long modlen, -- const void *sig, unsigned long siglen); -+extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module.c b/kernel/module.c -index 3e8b1a7..0cfcccc 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -2441,25 +2441,17 @@ static inline void kmemleak_load_module(const struct module *mod, - - #ifdef CONFIG_MODULE_SIG - static int module_sig_check(struct load_info *info, -- const void *mod, unsigned long *len) -+ const void *mod, unsigned long *_len) - { - int err = -ENOKEY; -- const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -- const void *p = mod, *end = mod + *len; -- -- /* Poor man's memmem. */ -- while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { -- if (p + markerlen > end) -- break; -- -- if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { -- const void *sig = p + markerlen; -- /* Truncate module up to signature. */ -- *len = p - mod; -- err = mod_verify_sig(mod, *len, sig, end - sig); -- break; -- } -- p++; -+ unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; -+ unsigned long len = *_len; -+ -+ if (len > markerlen && -+ memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { -+ /* We truncate the module to discard the signature */ -+ *_len -= markerlen; -+ err = mod_verify_sig(mod, _len); - } - - if (!err) { -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index 6b09f69..d492a23 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - /* - * Verify the signature on a module. - */ --int mod_verify_sig(const void *mod, unsigned long modlen, -- const void *sig, unsigned long siglen) -+int mod_verify_sig(const void *mod, unsigned long *_modlen) - { - struct public_key_signature *pks; - struct module_signature ms; - struct key *key; -- size_t sig_len; -+ const void *sig; -+ size_t modlen = *_modlen, sig_len; - int ret; - -- pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); -+ pr_devel("==>%s(,%lu)\n", __func__, modlen); - -- if (siglen <= sizeof(ms)) -+ if (modlen <= sizeof(ms)) - return -EBADMSG; - -- memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); -- siglen -= sizeof(ms); -+ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); -+ modlen -= sizeof(ms); - - sig_len = be32_to_cpu(ms.sig_len); -- if (sig_len >= siglen || -- siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) -+ if (sig_len >= modlen) - return -EBADMSG; -+ modlen -= sig_len; -+ if ((size_t)ms.signer_len + ms.key_id_len >= modlen) -+ return -EBADMSG; -+ modlen -= (size_t)ms.signer_len + ms.key_id_len; -+ -+ *_modlen = modlen; -+ sig = mod + modlen; - - /* For the moment, only support RSA and X.509 identifiers */ - if (ms.algo != PKEY_ALGO_RSA || -diff --git a/scripts/sign-file b/scripts/sign-file -index d37d130..87ca59d 100755 ---- a/scripts/sign-file -+++ b/scripts/sign-file -@@ -403,11 +403,11 @@ my $info = pack("CCCCCxxxN", - - if ($verbose) { - print "Size of unsigned module: ", length($unsigned_module), "\n"; -- print "Size of magic number : ", length($magic_number), "\n"; - print "Size of signer's name : ", length($signers_name), "\n"; - print "Size of key identifier : ", length($key_identifier), "\n"; - print "Size of signature : ", length($signature), "\n"; - print "Size of informaton : ", length($info), "\n"; -+ print "Size of magic number : ", length($magic_number), "\n"; - print "Signer's name : '", $signers_name, "'\n"; - print "Digest : $dgst\n"; - } -@@ -416,11 +416,11 @@ open(FD, ">$dest") || die $dest; - binmode FD; - print FD - $unsigned_module, -- $magic_number, - $signers_name, - $key_identifier, - $signature, -- $info -+ $info, -+ $magic_number - ; - close FD || die $dest; - --- -1.7.12.1 - -From f6a79af8f3701b5a0df431a76adee212616154dc Mon Sep 17 00:00:00 2001 -From: Rusty Russell -Date: Tue, 6 Nov 2012 11:46:59 +1030 -Subject: [PATCH] modules: don't break modules_install on external modules - with no key. - -The script still spits out an error ("Can't read private key") but we -don't break modules_install. - -Reported-by: Bruno Wolff III -Original-patch-by: Josh Boyer -Signed-off-by: Rusty Russell ---- - scripts/Makefile.modinst | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst -index dda4b2b..ecbb447 100644 ---- a/scripts/Makefile.modinst -+++ b/scripts/Makefile.modinst -@@ -16,8 +16,9 @@ PHONY += $(modules) - __modinst: $(modules) - @: - -+# Don't stop modules_install if we can't sign external modules. - quiet_cmd_modules_install = INSTALL $@ -- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) -+ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) - - # Modules built outside the kernel source tree go into extra by default - INSTALL_MOD_DIR ?= extra --- -1.7.6.5 - diff --git a/smp_irq_move_cleanup_interrupt.patch b/smp_irq_move_cleanup_interrupt.patch deleted file mode 100644 index c9b385a94..000000000 --- a/smp_irq_move_cleanup_interrupt.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 94777fc51b3ad85ff9f705ddf7cdd0eb3bbad5a6 -Author: Dimitri Sivanich -Date: Tue Oct 16 07:50:21 2012 -0500 - - x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt - - Posting this patch to fix an issue concerning sparse irq's that - I raised a while back. There was discussion about adding - refcounting to sparse irqs (to fix other potential race - conditions), but that does not appear to have been addressed - yet. This covers the only issue of this type that I've - encountered in this area. - - A NULL pointer dereference can occur in - smp_irq_move_cleanup_interrupt() if we haven't yet setup the - irq_cfg pointer in the irq_desc.irq_data.chip_data. - - In create_irq_nr() there is a window where we have set - vector_irq in __assign_irq_vector(), but not yet called - irq_set_chip_data() to set the irq_cfg pointer. - - Should an IRQ_MOVE_CLEANUP_VECTOR hit the cpu in question during - this time, smp_irq_move_cleanup_interrupt() will attempt to - process the aforementioned irq, but panic when accessing - irq_cfg. - - Only continue processing the irq if irq_cfg is non-NULL. - - Signed-off-by: Dimitri Sivanich - Cc: Suresh Siddha - Cc: Joerg Roedel - Cc: Yinghai Lu - Cc: Alexander Gordeev - Link: http://lkml.kernel.org/r/20121016125021.GA22935@sgi.com - Signed-off-by: Ingo Molnar - -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index c265593..1817fa9 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) - continue; - - cfg = irq_cfg(irq); -+ if (!cfg) -+ continue; -+ - raw_spin_lock(&desc->lock); - - /* diff --git a/sources b/sources index fdb1a3193..d19fe4262 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -bd4bba74093405887d521309a74c19e9 patch-3.6.11.xz +21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz +48f5f530b048e387e978e3e49de7742a patch-3.7.1.xz diff --git a/team-net-next-20120808.patch b/team-net-next-20120808.patch deleted file mode 100644 index c738a4724..000000000 --- a/team-net-next-20120808.patch +++ /dev/null @@ -1,499 +0,0 @@ -Update team driver to latest net-next. - -Split patches available here: -http://people.redhat.com/jpirko/f18_team_update_2/ - -Jiri Pirko (4): - netlink: add signed types - team: add signed 32-bit team option type - team: add per port priority option - team: add support for queue override by setting queue_id for port - - drivers/net/team/team.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++- - include/linux/if_team.h | 7 ++ - include/net/netlink.h | 98 +++++++++++++++++++++++ - 3 files changed, 303 insertions(+), 2 deletions(-) - -Signed-off-by: Jiri Pirko - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 87707ab..ba10c46 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -658,6 +658,122 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) - } - - -+/************************************* -+ * Multiqueue Tx port select override -+ *************************************/ -+ -+static int team_queue_override_init(struct team *team) -+{ -+ struct list_head *listarr; -+ unsigned int queue_cnt = team->dev->num_tx_queues - 1; -+ unsigned int i; -+ -+ if (!queue_cnt) -+ return 0; -+ listarr = kmalloc(sizeof(struct list_head) * queue_cnt, GFP_KERNEL); -+ if (!listarr) -+ return -ENOMEM; -+ team->qom_lists = listarr; -+ for (i = 0; i < queue_cnt; i++) -+ INIT_LIST_HEAD(listarr++); -+ return 0; -+} -+ -+static void team_queue_override_fini(struct team *team) -+{ -+ kfree(team->qom_lists); -+} -+ -+static struct list_head *__team_get_qom_list(struct team *team, u16 queue_id) -+{ -+ return &team->qom_lists[queue_id - 1]; -+} -+ -+/* -+ * note: already called with rcu_read_lock -+ */ -+static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb) -+{ -+ struct list_head *qom_list; -+ struct team_port *port; -+ -+ if (!team->queue_override_enabled || !skb->queue_mapping) -+ return false; -+ qom_list = __team_get_qom_list(team, skb->queue_mapping); -+ list_for_each_entry_rcu(port, qom_list, qom_list) { -+ if (!team_dev_queue_xmit(team, port, skb)) -+ return true; -+ } -+ return false; -+} -+ -+static void __team_queue_override_port_del(struct team *team, -+ struct team_port *port) -+{ -+ list_del_rcu(&port->qom_list); -+ synchronize_rcu(); -+ INIT_LIST_HEAD(&port->qom_list); -+} -+ -+static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, -+ struct team_port *cur) -+{ -+ if (port->priority < cur->priority) -+ return true; -+ if (port->priority > cur->priority) -+ return false; -+ if (port->index < cur->index) -+ return true; -+ return false; -+} -+ -+static void __team_queue_override_port_add(struct team *team, -+ struct team_port *port) -+{ -+ struct team_port *cur; -+ struct list_head *qom_list; -+ struct list_head *node; -+ -+ if (!port->queue_id || !team_port_enabled(port)) -+ return; -+ -+ qom_list = __team_get_qom_list(team, port->queue_id); -+ node = qom_list; -+ list_for_each_entry(cur, qom_list, qom_list) { -+ if (team_queue_override_port_has_gt_prio_than(port, cur)) -+ break; -+ node = &cur->qom_list; -+ } -+ list_add_tail_rcu(&port->qom_list, node); -+} -+ -+static void __team_queue_override_enabled_check(struct team *team) -+{ -+ struct team_port *port; -+ bool enabled = false; -+ -+ list_for_each_entry(port, &team->port_list, list) { -+ if (!list_empty(&port->qom_list)) { -+ enabled = true; -+ break; -+ } -+ } -+ if (enabled == team->queue_override_enabled) -+ return; -+ netdev_dbg(team->dev, "%s queue override\n", -+ enabled ? "Enabling" : "Disabling"); -+ team->queue_override_enabled = enabled; -+} -+ -+static void team_queue_override_port_refresh(struct team *team, -+ struct team_port *port) -+{ -+ __team_queue_override_port_del(team, port); -+ __team_queue_override_port_add(team, port); -+ __team_queue_override_enabled_check(team); -+} -+ -+ - /**************** - * Port handling - ****************/ -@@ -688,6 +804,7 @@ static void team_port_enable(struct team *team, - hlist_add_head_rcu(&port->hlist, - team_port_index_hash(team, port->index)); - team_adjust_ops(team); -+ team_queue_override_port_refresh(team, port); - if (team->ops.port_enabled) - team->ops.port_enabled(team, port); - } -@@ -716,6 +833,7 @@ static void team_port_disable(struct team *team, - hlist_del_rcu(&port->hlist); - __reconstruct_port_hlist(team, port->index); - port->index = -1; -+ team_queue_override_port_refresh(team, port); - __team_adjust_ops(team, team->en_port_count - 1); - /* - * Wait until readers see adjusted ops. This ensures that -@@ -881,6 +999,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) - - port->dev = port_dev; - port->team = team; -+ INIT_LIST_HEAD(&port->qom_list); - - port->orig.mtu = port_dev->mtu; - err = dev_set_mtu(port_dev, dev->mtu); -@@ -1092,6 +1211,49 @@ static int team_user_linkup_en_option_set(struct team *team, - return 0; - } - -+static int team_priority_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ ctx->data.s32_val = port->priority; -+ return 0; -+} -+ -+static int team_priority_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ port->priority = ctx->data.s32_val; -+ team_queue_override_port_refresh(team, port); -+ return 0; -+} -+ -+static int team_queue_id_option_get(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ ctx->data.u32_val = port->queue_id; -+ return 0; -+} -+ -+static int team_queue_id_option_set(struct team *team, -+ struct team_gsetter_ctx *ctx) -+{ -+ struct team_port *port = ctx->info->port; -+ -+ if (port->queue_id == ctx->data.u32_val) -+ return 0; -+ if (ctx->data.u32_val >= team->dev->real_num_tx_queues) -+ return -EINVAL; -+ port->queue_id = ctx->data.u32_val; -+ team_queue_override_port_refresh(team, port); -+ return 0; -+} -+ -+ - static const struct team_option team_options[] = { - { - .name = "mode", -@@ -1120,6 +1282,20 @@ static const struct team_option team_options[] = { - .getter = team_user_linkup_en_option_get, - .setter = team_user_linkup_en_option_set, - }, -+ { -+ .name = "priority", -+ .type = TEAM_OPTION_TYPE_S32, -+ .per_port = true, -+ .getter = team_priority_option_get, -+ .setter = team_priority_option_set, -+ }, -+ { -+ .name = "queue_id", -+ .type = TEAM_OPTION_TYPE_U32, -+ .per_port = true, -+ .getter = team_queue_id_option_get, -+ .setter = team_queue_id_option_set, -+ }, - }; - - static struct lock_class_key team_netdev_xmit_lock_key; -@@ -1155,6 +1331,9 @@ static int team_init(struct net_device *dev) - for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) - INIT_HLIST_HEAD(&team->en_port_hlist[i]); - INIT_LIST_HEAD(&team->port_list); -+ err = team_queue_override_init(team); -+ if (err) -+ goto err_team_queue_override_init; - - team_adjust_ops(team); - -@@ -1170,6 +1349,8 @@ static int team_init(struct net_device *dev) - return 0; - - err_options_register: -+ team_queue_override_fini(team); -+err_team_queue_override_init: - free_percpu(team->pcpu_stats); - - return err; -@@ -1187,6 +1368,7 @@ static void team_uninit(struct net_device *dev) - - __team_change_mode(team, NULL); /* cleanup */ - __team_options_unregister(team, team_options, ARRAY_SIZE(team_options)); -+ team_queue_override_fini(team); - mutex_unlock(&team->lock); - } - -@@ -1216,10 +1398,12 @@ static int team_close(struct net_device *dev) - static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct team *team = netdev_priv(dev); -- bool tx_success = false; -+ bool tx_success; - unsigned int len = skb->len; - -- tx_success = team->ops.transmit(team, skb); -+ tx_success = team_queue_override_transmit(team, skb); -+ if (!tx_success) -+ tx_success = team->ops.transmit(team, skb); - if (tx_success) { - struct team_pcpu_stats *pcpu_stats; - -@@ -1787,6 +1971,12 @@ static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team, - nla_put_flag(skb, TEAM_ATTR_OPTION_DATA)) - goto nest_cancel; - break; -+ case TEAM_OPTION_TYPE_S32: -+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_S32)) -+ goto nest_cancel; -+ if (nla_put_s32(skb, TEAM_ATTR_OPTION_DATA, ctx.data.s32_val)) -+ goto nest_cancel; -+ break; - default: - BUG(); - } -@@ -1975,6 +2165,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case NLA_FLAG: - opt_type = TEAM_OPTION_TYPE_BOOL; - break; -+ case NLA_S32: -+ opt_type = TEAM_OPTION_TYPE_S32; -+ break; - default: - goto team_put; - } -@@ -2031,6 +2224,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info) - case TEAM_OPTION_TYPE_BOOL: - ctx.data.bool_val = attr_data ? true : false; - break; -+ case TEAM_OPTION_TYPE_S32: -+ ctx.data.s32_val = nla_get_s32(attr_data); -+ break; - default: - BUG(); - } -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 6960fc1..33fcc20 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -67,6 +67,9 @@ struct team_port { - struct netpoll *np; - #endif - -+ s32 priority; /* lower number ~ higher priority */ -+ u16 queue_id; -+ struct list_head qom_list; /* node in queue override mapping list */ - long mode_priv[0]; - }; - -@@ -130,6 +133,7 @@ enum team_option_type { - TEAM_OPTION_TYPE_STRING, - TEAM_OPTION_TYPE_BINARY, - TEAM_OPTION_TYPE_BOOL, -+ TEAM_OPTION_TYPE_S32, - }; - - struct team_option_inst_info { -@@ -146,6 +150,7 @@ struct team_gsetter_ctx { - u32 len; - } bin_val; - bool bool_val; -+ s32 s32_val; - } data; - struct team_option_inst_info *info; - }; -@@ -197,6 +202,8 @@ struct team { - - const struct team_mode *mode; - struct team_mode_ops ops; -+ bool queue_override_enabled; -+ struct list_head *qom_lists; /* array of queue override mapping lists */ - long mode_priv[TEAM_MODE_PRIV_LONGS]; - }; - -diff --git a/include/net/netlink.h b/include/net/netlink.h -index 785f37a..09175d5 100644 ---- a/include/net/netlink.h -+++ b/include/net/netlink.h -@@ -98,6 +98,10 @@ - * nla_put_u16(skb, type, value) add u16 attribute to skb - * nla_put_u32(skb, type, value) add u32 attribute to skb - * nla_put_u64(skb, type, value) add u64 attribute to skb -+ * nla_put_s8(skb, type, value) add s8 attribute to skb -+ * nla_put_s16(skb, type, value) add s16 attribute to skb -+ * nla_put_s32(skb, type, value) add s32 attribute to skb -+ * nla_put_s64(skb, type, value) add s64 attribute to skb - * nla_put_string(skb, type, str) add string attribute to skb - * nla_put_flag(skb, type) add flag attribute to skb - * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb -@@ -121,6 +125,10 @@ - * nla_get_u16(nla) get payload for a u16 attribute - * nla_get_u32(nla) get payload for a u32 attribute - * nla_get_u64(nla) get payload for a u64 attribute -+ * nla_get_s8(nla) get payload for a s8 attribute -+ * nla_get_s16(nla) get payload for a s16 attribute -+ * nla_get_s32(nla) get payload for a s32 attribute -+ * nla_get_s64(nla) get payload for a s64 attribute - * nla_get_flag(nla) return 1 if flag is true - * nla_get_msecs(nla) get payload for a msecs attribute - * -@@ -160,6 +168,10 @@ enum { - NLA_NESTED_COMPAT, - NLA_NUL_STRING, - NLA_BINARY, -+ NLA_S8, -+ NLA_S16, -+ NLA_S32, -+ NLA_S64, - __NLA_TYPE_MAX, - }; - -@@ -183,6 +195,8 @@ enum { - * NLA_NESTED_COMPAT Minimum length of structure payload - * NLA_U8, NLA_U16, - * NLA_U32, NLA_U64, -+ * NLA_S8, NLA_S16, -+ * NLA_S32, NLA_S64, - * NLA_MSECS Leaving the length field zero will verify the - * given type fits, using it verifies minimum length - * just like "All other" -@@ -879,6 +893,50 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) - } - - /** -+ * nla_put_s8 - Add a s8 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s8), &value); -+} -+ -+/** -+ * nla_put_s16 - Add a s16 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s16), &value); -+} -+ -+/** -+ * nla_put_s32 - Add a s32 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s32), &value); -+} -+ -+/** -+ * nla_put_s64 - Add a s64 netlink attribute to a socket buffer -+ * @skb: socket buffer to add attribute to -+ * @attrtype: attribute type -+ * @value: numeric value -+ */ -+static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value) -+{ -+ return nla_put(skb, attrtype, sizeof(s64), &value); -+} -+ -+/** - * nla_put_string - Add a string netlink attribute to a socket buffer - * @skb: socket buffer to add attribute to - * @attrtype: attribute type -@@ -994,6 +1052,46 @@ static inline __be64 nla_get_be64(const struct nlattr *nla) - } - - /** -+ * nla_get_s32 - return payload of s32 attribute -+ * @nla: s32 netlink attribute -+ */ -+static inline s32 nla_get_s32(const struct nlattr *nla) -+{ -+ return *(s32 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s16 - return payload of s16 attribute -+ * @nla: s16 netlink attribute -+ */ -+static inline s16 nla_get_s16(const struct nlattr *nla) -+{ -+ return *(s16 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s8 - return payload of s8 attribute -+ * @nla: s8 netlink attribute -+ */ -+static inline s8 nla_get_s8(const struct nlattr *nla) -+{ -+ return *(s8 *) nla_data(nla); -+} -+ -+/** -+ * nla_get_s64 - return payload of s64 attribute -+ * @nla: s64 netlink attribute -+ */ -+static inline s64 nla_get_s64(const struct nlattr *nla) -+{ -+ s64 tmp; -+ -+ nla_memcpy(&tmp, nla, sizeof(tmp)); -+ -+ return tmp; -+} -+ -+/** - * nla_get_flag - return payload of flag attribute - * @nla: flag netlink attribute - */ - diff --git a/team-net-next-20121205.patch b/team-net-next-20121205.patch deleted file mode 100644 index 51249f9c1..000000000 --- a/team-net-next-20121205.patch +++ /dev/null @@ -1,60 +0,0 @@ - -Backport fixes from linus's tree. - -upstream commits backported: -commit 403f43c937d24832b18524f65415c0bbba6b5064 - team: bcast: convert return value of team_dev_queue_xmit() to bool correctly -commit 3ed7147189d2fbe8ac6da95db2fd9d6d52f53ce9 - team: fix hw_features setup - -Signed-off-by: Jiri Pirko ---- - drivers/net/team/team.c | 4 +++- - drivers/net/team/team_mode_broadcast.c | 6 +++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 5d8e1cb..f504773 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1792,10 +1792,12 @@ static void team_setup(struct net_device *dev) - - dev->features |= NETIF_F_LLTX; - dev->features |= NETIF_F_GRO; -- dev->hw_features = NETIF_F_HW_VLAN_TX | -+ dev->hw_features = TEAM_VLAN_FEATURES | -+ NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; - -+ dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM); - dev->features |= dev->hw_features; - } - -diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c -index 9db0171..c5db428 100644 ---- a/drivers/net/team/team_mode_broadcast.c -+++ b/drivers/net/team/team_mode_broadcast.c -@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) - if (last) { - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) { -- ret = team_dev_queue_xmit(team, last, -- skb2); -+ ret = !team_dev_queue_xmit(team, last, -+ skb2); - if (!sum_ret) - sum_ret = ret; - } -@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) - } - } - if (last) { -- ret = team_dev_queue_xmit(team, last, skb); -+ ret = !team_dev_queue_xmit(team, last, skb); - if (!sum_ret) - sum_ret = ret; - } --- -1.7.11.7 - diff --git a/team-net-next-update-20120927.patch b/team-net-next-update-20120927.patch deleted file mode 100644 index a61311619..000000000 --- a/team-net-next-update-20120927.patch +++ /dev/null @@ -1,335 +0,0 @@ ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/Kconfig -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/Kconfig -@@ -21,7 +21,7 @@ config NET_TEAM_MODE_BROADCAST - ---help--- - Basic mode where packets are transmitted always by all suitable ports. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_broadcast. -@@ -33,7 +33,7 @@ config NET_TEAM_MODE_ROUNDROBIN - Basic mode where port used for transmitting packets is selected in - round-robin fashion using packet counter. - -- All added ports are setup to have team's mac address. -+ All added ports are setup to have team's device address. - - To compile this team mode as a module, choose M here: the module - will be called team_mode_roundrobin. ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team.c -@@ -54,29 +54,29 @@ static struct team_port *team_port_get_r - } - - /* -- * Since the ability to change mac address for open port device is tested in -+ * Since the ability to change device address for open port device is tested in - * team_port_add, this function can be called without control of return value - */ --static int __set_port_mac(struct net_device *port_dev, -- const unsigned char *dev_addr) -+static int __set_port_dev_addr(struct net_device *port_dev, -+ const unsigned char *dev_addr) - { - struct sockaddr addr; - -- memcpy(addr.sa_data, dev_addr, ETH_ALEN); -- addr.sa_family = ARPHRD_ETHER; -+ memcpy(addr.sa_data, dev_addr, port_dev->addr_len); -+ addr.sa_family = port_dev->type; - return dev_set_mac_address(port_dev, &addr); - } - --static int team_port_set_orig_mac(struct team_port *port) -+static int team_port_set_orig_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->orig.dev_addr); -+ return __set_port_dev_addr(port->dev, port->orig.dev_addr); - } - --int team_port_set_team_mac(struct team_port *port) -+int team_port_set_team_dev_addr(struct team_port *port) - { -- return __set_port_mac(port->dev, port->team->dev->dev_addr); -+ return __set_port_dev_addr(port->dev, port->team->dev->dev_addr); - } --EXPORT_SYMBOL(team_port_set_team_mac); -+EXPORT_SYMBOL(team_port_set_team_dev_addr); - - static void team_refresh_port_linkup(struct team_port *port) - { -@@ -967,6 +967,8 @@ static struct netpoll_info *team_netpoll - #endif - - static void __team_port_change_port_added(struct team_port *port, bool linkup); -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev); - - static int team_port_add(struct team *team, struct net_device *port_dev) - { -@@ -975,9 +977,8 @@ static int team_port_add(struct team *te - char *portname = port_dev->name; - int err; - -- if (port_dev->flags & IFF_LOOPBACK || -- port_dev->type != ARPHRD_ETHER) { -- netdev_err(dev, "Device %s is of an unsupported type\n", -+ if (port_dev->flags & IFF_LOOPBACK) { -+ netdev_err(dev, "Device %s is loopback device. Loopback devices can't be added as a team port\n", - portname); - return -EINVAL; - } -@@ -988,6 +989,17 @@ static int team_port_add(struct team *te - return -EBUSY; - } - -+ if (port_dev->features & NETIF_F_VLAN_CHALLENGED && -+ vlan_uses_dev(dev)) { -+ netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n", -+ portname); -+ return -EPERM; -+ } -+ -+ err = team_dev_type_check_change(dev, port_dev); -+ if (err) -+ return err; -+ - if (port_dev->flags & IFF_UP) { - netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", - portname); -@@ -1010,7 +1022,7 @@ static int team_port_add(struct team *te - goto err_set_mtu; - } - -- memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN); -+ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); - - err = team_port_enter(team, port); - if (err) { -@@ -1091,7 +1103,7 @@ err_vids_add: - - err_dev_open: - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - - err_port_enter: - dev_set_mtu(port_dev, port->orig.mtu); -@@ -1129,7 +1141,7 @@ static int team_port_del(struct team *te - vlan_vids_del_by_dev(port_dev, dev); - dev_close(port_dev); - team_port_leave(team, port); -- team_port_set_orig_mac(port); -+ team_port_set_orig_dev_addr(port); - dev_set_mtu(port_dev, port->orig.mtu); - synchronize_rcu(); - kfree(port); -@@ -1480,17 +1492,18 @@ static void team_set_rx_mode(struct net_ - - static int team_set_mac_address(struct net_device *dev, void *p) - { -+ struct sockaddr *addr = p; - struct team *team = netdev_priv(dev); - struct team_port *port; -- int err; - -- err = eth_mac_addr(dev, p); -- if (err) -- return err; -+ if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; - rcu_read_lock(); - list_for_each_entry_rcu(port, &team->port_list, list) -- if (team->ops.port_change_mac) -- team->ops.port_change_mac(team, port); -+ if (team->ops.port_change_dev_addr) -+ team->ops.port_change_dev_addr(team, port); - rcu_read_unlock(); - return 0; - } -@@ -1721,6 +1734,45 @@ static const struct net_device_ops team_ - * rt netlink interface - ***********************/ - -+static void team_setup_by_port(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ dev->header_ops = port_dev->header_ops; -+ dev->type = port_dev->type; -+ dev->hard_header_len = port_dev->hard_header_len; -+ dev->addr_len = port_dev->addr_len; -+ dev->mtu = port_dev->mtu; -+ memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); -+ memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len); -+ dev->addr_assign_type &= ~NET_ADDR_RANDOM; -+} -+ -+static int team_dev_type_check_change(struct net_device *dev, -+ struct net_device *port_dev) -+{ -+ struct team *team = netdev_priv(dev); -+ char *portname = port_dev->name; -+ int err; -+ -+ if (dev->type == port_dev->type) -+ return 0; -+ if (!list_empty(&team->port_list)) { -+ netdev_err(dev, "Device %s is of different type\n", portname); -+ return -EBUSY; -+ } -+ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); -+ err = notifier_to_errno(err); -+ if (err) { -+ netdev_err(dev, "Refused to change device type\n"); -+ return err; -+ } -+ dev_uc_flush(dev); -+ dev_mc_flush(dev); -+ team_setup_by_port(dev, port_dev); -+ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); -+ return 0; -+} -+ - static void team_setup(struct net_device *dev) - { - ether_setup(dev); -@@ -2442,7 +2494,7 @@ static void __team_options_change_check( - list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); - } - err = team_nl_send_event_options_get(team, &sel_opt_inst_list); -- if (err) -+ if (err && err != -ESRCH) - netdev_warn(team->dev, "Failed to send options change via netlink (err %d)\n", - err); - } -@@ -2471,9 +2523,9 @@ static void __team_port_change_send(stru - - send_event: - err = team_nl_send_event_port_list_get(port->team); -- if (err) -- netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", -- port->dev->name); -+ if (err && err != -ESRCH) -+ netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", -+ port->dev->name, err); - - } - ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_broadcast.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_broadcast.c -@@ -48,18 +48,18 @@ static bool bc_transmit(struct team *tea - - static int bc_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void bc_port_change_mac(struct team *team, struct team_port *port) -+static void bc_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops bc_mode_ops = { - .transmit = bc_transmit, - .port_enter = bc_port_enter, -- .port_change_mac = bc_port_change_mac, -+ .port_change_dev_addr = bc_port_change_dev_addr, - }; - - static const struct team_mode bc_mode = { ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/drivers/net/team/team_mode_roundrobin.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/drivers/net/team/team_mode_roundrobin.c -@@ -66,18 +66,18 @@ drop: - - static int rr_port_enter(struct team *team, struct team_port *port) - { -- return team_port_set_team_mac(port); -+ return team_port_set_team_dev_addr(port); - } - --static void rr_port_change_mac(struct team *team, struct team_port *port) -+static void rr_port_change_dev_addr(struct team *team, struct team_port *port) - { -- team_port_set_team_mac(port); -+ team_port_set_team_dev_addr(port); - } - - static const struct team_mode_ops rr_mode_ops = { - .transmit = rr_transmit, - .port_enter = rr_port_enter, -- .port_change_mac = rr_port_change_mac, -+ .port_change_dev_addr = rr_port_change_dev_addr, - }; - - static const struct team_mode rr_mode = { ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_team.h -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_team.h -@@ -108,7 +108,7 @@ struct team_mode_ops { - bool (*transmit)(struct team *team, struct sk_buff *skb); - int (*port_enter)(struct team *team, struct team_port *port); - void (*port_leave)(struct team *team, struct team_port *port); -- void (*port_change_mac)(struct team *team, struct team_port *port); -+ void (*port_change_dev_addr)(struct team *team, struct team_port *port); - void (*port_enabled)(struct team *team, struct team_port *port); - void (*port_disabled)(struct team *team, struct team_port *port); - }; -@@ -238,7 +238,7 @@ static inline struct team_port *team_get - return NULL; - } - --extern int team_port_set_team_mac(struct team_port *port); -+extern int team_port_set_team_dev_addr(struct team_port *port); - extern int team_options_register(struct team *team, - const struct team_option *option, - size_t option_count); ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/include/linux/if_vlan.h -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/include/linux/if_vlan.h -@@ -74,8 +74,6 @@ static inline struct vlan_ethhdr *vlan_e - /* found in socket.c */ - extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); - --struct vlan_info; -- - static inline int is_vlan_dev(struct net_device *dev) - { - return dev->priv_flags & IFF_802_1Q_VLAN; -@@ -101,6 +99,8 @@ extern int vlan_vids_add_by_dev(struct n - const struct net_device *by_dev); - extern void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev); -+ -+extern bool vlan_uses_dev(const struct net_device *dev); - #else - static inline struct net_device * - __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) -@@ -151,6 +151,11 @@ static inline void vlan_vids_del_by_dev( - const struct net_device *by_dev) - { - } -+ -+static inline bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return false; -+} - #endif - - /** ---- linux-3.6.0-0.rc7.git2.1.fc18.x86_64.orig/net/8021q/vlan_core.c -+++ linux-3.6.0-0.rc7.git2.1.fc18.x86_64/net/8021q/vlan_core.c -@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_dev - vlan_vid_del(dev, vid_info->vid); - } - EXPORT_SYMBOL(vlan_vids_del_by_dev); -+ -+bool vlan_uses_dev(const struct net_device *dev) -+{ -+ return rtnl_dereference(dev->vlan_info) ? true : false; -+} -+EXPORT_SYMBOL(vlan_uses_dev); diff --git a/uprobes-upstream-backport.patch b/uprobes-upstream-backport.patch deleted file mode 100644 index 9614e41b9..000000000 --- a/uprobes-upstream-backport.patch +++ /dev/null @@ -1,1376 +0,0 @@ -Hello, - -Test builds: - f18: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635065 - f17: http://koji.fedoraproject.org/koji/taskinfo?taskID=4635062 - -The split-out series is available in the git repository at: - http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git - -Just jistone's patch is not upstream that exports functions. -Yes, I know it must go to upstream. :-) I will try to do what I can before -the next uprobes update. - ---------------------------------------------------------------- -Josh Stone (1): - uprobes: add exports necessary for uprobes use by modules - -Oleg Nesterov (35): - uprobes: Kill uprobes_state->count - uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap - uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending() - uprobes: Do not use -EEXIST in install_breakpoint() paths - uprobes: Introduce MMF_HAS_UPROBES - uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap() - uprobes: Remove "verify" argument from set_orig_insn() - uprobes: uprobes_treelock should not disable irqs - uprobes: Introduce MMF_RECALC_UPROBES - uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES - ptrace/x86: Introduce set_task_blockstep() helper - ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic - uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping - uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set - uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction - uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int" - uprobes: Do not leak UTASK_BP_HIT if find_active_uprobe() fails - uprobes: Do not setup ->active_uprobe/state prematurely - uprobes: Fix UPROBE_SKIP_SSTEP checks in handle_swbp() - uprobes: Kill UTASK_BP_HIT state - uprobes: Move clear_thread_flag(TIF_UPROBE) to uprobe_notify_resume() - uprobes: Change write_opcode() to use FOLL_FORCE - uprobes: Change valid_vma() to demand VM_MAYEXEC rather than VM_EXEC - uprobes: Restrict valid_vma(false) to skip VM_SHARED vmas - uprobes: Kill set_swbp()->is_swbp_at_addr() - uprobes: Introduce copy_opcode(), kill read_opcode() - uprobes: Kill set_orig_insn()->is_swbp_at_addr() - uprobes: Simplify is_swbp_at_addr(), remove stale comments - uprobes/x86: Only rep+nop can be emulated correctly - uprobes: Don't return success if alloc_uprobe() fails - uprobes: Do not delete uprobe if uprobe_unregister() fails - uprobes: Fix handle_swbp() vs unregister() + register() race - uprobes: Introduce prepare_uprobe() - uprobes: Fix prepare_uprobe() race with itself - uprobes: Fix the racy uprobe->flags manipulation - -Sebastian Andrzej Siewior (4): - uprobes: Remove check for uprobe variable in handle_swbp() - uprobes: Don't put NULL pointer in uprobe_register() - uprobes: Introduce arch_uprobe_enable/disable_step() - uprobes/x86: Implement x86 specific arch_uprobe_*_step - -Srikar Dronamraju (1): - uprobes: Remove redundant lock_page/unlock_page - - arch/x86/include/asm/processor.h | 2 + - arch/x86/include/asm/uprobes.h | 3 +- - arch/x86/kernel/signal.c | 4 +- - arch/x86/kernel/step.c | 53 ++-- - arch/x86/kernel/uprobes.c | 64 ++++- - include/linux/sched.h | 3 + - include/linux/uprobes.h | 26 +- - kernel/events/uprobes.c | 564 ++++++++++++++++++--------------------- - kernel/fork.c | 6 +- - kernel/ptrace.c | 6 + - 10 files changed, 375 insertions(+), 356 deletions(-) - -diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index d048cad..433d2e5 100644 ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -759,6 +759,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) - wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); - } - -+extern void set_task_blockstep(struct task_struct *task, bool on); -+ - /* - * from system description table in BIOS. Mostly for MCA use, but - * others may find it useful: -diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h -index f3971bb..8ff8be7 100644 ---- a/arch/x86/include/asm/uprobes.h -+++ b/arch/x86/include/asm/uprobes.h -@@ -42,10 +42,11 @@ struct arch_uprobe { - }; - - struct arch_uprobe_task { -- unsigned long saved_trap_nr; - #ifdef CONFIG_X86_64 - unsigned long saved_scratch_register; - #endif -+ unsigned int saved_trap_nr; -+ unsigned int saved_tf; - }; - - extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); -diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c -index b280908..0041e5a 100644 ---- a/arch/x86/kernel/signal.c -+++ b/arch/x86/kernel/signal.c -@@ -785,10 +785,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) - mce_notify_process(); - #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ - -- if (thread_info_flags & _TIF_UPROBE) { -- clear_thread_flag(TIF_UPROBE); -+ if (thread_info_flags & _TIF_UPROBE) - uprobe_notify_resume(regs); -- } - - /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) -diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c -index c346d11..cd3b243 100644 ---- a/arch/x86/kernel/step.c -+++ b/arch/x86/kernel/step.c -@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) - return 1; - } - -+void set_task_blockstep(struct task_struct *task, bool on) -+{ -+ unsigned long debugctl; -+ -+ /* -+ * Ensure irq/preemption can't change debugctl in between. -+ * Note also that both TIF_BLOCKSTEP and debugctl should -+ * be changed atomically wrt preemption. -+ * FIXME: this means that set/clear TIF_BLOCKSTEP is simply -+ * wrong if task != current, SIGKILL can wakeup the stopped -+ * tracee and set/clear can play with the running task, this -+ * can confuse the next __switch_to_xtra(). -+ */ -+ local_irq_disable(); -+ debugctl = get_debugctlmsr(); -+ if (on) { -+ debugctl |= DEBUGCTLMSR_BTF; -+ set_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } else { -+ debugctl &= ~DEBUGCTLMSR_BTF; -+ clear_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } -+ if (task == current) -+ update_debugctlmsr(debugctl); -+ local_irq_enable(); -+} -+ - /* - * Enable single or block step. - */ -@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) - * So no one should try to use debugger block stepping in a program - * that uses user-mode single stepping itself. - */ -- if (enable_single_step(child) && block) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl |= DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- set_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (enable_single_step(child) && block) -+ set_task_blockstep(child, true); -+ else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - } - - void user_enable_single_step(struct task_struct *child) -@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) - /* - * Make sure block stepping (BTF) is disabled. - */ -- if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - - /* Always clear TIF_SINGLESTEP... */ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); -diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c -index 36fd420..aafa555 100644 ---- a/arch/x86/kernel/uprobes.c -+++ b/arch/x86/kernel/uprobes.c -@@ -41,6 +41,9 @@ - /* Adjust the return address of a call insn */ - #define UPROBE_FIX_CALL 0x2 - -+/* Instruction will modify TF, don't change it */ -+#define UPROBE_FIX_SETF 0x4 -+ - #define UPROBE_FIX_RIP_AX 0x8000 - #define UPROBE_FIX_RIP_CX 0x4000 - -@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) - insn_get_opcode(insn); /* should be a nop */ - - switch (OPCODE1(insn)) { -+ case 0x9d: -+ /* popf */ -+ auprobe->fixups |= UPROBE_FIX_SETF; -+ break; - case 0xc3: /* ret/lret */ - case 0xcb: - case 0xc2: -@@ -644,32 +651,63 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) - - /* - * Skip these instructions as per the currently known x86 ISA. -- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } -+ * rep=0x66*; nop=0x90 - */ --bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) - { - int i; - - for (i = 0; i < MAX_UINSN_BYTES; i++) { -- if ((auprobe->insn[i] == 0x66)) -+ if (auprobe->insn[i] == 0x66) - continue; - - if (auprobe->insn[i] == 0x90) - return true; - -- if (i == (MAX_UINSN_BYTES - 1)) -- break; -+ break; -+ } -+ return false; -+} - -- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) -- return true; -+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ bool ret = __skip_sstep(auprobe, regs); -+ if (ret && (regs->flags & X86_EFLAGS_TF)) -+ send_sig(SIGTRAP, current, 0); -+ return ret; -+} - -- if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) -- return true; -+void arch_uprobe_enable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ struct pt_regs *regs = task_pt_regs(task); - -- if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) -- return true; -+ autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); - -- break; -+ regs->flags |= X86_EFLAGS_TF; -+ if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) -+ set_task_blockstep(task, false); -+} -+ -+void arch_uprobe_disable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); -+ struct pt_regs *regs = task_pt_regs(task); -+ /* -+ * The state of TIF_BLOCKSTEP was not saved so we can get an extra -+ * SIGTRAP if we do not clear TF. We need to examine the opcode to -+ * make it right. -+ */ -+ if (unlikely(trapped)) { -+ if (!autask->saved_tf) -+ regs->flags &= ~X86_EFLAGS_TF; -+ } else { -+ if (autask->saved_tf) -+ send_sig(SIGTRAP, task, 0); -+ else if (!(auprobe->fixups & UPROBE_FIX_SETF)) -+ regs->flags &= ~X86_EFLAGS_TF; - } -- return false; - } -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 23bddac..ba300be 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -446,6 +446,9 @@ extern int get_dumpable(struct mm_struct *mm); - #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ - #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ - -+#define MMF_HAS_UPROBES 19 /* has uprobes */ -+#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ -+ - #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) - - struct sighand_struct { -diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h -index efe4b33..2459457 100644 ---- a/include/linux/uprobes.h -+++ b/include/linux/uprobes.h -@@ -35,16 +35,6 @@ struct inode; - # include - #endif - --/* flags that denote/change uprobes behaviour */ -- --/* Have a copy of original instruction */ --#define UPROBE_COPY_INSN 0x1 -- --/* Dont run handlers when first register/ last unregister in progress*/ --#define UPROBE_RUN_HANDLER 0x2 --/* Can skip singlestep */ --#define UPROBE_SKIP_SSTEP 0x4 -- - struct uprobe_consumer { - int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); - /* -@@ -59,7 +49,6 @@ struct uprobe_consumer { - #ifdef CONFIG_UPROBES - enum uprobe_task_state { - UTASK_RUNNING, -- UTASK_BP_HIT, - UTASK_SSTEP, - UTASK_SSTEP_ACK, - UTASK_SSTEP_TRAPPED, -@@ -99,25 +88,27 @@ struct xol_area { - - struct uprobes_state { - struct xol_area *xol_area; -- atomic_t count; - }; -+ - extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); --extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); -+extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); - extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); - extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern int uprobe_mmap(struct vm_area_struct *vma); - extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); -+extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); - extern void uprobe_free_utask(struct task_struct *t); - extern void uprobe_copy_process(struct task_struct *t); - extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); -+extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); -+extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); - extern int uprobe_post_sstep_notifier(struct pt_regs *regs); - extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); - extern void uprobe_notify_resume(struct pt_regs *regs); - extern bool uprobe_deny_signal(void); - extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); - extern void uprobe_clear_state(struct mm_struct *mm); --extern void uprobe_reset_state(struct mm_struct *mm); - #else /* !CONFIG_UPROBES */ - struct uprobes_state { - }; -@@ -138,6 +129,10 @@ static inline void - uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { - } -+static inline void -+uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) -+{ -+} - static inline void uprobe_notify_resume(struct pt_regs *regs) - { - } -@@ -158,8 +153,5 @@ static inline void uprobe_copy_process(struct task_struct *t) - static inline void uprobe_clear_state(struct mm_struct *mm) - { - } --static inline void uprobe_reset_state(struct mm_struct *mm) --{ --} - #endif /* !CONFIG_UPROBES */ - #endif /* _LINUX_UPROBES_H */ -diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c -index c08a22d..e933f65 100644 ---- a/kernel/events/uprobes.c -+++ b/kernel/events/uprobes.c -@@ -27,6 +27,7 @@ - #include /* read_mapping_page */ - #include - #include -+#include - #include /* anon_vma_prepare */ - #include /* set_pte_at_notify */ - #include /* try_to_free_swap */ -@@ -78,15 +79,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; - */ - static atomic_t uprobe_events = ATOMIC_INIT(0); - -+/* Have a copy of original instruction */ -+#define UPROBE_COPY_INSN 0 -+/* Dont run handlers when first register/ last unregister in progress*/ -+#define UPROBE_RUN_HANDLER 1 -+/* Can skip singlestep */ -+#define UPROBE_SKIP_SSTEP 2 -+ - struct uprobe { - struct rb_node rb_node; /* node in the rb tree */ - atomic_t ref; - struct rw_semaphore consumer_rwsem; -+ struct mutex copy_mutex; /* TODO: kill me and UPROBE_COPY_INSN */ - struct list_head pending_list; - struct uprobe_consumer *consumers; - struct inode *inode; /* Also hold a ref to inode */ - loff_t offset; -- int flags; -+ unsigned long flags; - struct arch_uprobe arch; - }; - -@@ -100,17 +109,12 @@ struct uprobe { - */ - static bool valid_vma(struct vm_area_struct *vma, bool is_register) - { -- if (!vma->vm_file) -- return false; -+ vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED; - -- if (!is_register) -- return true; -+ if (is_register) -+ flags |= VM_WRITE; - -- if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) -- == (VM_READ|VM_EXEC)) -- return true; -- -- return false; -+ return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC; - } - - static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) -@@ -188,19 +192,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) - return *insn == UPROBE_SWBP_INSN; - } - -+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode) -+{ -+ void *kaddr = kmap_atomic(page); -+ memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE); -+ kunmap_atomic(kaddr); -+} -+ -+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode) -+{ -+ uprobe_opcode_t old_opcode; -+ bool is_swbp; -+ -+ copy_opcode(page, vaddr, &old_opcode); -+ is_swbp = is_swbp_insn(&old_opcode); -+ -+ if (is_swbp_insn(new_opcode)) { -+ if (is_swbp) /* register: already installed? */ -+ return 0; -+ } else { -+ if (!is_swbp) /* unregister: was it changed by us? */ -+ return 0; -+ } -+ -+ return 1; -+} -+ - /* - * NOTE: - * Expect the breakpoint instruction to be the smallest size instruction for - * the architecture. If an arch has variable length instruction and the - * breakpoint instruction is not of the smallest length instruction -- * supported by that architecture then we need to modify read_opcode / -+ * supported by that architecture then we need to modify is_swbp_at_addr and - * write_opcode accordingly. This would never be a problem for archs that - * have fixed length instructions. - */ - - /* - * write_opcode - write the opcode at a given virtual address. -- * @auprobe: arch breakpointing information. - * @mm: the probed process address space. - * @vaddr: the virtual address to store the opcode. - * @opcode: opcode to be written at @vaddr. -@@ -211,8 +240,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) - * For mm @mm, write the opcode at @vaddr. - * Return 0 (success) or a negative errno. - */ --static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, -- unsigned long vaddr, uprobe_opcode_t opcode) -+static int write_opcode(struct mm_struct *mm, unsigned long vaddr, -+ uprobe_opcode_t opcode) - { - struct page *old_page, *new_page; - void *vaddr_old, *vaddr_new; -@@ -221,10 +250,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - - retry: - /* Read the page with vaddr into memory */ -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); - if (ret <= 0) - return ret; - -+ ret = verify_opcode(old_page, vaddr, &opcode); -+ if (ret <= 0) -+ goto put_old; -+ - ret = -ENOMEM; - new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); - if (!new_page) -@@ -259,65 +292,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - } - - /** -- * read_opcode - read the opcode at a given virtual address. -- * @mm: the probed process address space. -- * @vaddr: the virtual address to read the opcode. -- * @opcode: location to store the read opcode. -- * -- * Called with mm->mmap_sem held (for read and with a reference to -- * mm. -- * -- * For mm @mm, read the opcode at @vaddr and store it in @opcode. -- * Return 0 (success) or a negative errno. -- */ --static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) --{ -- struct page *page; -- void *vaddr_new; -- int ret; -- -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); -- if (ret <= 0) -- return ret; -- -- lock_page(page); -- vaddr_new = kmap_atomic(page); -- vaddr &= ~PAGE_MASK; -- memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); -- kunmap_atomic(vaddr_new); -- unlock_page(page); -- -- put_page(page); -- -- return 0; --} -- --static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) --{ -- uprobe_opcode_t opcode; -- int result; -- -- if (current->mm == mm) { -- pagefault_disable(); -- result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -- sizeof(opcode)); -- pagefault_enable(); -- -- if (likely(result == 0)) -- goto out; -- } -- -- result = read_opcode(mm, vaddr, &opcode); -- if (result) -- return result; --out: -- if (is_swbp_insn(&opcode)) -- return 1; -- -- return 0; --} -- --/** - * set_swbp - store breakpoint at a given address. - * @auprobe: arch specific probepoint information. - * @mm: the probed process address space. -@@ -328,18 +302,7 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - */ - int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { -- int result; -- /* -- * See the comment near uprobes_hash(). -- */ -- result = is_swbp_at_addr(mm, vaddr); -- if (result == 1) -- return -EEXIST; -- -- if (result) -- return result; -- -- return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); -+ return write_opcode(mm, vaddr, UPROBE_SWBP_INSN); - } - - /** -@@ -347,25 +310,14 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned - * @mm: the probed process address space. - * @auprobe: arch specific probepoint information. - * @vaddr: the virtual address to insert the opcode. -- * @verify: if true, verify existance of breakpoint instruction. - * - * For mm @mm, restore the original opcode (opcode) at @vaddr. - * Return 0 (success) or a negative errno. - */ - int __weak --set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) -+set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (verify) { -- int result; -- -- result = is_swbp_at_addr(mm, vaddr); -- if (!result) -- return -EINVAL; -- -- if (result != 1) -- return result; -- } -- return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); -+ return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); - } - - static int match_uprobe(struct uprobe *l, struct uprobe *r) -@@ -415,11 +367,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) - static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) - { - struct uprobe *uprobe; -- unsigned long flags; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - uprobe = __find_uprobe(inode, offset); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - return uprobe; - } -@@ -466,15 +417,14 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) - */ - static struct uprobe *insert_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; - struct uprobe *u; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - u = __insert_uprobe(uprobe); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - /* For now assume that the instruction need not be single-stepped */ -- uprobe->flags |= UPROBE_SKIP_SSTEP; -+ __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); - - return u; - } -@@ -496,6 +446,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) - uprobe->inode = igrab(inode); - uprobe->offset = offset; - init_rwsem(&uprobe->consumer_rwsem); -+ mutex_init(&uprobe->copy_mutex); - - /* add to uprobes_tree, sorted on inode:offset */ - cur_uprobe = insert_uprobe(uprobe); -@@ -516,7 +467,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) - { - struct uprobe_consumer *uc; - -- if (!(uprobe->flags & UPROBE_RUN_HANDLER)) -+ if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags)) - return; - - down_read(&uprobe->consumer_rwsem); -@@ -622,33 +573,48 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) - return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); - } - --/* -- * How mm->uprobes_state.count gets updated -- * uprobe_mmap() increments the count if -- * - it successfully adds a breakpoint. -- * - it cannot add a breakpoint, but sees that there is a underlying -- * breakpoint (via a is_swbp_at_addr()). -- * -- * uprobe_munmap() decrements the count if -- * - it sees a underlying breakpoint, (via is_swbp_at_addr) -- * (Subsequent uprobe_unregister wouldnt find the breakpoint -- * unless a uprobe_mmap kicks in, since the old vma would be -- * dropped just after uprobe_munmap.) -- * -- * uprobe_register increments the count if: -- * - it successfully adds a breakpoint. -- * -- * uprobe_unregister decrements the count if: -- * - it sees a underlying breakpoint and removes successfully. -- * (via is_swbp_at_addr) -- * (Subsequent uprobe_munmap wouldnt find the breakpoint -- * since there is no underlying breakpoint after the -- * breakpoint removal.) -- */ -+static int prepare_uprobe(struct uprobe *uprobe, struct file *file, -+ struct mm_struct *mm, unsigned long vaddr) -+{ -+ int ret = 0; -+ -+ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) -+ return ret; -+ -+ mutex_lock(&uprobe->copy_mutex); -+ if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) -+ goto out; -+ -+ ret = copy_insn(uprobe, file); -+ if (ret) -+ goto out; -+ -+ ret = -ENOTSUPP; -+ if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -+ goto out; -+ -+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); -+ if (ret) -+ goto out; -+ -+ /* write_opcode() assumes we don't cross page boundary */ -+ BUG_ON((uprobe->offset & ~PAGE_MASK) + -+ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ -+ smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ -+ set_bit(UPROBE_COPY_INSN, &uprobe->flags); -+ -+ out: -+ mutex_unlock(&uprobe->copy_mutex); -+ -+ return ret; -+} -+ - static int - install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - struct vm_area_struct *vma, unsigned long vaddr) - { -+ bool first_uprobe; - int ret; - - /* -@@ -659,48 +625,38 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - * Hence behave as if probe already existed. - */ - if (!uprobe->consumers) -- return -EEXIST; -- -- if (!(uprobe->flags & UPROBE_COPY_INSN)) { -- ret = copy_insn(uprobe, vma->vm_file); -- if (ret) -- return ret; -- -- if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -- return -ENOTSUPP; -- -- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); -- if (ret) -- return ret; -- -- /* write_opcode() assumes we don't cross page boundary */ -- BUG_ON((uprobe->offset & ~PAGE_MASK) + -- UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ return 0; - -- uprobe->flags |= UPROBE_COPY_INSN; -- } -+ ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr); -+ if (ret) -+ return ret; - - /* -- * Ideally, should be updating the probe count after the breakpoint -- * has been successfully inserted. However a thread could hit the -- * breakpoint we just inserted even before the probe count is -- * incremented. If this is the first breakpoint placed, breakpoint -- * notifier might ignore uprobes and pass the trap to the thread. -- * Hence increment before and decrement on failure. -+ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), -+ * the task can hit this breakpoint right after __replace_page(). - */ -- atomic_inc(&mm->uprobes_state.count); -+ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); -+ if (first_uprobe) -+ set_bit(MMF_HAS_UPROBES, &mm->flags); -+ - ret = set_swbp(&uprobe->arch, mm, vaddr); -- if (ret) -- atomic_dec(&mm->uprobes_state.count); -+ if (!ret) -+ clear_bit(MMF_RECALC_UPROBES, &mm->flags); -+ else if (first_uprobe) -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); - - return ret; - } - --static void -+static int - remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) -- atomic_dec(&mm->uprobes_state.count); -+ /* can happen if uprobe_register() fails */ -+ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) -+ return 0; -+ -+ set_bit(MMF_RECALC_UPROBES, &mm->flags); -+ return set_orig_insn(&uprobe->arch, mm, vaddr); - } - - /* -@@ -710,11 +666,9 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad - */ - static void delete_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; -- -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - rb_erase(&uprobe->rb_node, &uprobes_tree); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - iput(uprobe->inode); - put_uprobe(uprobe); - atomic_dec(&uprobe_events); -@@ -818,7 +772,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - struct mm_struct *mm = info->mm; - struct vm_area_struct *vma; - -- if (err) -+ if (err && is_register) - goto free; - - down_write(&mm->mmap_sem); -@@ -831,17 +785,11 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - vaddr_to_offset(vma, info->vaddr) != uprobe->offset) - goto unlock; - -- if (is_register) { -+ if (is_register) - err = install_breakpoint(uprobe, mm, vma, info->vaddr); -- /* -- * We can race against uprobe_mmap(), see the -- * comment near uprobe_hash(). -- */ -- if (err == -EEXIST) -- err = 0; -- } else { -- remove_breakpoint(uprobe, mm, info->vaddr); -- } -+ else -+ err |= remove_breakpoint(uprobe, mm, info->vaddr); -+ - unlock: - up_write(&mm->mmap_sem); - free: -@@ -897,21 +845,25 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * - mutex_lock(uprobes_hash(inode)); - uprobe = alloc_uprobe(inode, offset); - -- if (uprobe && !consumer_add(uprobe, uc)) { -+ if (!uprobe) { -+ ret = -ENOMEM; -+ } else if (!consumer_add(uprobe, uc)) { - ret = __uprobe_register(uprobe); - if (ret) { - uprobe->consumers = NULL; - __uprobe_unregister(uprobe); - } else { -- uprobe->flags |= UPROBE_RUN_HANDLER; -+ set_bit(UPROBE_RUN_HANDLER, &uprobe->flags); - } - } - - mutex_unlock(uprobes_hash(inode)); -- put_uprobe(uprobe); -+ if (uprobe) -+ put_uprobe(uprobe); - - return ret; - } -+EXPORT_SYMBOL_GPL(uprobe_register); - - /* - * uprobe_unregister - unregister a already registered probe. -@@ -935,7 +887,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (consumer_del(uprobe, uc)) { - if (!uprobe->consumers) { - __uprobe_unregister(uprobe); -- uprobe->flags &= ~UPROBE_RUN_HANDLER; -+ clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags); - } - } - -@@ -943,6 +895,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (uprobe) - put_uprobe(uprobe); - } -+EXPORT_SYMBOL_GPL(uprobe_unregister); - - static struct rb_node * - find_node_in_range(struct inode *inode, loff_t min, loff_t max) -@@ -978,7 +931,6 @@ static void build_probe_list(struct inode *inode, - struct list_head *head) - { - loff_t min, max; -- unsigned long flags; - struct rb_node *n, *t; - struct uprobe *u; - -@@ -986,7 +938,7 @@ static void build_probe_list(struct inode *inode, - min = vaddr_to_offset(vma, start); - max = min + (end - start) - 1; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - n = find_node_in_range(inode, min, max); - if (n) { - for (t = n; t; t = rb_prev(t)) { -@@ -1004,27 +956,20 @@ static void build_probe_list(struct inode *inode, - atomic_inc(&u->ref); - } - } -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - } - - /* -- * Called from mmap_region. -- * called with mm->mmap_sem acquired. -- * -- * Return -ve no if we fail to insert probes and we cannot -- * bail-out. -- * Return 0 otherwise. i.e: -+ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. - * -- * - successful insertion of probes -- * - (or) no possible probes to be inserted. -- * - (or) insertion of probes failed but we can bail-out. -+ * Currently we ignore all errors and always return 0, the callers -+ * can't handle the failure anyway. - */ - int uprobe_mmap(struct vm_area_struct *vma) - { - struct list_head tmp_list; - struct uprobe *uprobe, *u; - struct inode *inode; -- int ret, count; - - if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) - return 0; -@@ -1036,44 +981,35 @@ int uprobe_mmap(struct vm_area_struct *vma) - mutex_lock(uprobes_mmap_hash(inode)); - build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); - -- ret = 0; -- count = 0; -- - list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- if (!ret) { -+ if (!fatal_signal_pending(current)) { - unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); -- -- ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); -- /* -- * We can race against uprobe_register(), see the -- * comment near uprobe_hash(). -- */ -- if (ret == -EEXIST) { -- ret = 0; -- -- if (!is_swbp_at_addr(vma->vm_mm, vaddr)) -- continue; -- -- /* -- * Unable to insert a breakpoint, but -- * breakpoint lies underneath. Increment the -- * probe count. -- */ -- atomic_inc(&vma->vm_mm->uprobes_state.count); -- } -- -- if (!ret) -- count++; -+ install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); - } - put_uprobe(uprobe); - } -- - mutex_unlock(uprobes_mmap_hash(inode)); - -- if (ret) -- atomic_sub(count, &vma->vm_mm->uprobes_state.count); -+ return 0; -+} - -- return ret; -+static bool -+vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) -+{ -+ loff_t min, max; -+ struct inode *inode; -+ struct rb_node *n; -+ -+ inode = vma->vm_file->f_mapping->host; -+ -+ min = vaddr_to_offset(vma, start); -+ max = min + (end - start) - 1; -+ -+ spin_lock(&uprobes_treelock); -+ n = find_node_in_range(inode, min, max); -+ spin_unlock(&uprobes_treelock); -+ -+ return !!n; - } - - /* -@@ -1081,37 +1017,18 @@ int uprobe_mmap(struct vm_area_struct *vma) - */ - void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { -- struct list_head tmp_list; -- struct uprobe *uprobe, *u; -- struct inode *inode; -- - if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) - return; - - if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ - return; - -- if (!atomic_read(&vma->vm_mm->uprobes_state.count)) -- return; -- -- inode = vma->vm_file->f_mapping->host; -- if (!inode) -+ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || -+ test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) - return; - -- mutex_lock(uprobes_mmap_hash(inode)); -- build_probe_list(inode, vma, start, end, &tmp_list); -- -- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); -- /* -- * An unregister could have removed the probe before -- * unmap. So check before we decrement the count. -- */ -- if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) -- atomic_dec(&vma->vm_mm->uprobes_state.count); -- put_uprobe(uprobe); -- } -- mutex_unlock(uprobes_mmap_hash(inode)); -+ if (vma_has_uprobes(vma, start, end)) -+ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); - } - - /* Slot allocation for XOL */ -@@ -1213,13 +1130,15 @@ void uprobe_clear_state(struct mm_struct *mm) - kfree(area); - } - --/* -- * uprobe_reset_state - Free the area allocated for slots. -- */ --void uprobe_reset_state(struct mm_struct *mm) -+void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) - { -- mm->uprobes_state.xol_area = NULL; -- atomic_set(&mm->uprobes_state.count, 0); -+ newmm->uprobes_state.xol_area = NULL; -+ -+ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { -+ set_bit(MMF_HAS_UPROBES, &newmm->flags); -+ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ -+ set_bit(MMF_RECALC_UPROBES, &newmm->flags); -+ } - } - - /* -@@ -1430,13 +1349,57 @@ bool uprobe_deny_signal(void) - */ - static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) - { -- if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) -- return true; -- -- uprobe->flags &= ~UPROBE_SKIP_SSTEP; -+ if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) { -+ if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) -+ return true; -+ clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); -+ } - return false; - } - -+static void mmf_recalc_uprobes(struct mm_struct *mm) -+{ -+ struct vm_area_struct *vma; -+ -+ for (vma = mm->mmap; vma; vma = vma->vm_next) { -+ if (!valid_vma(vma, false)) -+ continue; -+ /* -+ * This is not strictly accurate, we can race with -+ * uprobe_unregister() and see the already removed -+ * uprobe if delete_uprobe() was not yet called. -+ */ -+ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) -+ return; -+ } -+ -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); -+} -+ -+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) -+{ -+ struct page *page; -+ uprobe_opcode_t opcode; -+ int result; -+ -+ pagefault_disable(); -+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -+ sizeof(opcode)); -+ pagefault_enable(); -+ -+ if (likely(result == 0)) -+ goto out; -+ -+ result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); -+ if (result < 0) -+ return result; -+ -+ copy_opcode(page, vaddr, &opcode); -+ put_page(page); -+ out: -+ return is_swbp_insn(&opcode); -+} -+ - static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) - { - struct mm_struct *mm = current->mm; -@@ -1458,11 +1421,24 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) - } else { - *is_swbp = -EFAULT; - } -+ -+ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) -+ mmf_recalc_uprobes(mm); - up_read(&mm->mmap_sem); - - return uprobe; - } - -+void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) -+{ -+ user_enable_single_step(current); -+} -+ -+void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) -+{ -+ user_disable_single_step(current); -+} -+ - /* - * Run handler and ask thread to singlestep. - * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. -@@ -1494,41 +1470,42 @@ static void handle_swbp(struct pt_regs *regs) - } - return; - } -+ /* -+ * TODO: move copy_insn/etc into _register and remove this hack. -+ * After we hit the bp, _unregister + _register can install the -+ * new and not-yet-analyzed uprobe at the same address, restart. -+ */ -+ smp_rmb(); /* pairs with wmb() in install_breakpoint() */ -+ if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) -+ goto restart; - - utask = current->utask; - if (!utask) { - utask = add_utask(); - /* Cannot allocate; re-execute the instruction. */ - if (!utask) -- goto cleanup_ret; -+ goto restart; - } -- utask->active_uprobe = uprobe; -+ - handler_chain(uprobe, regs); -- if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) -- goto cleanup_ret; -+ if (can_skip_sstep(uprobe, regs)) -+ goto out; - -- utask->state = UTASK_SSTEP; - if (!pre_ssout(uprobe, regs, bp_vaddr)) { -- user_enable_single_step(current); -+ arch_uprobe_enable_step(&uprobe->arch); -+ utask->active_uprobe = uprobe; -+ utask->state = UTASK_SSTEP; - return; - } - --cleanup_ret: -- if (utask) { -- utask->active_uprobe = NULL; -- utask->state = UTASK_RUNNING; -- } -- if (uprobe) { -- if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) -- -- /* -- * cannot singlestep; cannot skip instruction; -- * re-execute the instruction. -- */ -- instruction_pointer_set(regs, bp_vaddr); -- -- put_uprobe(uprobe); -- } -+restart: -+ /* -+ * cannot singlestep; cannot skip instruction; -+ * re-execute the instruction. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); -+out: -+ put_uprobe(uprobe); - } - - /* -@@ -1547,10 +1524,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) - else - WARN_ON_ONCE(1); - -+ arch_uprobe_disable_step(&uprobe->arch); - put_uprobe(uprobe); - utask->active_uprobe = NULL; - utask->state = UTASK_RUNNING; -- user_disable_single_step(current); - xol_free_insn_slot(current); - - spin_lock_irq(¤t->sighand->siglock); -@@ -1559,13 +1536,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) - } - - /* -- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on -- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and -- * allows the thread to return from interrupt. -+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and -+ * allows the thread to return from interrupt. After that handle_swbp() -+ * sets utask->active_uprobe. - * -- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and -- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from -- * interrupt. -+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag -+ * and allows the thread to return from interrupt. - * - * While returning to userspace, thread notices the TIF_UPROBE flag and calls - * uprobe_notify_resume(). -@@ -1574,11 +1550,13 @@ void uprobe_notify_resume(struct pt_regs *regs) - { - struct uprobe_task *utask; - -+ clear_thread_flag(TIF_UPROBE); -+ - utask = current->utask; -- if (!utask || utask->state == UTASK_BP_HIT) -- handle_swbp(regs); -- else -+ if (utask && utask->active_uprobe) - handle_singlestep(utask, regs); -+ else -+ handle_swbp(regs); - } - - /* -@@ -1587,18 +1565,10 @@ void uprobe_notify_resume(struct pt_regs *regs) - */ - int uprobe_pre_sstep_notifier(struct pt_regs *regs) - { -- struct uprobe_task *utask; -- -- if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) -- /* task is currently not uprobed */ -+ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) - return 0; - -- utask = current->utask; -- if (utask) -- utask->state = UTASK_BP_HIT; -- - set_thread_flag(TIF_UPROBE); -- - return 1; - } - -diff --git a/kernel/fork.c b/kernel/fork.c -index 2c8857e..2343c9e 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -353,6 +353,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - down_write(&oldmm->mmap_sem); - flush_cache_dup_mm(oldmm); -+ uprobe_dup_mmap(oldmm, mm); - /* - * Not linked in yet - no deadlock potential: - */ -@@ -454,9 +455,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - if (retval) - goto out; -- -- if (file) -- uprobe_mmap(tmp); - } - /* a new mm has just been created */ - arch_dup_mmap(oldmm, mm); -@@ -839,8 +837,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - mm->pmd_huge_pte = NULL; - #endif -- uprobe_reset_state(mm); -- - if (!mm_init(mm, tsk)) - goto fail_nomem; - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index a232bb5..764fcd1 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags) - } - - /* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ -+/* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. - * -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/vt-Drop-K_OFF-for-VC_MUTE.patch b/vt-Drop-K_OFF-for-VC_MUTE.patch index ab85411cb..e9bc4fffa 100644 --- a/vt-Drop-K_OFF-for-VC_MUTE.patch +++ b/vt-Drop-K_OFF-for-VC_MUTE.patch @@ -64,7 +64,7 @@ Signed-off-by: Adam Jackson drivers/tty/vt/vt_ioctl.c | 13 +++++++++++++ include/linux/kbd_kern.h | 6 +++--- include/linux/vt_kern.h | 2 ++ - include/linux/kd.h | 5 +++++ + include/uapi/linux/kd.h | 5 +++++ 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c @@ -222,10 +222,10 @@ index 50ae7d0..a886915 100644 extern int vt_do_kdgkbmode(int console); extern int vt_do_kdgkbmeta(int console); extern void vt_reset_unicode(int console); -diff --git a/include/linux/kd.h b/include/linux/kd.h +diff --git a/include/uapi/linux/kd.h b/include/uapi/linux/kd.h index 87b7cc4..c3de63c 100644 ---- a/include/linux/kd.h -+++ b/include/linux/kd.h +--- a/include/uapi/linux/kd.h ++++ b/include/uapi/linux/kd.h @@ -81,6 +81,7 @@ struct unimapinit { #define K_XLATE 0x01 #define K_MEDIUMRAW 0x02 From 5b55e6434ac147797945e5d8874cc965c0a0bdb5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Jan 2013 15:52:03 -0500 Subject: [PATCH 134/492] Fixup secure boot patchset for 3.7 rebase --- kernel.spec | 9 ++- secure-boot-20121212.patch | 122 ++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 63 deletions(-) diff --git a/kernel.spec b/kernel.spec index b6f407309..d54266bc7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1442,7 +1442,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.7.patch -#ApplyPatch secure-boot-20121212.patch +ApplyPatch secure-boot-20121212.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -2272,6 +2272,7 @@ fi %dir %{_libexecdir}/perf-core %{_libexecdir}/perf-core/* %{_mandir}/man[1-8]/perf* +%{_sysconfdir}/bash_completion.d/perf %doc linux-%{KVERREL}/tools/perf/Documentation/examples.txt %files -n python-perf @@ -2391,6 +2392,10 @@ fi # ||----w | # || || %changelog +* Thu Jan 03 2013 Josh Boyer - 3.7.1-2 +- Fixup secure boot patchset for 3.7 rebase +- Package bash completion script for perf + * Thu Jan 03 2013 Dave Jones - Rebase to 3.7.1 diff --git a/secure-boot-20121212.patch b/secure-boot-20121212.patch index d435eb217..387302b90 100644 --- a/secure-boot-20121212.patch +++ b/secure-boot-20121212.patch @@ -1,4 +1,4 @@ -From 925befaba2477067aa12fa1fdc9fcc135c80b4fd Mon Sep 17 00:00:00 2001 +From d510ea864f470d96aafb75d0de7f09450407095e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 Subject: [PATCH 01/20] Secure boot: Add new capability @@ -11,14 +11,14 @@ capability set if required. Signed-off-by: Matthew Garrett --- - include/linux/capability.h | 6 +++++- + include/uapi/linux/capability.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) -diff --git a/include/linux/capability.h b/include/linux/capability.h -index d10b7ed..4345bc8 100644 ---- a/include/linux/capability.h -+++ b/include/linux/capability.h -@@ -364,7 +364,11 @@ struct cpu_vfs_cap_data { +diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h +index ba478fa..7109e65 100644 +--- a/include/uapi/linux/capability.h ++++ b/include/uapi/linux/capability.h +@@ -343,7 +343,11 @@ struct vfs_cap_data { #define CAP_BLOCK_SUSPEND 36 @@ -35,7 +35,7 @@ index d10b7ed..4345bc8 100644 1.8.0.1 -From 1c5873679d750bda038d22210d9fd40c8673211f Mon Sep 17 00:00:00 2001 +From a07ae01ac4b304ac7f0e2b5d4193519f1a9eee8d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 Subject: [PATCH 02/20] PCI: Lock down BAR access in secure boot environments @@ -87,7 +87,7 @@ index f39378d..1db1e74 100644 } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index af028c7..53372eb 100644 +index 9b8505c..35580bc 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof @@ -136,7 +136,7 @@ index e1c1ec5..97e785f 100644 1.8.0.1 -From f067c7702f46b85d06da6c34dd907b44e594c2cf Mon Sep 17 00:00:00 2001 +From 1b5a1b53577992b32a3f51b18aa07cb9b300a3b1 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 Subject: [PATCH 03/20] x86: Lock down IO port access in secure boot @@ -176,7 +176,7 @@ index 8c96897..a2578c4 100644 } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index e5eedfa..1e0a660 100644 +index 0537903..47501fc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, @@ -193,7 +193,7 @@ index e5eedfa..1e0a660 100644 1.8.0.1 -From 95b440833e9002bc7e1950f403f2fb2953b69317 Mon Sep 17 00:00:00 2001 +From 09c266136915eb1f4a9b36423b7ba65e3d024de4 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 Subject: [PATCH 04/20] ACPI: Limit access to custom_method @@ -225,7 +225,7 @@ index 5d42c24..247d58b 100644 1.8.0.1 -From fd40b868d55992f71acffa74b559923ffde81638 Mon Sep 17 00:00:00 2001 +From f3e9cb16e5ab3e680ec3ef464682c52371bbbbe3 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 Subject: [PATCH 05/20] asus-wmi: Restrict debugfs interface @@ -278,7 +278,7 @@ index c0e9ff4..3c10167 100644 1.8.0.1 -From 470e4dbf6215d40a340b3ad7fd6d4533ffbf6a6d Mon Sep 17 00:00:00 2001 +From 23372d2a40135aca7a6d73511bd88790b598b489 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 Subject: [PATCH 06/20] Restrict /dev/mem and /dev/kmem in secure boot setups @@ -292,7 +292,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 6 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 1e0a660..33eb947 100644 +index 47501fc..8817cdc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, @@ -319,7 +319,7 @@ index 1e0a660..33eb947 100644 1.8.0.1 -From fdb24af2d20faea8bae60058f0cda8db8be9394d Mon Sep 17 00:00:00 2001 +From a0c80b01e80a1f6484a2a2811b4a212322494614 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 Subject: [PATCH 07/20] Secure boot: Add a dummy kernel parameter that will @@ -336,10 +336,10 @@ Signed-off-by: Josh Boyer 2 files changed, 24 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 9b2b8d3..93978d5 100644 +index 9776f06..0d6c28d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -2562,6 +2562,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Note: increases power consumption, thus should only be enabled if running jitter sensitive (HPC/RT) workloads. @@ -354,7 +354,7 @@ index 9b2b8d3..93978d5 100644 If this boot parameter is not specified, only the first security module asking for security registration will be diff --git a/kernel/cred.c b/kernel/cred.c -index de728ac..7e6e83f 100644 +index 48cea3d..3f5be65 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -623,6 +623,23 @@ void __init cred_init(void) @@ -385,7 +385,7 @@ index de728ac..7e6e83f 100644 1.8.0.1 -From 033a0db83fe140b040a5f5a5754ba326b0d4f587 Mon Sep 17 00:00:00 2001 +From 640f088c49da87a344417f58d3faa72d63a4f6ed Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 Subject: [PATCH 08/20] efi: Enable secure boot lockdown automatically when @@ -418,10 +418,10 @@ index cf5437d..7f9ed48 100644 2D0/A00 ALL e820_map E820 memory map table (array of struct e820entry) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 90201aa..bdf0eb7 100644 +index e87b0ca..260cace 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -726,6 +726,36 @@ fail: +@@ -732,6 +732,36 @@ fail: return status; } @@ -458,7 +458,7 @@ index 90201aa..bdf0eb7 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1020,6 +1050,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1026,6 +1056,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -482,10 +482,10 @@ index 2ad874c..c7338e0 100644 __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 5cee802..b4f4666 100644 +index ca45696..800673d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -961,6 +961,9 @@ void __init setup_arch(char **cmdline_p) +@@ -962,6 +962,9 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -512,7 +512,7 @@ index ebbed2c..a24faf1 100644 1.8.0.1 -From 7a24fb283b72797e219a3283c5cf880ebb80443f Mon Sep 17 00:00:00 2001 +From 994d895b5b684fc53c3b43dda9aee460c1f526f2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 09/20] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -544,7 +544,7 @@ index 9eaf708..f94341b 100644 1.8.0.1 -From a21ccbd8461fd9780c348faa78bbd3d13db04e3d Mon Sep 17 00:00:00 2001 +From c80aaf3eee3cb6b0d1a051e418ee99cd238c868c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 Subject: [PATCH 10/20] SELinux: define mapping for new Secure Boot capability @@ -577,7 +577,7 @@ index df2de54..70e2834 100644 1.8.0.1 -From 01af02988477c4bde39436adec1edfd1499709d9 Mon Sep 17 00:00:00 2001 +From 26352bcb92468233dd960b5d02ba1db344df72b9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 11/20] kexec: Disable in a secure boot environment @@ -593,10 +593,10 @@ Signed-off-by: Matthew Garrett 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c -index 0668d58..8b976a5 100644 +index 5e4bd78..dd464e0 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c -@@ -944,7 +944,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, +@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, int result; /* We only trust the superuser with rebooting the system. */ @@ -609,7 +609,7 @@ index 0668d58..8b976a5 100644 1.8.0.1 -From 883409d0fadeefe2c44d7034d2acc0e366c339f3 Mon Sep 17 00:00:00 2001 +From c03c68adceaec9656c55c47190fb4243bf903b40 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Jun 2012 21:29:46 -0400 Subject: [PATCH 12/20] Documentation: kernel-parameters.txt remove @@ -630,7 +630,7 @@ Signed-off-by: Josh Boyer 1 file changed, 6 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 93978d5..e3e5f8c 100644 +index 0d6c28d..d9af501 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. @@ -650,7 +650,7 @@ index 93978d5..e3e5f8c 100644 1.8.0.1 -From b2ee7008ee39d04b3439f81e42586ee8e16af2e9 Mon Sep 17 00:00:00 2001 +From 3f1bda64d2c7b369e2833bd32cd1f3ba6c90348f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 13/20] modsign: Always enforce module signing in a Secure Boot @@ -669,7 +669,7 @@ Signed-off-by: Josh Boyer 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c -index 7e6e83f..6e828e2 100644 +index 3f5be65..a381e27 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -623,11 +623,19 @@ void __init cred_init(void) @@ -693,7 +693,7 @@ index 7e6e83f..6e828e2 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index e0785b3..b964a03 100644 +index 6e48c3a..6d5d2aa 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ @@ -712,7 +712,7 @@ index e0785b3..b964a03 100644 1.8.0.1 -From 4fe6ecce3e9168f538fc8970fe8a964438beabbb Mon Sep 17 00:00:00 2001 +From e6e3ec77b2fa037b32829e7f5ee468ad8a62dd05 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 Subject: [PATCH 14/20] Add EFI signature data types, such as are used for @@ -724,7 +724,7 @@ Signed-off-by: David Howells 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index bff4b5e..52ce2c4 100644 +index 337aefb..a01f8a7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -317,6 +317,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, @@ -765,7 +765,7 @@ index bff4b5e..52ce2c4 100644 1.8.0.1 -From 768ab9ef88b2caa9588e577fe547792dfe513fca Mon Sep 17 00:00:00 2001 +From c2542256f632a22232cf02d5fd64568a5afa4516 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 Subject: [PATCH 15/20] Add an EFI signature blob parser and key loader. X.509 @@ -922,10 +922,10 @@ index 0000000..59b859a + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index 52ce2c4..54b5936 100644 +index a01f8a7..44a7faa 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -538,6 +538,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -541,6 +541,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -940,7 +940,7 @@ index 52ce2c4..54b5936 100644 1.8.0.1 -From 967a1b02af199f07fd7603bda2f0aeec50b412b9 Mon Sep 17 00:00:00 2001 +From a418e6fdd2aa946a30cf1bee5c9540d03d626981 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:29:49 -0400 Subject: [PATCH 16/20] EFI: Add in-kernel variable to determine if Secure Boot @@ -959,10 +959,10 @@ Signed-off-by: Josh Boyer 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index b4f4666..db74940 100644 +index 800673d..cf8823b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -961,8 +961,12 @@ void __init setup_arch(char **cmdline_p) +@@ -962,8 +962,12 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -977,10 +977,10 @@ index b4f4666..db74940 100644 /* * Parse the ACPI tables for possible boot-time SMP configuration. diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 72d8899..882d794 100644 +index ad44391..d22bfeb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c -@@ -53,6 +53,8 @@ +@@ -54,6 +54,8 @@ int efi_enabled; EXPORT_SYMBOL(efi_enabled); @@ -990,10 +990,10 @@ index 72d8899..882d794 100644 .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, diff --git a/include/linux/efi.h b/include/linux/efi.h -index 54b5936..411997f 100644 +index 44a7faa..b5403ae 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -575,11 +575,14 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -578,11 +578,14 @@ extern int __init efi_setup_pcdp_console(char *); # ifdef CONFIG_X86 extern int efi_enabled; extern bool efi_64bit; @@ -1012,7 +1012,7 @@ index 54b5936..411997f 100644 1.8.0.1 -From 6e946d64dc843d9caa587780801de035b38fd4b3 Mon Sep 17 00:00:00 2001 +From f6d05f0974f6a7667ebbbf91624678bcf32169ae Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 Subject: [PATCH 17/20] MODSIGN: Add module certificate blacklist keyring @@ -1031,10 +1031,10 @@ Signed-off-by: Josh Boyer 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig -index abc6e63..78f3e280 100644 +index 6fdd6e3..7a9bf00 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1613,6 +1613,14 @@ config MODULE_SIG_FORCE +@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE Reject unsigned modules or signed modules for which we don't have a key. Without this, such modules will simply taint the kernel. @@ -1050,7 +1050,7 @@ index abc6e63..78f3e280 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 4646eb2..6d70783 100644 +index 767e559..3bfb7ed 100644 --- a/kernel/modsign_pubkey.c +++ b/kernel/modsign_pubkey.c @@ -17,6 +17,9 @@ @@ -1098,7 +1098,7 @@ index 24f9247..51a8380 100644 extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index d492a23..39131d3 100644 +index f2970bd..8ab83a6 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, @@ -1133,7 +1133,7 @@ index d492a23..39131d3 100644 1.8.0.1 -From 02905ddf41b18af3c3dd5d99771eba4e453d24ca Mon Sep 17 00:00:00 2001 +From ff0ed221fe8d5a46a9bc36323ca8fb6f75c22a83 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot @@ -1161,7 +1161,7 @@ Signed-off-by: Josh Boyer create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index 411997f..31f84ff 100644 +index b5403ae..bba53e3 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -323,6 +323,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, @@ -1178,10 +1178,10 @@ index 411997f..31f84ff 100644 efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index 78f3e280..754ee66 100644 +index 7a9bf00..51aa170 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1621,6 +1621,15 @@ config MODULE_SIG_BLACKLIST +@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST should not pass module signature verification. If a module is signed with something in this keyring, the load will be rejected. @@ -1198,10 +1198,10 @@ index 78f3e280..754ee66 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/Makefile b/kernel/Makefile -index d3611c8..927a264 100644 +index 86e3285..12e17ab 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -56,6 +56,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o +@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o @@ -1209,7 +1209,7 @@ index d3611c8..927a264 100644 obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o -@@ -114,6 +115,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o +@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o $(obj)/configs.o: $(obj)/config_data.h @@ -1318,7 +1318,7 @@ index 0000000..76a5a34 1.8.0.1 -From b1bc4417dcec5c603baae2de2523bdf3a0c96b11 Mon Sep 17 00:00:00 2001 +From 7d5629a2000d9dc92da91d2f1258af748e89cfd7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 19/20] hibernate: Disable in a Secure Boot environment @@ -1414,7 +1414,7 @@ index 4ed81e7..b11a0f4 100644 1.8.0.1 -From 96c9c61996828908833b680149525b4b7acff664 Mon Sep 17 00:00:00 2001 +From 81adc779dba0f45f10b5ff307bd55832305f1112 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Dec 2012 11:48:49 -0500 Subject: [PATCH 20/20] Don't soft lockup on bad EFI signature lists From 1c6f1e3b70e84a6f0db509629ac1c11f52d54e2c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Jan 2013 18:56:35 -0500 Subject: [PATCH 135/492] Fix arm configs Sort of. --- config-arm-highbank | 3 +++ config-arm-versatile | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config-arm-highbank b/config-arm-highbank index 952a21ac4..ca27f65cb 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -59,4 +59,7 @@ CONFIG_OC_ETM=y # CONFIG_MEDIA_SUPPORT is not set # CONFIG_DRM is not set # CONFIG_SND is not set +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set # end of list of requested disabled options diff --git a/config-arm-versatile b/config-arm-versatile index 89d4f7b09..758a78c76 100644 --- a/config-arm-versatile +++ b/config-arm-versatile @@ -95,3 +95,8 @@ CONFIG_PATA_OF_PLATFORM=m # unset on versatille for jon masters # CONFIG_GPIOLIB is not set +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_DRM_EXYNOS is not set + From 3ae631a535b05d84ac8da3f550488e1169bb5233 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 4 Jan 2013 08:13:12 -0500 Subject: [PATCH 136/492] Fix oops on aoe module removal (rhbz 853064) --- ...e-vestigial-request-queue-allocation.patch | 69 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 aoe-remove-vestigial-request-queue-allocation.patch diff --git a/aoe-remove-vestigial-request-queue-allocation.patch b/aoe-remove-vestigial-request-queue-allocation.patch new file mode 100644 index 000000000..fa4ad1ac8 --- /dev/null +++ b/aoe-remove-vestigial-request-queue-allocation.patch @@ -0,0 +1,69 @@ +From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 +From: Ed Cashin +Date: Mon, 17 Dec 2012 16:03:58 -0800 +Subject: [PATCH] aoe: remove vestigial request queue allocation + +Before the aoe driver was an I/O request handler, it was a +make_request-style block driver. Even so, there was a problem where +sysfs expected a request queue to exist, so one was provided in commit +7135a71b19be ("aoe: allocate unused request_queue for sysfs"). + +During the transition to the request-handler style, a patch was merged +that was based on a driver without the noop queue, and the noop queue +remained in place after the patch was merged, even though a new +functional queue was introduced by the patch, allocated through +blk_init_queue. + +The user impact is a memory leak proportional to the number of AoE +targets discovered. This patch removes the memory leak and cleans up +vestiges of the old do-nothing queue from the aoeblk_gdalloc function. + +Signed-off-by: Ed Cashin +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + drivers/block/aoe/aoeblk.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c +index 7ba0fcf..57ac72c 100644 +--- a/drivers/block/aoe/aoeblk.c ++++ b/drivers/block/aoe/aoeblk.c +@@ -278,18 +278,12 @@ aoeblk_gdalloc(void *vp) + if (q == NULL) { + pr_err("aoe: cannot allocate block queue for %ld.%d\n", + d->aoemajor, d->aoeminor); +- mempool_destroy(mp); +- goto err_disk; ++ goto err_mempool; + } + +- d->blkq = blk_alloc_queue(GFP_KERNEL); +- if (!d->blkq) +- goto err_mempool; +- d->blkq->backing_dev_info.name = "aoe"; +- if (bdi_init(&d->blkq->backing_dev_info)) +- goto err_blkq; + spin_lock_irqsave(&d->lock, flags); +- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); ++ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); ++ q->backing_dev_info.name = "aoe"; + q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; + d->bufpool = mp; + d->blkq = gd->queue = q; +@@ -314,11 +308,8 @@ aoeblk_gdalloc(void *vp) + aoedisk_add_sysfs(d); + return; + +-err_blkq: +- blk_cleanup_queue(d->blkq); +- d->blkq = NULL; + err_mempool: +- mempool_destroy(d->bufpool); ++ mempool_destroy(mp); + err_disk: + put_disk(gd); + err: +-- +1.8.0.1 + diff --git a/kernel.spec b/kernel.spec index d54266bc7..24036e213 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -790,6 +790,9 @@ Patch21234: mac80211-fix-ibss-scanning.patch #rhbz 873107 Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 853064 +Patch21239: aoe-remove-vestigial-request-queue-allocation.patch + # END OF PATCH DEFINITIONS %endif @@ -1519,6 +1522,9 @@ ApplyPatch mac80211-fix-ibss-scanning.patch #rhbz 873107 ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 853064 +ApplyPatch aoe-remove-vestigial-request-queue-allocation.patch + # END OF PATCH APPLICATIONS @@ -2392,6 +2398,9 @@ fi # ||----w | # || || %changelog +* Fri Jan 04 2013 Josh Boyer +- Fix oops on aoe module removal (rhbz 853064) + * Thu Jan 03 2013 Josh Boyer - 3.7.1-2 - Fixup secure boot patchset for 3.7 rebase - Package bash completion script for perf From 34e02d724cc87ac7b70eb3695c62e52cc10cc136 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 6 Jan 2013 18:47:15 -0500 Subject: [PATCH 137/492] Fix version.h include due to UAPI change in 3.7 (rhbz 892372) --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 24036e213..9d365a756 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1761,7 +1761,7 @@ BuildKernel() { # Make sure the Makefile and version.h have a matching timestamp so that # external modules can be built - touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Makefile $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/version.h + touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Makefile $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/generated/uapi/linux/version.h # Copy .config to include/config/auto.conf so "make prepare" is unnecessary. cp $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/config/auto.conf @@ -2398,6 +2398,9 @@ fi # ||----w | # || || %changelog +* Sun Jan 06 2013 Josh Boyer +- Fix version.h include due to UAPI change in 3.7 (rhbz 892372) + * Fri Jan 04 2013 Josh Boyer - Fix oops on aoe module removal (rhbz 853064) From 635263af292c128f4aa61346024b3852d3ab9aa9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 7 Jan 2013 10:47:48 -0500 Subject: [PATCH 138/492] Fix bug number in changelog --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 9d365a756..fc24a6d5c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2399,7 +2399,7 @@ fi # || || %changelog * Sun Jan 06 2013 Josh Boyer -- Fix version.h include due to UAPI change in 3.7 (rhbz 892372) +- Fix version.h include due to UAPI change in 3.7 (rhbz 892373) * Fri Jan 04 2013 Josh Boyer - Fix oops on aoe module removal (rhbz 853064) From ac003e409f309dd7dee2518364fbb18d2983c7aa Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 7 Jan 2013 11:23:18 -0500 Subject: [PATCH 139/492] Patch to fix efivarfs underflow from Lingzhu Xiang (rhbz 888163) --- efivarfs-3.7.patch | 24 ++++++++++++++++++++++++ kernel.spec | 3 +++ 2 files changed, 27 insertions(+) diff --git a/efivarfs-3.7.patch b/efivarfs-3.7.patch index 300910716..662406405 100644 --- a/efivarfs-3.7.patch +++ b/efivarfs-3.7.patch @@ -1628,3 +1628,27 @@ index 58cec62..9ac9340 100644 -- 1.7.12.1 +efivarfs_unlink() should drop the file's link count, not the directory's. + +Tested-by: Lee, Chun-Yi +Signed-off-by: Lingzhu Xiang +--- + drivers/firmware/efivars.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index d6b8d2f..60f5324 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -995,7 +995,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) + list_del(&var->list); + spin_unlock(&efivars->lock); + efivar_unregister(var); +- drop_nlink(dir); ++ drop_nlink(dentry->d_inode); + dput(dentry); + return 0; + } +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index fc24a6d5c..8ef0cb944 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2398,6 +2398,9 @@ fi # ||----w | # || || %changelog +* Mon Jan 07 2013 Josh Boyer +- Patch to fix efivarfs underflow from Lingzhu Xiang (rhbz 888163) + * Sun Jan 06 2013 Josh Boyer - Fix version.h include due to UAPI change in 3.7 (rhbz 892373) From a3656fed6cd0c0bed77539919672e669241a0577 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Jan 2013 08:28:32 -0500 Subject: [PATCH 140/492] Add patch to fix shutdown on some machines (rhbz 890547) --- ...e-Lid-and-Sleep-button-for-S5-wakeup.patch | 46 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch diff --git a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch new file mode 100644 index 000000000..f6e997c41 --- /dev/null +++ b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch @@ -0,0 +1,46 @@ +From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Tue, 4 Dec 2012 23:23:16 +0100 +Subject: [PATCH] ACPI : do not use Lid and Sleep button for S5 wakeup + +When system enters power off, the _PSW of Lid device is enabled. +But this may cause the system to reboot instead of power off. + +A proper way to fix this is to always disable lid wakeup capability for S5. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 +Signed-off-by: Zhang Rui +Signed-off-by: Rafael J. Wysocki +--- + drivers/acpi/scan.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index d0b38ab..bd523bf 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -917,8 +917,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, + static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + { + struct acpi_device_id button_device_ids[] = { +- {"PNP0C0D", 0}, + {"PNP0C0C", 0}, ++ {"PNP0C0D", 0}, + {"PNP0C0E", 0}, + {"", 0}, + }; +@@ -930,6 +930,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + /* Power button, Lid switch always enable wakeup */ + if (!acpi_match_device_ids(device, button_device_ids)) { + device->wakeup.flags.run_wake = 1; ++ if (!acpi_match_device_ids(device, &button_device_ids[1])) { ++ /* Do not use Lid/sleep button for S5 wakeup */ ++ if (device->wakeup.sleep_state == ACPI_STATE_S5) ++ device->wakeup.sleep_state = ACPI_STATE_S4; ++ } + device_set_wakeup_capable(&device->dev, true); + return; + } +-- +1.8.0.1 + diff --git a/kernel.spec b/kernel.spec index 8ef0cb944..40945c23c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -793,6 +793,9 @@ Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch #rhbz 853064 Patch21239: aoe-remove-vestigial-request-queue-allocation.patch +#rhbz 890547 +Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch + # END OF PATCH DEFINITIONS %endif @@ -1525,6 +1528,9 @@ ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch #rhbz 853064 ApplyPatch aoe-remove-vestigial-request-queue-allocation.patch +#rhbz 890547 +ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch + # END OF PATCH APPLICATIONS @@ -2398,6 +2404,9 @@ fi # ||----w | # || || %changelog +* Tue Jan 08 2013 Josh Boyer +- Add patch to fix shutdown on some machines (rhbz 890547) + * Mon Jan 07 2013 Josh Boyer - Patch to fix efivarfs underflow from Lingzhu Xiang (rhbz 888163) From dc100f5f14bc4050dab0458d8c197b6901a05230 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 10 Jan 2013 13:34:23 -0500 Subject: [PATCH 141/492] Add audit-libs-devel to perf build-deps to enable trace command. (rhbz 892893) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 40945c23c..38b44b51d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -546,7 +546,7 @@ BuildRequires: xmlto, asciidoc BuildRequires: sparse >= 0.4.1 %endif %if %{with_perf} -BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) bison +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) bison audit-libs-devel %endif %if %{with_tools} BuildRequires: pciutils-devel gettext @@ -2404,6 +2404,9 @@ fi # ||----w | # || || %changelog +* Thu Jan 10 2013 Dave Jones +- Add audit-libs-devel to perf build-deps to enable trace command. (rhbz 892893) + * Tue Jan 08 2013 Josh Boyer - Add patch to fix shutdown on some machines (rhbz 890547) From 08c8fb227bacce44bac89c28dc555898c00168e4 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 11 Jan 2013 15:54:11 -0600 Subject: [PATCH 142/492] Linux v3.7.2 --- Bluetooth-Add-support-for-BCM20702A0.patch | 43 ------- config-x86-generic | 2 +- exec-do-not-leave-bprm-interp-on-stack.patch | 118 ------------------- kernel.spec | 16 +-- sources | 2 +- 5 files changed, 8 insertions(+), 173 deletions(-) delete mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch delete mode 100644 exec-do-not-leave-bprm-interp-on-stack.patch diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch deleted file mode 100644 index 99178d757..000000000 --- a/Bluetooth-Add-support-for-BCM20702A0.patch +++ /dev/null @@ -1,43 +0,0 @@ -From a5f86c3423428c8e28b6501d0e9c3929ca91f07d Mon Sep 17 00:00:00 2001 -From: Jeff Cook -Date: Fri, 9 Nov 2012 16:39:48 -0700 -Subject: [PATCH 2/2] Bluetooth: Add support for BCM20702A0 [0b05, 17b5] - -Vendor-specific ID for BCM20702A0. -Support for bluetooth over Asus Wi-Fi GO!, included with Asus P8Z77-V -Deluxe. - -T: Bus=07 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 -D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=0b05 ProdID=17b5 Rev=01.12 -S: Manufacturer=Broadcom Corp -S: Product=BCM20702A0 -S: SerialNumber=94DBC98AC113 -C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA -I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) -I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) -I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) -I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) - -Cc: stable@vger.kernel.org -Signed-off-by: Jeff Cook -Signed-off-by: Gustavo Padovan ---- - drivers/bluetooth/btusb.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index b167944..6dc44ff 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { - { USB_DEVICE(0x0c10, 0x0000) }, - - /* Broadcom BCM20702A0 */ -+ { USB_DEVICE(0x0b05, 0x17b5) }, - { USB_DEVICE(0x04ca, 0x2003) }, - { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x413c, 0x8197) }, --- -1.8.0 - diff --git a/config-x86-generic b/config-x86-generic index 2bcd498eb..b3d19ea45 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -45,7 +45,7 @@ CONFIG_FB_EFI=y CONFIG_INTEL_IOMMU=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_INTEL_IOMMU_FLOPPY_WA=y -# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_DEFAULT_ON=y CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y diff --git a/exec-do-not-leave-bprm-interp-on-stack.patch b/exec-do-not-leave-bprm-interp-on-stack.patch deleted file mode 100644 index 5198824ed..000000000 --- a/exec-do-not-leave-bprm-interp-on-stack.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 6752ab4cb863fc63ed85f1ca78a42235c09fad83 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Mon, 26 Nov 2012 09:07:50 -0500 -Subject: [PATCH 1/2] exec: do not leave bprm->interp on stack - -If a series of scripts are executed, each triggering module loading via -unprintable bytes in the script header, kernel stack contents can leak -into the command line. - -Normally execution of binfmt_script and binfmt_misc happens recursively. -However, when modules are enabled, and unprintable bytes exist in the -bprm->buf, execution will restart after attempting to load matching binfmt -modules. Unfortunately, the logic in binfmt_script and binfmt_misc does -not expect to get restarted. They leave bprm->interp pointing to their -local stack. This means on restart bprm->interp is left pointing into -unused stack memory which can then be copied into the userspace argv -areas. - -After additional study, it seems that both recursion and restart remains -the desirable way to handle exec with scripts, misc, and modules. As -such, we need to protect the changes to interp. - -This changes the logic to require allocation for any changes to the -bprm->interp. To avoid adding a new kmalloc to every exec, the default -value is left as-is. Only when passing through binfmt_script or -binfmt_misc does an allocation take place. - -For a proof of concept, see DoTest.sh from: -http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/ - -Signed-off-by: Kees Cook -Cc: halfdog -Cc: P J P -Cc: Alexander Viro -Cc: -Signed-off-by: Andrew Morton ---- - fs/binfmt_misc.c | 5 ++++- - fs/binfmt_script.c | 4 +++- - fs/exec.c | 15 +++++++++++++++ - include/linux/binfmts.h | 1 + - 4 files changed, 23 insertions(+), 2 deletions(-) - -diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c -index 790b3cd..772428d 100644 ---- a/fs/binfmt_misc.c -+++ b/fs/binfmt_misc.c -@@ -176,7 +176,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) - goto _error; - bprm->argc ++; - -- bprm->interp = iname; /* for binfmt_script */ -+ /* Update interp in case binfmt_script needs it. */ -+ retval = bprm_change_interp(iname, bprm); -+ if (retval < 0) -+ goto _error; - - interp_file = open_exec (iname); - retval = PTR_ERR (interp_file); -diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c -index d3b8c1f..df49d48 100644 ---- a/fs/binfmt_script.c -+++ b/fs/binfmt_script.c -@@ -82,7 +82,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) - retval = copy_strings_kernel(1, &i_name, bprm); - if (retval) return retval; - bprm->argc++; -- bprm->interp = interp; -+ retval = bprm_change_interp(interp, bprm); -+ if (retval < 0) -+ return retval; - - /* - * OK, now restart the process with the interpreter's dentry. -diff --git a/fs/exec.c b/fs/exec.c -index 0039055..c6e6de4 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1175,9 +1175,24 @@ void free_bprm(struct linux_binprm *bprm) - mutex_unlock(¤t->signal->cred_guard_mutex); - abort_creds(bprm->cred); - } -+ /* If a binfmt changed the interp, free it. */ -+ if (bprm->interp != bprm->filename) -+ kfree(bprm->interp); - kfree(bprm); - } - -+int bprm_change_interp(char *interp, struct linux_binprm *bprm) -+{ -+ /* If a binfmt changed the interp, free it first. */ -+ if (bprm->interp != bprm->filename) -+ kfree(bprm->interp); -+ bprm->interp = kstrdup(interp, GFP_KERNEL); -+ if (!bprm->interp) -+ return -ENOMEM; -+ return 0; -+} -+EXPORT_SYMBOL(bprm_change_interp); -+ - /* - * install the new credentials for this executable - */ -diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index cfcc6bf..de0628e 100644 ---- a/include/linux/binfmts.h -+++ b/include/linux/binfmts.h -@@ -114,6 +114,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, - unsigned long stack_top, - int executable_stack); - extern int bprm_mm_init(struct linux_binprm *bprm); -+extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); - extern int copy_strings_kernel(int argc, const char *const *argv, - struct linux_binprm *bprm); - extern int prepare_bprm_creds(struct linux_binprm *bprm); --- -1.8.0 - diff --git a/kernel.spec b/kernel.spec index 38b44b51d..cf9f7d5ca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -769,14 +769,10 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 871078 Patch22112: USB-report-submission-of-active-URBs.patch -#rhbz 874791 -Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch - #rhbz 859485 Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz CVE-2012-4530 868285 880147 -Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 851278 @@ -1504,14 +1500,10 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 871078 ApplyPatch USB-report-submission-of-active-URBs.patch -#rhbz 874791 -ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch - #rhbz 859485 ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz CVE-2012-4530 868285 880147 -ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch #rhbz 851278 @@ -2404,6 +2396,10 @@ fi # ||----w | # || || %changelog +* Fri Jan 11 2013 Justin M. Forbes 3.7.1-1 +- Linux v3.7.2 +- Enable Intel IOMMU by default + * Thu Jan 10 2013 Dave Jones - Add audit-libs-devel to perf build-deps to enable trace command. (rhbz 892893) diff --git a/sources b/sources index d19fe4262..764eb4a60 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -48f5f530b048e387e978e3e49de7742a patch-3.7.1.xz +132211742278e18b8f4808754d85e66c patch-3.7.2.xz From 2aae8f448aba4f718508ca2c6750398b583f3623 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Jan 2013 13:57:30 -0500 Subject: [PATCH 143/492] Enable Orinoco drivers in kernel-modules-extra (rhbz 894069) --- config-generic | 11 ++++++++++- kernel.spec | 5 ++++- mod-extra.list | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/config-generic b/config-generic index e9a9307f8..926733e94 100644 --- a/config-generic +++ b/config-generic @@ -1532,7 +1532,16 @@ CONFIG_BRCMFMAC_SDIO_OOB=y CONFIG_BRCMFMAC_USB=y # CONFIG_BRCMISCAN is not set # CONFIG_BRCMDBG is not set -# CONFIG_HERMES is not set +CONFIG_HERMES=m +CONFIG_HERMES_CACHE_FW_ON_INIT=y +# CONFIG_HERMES_PRISM is not set +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_ORINOCO_USB=m +# CONFIG_TMD_HERMES is not set +# CONFIG_PCMCIA_SPECTRUM is not set # CONFIG_HOSTAP is not set # CONFIG_IPW2100 is not set # CONFIG_IPW2200 is not set diff --git a/kernel.spec b/kernel.spec index cf9f7d5ca..e22c83e16 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2396,6 +2396,9 @@ fi # ||----w | # || || %changelog +* Mon Jan 14 2013 Josh Boyer +- Enable Orinoco drivers in kernel-modules-extra (rhbz 894069) + * Fri Jan 11 2013 Justin M. Forbes 3.7.1-1 - Linux v3.7.2 - Enable Intel IOMMU by default diff --git a/mod-extra.list b/mod-extra.list index 124d74ef2..53f8c36b9 100644 --- a/mod-extra.list +++ b/mod-extra.list @@ -188,3 +188,9 @@ w1_ds2431.ko w1_ds2423.ko w1_bq27000.ko ubifs.ko +orinoco.ko +orinoco_cs.ko +orinoco_plx.ko +orinoco_pci.ko +orinoco_nortel.ko +orinoco_usb.ko From 3d3849a2e81d87ae4854ecc05a1742dda1780812 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 15 Jan 2013 11:01:00 -0500 Subject: [PATCH 144/492] Enable CONFIG_DVB_USB_V2 (rhbz 895460) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 926733e94..069aaf111 100644 --- a/config-generic +++ b/config-generic @@ -2689,7 +2689,7 @@ CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_USB_TECHNISAT_USB2=m -# CONFIG_DVB_USB_V2 is not set +CONFIG_DVB_USB_V2=m CONFIG_DVB_AV7110=m CONFIG_DVB_AV7110_OSD=y diff --git a/kernel.spec b/kernel.spec index e22c83e16..71033f5e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2396,6 +2396,9 @@ fi # ||----w | # || || %changelog +* Tue Jan 15 2013 Josh Boyer +- Enable CONFIG_DVB_USB_V2 (rhbz 895460) + * Mon Jan 14 2013 Josh Boyer - Enable Orinoco drivers in kernel-modules-extra (rhbz 894069) From b7b0a09dedc45f35ba1041fd123757079da2c4a2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 15 Jan 2013 16:13:12 -0600 Subject: [PATCH 145/492] Turn off Intel IOMMU by default --- ...-do-proper-memcpy-for-ACPI_TYPE_INTE.patch | 50 - 3.7.3-stable-queue.patch | 15769 ++++++++++++++++ ...e-Lid-and-Sleep-button-for-S5-wakeup.patch | 46 - ...e-vestigial-request-queue-allocation.patch | 69 - config-x86-generic | 2 +- kernel.spec | 33 +- mac80211-fix-ibss-scanning.patch | 132 - 7 files changed, 15779 insertions(+), 322 deletions(-) delete mode 100644 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch create mode 100644 3.7.3-stable-queue.patch delete mode 100644 ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch delete mode 100644 aoe-remove-vestigial-request-queue-allocation.patch delete mode 100644 mac80211-fix-ibss-scanning.patch diff --git a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch deleted file mode 100644 index 857c73c51..000000000 --- a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 690b1ad9d2032d6f2565d44f6564590d47835ae8 Mon Sep 17 00:00:00 2001 -From: Zhang Rui -Date: Thu, 29 Nov 2012 01:30:43 +0800 -Subject: [PATCH 1/2] ACPI sony-laptop: do proper memcpy for ACPI_TYPE_INTEGER - acpi_object - -the return value of __call_snc_method can either be -an ACPI_TYPE_BUFFER object or a ACPI_TYPE_INTEGER object. -do proper memcpy for ACPI_TYPE_INTEGER object. - -https://bugzilla.kernel.org/show_bug.cgi?id=50111 - -Signed-off-by: Zhang Rui ---- - drivers/platform/x86/sony-laptop.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c -index daaddec..92e0da2 100644 ---- a/drivers/platform/x86/sony-laptop.c -+++ b/drivers/platform/x86/sony-laptop.c -@@ -792,20 +792,19 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, - if (!object) - return -EINVAL; - -- if (object->type == ACPI_TYPE_BUFFER) -+ if (object->type == ACPI_TYPE_BUFFER) { - len = MIN(buflen, object->buffer.length); -- -- else if (object->type == ACPI_TYPE_INTEGER) -+ memcpy(buffer, object->buffer.pointer, len); -+ } else if (object->type == ACPI_TYPE_INTEGER) { - len = MIN(buflen, sizeof(object->integer.value)); -- -- else { -+ memcpy(buffer, (void *)&object->integer.value, len); -+ } else { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_BUFFER, object->type); - kfree(object); - return -EINVAL; - } - -- memcpy(buffer, object->buffer.pointer, len); - kfree(object); - return 0; - } --- -1.7.9.5 - diff --git a/3.7.3-stable-queue.patch b/3.7.3-stable-queue.patch new file mode 100644 index 000000000..e9b57d5a5 --- /dev/null +++ b/3.7.3-stable-queue.patch @@ -0,0 +1,15769 @@ +From 13ae633cf729b0ecb677b75b04886ff8fada8fad Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 20 Nov 2012 10:02:06 +0900 +Subject: regulator: wm831x: Set the new rather than old value for DVS VSEL + +From: Mark Brown + +commit 13ae633cf729b0ecb677b75b04886ff8fada8fad upstream. + +Reported-by: Guennadi Liakhovetski +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/wm831x-dcdc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/wm831x-dcdc.c ++++ b/drivers/regulator/wm831x-dcdc.c +@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel( + if (vsel > dcdc->dvs_vsel) { + ret = wm831x_set_bits(wm831x, dvs_reg, + WM831X_DC1_DVS_VSEL_MASK, +- dcdc->dvs_vsel); ++ vsel); + if (ret == 0) + dcdc->dvs_vsel = vsel; + else +From 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 10 Dec 2012 16:40:41 +0100 +Subject: ath5k: fix tx path skb leaks + +From: Felix Fietkau + +commit 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c upstream. + +ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for +tx packets passed to the driver from mac80211 + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath5k/base.c | 4 ++-- + drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -848,7 +848,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah + return; + dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, + DMA_TO_DEVICE); +- dev_kfree_skb_any(bf->skb); ++ ieee80211_free_txskb(ah->hw, bf->skb); + bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; +@@ -1575,7 +1575,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, + return; + + drop_packet: +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + + static void +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -62,7 +62,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct + u16 qnum = skb_get_queue_mapping(skb); + + if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + return; + } + +From 25a172655f837bdb032e451f95441bb4acec51bb Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Wed, 28 Nov 2012 10:51:34 +0200 +Subject: iwlwifi: don't handle masked interrupt + +From: Emmanuel Grumbach + +commit 25a172655f837bdb032e451f95441bb4acec51bb upstream. + +This can lead to a panic if the driver isn't ready to +handle them. Since our interrupt line is shared, we can get +an interrupt at any time (and CONFIG_DEBUG_SHIRQ checks +that even when the interrupt is being freed). + +If the op_mode has gone away, we musn't call it. To avoid +this the transport disables the interrupts when the hw is +stopped and the op_mode is leaving. +If there is an event that would cause an interrupt the INTA +register is updated regardless of the enablement of the +interrupts: even if the interrupts are disabled, the INTA +will be changed, but the device won't issue an interrupt. +But the ISR can be called at any time, so we ought ignore +the value in the INTA otherwise we can call the op_mode +after it was freed. + +I found this bug when the op_mode_start failed, and called +iwl_trans_stop_hw(trans, true). Then I played with the +RFKILL button, and removed the module. +While removing the module, the IRQ is freed, and the ISR is +called (CONFIG_DEBUG_SHIRQ enabled). Panic. + +Signed-off-by: Emmanuel Grumbach +Reviewed-by: Gregory Greenman +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/rx.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c +@@ -927,12 +927,20 @@ static irqreturn_t iwl_isr(int irq, void + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(trans, CSR_INT); + ++ if (inta & (~inta_mask)) { ++ IWL_DEBUG_ISR(trans, ++ "We got a masked interrupt (0x%08x)...Ack and ignore\n", ++ inta & (~inta_mask)); ++ iwl_write32(trans, CSR_INT, inta & (~inta_mask)); ++ inta &= inta_mask; ++ } ++ + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ +@@ -1015,7 +1023,7 @@ irqreturn_t iwl_isr_ict(int irq, void *d + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + +From 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Sun, 2 Dec 2012 09:56:44 +0200 +Subject: iwlwifi: silently ignore fw flaws in Tx path + +From: Emmanuel Grumbach + +commit 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 upstream. + +We know that we have issues with the fw in the reclaim path. +This is why iwl_reclaim doesn't complain too loud when it +happens since it is recoverable. Somehow, the caller of +iwl_reclaim however WARNed when it happens. This doesn't +make any sense. + +When I digged into the history of that code, I discovered +that this bug occurs only when we receive a BA notification. +So move the W/A in the BA notification handling code where +it was before. + +This patch addresses: +http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2387 + +Reported-by: Florian Reitmeir +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/dvm/tx.c | 49 ++++++++++++---------------------- + 1 file changed, 18 insertions(+), 31 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -1100,29 +1100,6 @@ static void iwl_check_abort_status(struc + } + } + +-static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid, +- int txq_id, int ssn, struct sk_buff_head *skbs) +-{ +- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && +- tid != IWL_TID_NON_QOS && +- txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) { +- /* +- * FIXME: this is a uCode bug which need to be addressed, +- * log the information and return for now. +- * Since it is can possibly happen very often and in order +- * not to fill the syslog, don't use IWL_ERR or IWL_WARN +- */ +- IWL_DEBUG_TX_QUEUES(priv, +- "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", +- txq_id, sta_id, tid, +- priv->tid_data[sta_id][tid].agg.txq_id); +- return 1; +- } +- +- iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs); +- return 0; +-} +- + int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd) + { +@@ -1184,9 +1161,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + next_reclaimed); + } + +- /*we can free until ssn % q.n_bd not inclusive */ +- WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid, +- txq_id, ssn, &skbs)); ++ iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); ++ + iwlagn_check_ratid_empty(priv, sta_id, tid); + freed = 0; + +@@ -1311,16 +1287,27 @@ int iwlagn_rx_reply_compressed_ba(struct + return 0; + } + ++ if (unlikely(scd_flow != agg->txq_id)) { ++ /* ++ * FIXME: this is a uCode bug which need to be addressed, ++ * log the information and return for now. ++ * Since it is can possibly happen very often and in order ++ * not to fill the syslog, don't use IWL_ERR or IWL_WARN ++ */ ++ IWL_DEBUG_TX_QUEUES(priv, ++ "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", ++ scd_flow, sta_id, tid, agg->txq_id); ++ spin_unlock(&priv->sta_lock); ++ return 0; ++ } ++ + __skb_queue_head_init(&reclaimed_skbs); + + /* Release all TFDs before the SSN, i.e. all TFDs in front of + * block-ack window (we assume that they've been successfully + * transmitted ... if not, it's too late anyway). */ +- if (iwl_reclaim(priv, sta_id, tid, scd_flow, +- ba_resp_scd_ssn, &reclaimed_skbs)) { +- spin_unlock(&priv->sta_lock); +- return 0; +- } ++ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn, ++ &reclaimed_skbs); + + IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " + "sta_id = %d\n", +From cbbc0138efe1dcd5426b8fc5d87741f5057aee72 Mon Sep 17 00:00:00 2001 +From: RafaÅ‚ MiÅ‚ecki +Date: Mon, 10 Dec 2012 07:53:56 +0100 +Subject: bcma: mips: fix clearing device IRQ + +From: RafaÅ‚ MiÅ‚ecki + +commit cbbc0138efe1dcd5426b8fc5d87741f5057aee72 upstream. + +We were using wrong IRQ number so clearing wasn't working at all. +Depending on a platform this could result in a one device having two +interrupts assigned. On BCM4706 this resulted in all IRQs being broken. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Cc: Hauke Mehrtens +Acked-by: Hauke Mehrtens +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/bcma/driver_mips.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/bcma/driver_mips.c ++++ b/drivers/bcma/driver_mips.c +@@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struc + bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & + ~(1 << irqflag)); + else +- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); + + /* assign the new one */ + if (irq == 0) { +From f5685ba675449b072feab6a5391a9ef9f604bc94 Mon Sep 17 00:00:00 2001 +From: Helmut Schaa +Date: Mon, 3 Dec 2012 22:35:39 +0100 +Subject: rt2x00: Only specify interface combinations if more then one interface is possible + +From: Helmut Schaa + +commit f5685ba675449b072feab6a5391a9ef9f604bc94 upstream. + +Otherwise rt2500* triggers a warning in cfg80211, from net/wireless/core.c: + + /* Combinations with just one interface aren't real */ + if (WARN_ON(c->max_interfaces < 2)) + +This was introduced in commit 55d2e9da744ba11eae900b4bfc2da72eace3c1e1: +rt2x00: Replace open coded interface checking with interface combinations. + +Reported-by: Stefan Lippers-Hollmann +Tested-by: Stefan Lippers-Hollmann +Signed-off-by: Helmut Schaa +Acked-by: Gertjan van Wingerde +Acked-by: Stanislaw Gruszka +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2x00dev.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1123,6 +1123,9 @@ static inline void rt2x00lib_set_if_comb + struct ieee80211_iface_limit *if_limit; + struct ieee80211_iface_combination *if_combination; + ++ if (rt2x00dev->ops->max_ap_intf < 2) ++ return; ++ + /* + * Build up AP interface limits structure. + */ +From 87cac8f879a5ecd7109dbe688087e8810b3364eb Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Tue, 2 Oct 2012 16:25:38 +0200 +Subject: s390/kvm: dont announce RRBM support + +From: Christian Borntraeger + +commit 87cac8f879a5ecd7109dbe688087e8810b3364eb upstream. + +Newer kernels (linux-next with the transparent huge page patches) +use rrbm if the feature is announced via feature bit 66. +RRBM will cause intercepts, so KVM does not handle it right now, +causing an illegal instruction in the guest. +The easy solution is to disable the feature bit for the guest. + +This fixes bugs like: +Kernel BUG at 0000000000124c2a [verbose debug info unavailable] +illegal operation: 0001 [#1] SMP +Modules linked in: virtio_balloon virtio_net ipv6 autofs4 +CPU: 0 Not tainted 3.5.4 #1 +Process fmempig (pid: 659, task: 000000007b712fd0, ksp: 000000007bed3670) +Krnl PSW : 0704d00180000000 0000000000124c2a (pmdp_clear_flush_young+0x5e/0x80) + R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3 + 00000000003cc000 0000000000000004 0000000000000000 0000000079800000 + 0000000000040000 0000000000000000 000000007bed3918 000000007cf40000 + 0000000000000001 000003fff7f00000 000003d281a94000 000000007bed383c + 000000007bed3918 00000000005ecbf8 00000000002314a6 000000007bed36e0 + Krnl Code:>0000000000124c2a: b9810025 ogr %r2,%r5 + 0000000000124c2e: 41343000 la %r3,0(%r4,%r3) + 0000000000124c32: a716fffa brct %r1,124c26 + 0000000000124c36: b9010022 lngr %r2,%r2 + 0000000000124c3a: e3d0f0800004 lg %r13,128(%r15) + 0000000000124c40: eb22003f000c srlg %r2,%r2,63 +[ 2150.713198] Call Trace: +[ 2150.713223] ([<00000000002312c4>] page_referenced_one+0x6c/0x27c) +[ 2150.713749] [<0000000000233812>] page_referenced+0x32a/0x410 +[...] + +Signed-off-by: Martin Schwidefsky +CC: Alex Graf +Signed-off-by: Christian Borntraeger +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kvm/kvm-s390.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -997,7 +997,7 @@ static int __init kvm_s390_init(void) + } + memcpy(facilities, S390_lowcore.stfle_fac_list, 16); + facilities[0] &= 0xff00fff3f47c0000ULL; +- facilities[1] &= 0x201c000000000000ULL; ++ facilities[1] &= 0x001c000000000000ULL; + return 0; + } + +From ce6a04ac1b759beafc88dbc443ae5da867579eeb Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Thu, 15 Nov 2012 09:35:16 +0100 +Subject: s390/kvm: Fix address space mixup + +From: Christian Borntraeger + +commit ce6a04ac1b759beafc88dbc443ae5da867579eeb upstream. + +I was chasing down a bug of random validity intercepts on s390. +(guest prefix page not mapped in the host virtual aspace). Turns out +that the problem was a wrong address space control element. The +cause was quite complex: + +During paging activity a DAT protection during SIE caused a program +interrupt. Normally, the sie retry loop tries to catch all +interrupts during and shortly before sie to rerun the setup. The +problem is now that protection causes a suppressing program interrupt, +causing the PSW to point to the instruction AFTER SIE in case of DAT +protection. This confused the logic of the retry loop to not trigger, +instead we jumped directly back to SIE after return from +the program interrupt. (the protection fault handler itself did +a rewind of the psw). This usually works quite well, but: + +If now the protection fault handler has to wait, another program +might be scheduled in. Later on the sie process will be schedules +in again. In that case the content of CR1 (primary address space) +will be wrong because switch_to will put the user space ASCE into CR1 +and not the guest ASCE. + +In addition the program parameter is also wrong for every protection +fault of a guest, since we dont issue the SPP instruction. + +So lets also check for PSW == instruction after SIE in the program +check handler. Instead of expensively checking all program +interruption codes that might be suppressing we assume that a program +interrupt pointing after SIE was always a program interrupt in SIE. +(Otherwise we have a kernel bug anyway). + +We also have to compensate the rewinding, since the C-level handlers +will do that. Therefore we need to add a nop with the same length +as SIE before the sie_loop. + +Signed-off-by: Christian Borntraeger +Signed-off-by: Martin Schwidefsky +CC: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/entry64.S | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/arch/s390/kernel/entry64.S ++++ b/arch/s390/kernel/entry64.S +@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_ + #endif + .endm + +- .macro HANDLE_SIE_INTERCEPT scratch ++ .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck + #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + tmhh %r8,0x0001 # interrupting from user ? + jnz .+42 + lgr \scratch,%r9 + slg \scratch,BASED(.Lsie_loop) + clg \scratch,BASED(.Lsie_length) ++ .if \pgmcheck ++ # Some program interrupts are suppressing (e.g. protection). ++ # We must also check the instruction after SIE in that case. ++ # do_protection_exception will rewind to rewind_pad ++ jh .+22 ++ .else + jhe .+22 ++ .endif + lg %r9,BASED(.Lsie_loop) + SPP BASED(.Lhost_id) # set host id + #endif +@@ -391,7 +398,7 @@ ENTRY(pgm_check_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_PGM_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,1 + tmhh %r8,0x0001 # test problem state bit + jnz 1f # -> fault in user space + tmhh %r8,0x4000 # PER bit set in old PSW ? +@@ -467,7 +474,7 @@ ENTRY(io_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_IO_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT + tmhh %r8,0x0001 # interrupting from user? + jz io_skip +@@ -613,7 +620,7 @@ ENTRY(ext_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_EXT_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT + tmhh %r8,0x0001 # interrupting from user ? + jz ext_skip +@@ -661,7 +668,7 @@ ENTRY(mcck_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_MCK_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + tm __LC_MCCK_CODE,0x80 # system damage? + jo mcck_panic # yes -> rest of mcck code invalid + lghi %r14,__LC_CPU_TIMER_SAVE_AREA +@@ -960,6 +967,13 @@ ENTRY(sie64a) + stg %r3,__SF_EMPTY+8(%r15) # save guest register save area + xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 + lmg %r0,%r13,0(%r3) # load guest gprs 0-13 ++# some program checks are suppressing. C code (e.g. do_protection_exception) ++# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other ++# instructions in the sie_loop should not cause program interrupts. So ++# lets use a nop (47 00 00 00) as a landing pad. ++# See also HANDLE_SIE_INTERCEPT ++rewind_pad: ++ nop 0 + sie_loop: + lg %r14,__LC_THREAD_INFO # pointer thread_info struct + tm __TI_flags+7(%r14),_TIF_EXIT_SIE +@@ -999,6 +1013,7 @@ sie_fault: + .Lhost_id: + .quad 0 + ++ EX_TABLE(rewind_pad,sie_fault) + EX_TABLE(sie_loop,sie_fault) + #endif + +From 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 Mon Sep 17 00:00:00 2001 +From: Anton Blanchard +Date: Sun, 11 Nov 2012 19:01:05 +0000 +Subject: powerpc: Fix CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n build + +From: Anton Blanchard + +commit 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 upstream. + +If we build a kernel with CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n, +the kernel fails when we run at a non zero offset. It turns out +we were incorrectly wrapping some of the relocatable kernel code +with CONFIG_CRASH_DUMP. + +Signed-off-by: Anton Blanchard +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/head_64.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/head_64.S ++++ b/arch/powerpc/kernel/head_64.S +@@ -422,7 +422,7 @@ _STATIC(__after_prom_start) + tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ + #endif + +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_RELOCATABLE + /* + * Check if the kernel has to be running as relocatable kernel based on the + * variable __run_at_load, if it is set the kernel is treated as relocatable +From ce73ec6db47af84d1466402781ae0872a9e7873c Mon Sep 17 00:00:00 2001 +From: Shan Hai +Date: Thu, 8 Nov 2012 15:57:49 +0000 +Subject: powerpc/vdso: Remove redundant locking in update_vsyscall_tz() + +From: Shan Hai + +commit ce73ec6db47af84d1466402781ae0872a9e7873c upstream. + +The locking in update_vsyscall_tz() is not only unnecessary because the vdso +code copies the data unproteced in __kernel_gettimeofday() but also +introduces a hard to reproduce race condition between update_vsyscall() +and update_vsyscall_tz(), which causes user space process to loop +forever in vdso code. + +The following patch removes the locking from update_vsyscall_tz(). + +Locking is not only unnecessary because the vdso code copies the data +unprotected in __kernel_gettimeofday() but also erroneous because updating +the tb_update_count is not atomic and introduces a hard to reproduce race +condition between update_vsyscall() and update_vsyscall_tz(), which further +causes user space process to loop forever in vdso code. + +The below scenario describes the race condition, +x==0 Boot CPU other CPU + proc_P: x==0 + timer interrupt + update_vsyscall +x==1 x++;sync settimeofday + update_vsyscall_tz +x==2 x++;sync +x==3 sync;x++ + sync;x++ + proc_P: x==3 (loops until x becomes even) + +Because the ++ operator would be implemented as three instructions and not +atomic on powerpc. + +A similar change was made for x86 in commit 6c260d58634 +("x86: vdso: Remove bogus locking in update_vsyscall_tz") + +Signed-off-by: Shan Hai +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/time.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -774,13 +774,8 @@ void update_vsyscall_old(struct timespec + + void update_vsyscall_tz(void) + { +- /* Make userspace gettimeofday spin until we're done. */ +- ++vdso_data->tb_update_count; +- smp_mb(); + vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; + vdso_data->tz_dsttime = sys_tz.tz_dsttime; +- smp_mb(); +- ++vdso_data->tb_update_count; + } + + static void __init clocksource_init(void) +From e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 20 Dec 2012 03:44:28 +0000 +Subject: powerpc: Add missing NULL terminator to avoid boot panic on PPC40x + +From: Gabor Juhos + +commit e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b upstream. + +The missing NULL terminator can cause a panic on +PPC405 boards during boot: + + Linux/PowerPC load: console=ttyS0,115200 root=/dev/mtdblock1 rootfstype=squashfs,jffs2 noinitrd init=/etc/preinit + Finalizing device tree... flat tree at 0x6a5160 + bootconsole [udbg0] enabled + Page fault in user mode with in_atomic() = 1 mm = (null) + NIP = c0275f50 MSR = fffffffe + Oops: Weird page fault, sig: 11 [#1] + PowerPC 40x Platform + Modules linked in: + NIP: c0275f50 LR: c0275f60 CTR: c0280000 + REGS: c0275eb0 TRAP: 636f7265 Not tainted (3.7.1) + MSR: fffffffe CR: c06a6190 XER: 00000001 + TASK = c02662a8[0] 'swapper' THREAD: c0274000 + GPR00: c0275ec0 c000c658 c027c4bf 00000000 c0275ee0 c000a0ec c020a1a8 c020a1f0 + GPR08: c020f631 c020f404 c025f078 c025f080 c0275f10 + Call Trace: + ---[ end trace 31fd0ba7d8756001 ]--- + + Kernel panic - not syncing: Attempted to kill the idle task! + +The panic happens since commit 9597abe00c1bab2aedce6b49866bf6d1e81c9eed +(sections: fix section conflicts in arch/powerpc), however the root +cause of this is that the NULL terminator were not added in commit +a4f740cf33f7f6c164bbde3c0cdbcc77b0c4997c (of/flattree: Add of_flat_dt_match() +helper function). + +Signed-off-by: Gabor Juhos +Cc: Grant Likely +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/platforms/40x/ppc40x_simple.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/40x/ppc40x_simple.c ++++ b/arch/powerpc/platforms/40x/ppc40x_simple.c +@@ -57,7 +57,8 @@ static const char * const board[] __init + "amcc,makalu", + "apm,klondike", + "est,hotfoot", +- "plathome,obs600" ++ "plathome,obs600", ++ NULL + }; + + static int __init ppc40x_probe(void) +From e400e72f250d2567e89c9bafb47ab91e8d9a15a2 Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Wed, 22 Aug 2012 15:04:23 +0000 +Subject: KVM: PPC: e500: fix allocation size error on g2h_tlb1_map + +From: Scott Wood + +commit e400e72f250d2567e89c9bafb47ab91e8d9a15a2 upstream. + +We were only allocating half the bytes we need, which was made more +obvious by a recent fix to the memset in clear_tlb1_bitmap(). + +Signed-off-by: Scott Wood +Signed-off-by: Alexander Graf +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kvm/e500_tlb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kvm/e500_tlb.c ++++ b/arch/powerpc/kvm/e500_tlb.c +@@ -1332,7 +1332,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_v + if (!vcpu_e500->gtlb_priv[1]) + goto err; + +- vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) * ++ vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) * + vcpu_e500->gtlb_params[1].entries, + GFP_KERNEL); + if (!vcpu_e500->g2h_tlb1_map) +From 5419369ed6bd4cf711fdda5e52a5999b940413f5 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 29 Nov 2012 14:07:59 -0700 +Subject: KVM: Fix user memslot overlap check + +From: Alex Williamson + +commit 5419369ed6bd4cf711fdda5e52a5999b940413f5 upstream. + +Prior to memory slot sorting this loop compared all of the user memory +slots for overlap with new entries. With memory slot sorting, we're +just checking some number of entries in the array that may or may not +be user slots. Instead, walk all the slots with kvm_for_each_memslot, +which has the added benefit of terminating early when we hit the first +empty slot, and skip comparison to private slots. + +Signed-off-by: Alex Williamson +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman + +--- + virt/kvm/kvm_main.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -709,8 +709,7 @@ int __kvm_set_memory_region(struct kvm * + int r; + gfn_t base_gfn; + unsigned long npages; +- unsigned long i; +- struct kvm_memory_slot *memslot; ++ struct kvm_memory_slot *memslot, *slot; + struct kvm_memory_slot old, new; + struct kvm_memslots *slots, *old_memslots; + +@@ -761,13 +760,11 @@ int __kvm_set_memory_region(struct kvm * + + /* Check for overlaps */ + r = -EEXIST; +- for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { +- struct kvm_memory_slot *s = &kvm->memslots->memslots[i]; +- +- if (s == memslot || !s->npages) ++ kvm_for_each_memslot(slot, kvm->memslots) { ++ if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot) + continue; +- if (!((base_gfn + npages <= s->base_gfn) || +- (base_gfn >= s->base_gfn + s->npages))) ++ if (!((base_gfn + npages <= slot->base_gfn) || ++ (base_gfn >= slot->base_gfn + slot->npages))) + goto out_free; + } + +From d99e79ec5574fc556c988f613ed6175f6de66f4a Mon Sep 17 00:00:00 2001 +From: Sebastian Ott +Date: Fri, 30 Nov 2012 16:48:59 +0100 +Subject: s390/cio: fix pgid reserved check + +From: Sebastian Ott + +commit d99e79ec5574fc556c988f613ed6175f6de66f4a upstream. + +The check to whom a device is reserved is done by checking the path +state of the affected channel paths. If it turns out that one path is +flagged as reserved by someone else the whole device is marked as such. + +However the meaning of the RESVD_ELSE bit is that the addressed device +is reserved to a different pathgroup (and not reserved to a different +LPAR). If we do this test on a path which is currently not a member of +the pathgroup we could erroneously mark the device as reserved to +someone else. + +To fix this collect the reserved state for all potential members of the +pathgroup and only mark the device as reserved if all of those potential +members have the RESVD_ELSE bit set. + +Acked-by: Peter Oberparleiter +Signed-off-by: Sebastian Ott +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/cio/device_pgid.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/s390/cio/device_pgid.c ++++ b/drivers/s390/cio/device_pgid.c +@@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, str + * Determine pathgroup state from PGID data. + */ + static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, +- int *mismatch, int *reserved, u8 *reset) ++ int *mismatch, u8 *reserved, u8 *reset) + { + struct pgid *pgid = &cdev->private->pgid[0]; + struct pgid *first = NULL; +@@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_devi + if ((cdev->private->pgid_valid_mask & lpm) == 0) + continue; + if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE) +- *reserved = 1; ++ *reserved |= lpm; + if (pgid_is_reset(pgid)) { + *reset |= lpm; + continue; +@@ -316,14 +316,14 @@ static void snid_done(struct ccw_device + struct subchannel *sch = to_subchannel(cdev->dev.parent); + struct pgid *pgid; + int mismatch = 0; +- int reserved = 0; ++ u8 reserved = 0; + u8 reset = 0; + u8 donepm; + + if (rc) + goto out; + pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset); +- if (reserved) ++ if (reserved == cdev->private->pgid_valid_mask) + rc = -EUSERS; + else if (mismatch) + rc = -EOPNOTSUPP; +@@ -336,7 +336,7 @@ static void snid_done(struct ccw_device + } + out: + CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x " +- "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid, ++ "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid, + id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm, + cdev->private->pgid_todo_mask, mismatch, reserved, reset); + switch (rc) { +From 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Mon, 13 Aug 2012 20:52:24 +0800 +Subject: MIPS: Fix poweroff failure when HOTPLUG_CPU configured. + +From: Huacai Chen + +commit 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 upstream. + +When poweroff machine, kernel_power_off() call disable_nonboot_cpus(). +And if we have HOTPLUG_CPU configured, disable_nonboot_cpus() is not an +empty function but attempt to actually disable the nonboot cpus. Since +system state is SYSTEM_POWER_OFF, play_dead() won't be called and thus +disable_nonboot_cpus() hangs. Therefore, we make this patch to avoid +poweroff failure. + +Signed-off-by: Huacai Chen +Signed-off-by: Hongliang Tao +Signed-off-by: Hua Yan +Cc: Yong Zhang +Cc: Fuxin Zhang +Cc: Zhangjin Wu +Patchwork: https://patchwork.linux-mips.org/patch/4211/ +Signed-off-by: Ralf Baechle +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kernel/process.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -72,9 +72,7 @@ void __noreturn cpu_idle(void) + } + } + #ifdef CONFIG_HOTPLUG_CPU +- if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && +- (system_state == SYSTEM_RUNNING || +- system_state == SYSTEM_BOOTING)) ++ if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map)) + play_dead(); + #endif + rcu_idle_exit(); +From 7964c06d66c76507d8b6b662bffea770c29ef0ce Mon Sep 17 00:00:00 2001 +From: Jason Liu +Date: Fri, 11 Jan 2013 14:31:47 -0800 +Subject: mm: compaction: fix echo 1 > compact_memory return error issue + +From: Jason Liu + +commit 7964c06d66c76507d8b6b662bffea770c29ef0ce upstream. + +when run the folloing command under shell, it will return error + + sh/$ echo 1 > /proc/sys/vm/compact_memory + sh/$ sh: write error: Bad address + +After strace, I found the following log: + + ... + write(1, "1\n", 2) = 3 + write(1, "", 4294967295) = -1 EFAULT (Bad address) + write(2, "echo: write error: Bad address\n", 31echo: write error: Bad address + ) = 31 + +This tells system return 3(COMPACT_COMPLETE) after write data to +compact_memory. + +The fix is to make the system just return 0 instead 3(COMPACT_COMPLETE) +from sysctl_compaction_handler after compaction_nodes finished. + +Signed-off-by: Jason Liu +Suggested-by: David Rientjes +Acked-by: Mel Gorman +Cc: Rik van Riel +Cc: Minchan Kim +Cc: KAMEZAWA Hiroyuki +Acked-by: David Rientjes +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/compaction.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -1174,7 +1174,7 @@ static int compact_node(int nid) + } + + /* Compact all nodes in the system */ +-static int compact_nodes(void) ++static void compact_nodes(void) + { + int nid; + +@@ -1183,8 +1183,6 @@ static int compact_nodes(void) + + for_each_online_node(nid) + compact_node(nid); +- +- return COMPACT_COMPLETE; + } + + /* The written value is actually unused, all memory is compacted */ +@@ -1195,7 +1193,7 @@ int sysctl_compaction_handler(struct ctl + void __user *buffer, size_t *length, loff_t *ppos) + { + if (write) +- return compact_nodes(); ++ compact_nodes(); + + return 0; + } +From c060f943d0929f3e429c5d9522290584f6281d6e Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Fri, 11 Jan 2013 14:31:51 -0800 +Subject: mm: use aligned zone start for pfn_to_bitidx calculation + +From: Laura Abbott + +commit c060f943d0929f3e429c5d9522290584f6281d6e upstream. + +The current calculation in pfn_to_bitidx assumes that (pfn - +zone->zone_start_pfn) >> pageblock_order will return the same bit for +all pfn in a pageblock. If zone_start_pfn is not aligned to +pageblock_nr_pages, this may not always be correct. + +Consider the following with pageblock order = 10, zone start 2MB: + + pfn | pfn - zone start | (pfn - zone start) >> page block order + ---------------------------------------------------------------- + 0x26000 | 0x25e00 | 0x97 + 0x26100 | 0x25f00 | 0x97 + 0x26200 | 0x26000 | 0x98 + 0x26300 | 0x26100 | 0x98 + +This means that calling {get,set}_pageblock_migratetype on a single page +will not set the migratetype for the full block. Fix this by rounding +down zone_start_pfn when doing the bitidx calculation. + +For our use case, the effects of this bug were mostly tied to the fact +that CMA allocations would either take a long time or fail to happen. +Depending on the driver using CMA, this could result in anything from +visual glitches to application failures. + +Signed-off-by: Laura Abbott +Acked-by: Mel Gorman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -5506,7 +5506,7 @@ static inline int pfn_to_bitidx(struct z + pfn &= (PAGES_PER_SECTION-1); + return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; + #else +- pfn = pfn - zone->zone_start_pfn; ++ pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); + return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; + #endif /* CONFIG_SPARSEMEM */ + } +From 10d73e655cef6e86ea8589dca3df4e495e4900b0 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Fri, 11 Jan 2013 14:31:52 -0800 +Subject: mm: bootmem: fix free_all_bootmem_core() with odd bitmap alignment + +From: Max Filippov + +commit 10d73e655cef6e86ea8589dca3df4e495e4900b0 upstream. + +Currently free_all_bootmem_core ignores that node_min_pfn may be not +multiple of BITS_PER_LONG. Eg commit 6dccdcbe2c3e ("mm: bootmem: fix +checking the bitmap when finally freeing bootmem") shifts vec by lower +bits of start instead of lower bits of idx. Also + + if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) + +assumes that vec bit 0 corresponds to start pfn, which is only true when +node_min_pfn is a multiple of BITS_PER_LONG. Also loop in the else +clause can double-free pages (e.g. with node_min_pfn == start == 1, +map[0] == ~0 on 32-bit machine page 32 will be double-freed). + +This bug causes the following message during xtensa kernel boot: + + bootmem::free_all_bootmem_core nid=0 start=1 end=8000 + BUG: Bad page state in process swapper pfn:00001 + page:d04bd020 count:0 mapcount:-127 mapping: (null) index:0x2 + page flags: 0x0() + Call Trace: + bad_page+0x8c/0x9c + free_pages_prepare+0x5e/0x88 + free_hot_cold_page+0xc/0xa0 + __free_pages+0x24/0x38 + __free_pages_bootmem+0x54/0x56 + free_all_bootmem_core$part$11+0xeb/0x138 + free_all_bootmem+0x46/0x58 + mem_init+0x25/0xa4 + start_kernel+0x11e/0x25c + should_never_return+0x0/0x3be7 + +The fix is the following: + - always align vec so that its bit 0 corresponds to start + - provide BITS_PER_LONG bits in vec, if those bits are available in the + map + - don't free pages past next start position in the else clause. + +Signed-off-by: Max Filippov +Cc: Gavin Shan +Cc: Johannes Weiner +Cc: Tejun Heo +Cc: Yinghai Lu +Cc: Joonsoo Kim +Cc: Prasad Koya +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/bootmem.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/mm/bootmem.c ++++ b/mm/bootmem.c +@@ -185,10 +185,23 @@ static unsigned long __init free_all_boo + + while (start < end) { + unsigned long *map, idx, vec; ++ unsigned shift; + + map = bdata->node_bootmem_map; + idx = start - bdata->node_min_pfn; ++ shift = idx & (BITS_PER_LONG - 1); ++ /* ++ * vec holds at most BITS_PER_LONG map bits, ++ * bit 0 corresponds to start. ++ */ + vec = ~map[idx / BITS_PER_LONG]; ++ ++ if (shift) { ++ vec >>= shift; ++ if (end - start >= BITS_PER_LONG) ++ vec |= ~map[idx / BITS_PER_LONG + 1] << ++ (BITS_PER_LONG - shift); ++ } + /* + * If we have a properly aligned and fully unreserved + * BITS_PER_LONG block of pages in front of us, free +@@ -201,19 +214,18 @@ static unsigned long __init free_all_boo + count += BITS_PER_LONG; + start += BITS_PER_LONG; + } else { +- unsigned long off = 0; ++ unsigned long cur = start; + +- vec >>= start & (BITS_PER_LONG - 1); +- while (vec) { ++ start = ALIGN(start + 1, BITS_PER_LONG); ++ while (vec && cur != start) { + if (vec & 1) { +- page = pfn_to_page(start + off); ++ page = pfn_to_page(cur); + __free_pages_bootmem(page, 0); + count++; + } + vec >>= 1; +- off++; ++ ++cur; + } +- start = ALIGN(start + 1, BITS_PER_LONG); + } + } + +From 1680260226a8fd2aab590319da83ad8e610da9bd Mon Sep 17 00:00:00 2001 +From: Rajkumar Manoharan +Date: Thu, 25 Oct 2012 17:11:31 +0530 +Subject: ath9k_hw: Enable hw PLL power save for AR9462 + +From: Rajkumar Manoharan + +commit 1680260226a8fd2aab590319da83ad8e610da9bd upstream. + +This reduced the power consumption to half in full and network sleep. + +Signed-off-by: Rajkumar Manoharan +Cc: Paul Stewart +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c +@@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(str + + /* Awake -> Sleep Setting */ + INIT_INI_ARRAY(&ah->iniPcieSerdes, +- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); ++ ar9462_pciephy_clkreq_disable_L1_2p0); + /* Sleep -> Awake Setting */ + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, +- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); ++ ar9462_pciephy_clkreq_disable_L1_2p0); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesFastClock, +From 9c170e068636deb3e3f96114034bb711675f0faa Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 6 Dec 2012 18:40:11 +0100 +Subject: Revert "ath9k_hw: Update AR9003 high_power tx gain table" + +From: Felix Fietkau + +commit 9c170e068636deb3e3f96114034bb711675f0faa upstream. + +This reverts commit f74b9d365ddd33a375802b064f96a5d0e99af7c0. + +Turns out reverting commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd +"ath9k_hw: Updated AR9003 tx gain table for 5GHz" was not enough to +bring the tx power back to normal levels on devices like the +Buffalo WZR-HP-G450H, this one needs to be reverted as well. + +This revert improves tx power by ~10 db on that device + +Signed-off-by: Felix Fietkau +Cc: rmanohar@qca.qualcomm.com +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 172 +++++++++---------- + 1 file changed, 86 insertions(+), 86 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +@@ -534,98 +534,98 @@ static const u32 ar9300_2p2_baseband_cor + + static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ +- {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +- {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +- {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +- {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, +- {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, +- {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, +- {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, +- {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, +- {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, +- {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, +- {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, +- {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +- {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +- {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +- {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, +- {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, +- {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, +- {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, +- {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, +- {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, +- {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, +- {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, +- {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, ++ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, ++ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, ++ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, ++ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, ++ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, ++ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, ++ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, ++ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, ++ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, ++ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, ++ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, ++ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, ++ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, ++ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, ++ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, ++ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, ++ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, ++ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, ++ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, ++ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, ++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, ++ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, ++ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, ++ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, ++ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, ++ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, ++ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, ++ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, ++ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, ++ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, ++ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, ++ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, ++ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, ++ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, ++ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, ++ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, ++ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, ++ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, ++ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, ++ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, ++ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, ++ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, ++ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, ++ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, ++ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, ++ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, ++ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, ++ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, ++ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, ++ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, ++ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, ++ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, +- {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, +- {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, +- {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, +- {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, +- {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, +- {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, ++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, ++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, ++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, ++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, ++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, ++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, ++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +- {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +From b3cd8021379306c0be6932e4d3b4b01efc681769 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 9 Dec 2012 23:57:09 +0100 +Subject: ath9k: ar9003: fix OTP register offsets for AR9340 + +From: Gabor Juhos + +commit b3cd8021379306c0be6932e4d3b4b01efc681769 upstream. + +Trying to access the OTP memory on the AR9340 +causes a data bus error like this: + + Data bus error, epc == 86e84164, ra == 86e84164 + Oops[#1]: + Cpu 0 + $ 0 : 00000000 00000061 deadc0de 00000000 + $ 4 : b8115f18 00015f18 00000007 00000004 + $ 8 : 00000001 7c7c3c7c 7c7c7c7c 7c7c7c7c + $12 : 7c7c3c7c 001f0041 00000000 7c7c7c3c + $16 : 86ee0000 00015f18 00000000 00000007 + $20 : 00000004 00000064 00000004 86d71c44 + $24 : 00000000 86e6ca00 + $28 : 86d70000 86d71b20 86ece0c0 86e84164 + Hi : 00000000 + Lo : 00000064 + epc : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + Tainted: G O + ra : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + Status: 1100d403 KERNEL EXL IE + Cause : 4080801c + PrId : 0001974c (MIPS 74Kc) + Modules linked in: ath9k(O+) ath9k_common(O) ath9k_hw(O) ath(O) ar934x_nfc + mac80211(O) usbcore usb_common scsi_mod nls_base nand nand_ecc nand_ids + crc_ccitt cfg80211(O) compat(O) arc4 aes_generic crypto_blkcipher cryptomgr + aead crypto_hash crypto_algapi ledtrig_timer ledtrig_default_on leds_gpio + Process insmod (pid: 459, threadinfo=86d70000, task=87942140, tls=779ac440) + Stack : 802fb500 000200da 804db150 804e0000 87816130 86ee0000 00010000 86d71b88 + 86d71bc0 00000004 00000003 86e9fcd0 80305300 0002c0d0 86e74c50 800b4c20 + 000003e8 00000001 00000000 86ee0000 000003ff 86e9fd64 80305300 80123938 + fffffffc 00000004 000058bc 00000000 86ea0000 86ee0000 000001ff 878d6000 + 99999999 86e9fdc0 86ee0fcc 86e9e664 0000c0d0 86ee0000 0000700000007000 + ... + Call Trace: + [<86e84164>] ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + [<86e9fcd0>] ath9k_hw_setup_statusring+0x16b8/0x1c7c [ath9k_hw] + + Code: 0000a812 0040f809 00000000 <00531024> 1054000b 24020001 0c05b5dc 2404000a 26520001 + +The cause of the error is that the OTP register +offsets are different on the AR9340 than the +actually used values. + +Signed-off-by: Gabor Juhos +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +@@ -68,13 +68,13 @@ + #define AR9300_BASE_ADDR 0x3ff + #define AR9300_BASE_ADDR_512 0x1ff + +-#define AR9300_OTP_BASE 0x14000 +-#define AR9300_OTP_STATUS 0x15f18 ++#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) ++#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) + #define AR9300_OTP_STATUS_TYPE 0x7 + #define AR9300_OTP_STATUS_VALID 0x4 + #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 + #define AR9300_OTP_STATUS_SM_BUSY 0x1 +-#define AR9300_OTP_READ_DATA 0x15f1c ++#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) + + enum targetPowerHTRates { + HT_TARGET_RATE_0_8_16, +From b7c0c238898d200e80487516e2b67aba2a522cc0 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 10 Dec 2012 14:03:17 +0100 +Subject: ath9k_hw: Fix signal strength / channel noise reporting + +From: Felix Fietkau + +commit b7c0c238898d200e80487516e2b67aba2a522cc0 upstream. + +While AR_PHY_CCA_NOM_VAL_* does contain the expected internal noise floor +for a chip measured in clean air, it refers to the lowest expected reading. + +Depending on the frequency, this measurement can vary by about 6db, thus +causing a higher reported channel noise and signal strength. + +Factor in the 6db offset when converting internal noisefloor to channel noise. + +This patch makes the reported values more accurate for all chips without +affecting NF calibration behavior. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/calib.c | 1 + + drivers/net/wireless/ath/ath9k/calib.h | 3 +++ + 2 files changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath9k/calib.c ++++ b/drivers/net/wireless/ath/ath9k/calib.c +@@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw + + if (chan && chan->noisefloor) { + s8 delta = chan->noisefloor - ++ ATH9K_NF_CAL_NOISE_THRESH - + ath9k_hw_get_default_nf(ah, chan); + if (delta > 0) + noise += delta; +--- a/drivers/net/wireless/ath/ath9k/calib.h ++++ b/drivers/net/wireless/ath/ath9k/calib.h +@@ -21,6 +21,9 @@ + + #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 + ++/* Internal noise floor can vary by about 6db depending on the frequency */ ++#define ATH9K_NF_CAL_NOISE_THRESH 6 ++ + #define NUM_NF_READINGS 6 + #define ATH9K_NF_CAL_HIST_MAX 5 + +From a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 Mon Sep 17 00:00:00 2001 +From: Sujith Manoharan +Date: Wed, 26 Dec 2012 12:27:39 +0530 +Subject: ath9k_hw: Fix RX gain initvals for AR9485 + +From: Sujith Manoharan + +commit a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 upstream. + +Populate iniModesRxGain with the correct initvals +array for AR9485 v1.1 + +Signed-off-by: Sujith Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c +@@ -540,7 +540,7 @@ static void ar9003_rx_gain_table_mode0(s + ar9340Common_rx_gain_table_1p0); + else if (AR_SREV_9485_11(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, +- ar9485Common_wo_xlna_rx_gain_1_1); ++ ar9485_common_rx_gain_1_1); + else if (AR_SREV_9550(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar955x_1p0_common_rx_gain_table); +From 5b632fe85ec82e5c43740b52e74c66df50a37db3 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 3 Dec 2012 12:56:33 +0100 +Subject: mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL + +From: Stanislaw Gruszka + +commit 5b632fe85ec82e5c43740b52e74c66df50a37db3 upstream. + +Commit f0425beda4d404a6e751439b562100b902ba9c98 "mac80211: retry sending +failed BAR frames later instead of tearing down aggr" caused regression +on rt2x00 hardware (connection hangs). This regression was fixed by +commit be03d4a45c09ee5100d3aaaedd087f19bc20d01 "rt2x00: Don't let +mac80211 send a BAR when an AMPDU subframe fails". But the latter +commit caused yet another problem reported in +https://bugzilla.kernel.org/show_bug.cgi?id=42828#c22 + +After long discussion in this thread: +http://mid.gmane.org/20121018075615.GA18212@redhat.com +and testing various alternative solutions, which failed on one or other +setup, we have no other good fix for the issues like just revert both +mentioned earlier commits. + +To do not affect other hardware which benefit from commit +f0425beda4d404a6e751439b562100b902ba9c98, instead of reverting it, +introduce flag that when used will restore mac80211 behaviour before +the commit. + +Signed-off-by: Stanislaw Gruszka +[replaced link with mid.gmane.org that has message-id] +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/mac80211.h | 5 +++++ + net/mac80211/status.c | 6 +++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1253,6 +1253,10 @@ struct ieee80211_tx_control { + * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any + * P2P Interface. This will be honoured even if more than one interface + * is supported. ++ * ++ * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session ++ * should be tear down once BAR frame will not be acked. ++ * + */ + enum ieee80211_hw_flags { + IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, +@@ -1281,6 +1285,7 @@ enum ieee80211_hw_flags { + IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, + IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, + IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26, + }; + + /** +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -432,7 +432,11 @@ void ieee80211_tx_status(struct ieee8021 + IEEE80211_BAR_CTRL_TID_INFO_MASK) >> + IEEE80211_BAR_CTRL_TID_INFO_SHIFT; + +- ieee80211_set_bar_pending(sta, tid, ssn); ++ if (local->hw.flags & ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL) ++ ieee80211_stop_tx_ba_session(&sta->sta, tid); ++ else ++ ieee80211_set_bar_pending(sta, tid, ssn); + } + } + +From 6c653f66772c39c5e25db715bbd4730596fccd9e Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 22 Dec 2012 04:35:24 +0100 +Subject: carl9170: fix -EINVAL bailout during init with !CONFIG_MAC80211_MESH + +From: Christian Lamparter + +commit 6c653f66772c39c5e25db715bbd4730596fccd9e upstream. + +Sean reported that as of 3.7, his AR9170 device no longer works +because the driver fails during initialization. He noted this +is due to: +"In carl9170/fw.c, ar->hw->wiphy is tagged with +NL80211_IFTYPE_MESH_POINT support if the firmware has Content +after Beacon Queuing. This is both in interface_modes and the +only iface_combinations entry. + +If CONFIG_MAC80211_MESH is not set, ieee80211_register_hw +removes NL80211_IFTYPE_MESH_POINT from interface_modes, but +not iface_combinations. + +wiphy_register then checks to see if every interface type in +every interface combination is in interface_modes. +NL80211_IFTYPE_MESH_POINT was removed, so you get a WARN_ON +warning and it returns -EINVAL, giving up." + +Unfortunately, the iface_combination (types) feature bitmap +in ieee80211_iface_limit is part of a const member in the +ieee80211_iface_combination struct. Hence, the MESH_POINT +feature flag can't be masked by wiphy_register in the +same way as interface_modes in ieee80211_register_hw. + +Reported-by: Sean Patrick Santos +Signed-off-by: Christian Lamparter +Tested-by: Sean Patrick Santos +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/carl9170/fw.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/carl9170/fw.c ++++ b/drivers/net/wireless/ath/carl9170/fw.c +@@ -341,8 +341,12 @@ static int carl9170_fw(struct ar9170 *ar + if (SUPP(CARL9170FW_WLANTX_CAB)) { + if_comb_types |= + BIT(NL80211_IFTYPE_AP) | +- BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_P2P_GO); ++ ++#ifdef CONFIG_MAC80211_MESH ++ if_comb_types |= ++ BIT(NL80211_IFTYPE_MESH_POINT); ++#endif /* CONFIG_MAC80211_MESH */ + } + } + +From 9d2373420900a39f5212a3b289331aa3535b1000 Mon Sep 17 00:00:00 2001 +From: Stephan Gatzka +Date: Wed, 28 Nov 2012 20:04:32 +0100 +Subject: firewire: net: Fix handling of fragmented multicast/broadcast packets. + +From: Stephan Gatzka + +commit 9d2373420900a39f5212a3b289331aa3535b1000 upstream. + +This patch fixes both the transmit and receive portion of sending +fragmented mutlicast and broadcast packets. + +The transmit section was broken because the offset for INTFRAG and +LASTFRAG packets were just miscalculated by IEEE1394_GASP_HDR_SIZE (which +was reserved with skb_push() in fwnet_send_packet). + +The receive section was broken because in fwnet_incoming_packet is a call +to fwnet_peer_find_by_node_id(). Called with generation == -1 it will +not find a peer and the partial datagrams are associated to a peer. + +[Stefan R: The fix to use context->card->generation is not perfect. +It relies on the IR tasklet which processes packets from the prior bus +generation to run before the self-ID-complete worklet which sets the +current card generation. Alas, there is no simple way of a race-free +implementation. Let's do it this way for now.] + +Signed-off-by: Stephan Gatzka +Signed-off-by: Stefan Richter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/net.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(stru + if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { + buf_ptr += 2; + length -= IEEE1394_GASP_HDR_SIZE; +- fwnet_incoming_packet(dev, buf_ptr, length, +- source_node_id, -1, true); ++ fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, ++ context->card->generation, true); + } + + packet.payload_length = dev->rcv_buffer_size; +@@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(s + break; + } + +- skb_pull(skb, ptask->max_payload); ++ if (ptask->dest_node == IEEE1394_ALL_NODES) { ++ skb_pull(skb, ++ ptask->max_payload + IEEE1394_GASP_HDR_SIZE); ++ } else { ++ skb_pull(skb, ptask->max_payload); ++ } + if (ptask->outstanding_pkts > 1) { + fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, + dg_size, fg_off, datagram_label); +@@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwne + smp_rmb(); + node_id = dev->card->node_id; + +- p = skb_push(ptask->skb, 8); ++ p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); + put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); + put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 + | RFC2734_SW_VERSION, &p[4]); +From 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Wed, 19 Dec 2012 20:51:31 +0100 +Subject: watchdog: Fix disable/enable regression + +From: Bjørn Mork + +commit 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 upstream. + +Commit 8d4516904b39 ("watchdog: Fix CPU hotplug regression") causes an +oops or hard lockup when doing + + echo 0 > /proc/sys/kernel/nmi_watchdog + echo 1 > /proc/sys/kernel/nmi_watchdog + +and the kernel is booted with nmi_watchdog=1 (default) + +Running laptop-mode-tools and disconnecting/connecting AC power will +cause this to trigger, making it a common failure scenario on laptops. + +Instead of bailing out of watchdog_disable() when !watchdog_enabled we +can initialize the hrtimer regardless of watchdog_enabled status. This +makes it safe to call watchdog_disable() in the nmi_watchdog=0 case, +without the negative effect on the enabled => disabled => enabled case. + +All these tests pass with this patch: +- nmi_watchdog=1 + echo 0 > /proc/sys/kernel/nmi_watchdog + echo 1 > /proc/sys/kernel/nmi_watchdog + +- nmi_watchdog=0 + echo 0 > /sys/devices/system/cpu/cpu1/online + +- nmi_watchdog=0 + echo mem > /sys/power/state + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51661 + +Signed-off-by: Bjørn Mork +Cc: Norbert Warmuth +Cc: Joseph Salisbury +Cc: Thomas Gleixner +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/watchdog.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -343,6 +343,10 @@ static void watchdog_enable(unsigned int + { + struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + ++ /* kick off the timer for the hardlockup detector */ ++ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer->function = watchdog_timer_fn; ++ + if (!watchdog_enabled) { + kthread_park(current); + return; +@@ -351,10 +355,6 @@ static void watchdog_enable(unsigned int + /* Enable the perf event */ + watchdog_nmi_enable(cpu); + +- /* kick off the timer for the hardlockup detector */ +- hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +- hrtimer->function = watchdog_timer_fn; +- + /* done here because hrtimer_start can only pin to smp_processor_id() */ + hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()), + HRTIMER_MODE_REL_PINNED); +@@ -368,9 +368,6 @@ static void watchdog_disable(unsigned in + { + struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + +- if (!watchdog_enabled) +- return; +- + watchdog_set_prio(SCHED_NORMAL, 0); + hrtimer_cancel(hrtimer); + /* disable the perf event */ +From 72222be39afbd39c16eb180646b0ac44bb1ba460 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Wed, 28 Nov 2012 13:46:56 +0000 +Subject: ASoC: wm8994: Use the same DCS codes for all WM1811 variants + +From: Mark Brown + +commit 72222be39afbd39c16eb180646b0ac44bb1ba460 upstream. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8994.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -3839,20 +3839,8 @@ static int wm8994_codec_probe(struct snd + wm8994->hubs.no_cache_dac_hp_direct = true; + wm8994->fll_byp = true; + +- switch (control->cust_id) { +- case 0: +- case 2: +- wm8994->hubs.dcs_codes_l = -9; +- wm8994->hubs.dcs_codes_r = -7; +- break; +- case 1: +- case 3: +- wm8994->hubs.dcs_codes_l = -8; +- wm8994->hubs.dcs_codes_r = -7; +- break; +- default: +- break; +- } ++ wm8994->hubs.dcs_codes_l = -9; ++ wm8994->hubs.dcs_codes_r = -7; + + snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, + WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); +From a3adb1432d7a3ad86bb17a1638e44414537e4118 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Fri, 7 Dec 2012 18:30:51 +0100 +Subject: ASoC: sigmadsp: Fix endianness conversion issue + +From: Lars-Peter Clausen + +commit a3adb1432d7a3ad86bb17a1638e44414537e4118 upstream. + +The 'addr' field of the sigma_action struct is stored as big endian in the +firmware file. + +Signed-off-by: Lars-Peter Clausen +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/sigmadsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/codecs/sigmadsp.c ++++ b/sound/soc/codecs/sigmadsp.c +@@ -225,7 +225,7 @@ EXPORT_SYMBOL(process_sigma_firmware); + static int sigma_action_write_regmap(void *control_data, + const struct sigma_action *sa, size_t len) + { +- return regmap_raw_write(control_data, le16_to_cpu(sa->addr), ++ return regmap_raw_write(control_data, be16_to_cpu(sa->addr), + sa->payload, len - 2); + } + +From f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa Mon Sep 17 00:00:00 2001 +From: Sangbeom Kim +Date: Sat, 24 Nov 2012 11:13:28 +0900 +Subject: regulator: s2mps11: Fix ramp delay value shift operation + +From: Sangbeom Kim + +commit f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa upstream. + +This patch fix the abnormal ramp delay setting. +The shift operation was wrong. + +Signed-off-by: Sangbeom Kim +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/s2mps11.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/regulator/s2mps11.c ++++ b/drivers/regulator/s2mps11.c +@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe( + + if (ramp_enable) { + if (s2mps11->buck2_ramp) +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6; + if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4; + sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); + } + + ramp_reg &= 0x00; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); + sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); + +From beecadea1b8d67f591b13f7099559f32f3fd601d Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Fri, 16 Nov 2012 14:40:03 -0500 +Subject: SCSI: mvsas: fix undefined bit shift + +From: Xi Wang + +commit beecadea1b8d67f591b13f7099559f32f3fd601d upstream. + +The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't work +with n >= 32, such as in mvs_94xx_assign_reg_set(): + + if (i >= 32) { + mvi->sata_reg_set |= bit(i); + ... + } + +The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior. +The result varies depending on the architecture. + +This patch changes bit(n) to do a 64-bit shift. It also simplifies +mv_ffc64() using __ffs64(), since invoking ffz() with ~0 is undefined. + +Signed-off-by: Xi Wang +Acked-by: Xiangliang Yu +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/mvsas/mv_94xx.h | 14 ++------------ + drivers/scsi/mvsas/mv_sas.h | 2 +- + 2 files changed, 3 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/mvsas/mv_94xx.h ++++ b/drivers/scsi/mvsas/mv_94xx.h +@@ -258,21 +258,11 @@ enum sas_sata_phy_regs { + #define SPI_ADDR_VLD_94XX (1U << 1) + #define SPI_CTRL_SpiStart_94XX (1U << 0) + +-#define mv_ffc(x) ffz(x) +- + static inline int + mv_ffc64(u64 v) + { +- int i; +- i = mv_ffc((u32)v); +- if (i >= 0) +- return i; +- i = mv_ffc((u32)(v>>32)); +- +- if (i != 0) +- return 32 + i; +- +- return -1; ++ u64 x = ~v; ++ return x ? __ffs64(x) : -1; + } + + #define r_reg_set_enable(i) \ +--- a/drivers/scsi/mvsas/mv_sas.h ++++ b/drivers/scsi/mvsas/mv_sas.h +@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_ + #define DEV_IS_EXPANDER(type) \ + ((type == EDGE_DEV) || (type == FANOUT_DEV)) + +-#define bit(n) ((u32)1 << n) ++#define bit(n) ((u64)1 << n) + + #define for_each_phy(__lseq_mask, __mc, __lseq) \ + for ((__mc) = (__lseq_mask), (__lseq) = 0; \ +From 072f19b4bea31cdd482d79f805413f2f9ac9e233 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Nov 2012 15:51:46 -0500 +Subject: SCSI: prevent stack buffer overflow in host_reset + +From: Sasha Levin + +commit 072f19b4bea31cdd482d79f805413f2f9ac9e233 upstream. + +store_host_reset() has tried to re-invent the wheel to compare sysfs strings. +Unfortunately it did so poorly and never bothered to check the input from +userspace before overwriting stack with it, so something simple as: + +echo "WoopsieWoopsie" > +/sys/devices/pseudo_0/adapter0/host0/scsi_host/host0/host_reset + +would result in: + +[ 316.310101] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81f5bac7 +[ 316.310101] +[ 316.320051] Pid: 6655, comm: sh Tainted: G W 3.7.0-rc5-next-20121114-sasha-00016-g5c9d68d-dirty #129 +[ 316.320051] Call Trace: +[ 316.340058] pps pps0: PPS event at 1352918752.620355751 +[ 316.340062] pps pps0: capture assert seq #303 +[ 316.320051] [] panic+0xcd/0x1f4 +[ 316.320051] [] ? store_host_reset+0xd7/0x100 +[ 316.320051] [] __stack_chk_fail+0x16/0x20 +[ 316.320051] [] store_host_reset+0xd7/0x100 +[ 316.320051] [] dev_attr_store+0x13/0x30 +[ 316.320051] [] sysfs_write_file+0x101/0x170 +[ 316.320051] [] vfs_write+0xb8/0x180 +[ 316.320051] [] sys_write+0x50/0xa0 +[ 316.320051] [] tracesys+0xe1/0xe6 + +Fix this by uninventing whatever was going on there and just use sysfs_streq. + +Bug introduced by 29443691 ("[SCSI] scsi: Added support for adapter and +firmware reset"). + +[jejb: added necessary const to prevent compile warnings] +Signed-off-by: Sasha Levin +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_sysfs.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -247,11 +247,11 @@ show_shost_active_mode(struct device *de + + static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); + +-static int check_reset_type(char *str) ++static int check_reset_type(const char *str) + { +- if (strncmp(str, "adapter", 10) == 0) ++ if (sysfs_streq(str, "adapter")) + return SCSI_ADAPTER_RESET; +- else if (strncmp(str, "firmware", 10) == 0) ++ else if (sysfs_streq(str, "firmware")) + return SCSI_FIRMWARE_RESET; + else + return 0; +@@ -264,12 +264,9 @@ store_host_reset(struct device *dev, str + struct Scsi_Host *shost = class_to_shost(dev); + struct scsi_host_template *sht = shost->hostt; + int ret = -EINVAL; +- char str[10]; + int type; + +- sscanf(buf, "%s", str); +- type = check_reset_type(str); +- ++ type = check_reset_type(buf); + if (!type) + goto exit_store_host_reset; + +From 63ea923a97cb0d78efcbbd229950e101588f0ddb Mon Sep 17 00:00:00 2001 +From: Armen Baloyan +Date: Wed, 21 Nov 2012 02:39:53 -0500 +Subject: SCSI: qla2xxx: Properly set result field of bsg_job reply structure for success and failure. + +From: Armen Baloyan + +commit 63ea923a97cb0d78efcbbd229950e101588f0ddb upstream. + +FC transport on receiving bsg_job submission failure, calls bsg_job->job_done() +and sets the bsg_job->reply->result the returned value. In contrast, when the +success code (0) is returned fc transport doesn't call bsg_job->job_done() and +doesn't populate bsg_job->reply->result. + +Signed-off-by: Steve Hodgson +Signed-off-by: Armen Baloyan +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_bsg.c | 65 +++++++++++++++-------------------------- + 1 file changed, 24 insertions(+), 41 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -219,7 +219,8 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_ + break; + } + exit_fcp_prio_cfg: +- bsg_job->job_done(bsg_job); ++ if (!ret) ++ bsg_job->job_done(bsg_job); + return ret; + } + +@@ -741,7 +742,6 @@ qla2x00_process_loopback(struct fc_bsg_j + if (qla81xx_get_port_config(vha, config)) { + ql_log(ql_log_warn, vha, 0x701f, + "Get port config failed.\n"); +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } +@@ -761,7 +761,6 @@ qla2x00_process_loopback(struct fc_bsg_j + new_config, elreq.options); + + if (rval) { +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } +@@ -795,7 +794,6 @@ qla2x00_process_loopback(struct fc_bsg_j + "MPI reset failed.\n"); + } + +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EIO; + goto done_free_dma_req; + } +@@ -812,33 +810,25 @@ qla2x00_process_loopback(struct fc_bsg_j + ql_log(ql_log_warn, vha, 0x702c, + "Vendor request %s failed.\n", type); + +- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + +- sizeof(struct fc_bsg_reply); +- +- memcpy(fw_sts_ptr, response, sizeof(response)); +- fw_sts_ptr += sizeof(response); +- *fw_sts_ptr = command_sent; + rval = 0; + bsg_job->reply->result = (DID_ERROR << 16); ++ bsg_job->reply->reply_payload_rcv_len = 0; + } else { + ql_dbg(ql_dbg_user, vha, 0x702d, + "Vendor request %s completed.\n", type); +- +- bsg_job->reply_len = sizeof(struct fc_bsg_reply) + +- sizeof(response) + sizeof(uint8_t); +- bsg_job->reply->reply_payload_rcv_len = +- bsg_job->reply_payload.payload_len; +- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + +- sizeof(struct fc_bsg_reply); +- memcpy(fw_sts_ptr, response, sizeof(response)); +- fw_sts_ptr += sizeof(response); +- *fw_sts_ptr = command_sent; +- bsg_job->reply->result = DID_OK; ++ bsg_job->reply->result = (DID_OK << 16); + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, rsp_data, + rsp_data_len); + } +- bsg_job->job_done(bsg_job); ++ ++ bsg_job->reply_len = sizeof(struct fc_bsg_reply) + ++ sizeof(response) + sizeof(uint8_t); ++ fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + ++ sizeof(struct fc_bsg_reply); ++ memcpy(fw_sts_ptr, response, sizeof(response)); ++ fw_sts_ptr += sizeof(response); ++ *fw_sts_ptr = command_sent; + + dma_free_coherent(&ha->pdev->dev, rsp_data_len, + rsp_data, rsp_data_dma); +@@ -853,6 +843,8 @@ done_unmap_req_sg: + dma_unmap_sg(&ha->pdev->dev, + bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -877,16 +869,15 @@ qla84xx_reset(struct fc_bsg_job *bsg_job + if (rval) { + ql_log(ql_log_warn, vha, 0x7030, + "Vendor request 84xx reset failed.\n"); +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + + } else { + ql_dbg(ql_dbg_user, vha, 0x7031, + "Vendor request 84xx reset completed.\n"); + bsg_job->reply->result = DID_OK; ++ bsg_job->job_done(bsg_job); + } + +- bsg_job->job_done(bsg_job); + return rval; + } + +@@ -976,8 +967,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ + ql_log(ql_log_warn, vha, 0x7037, + "Vendor request 84xx updatefw failed.\n"); + +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + } else { + ql_dbg(ql_dbg_user, vha, 0x7038, + "Vendor request 84xx updatefw completed.\n"); +@@ -986,7 +976,6 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ + bsg_job->reply->result = DID_OK; + } + +- bsg_job->job_done(bsg_job); + dma_pool_free(ha->s_dma_pool, mn, mn_dma); + + done_free_fw_buf: +@@ -996,6 +985,8 @@ done_unmap_sg: + dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); + ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1163,8 +1154,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ + ql_log(ql_log_warn, vha, 0x7043, + "Vendor request 84xx mgmt failed.\n"); + +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + + } else { + ql_dbg(ql_dbg_user, vha, 0x7044, +@@ -1184,8 +1174,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ + } + } + +- bsg_job->job_done(bsg_job); +- + done_unmap_sg: + if (mgmt_b) + dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma); +@@ -1200,6 +1188,8 @@ done_unmap_sg: + exit_mgmt: + dma_pool_free(ha->s_dma_pool, mn, mn_dma); + ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1276,9 +1266,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]); +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); +- ++ rval = (DID_ERROR << 16); + } else { + if (!port_param->mode) { + bsg_job->reply_len = sizeof(struct fc_bsg_reply) + +@@ -1292,9 +1280,9 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job + } + + bsg_job->reply->result = DID_OK; ++ bsg_job->job_done(bsg_job); + } + +- bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1887,8 +1875,6 @@ qla2x00_process_vendor_specific(struct f + return qla24xx_process_bidir_cmd(bsg_job); + + default: +- bsg_job->reply->result = (DID_ERROR << 16); +- bsg_job->job_done(bsg_job); + return -ENOSYS; + } + } +@@ -1919,8 +1905,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b + ql_dbg(ql_dbg_user, vha, 0x709f, + "BSG: ISP abort active/needed -- cmd=%d.\n", + bsg_job->request->msgcode); +- bsg_job->reply->result = (DID_ERROR << 16); +- bsg_job->job_done(bsg_job); + return -EBUSY; + } + +@@ -1943,7 +1927,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b + case FC_BSG_RPT_CT: + default: + ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n"); +- bsg_job->reply->result = ret; + break; + } + return ret; +From a394aac88506159e047630fc90dc2242568382d8 Mon Sep 17 00:00:00 2001 +From: David Jeffery +Date: Wed, 21 Nov 2012 02:39:54 -0500 +Subject: SCSI: qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically. + +From: David Jeffery + +commit a394aac88506159e047630fc90dc2242568382d8 upstream. + +When the qla2xxx driver loses access to multiple, remote ports, there is a race +condition which can occur which will keep the request stuck on a scsi request +queue indefinitely. + +This bad state occurred do to a race condition with how the FCPORT_UPDATE_NEEDED +bit is set in qla2x00_schedule_rport_del(), and how it is cleared in +qla2x00_do_dpc(). The problem port has its drport pointer set, but it has never +been processed by the driver to inform the fc transport that the port has been +lost. qla2x00_schedule_rport_del() sets drport, and then sets the +FCPORT_UPDATE_NEEDED bit. In qla2x00_do_dpc(), the port lists are walked and +any drport pointer is handled and the fc transport informed of the port loss, +then the FCPORT_UPDATE_NEEDED bit is cleared. This leaves a race where the +dpc thread is processing one port removal, another port removal is marked +with a call to qla2x00_schedule_rport_del(), and the dpc thread clears the +bit for both removals, even though only the first removal was actually +handled. Until another event occurs to set FCPORT_UPDATE_NEEDED, the later +port removal is never finished and qla2xxx stays in a bad state which causes +requests to become stuck on request queues. + +This patch updates the driver to test and clear FCPORT_UPDATE_NEEDED +atomically. This ensures the port state changes are processed and not lost. + +Signed-off-by: David Jeffery +Signed-off-by: Chad Dupuis +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_os.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4505,9 +4505,9 @@ qla2x00_do_dpc(void *data) + "ISP abort end.\n"); + } + +- if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { ++ if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, ++ &base_vha->dpc_flags)) { + qla2x00_update_fcports(base_vha); +- clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); + } + + if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) { +From 220d36b4c2d96446e88d561714829ec5801b4fc7 Mon Sep 17 00:00:00 2001 +From: Giridhar Malavali +Date: Wed, 21 Nov 2012 02:39:55 -0500 +Subject: SCSI: qla2xxx: Change in setting UNLOADING flag and FC vports logout sequence while unloading qla2xxx driver. + +From: Giridhar Malavali + +commit 220d36b4c2d96446e88d561714829ec5801b4fc7 upstream. + +Signed-off-by: Giridhar Malavali +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_attr.c | 3 +-- + drivers/scsi/qla2xxx/qla_os.c | 3 +-- + 2 files changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -1615,8 +1615,7 @@ qla2x00_terminate_rport_io(struct fc_rpo + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). + */ +- if (fcport->loop_id != FC_NO_LOOP_ID && +- !test_bit(UNLOADING, &fcport->vha->dpc_flags)) { ++ if (fcport->loop_id != FC_NO_LOOP_ID) { + if (IS_FWI2_CAPABLE(fcport->vha->hw)) + fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, + fcport->loop_id, fcport->d_id.b.domain, +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2755,6 +2755,7 @@ qla2x00_remove_one(struct pci_dev *pdev) + + ha->flags.host_shutting_down = 1; + ++ set_bit(UNLOADING, &base_vha->dpc_flags); + mutex_lock(&ha->vport_lock); + while (ha->cur_vport_count) { + struct Scsi_Host *scsi_host; +@@ -2784,8 +2785,6 @@ qla2x00_remove_one(struct pci_dev *pdev) + "Error while clearing DRV-Presence.\n"); + } + +- set_bit(UNLOADING, &base_vha->dpc_flags); +- + qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); + + qla2x00_dfs_remove(base_vha); +From 9bceab4e08c5e329e9def7fe1cab41c467236517 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Wed, 21 Nov 2012 02:39:56 -0500 +Subject: SCSI: qla2xxx: Free rsp_data even on error in qla2x00_process_loopback() + +From: Steve Hodgson + +commit 9bceab4e08c5e329e9def7fe1cab41c467236517 upstream. + +Signed-off-by: Steve Hodgson +Signed-off-by: Armen Baloyan +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_bsg.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -743,7 +743,7 @@ qla2x00_process_loopback(struct fc_bsg_j + ql_log(ql_log_warn, vha, 0x701f, + "Get port config failed.\n"); + rval = -EPERM; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + + ql_dbg(ql_dbg_user, vha, 0x70c0, +@@ -762,7 +762,7 @@ qla2x00_process_loopback(struct fc_bsg_j + + if (rval) { + rval = -EPERM; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + + type = "FC_BSG_HST_VENDOR_LOOPBACK"; +@@ -795,7 +795,7 @@ qla2x00_process_loopback(struct fc_bsg_j + } + + rval = -EIO; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + } else { + type = "FC_BSG_HST_VENDOR_LOOPBACK"; +@@ -830,6 +830,7 @@ qla2x00_process_loopback(struct fc_bsg_j + fw_sts_ptr += sizeof(response); + *fw_sts_ptr = command_sent; + ++done_free_dma_rsp: + dma_free_coherent(&ha->pdev->dev, rsp_data_len, + rsp_data, rsp_data_dma); + done_free_dma_req: +From 64c13330a38935120501b19c97a3e6095747c7a1 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Mon, 5 Nov 2012 18:02:41 -0800 +Subject: iscsi-target: Fix bug in handling of ExpStatSN ACK during u32 wrap-around + +From: Steve Hodgson + +commit 64c13330a38935120501b19c97a3e6095747c7a1 upstream. + +This patch fixes a bug in the hanlding of initiator provided ExpStatSN and +individual iscsi_cmd->stat_sn comparision during iscsi_conn->stat_sn +wrap-around within iscsit_ack_from_expstatsn() code. + +This bug would manifest itself as iscsi_cmd descriptors not being Acked +by a lower ExpStatSn, causing them to be leaked until an iSCSI connection +or session reinstatement event occurs to release all commands. + +Also fix up two other uses of incorrect CmdSN SNA comparison to use wrapper +usage from include/scsi/iscsi_proto.h. + +Signed-off-by: Steve Hodgson +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + drivers/target/iscsi/iscsi_target_erl2.c | 2 +- + drivers/target/iscsi/iscsi_target_tmr.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(st + list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { + spin_lock(&cmd->istate_lock); + if ((cmd->i_state == ISTATE_SENT_STATUS) && +- (cmd->stat_sn < exp_statsn)) { ++ iscsi_sna_lt(cmd->stat_sn, exp_statsn)) { + cmd->i_state = ISTATE_REMOVE; + spin_unlock(&cmd->istate_lock); + iscsit_add_cmd_to_immediate_queue(cmd, conn, +--- a/drivers/target/iscsi/iscsi_target_erl2.c ++++ b/drivers/target/iscsi/iscsi_target_erl2.c +@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance( + * made generic here. + */ + if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && +- (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { ++ iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { + list_del(&cmd->i_conn_node); + spin_unlock_bh(&conn->cmd_lock); + iscsit_free_cmd(cmd); +--- a/drivers/target/iscsi/iscsi_target_tmr.c ++++ b/drivers/target/iscsi/iscsi_target_tmr.c +@@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task( + if (!ref_cmd) { + pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" + " %hu.\n", hdr->rtt, conn->cid); +- return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn && +- be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ? ++ return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && ++ iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? + ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; + } + if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { +From 1c5c12c666fda27c7c494b34934a0a0631a48130 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Mon, 5 Nov 2012 18:02:42 -0800 +Subject: iscsi-target: Always send a response before terminating iSCSI connection + +From: Roland Dreier + +commit 1c5c12c666fda27c7c494b34934a0a0631a48130 upstream. + +There are some cases, for example when the initiator sends an +out-of-bounds ErrorRecoveryLevel value, where the iSCSI target +terminates the connection without sending back any error. Audit the +login path and add appropriate iscsit_tx_login_rsp() calls to make +sure this doesn't happen. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_login.c | 8 ++++---- + drivers/target/iscsi/iscsi_target_nego.c | 10 ++++++++-- + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatemen + + initiatorname_param = iscsi_find_param_from_key( + INITIATORNAME, conn->param_list); +- if (!initiatorname_param) +- return -1; +- + sessiontype_param = iscsi_find_param_from_key( + SESSIONTYPE, conn->param_list); +- if (!sessiontype_param) ++ if (!initiatorname_param || !sessiontype_param) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_MISSING_FIELDS); + return -1; ++ } + + sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; + +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(s + login->req_buf, + payload_length, + conn); +- if (ret < 0) ++ if (ret < 0) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_INIT_ERR); + return -1; ++ } + + if (login->first_request) + if (iscsi_target_check_first_request(conn, login) < 0) +@@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(s + login->rsp_buf, + &login->rsp_length, + conn->param_list); +- if (ret < 0) ++ if (ret < 0) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_INIT_ERR); + return -1; ++ } + + if (!login->auth_complete && + ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { +From 3c989d7603872bf878840f7ce3ea49b73bea4c6c Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Fri, 23 Nov 2012 12:07:39 +0800 +Subject: iscsit: use GFP_ATOMIC under spin lock + +From: Wei Yongjun + +commit 3c989d7603872bf878840f7ce3ea49b73bea4c6c upstream. + +The function iscsit_build_conn_drop_async_message() is called +from iscsit_close_connection() with spin lock 'sess->conn_lock' +held, so we should use GFP_ATOMIC instead of GFP_KERNEL. + +Signed-off-by: Wei Yongjun +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -2360,7 +2360,7 @@ static void iscsit_build_conn_drop_async + if (!conn_p) + return; + +- cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); ++ cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); + if (!cmd) { + iscsit_dec_conn_usage_count(conn_p); + return; +From 06e97b489006f28e23bb028febfa1c01c266d676 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Fri, 16 Nov 2012 08:06:17 -0800 +Subject: qla2xxx: Look up LUN for abort requests + +From: Steve Hodgson + +commit 06e97b489006f28e23bb028febfa1c01c266d676 upstream. + +Search through the list of pending commands on the session list to find +the command the initiator is actually aborting, so that we can pass the +correct LUN to the core TMR handling code. + +(nab: Allow abort requests to work to LUN=0 with mainline target code) + +Signed-off-by: Steve Hodgson +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_target.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct + struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) + { + struct qla_hw_data *ha = vha->hw; ++ struct se_session *se_sess = sess->se_sess; + struct qla_tgt_mgmt_cmd *mcmd; ++ struct se_cmd *se_cmd; ++ u32 lun = 0; + int rc; ++ bool found_lun = false; ++ ++ spin_lock(&se_sess->sess_cmd_lock); ++ list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { ++ struct qla_tgt_cmd *cmd = ++ container_of(se_cmd, struct qla_tgt_cmd, se_cmd); ++ if (cmd->tag == abts->exchange_addr_to_abort) { ++ lun = cmd->unpacked_lun; ++ found_lun = true; ++ break; ++ } ++ } ++ spin_unlock(&se_sess->sess_cmd_lock); ++ ++ if (!found_lun) ++ return -ENOENT; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, + "qla_target(%d): task abort (tag=%d)\n", +@@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct + mcmd->sess = sess; + memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); + +- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, ++ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK, + abts->exchange_addr_to_abort); + if (rc != 0) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, +From 3100d49d3cd236443faae9d81137c81b22d36003 Mon Sep 17 00:00:00 2001 +From: Mikael Pettersson +Date: Sun, 16 Sep 2012 20:53:43 +0200 +Subject: sata_promise: fix hardreset lockdep error + +From: Mikael Pettersson + +commit 3100d49d3cd236443faae9d81137c81b22d36003 upstream. + +sata_promise's pdc_hard_reset_port() needs to serialize because it +flips a port-specific bit in controller register that's shared by +all ports. The code takes the ata host lock for this, but that's +broken because an interrupt may arrive on our irq during the hard +reset sequence, and that too will take the ata host lock. With +lockdep enabled a big nasty warning is seen. + +Fixed by adding private state to the ata host structure, containing +a second lock used only for serializing the hard reset sequences. +This eliminated the lockdep warnings both on my test rig and on +the original reporter's machine. + +Signed-off-by: Mikael Pettersson +Tested-by: Adko Branil +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/sata_promise.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/ata/sata_promise.c ++++ b/drivers/ata/sata_promise.c +@@ -147,6 +147,10 @@ struct pdc_port_priv { + dma_addr_t pkt_dma; + }; + ++struct pdc_host_priv { ++ spinlock_t hard_reset_lock; ++}; ++ + static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); + static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); + static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct a + void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; + void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; + unsigned int ata_no = pdc_ata_port_to_ata_no(ap); ++ struct pdc_host_priv *hpriv = ap->host->private_data; + u8 tmp; + +- spin_lock(&ap->host->lock); ++ spin_lock(&hpriv->hard_reset_lock); + + tmp = readb(pcictl_b1_mmio); + tmp &= ~(0x10 << ata_no); +@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct a + writeb(tmp, pcictl_b1_mmio); + readb(pcictl_b1_mmio); /* flush */ + +- spin_unlock(&ap->host->lock); ++ spin_unlock(&hpriv->hard_reset_lock); + } + + static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, +@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_d + const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; + const struct ata_port_info *ppi[PDC_MAX_PORTS]; + struct ata_host *host; ++ struct pdc_host_priv *hpriv; + void __iomem *host_mmio; + int n_ports, i, rc; + int is_sataii_tx4; +@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_d + dev_err(&pdev->dev, "failed to allocate host\n"); + return -ENOMEM; + } ++ hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); ++ if (!hpriv) ++ return -ENOMEM; ++ spin_lock_init(&hpriv->hard_reset_lock); ++ host->private_data = hpriv; + host->iomap = pcim_iomap_table(pdev); + + is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); +From dcbeec264d73b7228ffdfe767eab69b2353099b1 Mon Sep 17 00:00:00 2001 +From: Mattia Dongili +Date: Fri, 21 Dec 2012 07:21:09 +0900 +Subject: sony-laptop: fix SNC buffer calls when SN06 returns Integers + +From: Mattia Dongili + +commit dcbeec264d73b7228ffdfe767eab69b2353099b1 upstream. + +SN06 in some cases returns an Integer instead of a buffer. While the +code handling the return value was trying to cope with the difference, +the memcpy call was not making any difference between the two types of +acpi_object union. This regression was introduced in 3.5. +While there also rework the return value logic to improve readability. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48671 +Cc: Fabrizio Narni +Cc: +Signed-off-by: Mattia Dongili +Signed-off-by: Matthew Garrett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/sony-laptop.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle + static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, + void *buffer, size_t buflen) + { ++ int ret = 0; + size_t len = len; + union acpi_object *object = __call_snc_method(handle, name, value); + + if (!object) + return -EINVAL; + +- if (object->type == ACPI_TYPE_BUFFER) ++ if (object->type == ACPI_TYPE_BUFFER) { + len = MIN(buflen, object->buffer.length); ++ memcpy(buffer, object->buffer.pointer, len); + +- else if (object->type == ACPI_TYPE_INTEGER) ++ } else if (object->type == ACPI_TYPE_INTEGER) { + len = MIN(buflen, sizeof(object->integer.value)); ++ memcpy(buffer, &object->integer.value, len); + +- else { ++ } else { + pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", + ACPI_TYPE_BUFFER, object->type); +- kfree(object); +- return -EINVAL; ++ ret = -EINVAL; + } + +- memcpy(buffer, object->buffer.pointer, len); + kfree(object); +- return 0; ++ return ret; + } + + struct sony_nc_handles { +From ceb7decb366591e9b67d70832e07f5d240572a3d Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Tue, 27 Nov 2012 16:24:29 +0000 +Subject: IB/mlx4: Fix spinlock order to avoid lockdep warnings + +From: Jack Morgenstein + +commit ceb7decb366591e9b67d70832e07f5d240572a3d upstream. + +lockdep warns about taking a hard-irq-unsafe lock (sriov->id_map_lock) +inside a hard-irq-safe lock (sriov->going_down_lock). + +Since id_map_lock is never taken in the interrupt context, we can +simply reverse the order of taking the two spinlocks, thus avoiding +the warning and the depencency. + +Signed-off-by: Jack Morgenstein +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx4/cm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/infiniband/hw/mlx4/cm.c ++++ b/drivers/infiniband/hw/mlx4/cm.c +@@ -268,15 +268,15 @@ static void schedule_delayed(struct ib_d + struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov; + unsigned long flags; + +- spin_lock_irqsave(&sriov->going_down_lock, flags); + spin_lock(&sriov->id_map_lock); ++ spin_lock_irqsave(&sriov->going_down_lock, flags); + /*make sure that there is no schedule inside the scheduled work.*/ + if (!sriov->is_going_down) { + id->scheduled_delete = 1; + schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT); + } +- spin_unlock(&sriov->id_map_lock); + spin_unlock_irqrestore(&sriov->going_down_lock, flags); ++ spin_unlock(&sriov->id_map_lock); + } + + int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id, +From 311f813a2daefcba03f706a692fe0c67888d7622 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Tue, 27 Nov 2012 16:24:30 +0000 +Subject: mlx4_core: Fix potential deadlock in mlx4_eq_int() + +From: Jack Morgenstein + +commit 311f813a2daefcba03f706a692fe0c67888d7622 upstream. + +The slave_state_lock spinlock is used in both interrupt context and +process context, hence irq locking must be used. Found by lockdep. + +Signed-off-by: Jack Morgenstein +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 +++++---- + drivers/net/ethernet/mellanox/mlx4/eq.c | 10 ++++++---- + 2 files changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c +@@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct ml + u32 reply; + u8 is_going_down = 0; + int i; ++ unsigned long flags; + + slave_state[slave].comm_toggle ^= 1; + reply = (u32) slave_state[slave].comm_toggle << 31; +@@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct ml + mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); + goto reset_slave; + } +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (!slave_state[slave].is_slave_going_down) + slave_state[slave].last_cmd = cmd; + else + is_going_down = 1; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + if (is_going_down) { + mlx4_warn(dev, "Slave is going down aborting command(%d)" + " executing from slave:%d\n", +@@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct ml + reset_slave: + /* cleanup any slave resources */ + mlx4_delete_all_resources_for_slave(dev, slave); +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (!slave_state[slave].is_slave_going_down) + slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + /*with slave in the middle of flr, no need to clean resources again.*/ + inform_slave_state: + memset(&slave_state[slave].event_eq, 0, +--- a/drivers/net/ethernet/mellanox/mlx4/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/eq.c +@@ -401,6 +401,7 @@ void mlx4_master_handle_slave_flr(struct + struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; + int i; + int err; ++ unsigned long flags; + + mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); + +@@ -412,10 +413,10 @@ void mlx4_master_handle_slave_flr(struct + + mlx4_delete_all_resources_for_slave(dev, i); + /*return the slave to running mode*/ +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; + slave_state[i].is_slave_going_down = 0; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + /*notify the FW:*/ + err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, + MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); +@@ -440,6 +441,7 @@ static int mlx4_eq_int(struct mlx4_dev * + u8 update_slave_state; + int i; + enum slave_port_gen_event gen_event; ++ unsigned long flags; + + while ((eqe = next_eqe_sw(eq))) { + /* +@@ -647,13 +649,13 @@ static int mlx4_eq_int(struct mlx4_dev * + } else + update_slave_state = 1; + +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (update_slave_state) { + priv->mfunc.master.slave_state[flr_slave].active = false; + priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; + priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; + } +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + queue_work(priv->mfunc.master.comm_wq, + &priv->mfunc.master.slave_flr_event_work); + break; +From b042e47491ba5f487601b5141a3f1d8582304170 Mon Sep 17 00:00:00 2001 +From: Maxime Bizon +Date: Mon, 22 Oct 2012 11:19:28 +0200 +Subject: pstore/ram: Fix undefined usage of rounddown_pow_of_two(0) + +From: Maxime Bizon + +commit b042e47491ba5f487601b5141a3f1d8582304170 upstream. + +record_size / console_size / ftrace_size can be 0 (this is how you disable +the feature), but rounddown_pow_of_two(0) is undefined. As suggested by +Kees Cook, use !is_power_of_2() as a condition to call +rounddown_pow_of_two and avoid its undefined behavior on the value 0. This +issue has been present since commit 1894a253 (ramoops: Move to +fs/pstore/ram.c). + +Signed-off-by: Maxime Bizon +Signed-off-by: Florian Fainelli +Acked-by: Kees Cook +Signed-off-by: Anton Vorontsov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/pstore/ram.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -374,10 +374,14 @@ static int __devinit ramoops_probe(struc + goto fail_out; + } + +- pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); +- pdata->record_size = rounddown_pow_of_two(pdata->record_size); +- pdata->console_size = rounddown_pow_of_two(pdata->console_size); +- pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); ++ if (!is_power_of_2(pdata->mem_size)) ++ pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); ++ if (!is_power_of_2(pdata->record_size)) ++ pdata->record_size = rounddown_pow_of_two(pdata->record_size); ++ if (!is_power_of_2(pdata->console_size)) ++ pdata->console_size = rounddown_pow_of_two(pdata->console_size); ++ if (!is_power_of_2(pdata->ftrace_size)) ++ pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + + cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; +From 5416912af75de9cba5d1c75b99a7888b0bbbd2fb Mon Sep 17 00:00:00 2001 +From: Aaron Lu +Date: Mon, 3 Dec 2012 11:35:02 +0800 +Subject: libata: set dma_mode to 0xff in reset + +From: Aaron Lu + +commit 5416912af75de9cba5d1c75b99a7888b0bbbd2fb upstream. + +ata_device->dma_mode's initial value is zero, which is not a valid dma +mode, but ata_dma_enabled will return true for this value. This patch +sets dma_mode to 0xff in reset function, so that ata_dma_enabled will +not return true for this case, or it will cause problem for pata_acpi. + +The corrsponding bugzilla page is at: +https://bugzilla.kernel.org/show_bug.cgi?id=49151 + +Reported-by: Phillip Wood +Signed-off-by: Aaron Lu +Tested-by: Szymon Janc +Tested-by: Dutra Julio +Acked-by: Alan Cox +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-core.c | 1 + + drivers/ata/libata-eh.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2560,6 +2560,7 @@ int ata_bus_probe(struct ata_port *ap) + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; ++ dev->dma_mode = 0xff; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -2657,6 +2657,7 @@ int ata_eh_reset(struct ata_link *link, + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; ++ dev->dma_mode = 0xff; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't +From 26cd4d65deba587f3cf2329b6869ce02bcbe68ec Mon Sep 17 00:00:00 2001 +From: Xiaotian Feng +Date: Thu, 13 Dec 2012 16:12:18 +0800 +Subject: libata: fix Null pointer dereference on disk error + +From: Xiaotian Feng + +commit 26cd4d65deba587f3cf2329b6869ce02bcbe68ec upstream. + +Following oops were observed when disk error happened: + +[ 4272.896937] sd 0:0:0:0: [sda] Unhandled error code +[ 4272.896939] sd 0:0:0:0: [sda] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK +[ 4272.896942] sd 0:0:0:0: [sda] CDB: Read(10): 28 00 00 5a de a7 00 00 08 00 +[ 4272.896951] end_request: I/O error, dev sda, sector 5955239 +[ 4291.574947] BUG: unable to handle kernel NULL pointer dereference at (null) +[ 4291.658305] IP: [] ahci_activity_show+0x1/0x40 +[ 4291.730090] PGD 76dbbc067 PUD 6c4fba067 PMD 0 +[ 4291.783408] Oops: 0000 [#1] SMP +[ 4291.822100] last sysfs file: /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sw_activity +[ 4291.934235] CPU 9 +[ 4291.958301] Pid: 27942, comm: hwinfo ...... + +ata_scsi_find_dev could return NULL, so ata_scsi_activity_{show,store} should check if atadev is NULL. + +Signed-off-by: Xiaotian Feng +Cc: James Bottomley +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-scsi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *de + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); + +- if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) ++ if (atadev && ap->ops->sw_activity_show && ++ (ap->flags & ATA_FLAG_SW_ACTIVITY)) + return ap->ops->sw_activity_show(atadev, buf); + return -EINVAL; + } +@@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *d + enum sw_activity val; + int rc; + +- if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { ++ if (atadev && ap->ops->sw_activity_store && ++ (ap->flags & ATA_FLAG_SW_ACTIVITY)) { + val = simple_strtoul(buf, NULL, 0); + switch (val) { + case OFF: case BLINK_ON: case BLINK_OFF: +From 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Wed, 5 Dec 2012 12:08:29 +0100 +Subject: target/file: Fix 32-bit highmem breakage for SGL -> iovec mapping + +From: Sebastian Andrzej Siewior + +commit 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf upstream. + +This patch changes vectored file I/O to use kmap + kunmap when mapping +incoming SGL memory -> struct iovec in order to properly support 32-bit +highmem configurations. This is because an extra bounce buffer may be +required when processing scatterlist pages allocated with GFP_KERNEL. + +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_file.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -260,7 +260,7 @@ static int fd_do_readv(struct se_cmd *cm + + for_each_sg(sgl, sg, sgl_nents, i) { + iov[i].iov_len = sg->length; +- iov[i].iov_base = sg_virt(sg); ++ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; + } + + old_fs = get_fs(); +@@ -268,6 +268,8 @@ static int fd_do_readv(struct se_cmd *cm + ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); + set_fs(old_fs); + ++ for_each_sg(sgl, sg, sgl_nents, i) ++ kunmap(sg_page(sg)); + kfree(iov); + /* + * Return zeros and GOOD status even if the READ did not return +@@ -313,7 +315,7 @@ static int fd_do_writev(struct se_cmd *c + + for_each_sg(sgl, sg, sgl_nents, i) { + iov[i].iov_len = sg->length; +- iov[i].iov_base = sg_virt(sg); ++ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; + } + + old_fs = get_fs(); +@@ -321,6 +323,9 @@ static int fd_do_writev(struct se_cmd *c + ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); + set_fs(old_fs); + ++ for_each_sg(sgl, sg, sgl_nents, i) ++ kunmap(sg_page(sg)); ++ + kfree(iov); + + if (ret < 0 || ret != cmd->data_length) { +From 9f4ad44b264f8bb61ffdd607148215566568430d Mon Sep 17 00:00:00 2001 +From: Yi Zou +Date: Mon, 10 Dec 2012 17:04:00 -0800 +Subject: target/tcm_fc: fix the lockdep warning due to inconsistent lock state + +From: Yi Zou + +commit 9f4ad44b264f8bb61ffdd607148215566568430d upstream. + +The lockdep warning below is in theory correct but it will be in really weird +rare situation that ends up that deadlock since the tcm fc session is hashed +based the rport id. Nonetheless, the complaining below is about rcu callback +that does the transport_deregister_session() is happening in softirq, where +transport_register_session() that happens earlier is not. This triggers the +lockdep warning below. So, just fix this to make lockdep happy by disabling +the soft irq before calling transport_register_session() in ft_prli. + +BTW, this was found in FCoE VN2VN over two VMs, couple of create and destroy +would get this triggered. + +v1: was enforcing register to be in softirq context which was not righ. See, +http://www.spinics.net/lists/target-devel/msg03614.html + +v2: following comments from Roland&Nick (thanks), it seems we don't have to +do transport_deregister_session() in rcu callback, so move it into ft_sess_free() +but still do kfree() of the corresponding ft_sess struct in rcu callback to +make sure the ft_sess is not freed till the rcu callback. + +... +[ 1328.370592] scsi2 : FCoE Driver +[ 1328.383429] fcoe: No FDMI support. +[ 1328.384509] host2: libfc: Link up on port (000000) +[ 1328.934229] host2: Assigned Port ID 00a292 +[ 1357.232132] host2: rport 00a393: Remove port +[ 1357.232568] host2: rport 00a393: Port sending LOGO from Ready state +[ 1357.233692] host2: rport 00a393: Delete port +[ 1357.234472] host2: rport 00a393: work event 3 +[ 1357.234969] host2: rport 00a393: callback ev 3 +[ 1357.235979] host2: rport 00a393: Received a LOGO response closed +[ 1357.236706] host2: rport 00a393: work delete +[ 1357.237481] +[ 1357.237631] ================================= +[ 1357.238064] [ INFO: inconsistent lock state ] +[ 1357.238450] 3.7.0-rc7-yikvm+ #3 Tainted: G O +[ 1357.238450] --------------------------------- +[ 1357.238450] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. +[ 1357.238450] ksoftirqd/0/3 [HC0[0]:SC1[1]:HE0:SE0] takes: +[ 1357.238450] (&(&se_tpg->session_lock)->rlock){+.?...}, at: [] transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] {SOFTIRQ-ON-W} state was registered at: +[ 1357.238450] [] mark_held_locks+0x6d/0x95 +[ 1357.238450] [] trace_hardirqs_on_caller+0x12d/0x197 +[ 1357.238450] [] trace_hardirqs_on+0xd/0xf +[ 1357.238450] [] _raw_spin_unlock_irq+0x2d/0x45 +[ 1357.238450] [] __transport_register_session+0xb8/0x122 [target_core_mod] +[ 1357.238450] [] transport_register_session+0x44/0x5a [target_core_mod] +[ 1357.238450] [] ft_prli+0x1e3/0x275 [tcm_fc] +[ 1357.238450] [] fc_rport_recv_req+0x95e/0xdc5 [libfc] +[ 1357.238450] [] fc_lport_recv_els_req+0xc4/0xd5 [libfc] +[ 1357.238450] [] fc_lport_recv_req+0x12f/0x18f [libfc] +[ 1357.238450] [] fc_exch_recv+0x8ba/0x981 [libfc] +[ 1357.238450] [] fcoe_percpu_receive_thread+0x47a/0x4e2 [fcoe] +[ 1357.238450] [] kthread+0xb1/0xb9 +[ 1357.238450] [] ret_from_fork+0x7c/0xb0 +[ 1357.238450] irq event stamp: 275411 +[ 1357.238450] hardirqs last enabled at (275410): [] rcu_process_callbacks+0x229/0x42a +[ 1357.238450] hardirqs last disabled at (275411): [] _raw_spin_lock_irqsave+0x22/0x8e +[ 1357.238450] softirqs last enabled at (275394): [] __do_softirq+0x246/0x26f +[ 1357.238450] softirqs last disabled at (275399): [] run_ksoftirqd+0x29/0x62 +[ 1357.238450] +[ 1357.238450] other info that might help us debug this: +[ 1357.238450] Possible unsafe locking scenario: +[ 1357.238450] +[ 1357.238450] CPU0 +[ 1357.238450] ---- +[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); +[ 1357.238450] +[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); +[ 1357.238450] +[ 1357.238450] *** DEADLOCK *** +[ 1357.238450] +[ 1357.238450] no locks held by ksoftirqd/0/3. +[ 1357.238450] +[ 1357.238450] stack backtrace: +[ 1357.238450] Pid: 3, comm: ksoftirqd/0 Tainted: G O 3.7.0-rc7-yikvm+ #3 +[ 1357.238450] Call Trace: +[ 1357.238450] [] print_usage_bug+0x1f5/0x206 +[ 1357.238450] [] ? save_stack_trace+0x2c/0x49 +[ 1357.238450] [] ? print_irq_inversion_bug.part.14+0x1ae/0x1ae +[ 1357.238450] [] mark_lock+0x106/0x258 +[ 1357.238450] [] __lock_acquire+0x2e7/0xe53 +[ 1357.238450] [] ? pvclock_clocksource_read+0x48/0xb4 +[ 1357.238450] [] ? rcu_process_gp_end+0xc0/0xc9 +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] lock_acquire+0x119/0x143 +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] _raw_spin_lock_irqsave+0x54/0x8e +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] ? rcu_process_callbacks+0x229/0x42a +[ 1357.238450] [] ft_sess_rcu_free+0x17/0x24 [tcm_fc] +[ 1357.238450] [] ? ft_sess_free+0x1b/0x1b [tcm_fc] +[ 1357.238450] [] rcu_process_callbacks+0x260/0x42a +[ 1357.238450] [] __do_softirq+0x13a/0x26f +[ 1357.238450] [] ? __schedule+0x65f/0x68e +[ 1357.238450] [] run_ksoftirqd+0x29/0x62 +[ 1357.238450] [] smpboot_thread_fn+0x1a5/0x1aa +[ 1357.238450] [] ? smpboot_unregister_percpu_thread+0x47/0x47 +[ 1357.238450] [] kthread+0xb1/0xb9 +[ 1357.238450] [] ? wait_for_common+0xbb/0x10a +[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 +[ 1357.238450] [] ret_from_fork+0x7c/0xb0 +[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 +[ 1417.440099] rport-2:0-0: blocked FC remote port time out: removing rport + +Signed-off-by: Yi Zou +Cc: Open-FCoE +Cc: Nicholas A. Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/tcm_fc/tfc_sess.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/target/tcm_fc/tfc_sess.c ++++ b/drivers/target/tcm_fc/tfc_sess.c +@@ -430,7 +430,6 @@ static void ft_sess_rcu_free(struct rcu_ + { + struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); + +- transport_deregister_session(sess->se_sess); + kfree(sess); + } + +@@ -438,6 +437,7 @@ static void ft_sess_free(struct kref *kr + { + struct ft_sess *sess = container_of(kref, struct ft_sess, kref); + ++ transport_deregister_session(sess->se_sess); + call_rcu(&sess->rcu, ft_sess_rcu_free); + } + +From e1fe2060d7e8f58a69374135e32e90f0bb79a7fd Mon Sep 17 00:00:00 2001 +From: Chris Boot +Date: Tue, 11 Dec 2012 21:58:48 +0000 +Subject: sbp-target: fix error path in sbp_make_tpg() + +From: Chris Boot + +commit e1fe2060d7e8f58a69374135e32e90f0bb79a7fd upstream. + +If the TPG memory is allocated successfully, but we fail further along +in the function, a dangling pointer to freed memory is left in the TPort +structure. This is mostly harmless, but does prevent re-trying the +operation without first removing the TPort altogether. + +Reported-by: Chen Gang +Signed-off-by: Chris Boot +Cc: Andy Grover +Cc: Nicholas A. Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/sbp/sbp_target.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/target/sbp/sbp_target.c ++++ b/drivers/target/sbp/sbp_target.c +@@ -2207,20 +2207,23 @@ static struct se_portal_group *sbp_make_ + tport->mgt_agt = sbp_management_agent_register(tport); + if (IS_ERR(tport->mgt_agt)) { + ret = PTR_ERR(tport->mgt_agt); +- kfree(tpg); +- return ERR_PTR(ret); ++ goto out_free_tpg; + } + + ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, + &tpg->se_tpg, (void *)tpg, + TRANSPORT_TPG_TYPE_NORMAL); +- if (ret < 0) { +- sbp_management_agent_unregister(tport->mgt_agt); +- kfree(tpg); +- return ERR_PTR(ret); +- } ++ if (ret < 0) ++ goto out_unreg_mgt_agt; + + return &tpg->se_tpg; ++ ++out_unreg_mgt_agt: ++ sbp_management_agent_unregister(tport->mgt_agt); ++out_free_tpg: ++ tport->tpg = NULL; ++ kfree(tpg); ++ return ERR_PTR(ret); + } + + static void sbp_drop_tpg(struct se_portal_group *se_tpg) +From fee546ce8cfd9dea1f53175f627e17ef5ff05df4 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 23 Nov 2012 12:05:33 +0900 +Subject: mfd: wm8994: Add support for WM1811 rev E + +From: Mark Brown + +commit fee546ce8cfd9dea1f53175f627e17ef5ff05df4 upstream. + +This is supported identically to the previous revisions. + +Signed-off-by: Mark Brown +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mfd/wm8994-core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mfd/wm8994-core.c ++++ b/drivers/mfd/wm8994-core.c +@@ -557,6 +557,7 @@ static __devinit int wm8994_device_init( + case 1: + case 2: + case 3: ++ case 4: + regmap_patch = wm1811_reva_patch; + patch_regs = ARRAY_SIZE(wm1811_reva_patch); + break; +From b9fbb62eb61452d728c39b2e5020739c575aac53 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 9 Nov 2012 16:15:28 +0000 +Subject: mfd: Only unregister platform devices allocated by the mfd core + +From: Charles Keepax + +commit b9fbb62eb61452d728c39b2e5020739c575aac53 upstream. + +mfd_remove_devices would iterate over all devices sharing a parent with +an mfd device regardless of whether they were allocated by the mfd core +or not. This especially caused problems when the device structure was +not contained within a platform_device, because to_platform_device is +used on each device pointer. + +This patch defines a device_type for mfd devices and checks this is +present from mfd_remove_devices_fn before processing the device. + +Signed-off-by: Charles Keepax +Tested-by: Peter Tyser +Reviewed-by: Mark Brown +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mfd/mfd-core.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/mfd/mfd-core.c ++++ b/drivers/mfd/mfd-core.c +@@ -21,6 +21,10 @@ + #include + #include + ++static struct device_type mfd_dev_type = { ++ .name = "mfd_device", ++}; ++ + int mfd_cell_enable(struct platform_device *pdev) + { + const struct mfd_cell *cell = mfd_get_cell(pdev); +@@ -91,6 +95,7 @@ static int mfd_add_device(struct device + goto fail_device; + + pdev->dev.parent = parent; ++ pdev->dev.type = &mfd_dev_type; + + if (parent->of_node && cell->of_compatible) { + for_each_child_of_node(parent->of_node, np) { +@@ -204,10 +209,16 @@ EXPORT_SYMBOL(mfd_add_devices); + + static int mfd_remove_devices_fn(struct device *dev, void *c) + { +- struct platform_device *pdev = to_platform_device(dev); +- const struct mfd_cell *cell = mfd_get_cell(pdev); ++ struct platform_device *pdev; ++ const struct mfd_cell *cell; + atomic_t **usage_count = c; + ++ if (dev->type != &mfd_dev_type) ++ return 0; ++ ++ pdev = to_platform_device(dev); ++ cell = mfd_get_cell(pdev); ++ + /* find the base address of usage_count pointers (for freeing) */ + if (!*usage_count || (cell->usage_count < *usage_count)) + *usage_count = cell->usage_count; +From 90a38d999739f35f4fc925c875e6ee518546b66c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Mon, 15 Oct 2012 22:44:45 +0200 +Subject: mfd: Remove Unicode Byte Order Marks from da9055 + +From: Geert Uytterhoeven + +commit 90a38d999739f35f4fc925c875e6ee518546b66c upstream. + +Older gcc (< 4.4) doesn't like files starting with Unicode BOMs: + +include/linux/mfd/da9055/core.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/core.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/core.h:1: error: stray ‘\277’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\277’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\277’ in program + +Remove the BOMs, the rest of the files is plain ASCII anyway. + +Output of "file" before: + +include/linux/mfd/da9055/core.h: UTF-8 Unicode (with BOM) C program text +include/linux/mfd/da9055/pdata.h: UTF-8 Unicode (with BOM) C program text +include/linux/mfd/da9055/reg.h: UTF-8 Unicode (with BOM) C program text + +Output of "file" after: + +include/linux/mfd/da9055/core.h: ASCII C program text +include/linux/mfd/da9055/pdata.h: ASCII C program text +include/linux/mfd/da9055/reg.h: ASCII C program text + +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/mfd/da9055/core.h | 2 +- + include/linux/mfd/da9055/pdata.h | 2 +- + include/linux/mfd/da9055/reg.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/include/linux/mfd/da9055/core.h ++++ b/include/linux/mfd/da9055/core.h +@@ -1,4 +1,4 @@ +-/* ++/* + * da9055 declarations for DA9055 PMICs. + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. +--- a/include/linux/mfd/da9055/pdata.h ++++ b/include/linux/mfd/da9055/pdata.h +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2012 Dialog Semiconductor Ltd. ++/* Copyright (C) 2012 Dialog Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +--- a/include/linux/mfd/da9055/reg.h ++++ b/include/linux/mfd/da9055/reg.h +@@ -1,4 +1,4 @@ +-/* ++/* + * DA9055 declarations for DA9055 PMICs. + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. +From 24ec19b0ae83a385ad9c55520716da671274b96c Mon Sep 17 00:00:00 2001 +From: Eugene Shatokhin +Date: Thu, 8 Nov 2012 15:11:11 -0500 +Subject: ext4: fix memory leak in ext4_xattr_set_acl()'s error path + +From: Eugene Shatokhin + +commit 24ec19b0ae83a385ad9c55520716da671274b96c upstream. + +In ext4_xattr_set_acl(), if ext4_journal_start() returns an error, +posix_acl_release() will not be called for 'acl' which may result in a +memory leak. + +This patch fixes that. + +Reviewed-by: Lukas Czerner +Signed-off-by: Eugene Shatokhin +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/acl.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/acl.c ++++ b/fs/ext4/acl.c +@@ -423,8 +423,10 @@ ext4_xattr_set_acl(struct dentry *dentry + + retry: + handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ error = PTR_ERR(handle); ++ goto release_and_out; ++ } + error = ext4_set_acl(handle, inode, type, acl); + ext4_journal_stop(handle); + if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) +From aeb1e5d69a5be592e86a926be73efb38c55af404 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 29 Nov 2012 21:21:22 -0500 +Subject: ext4: fix possible use after free with metadata csum + +From: Theodore Ts'o + +commit aeb1e5d69a5be592e86a926be73efb38c55af404 upstream. + +Commit fa77dcfafeaa introduces block bitmap checksum calculation into +ext4_new_inode() in the case that block group was uninitialized. +However we brelse() the bitmap buffer before we attempt to checksum it +so we have no guarantee that the buffer is still there. + +Fix this by releasing the buffer after the possible checksum +computation. + +Signed-off-by: Lukas Czerner +Signed-off-by: "Theodore Ts'o" +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ialloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -762,7 +762,6 @@ got: + + BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); + err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh); +- brelse(block_bitmap_bh); + + /* recheck and clear flag under lock if we still need to */ + ext4_lock_group(sb, group); +@@ -775,6 +774,7 @@ got: + ext4_group_desc_csum_set(sb, group, gdp); + } + ext4_unlock_group(sb, group); ++ brelse(block_bitmap_bh); + + if (err) + goto fail; +From d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee Mon Sep 17 00:00:00 2001 +From: Nathan Williams +Date: Thu, 22 Nov 2012 10:42:52 +1100 +Subject: mtd cs553x_nand: Initialise ecc.strength before nand_scan() + +From: Nathan Williams + +commit d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee upstream. + +Loading cs553x_nand with Hynix H27U1G8F2BTR NAND flash causes this bug: + +kernel BUG at drivers/mtd/nand/nand_base.c:3345! +invalid opcode: 0000 [#1] +Modules linked in: cs553x_nand(+) vfat fat usb_storage ehci_hcd usbcore usb_comr +Pid: 436, comm: modprobe Not tainted 3.6.7 #1 +EIP: 0060:[] EFLAGS: 00010296 CPU: 0 +EIP is at nand_scan_tail+0x64c/0x69c +EAX: 00000034 EBX: cea6ed98 ECX: 00000000 EDX: 00000000 +ESI: cea6ec00 EDI: cea6ec00 EBP: 20000000 ESP: cdd17e48 + DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 +CR0: 8005003b CR2: 0804e119 CR3: 0d850000 CR4: 00000090 +DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 +DR6: ffff0ff0 DR7: 00000400 +Process modprobe (pid: 436, ti=cdd16000 task=cdd1c320 task.ti=cdd16000) +Stack: + c12e962c c118f7ef 00000003 cea6ed98 d014b25c 20000000 fffff007 00000001 + 00000000 cdd53b00 d014b000 c1001021 cdd53b00 d01493c0 cdd53b00 cdd53b00 + d01493c0 c1047f83 d014b4a0 00000000 cdd17f9c ce4be454 cdd17f48 cdd1c320 +Call Trace: + [] ? nand_scan+0x1b/0x4d + [] ? init_module+0x25c/0x2de [cs553x_nand] + [] ? 0xd014afff + [] ? do_one_initcall+0x21/0x111 + [] ? sys_init_module+0xe4/0x1261 + [] ? task_work_run+0x36/0x43 + [] ? syscall_call+0x7/0xb +Code: fa ff ff c7 86 d8 00 00 00 01 00 00 00 e9 5f fc ff ff 68 f8 26 2e c1 e8 a7 +EIP: [] nand_scan_tail+0x64c/0x69c SS:ESP 0068:cdd17e48 + +Initialising ecc.strength before the call to nand_scan() fixes this. + +Signed-off-by: Nathan Williams +Acked-by: Brian Norris +Acked-by: Mike Dunn +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/nand/cs553x_nand.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/mtd/nand/cs553x_nand.c ++++ b/drivers/mtd/nand/cs553x_nand.c +@@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs + this->ecc.hwctl = cs_enable_hwecc; + this->ecc.calculate = cs_calculate_ecc; + this->ecc.correct = nand_correct_data; ++ this->ecc.strength = 1; + + /* Enable the following for a flash based bad block table */ + this->bbt_options = NAND_BBT_USE_FLASH; +@@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs + goto out_ior; + } + +- this->ecc.strength = 1; +- + new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); + + cs553x_mtd[cs] = new_mtd; +From 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 Mon Sep 17 00:00:00 2001 +From: Wolfram Sang +Date: Wed, 5 Dec 2012 21:46:02 +0100 +Subject: mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems + +From: Wolfram Sang + +commit 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 upstream. + +It could happen (1 out of 100 times) that NAND did not start up +correctly after warm rebooting, so the kernel could not find the UBI or +DMA timed out due to a stalled BCH. When resetting BCH together with +GPMI, the issue could not be observed anymore (after 10000+ reboots). We +probably need the consistent state already before sending any command to +NAND, even when no ECC is needed. I chose to keep the extra reset for +BCH when changing the flash layout to be on the safe side. + +Signed-off-by: Wolfram Sang +Acked-by: Huang Shijie +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c ++++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +@@ -166,6 +166,15 @@ int gpmi_init(struct gpmi_nand_data *thi + if (ret) + goto err_out; + ++ /* ++ * Reset BCH here, too. We got failures otherwise :( ++ * See later BCH reset for explanation of MX23 handling ++ */ ++ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); ++ if (ret) ++ goto err_out; ++ ++ + /* Choose NAND mode. */ + writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); + +From bd1ee804af8bdf2fd5131234330615f8aecbd9ed Mon Sep 17 00:00:00 2001 +From: Pawel Moll +Date: Mon, 29 Oct 2012 11:23:02 +0000 +Subject: kbuild: Do not remove vmlinux when cleaning external module + +From: Pawel Moll + +commit bd1ee804af8bdf2fd5131234330615f8aecbd9ed upstream. + +Since commit 1f2bfbd00e466ff3489b2ca5cc75b1cccd14c123 "kbuild: +link of vmlinux moved to a script" make clean with M= +argument (so cleaning external module) removes vmlinux, +System.map and couple of other files from the *main* kernel +build directory! This not what was happening before and almost +certainly not what one would expect. + +This patch moves makes the clean target of the script called +only when !KBUILD_EXTMOD. + +Signed-off-by: Pawel Moll +Signed-off-by: Michal Marek +Signed-off-by: Greg Kroah-Hartman + +--- + Makefile | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -1021,11 +1021,14 @@ clean: rm-dirs := $(CLEAN_DIRS) + clean: rm-files := $(CLEAN_FILES) + clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples) + +-PHONY += $(clean-dirs) clean archclean ++PHONY += $(clean-dirs) clean archclean vmlinuxclean + $(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +-clean: archclean ++vmlinuxclean: ++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean ++ ++clean: archclean vmlinuxclean + + # mrproper - Delete all generated files, including .config + # +@@ -1252,7 +1255,6 @@ scripts: ; + endif # KBUILD_EXTMOD + + clean: $(clean-dirs) +- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ +From ca2e16faa7378878c1522a7c1b6c38211de3331d Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 22 Nov 2012 10:39:56 +0200 +Subject: OMAP: board-files: fix i2c_bus for tfp410 + +From: Tomi Valkeinen + +commit ca2e16faa7378878c1522a7c1b6c38211de3331d upstream. + +The i2c handling in tfp410 driver, which handles converting parallel RGB +to DVI, was changed in 958f2717b84e88bf833d996997fda8f73276f2af +(OMAPDSS: TFP410: pdata rewrite). The patch changed what value the +driver considers as invalid/undefined. Before the patch, 0 was the +invalid value, but as 0 is a valid bus number, the patch changed this to +-1. + +However, the fact was missed that many board files do not define the bus +number at all, thus it's left to 0. This causes the driver to fail to +get the i2c bus, exiting from the driver's probe with an error, meaning +that the DVI output does not work for those boards. + +This patch fixes the issue by changing the i2c_bus number field in the +driver's platform data from u16 to int, and setting the bus number to -1 +in the board files for the boards that did not define the bus. The +exception is devkit8000, for which the bus is set to 1, which is the +correct bus for that board. + +The bug exists in v3.5+ kernels. + +Signed-off-by: Tomi Valkeinen +Reported-by: Thomas Weber +Cc: Thomas Weber +Signed-off-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-omap2/board-3430sdp.c | 1 + + arch/arm/mach-omap2/board-am3517evm.c | 1 + + arch/arm/mach-omap2/board-cm-t35.c | 1 + + arch/arm/mach-omap2/board-devkit8000.c | 1 + + arch/arm/mach-omap2/board-omap3evm.c | 1 + + arch/arm/mach-omap2/board-omap3stalker.c | 1 + + include/video/omap-panel-tfp410.h | 2 +- + 7 files changed, 7 insertions(+), 1 deletion(-) + +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -157,6 +157,7 @@ static struct omap_dss_device sdp3430_lc + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device sdp3430_dvi_device = { +--- a/arch/arm/mach-omap2/board-am3517evm.c ++++ b/arch/arm/mach-omap2/board-am3517evm.c +@@ -208,6 +208,7 @@ static struct omap_dss_device am3517_evm + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device am3517_evm_dvi_device = { +--- a/arch/arm/mach-omap2/board-cm-t35.c ++++ b/arch/arm/mach-omap2/board-cm-t35.c +@@ -243,6 +243,7 @@ static struct omap_dss_device cm_t35_lcd + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = CM_T35_DVI_EN_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device cm_t35_dvi_device = { +--- a/arch/arm/mach-omap2/board-devkit8000.c ++++ b/arch/arm/mach-omap2/board-devkit8000.c +@@ -139,6 +139,7 @@ static struct omap_dss_device devkit8000 + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = 1, + }; + + static struct omap_dss_device devkit8000_dvi_device = { +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -236,6 +236,7 @@ static struct omap_dss_device omap3_evm_ + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = OMAP3EVM_DVI_PANEL_EN_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device omap3_evm_dvi_device = { +--- a/arch/arm/mach-omap2/board-omap3stalker.c ++++ b/arch/arm/mach-omap2/board-omap3stalker.c +@@ -119,6 +119,7 @@ static struct omap_dss_device omap3_stal + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = DSS_ENABLE_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device omap3_stalker_dvi_device = { +--- a/include/video/omap-panel-tfp410.h ++++ b/include/video/omap-panel-tfp410.h +@@ -28,7 +28,7 @@ struct omap_dss_device; + * @power_down_gpio: gpio number for PD pin (or -1 if not available) + */ + struct tfp410_platform_data { +- u16 i2c_bus_num; ++ int i2c_bus_num; + int power_down_gpio; + }; + +From 642fe4d00db56d65060ce2fd4c105884414acb16 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 8 Nov 2012 10:01:26 -0500 +Subject: SUNRPC: Fix validity issues with rpc_pipefs sb->s_fs_info + +From: Trond Myklebust + +commit 642fe4d00db56d65060ce2fd4c105884414acb16 upstream. + +rpc_kill_sb() must defer calling put_net() until after the notifier +has been called, since most (all?) of the notifier callbacks assume +that sb->s_fs_info points to a valid net namespace. It also must not +call put_net() if the call to rpc_fill_super was unsuccessful. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48421 + +Signed-off-by: Trond Myklebust +Cc: Stanislav Kinsbursky +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/rpc_pipe.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -1152,14 +1152,19 @@ static void rpc_kill_sb(struct super_blo + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + + mutex_lock(&sn->pipefs_sb_lock); ++ if (sn->pipefs_sb != sb) { ++ mutex_unlock(&sn->pipefs_sb_lock); ++ goto out; ++ } + sn->pipefs_sb = NULL; + mutex_unlock(&sn->pipefs_sb_lock); +- put_net(net); + dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", + net, NET_NAME(net)); + blocking_notifier_call_chain(&rpc_pipefs_notifier_list, + RPC_PIPEFS_UMOUNT, + sb); ++ put_net(net); ++out: + kill_litter_super(sb); + } + +From cd6c5968582a273561464fe6b1e8cc8214be02df Mon Sep 17 00:00:00 2001 +From: Stanislav Kinsbursky +Date: Mon, 17 Dec 2012 20:18:52 +0300 +Subject: SUNRPC: continue run over clients list on PipeFS event instead of break + +From: Stanislav Kinsbursky + +commit cd6c5968582a273561464fe6b1e8cc8214be02df upstream. + +There are SUNRPC clients, which program doesn't have pipe_dir_name. These +clients can be skipped on PipeFS events, because nothing have to be created or +destroyed. But instead of breaking in case of such a client was found, search +for suitable client over clients list have to be continued. Otherwise some +clients could not be covered by PipeFS event handler. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/clnt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -234,7 +234,7 @@ static struct rpc_clnt *rpc_get_client_f + spin_lock(&sn->rpc_client_lock); + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { + if (clnt->cl_program->pipe_dir_name == NULL) +- break; ++ continue; + if (rpc_clnt_skip_event(clnt, event)) + continue; + if (atomic_inc_not_zero(&clnt->cl_count) == 0) +From 621eb19ce1ec216e03ad354cb0c4061736b2a436 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Wed, 14 Nov 2012 10:48:05 -0500 +Subject: svcrpc: Revert "sunrpc/cache.h: replace simple_strtoul" + +From: "J. Bruce Fields" + +commit 621eb19ce1ec216e03ad354cb0c4061736b2a436 upstream. + +Commit bbf43dc888833ac0539e437dbaeb28bfd4fbab9f "sunrpc/cache.h: replace +simple_strtoul" introduced new range-checking which could cause get_int +to fail on unsigned integers too large to be represented as an int. + +We could parse them as unsigned instead--but it turns out svcgssd is +actually passing down "-1" in some cases. Which is perhaps stupid, but +there's nothing we can do about it now. + +So just revert back to the previous "sloppy" behavior that accepts +either representation. + +Reported-by: Sven Geggus +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/sunrpc/cache.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/linux/sunrpc/cache.h ++++ b/include/linux/sunrpc/cache.h +@@ -217,6 +217,8 @@ extern int qword_get(char **bpp, char *d + static inline int get_int(char **bpp, int *anint) + { + char buf[50]; ++ char *ep; ++ int rv; + int len = qword_get(bpp, buf, sizeof(buf)); + + if (len < 0) +@@ -224,9 +226,11 @@ static inline int get_int(char **bpp, in + if (len == 0) + return -ENOENT; + +- if (kstrtoint(buf, 0, anint)) ++ rv = simple_strtol(buf, &ep, 0); ++ if (*ep) + return -EINVAL; + ++ *anint = rv; + return 0; + } + +From c6567ed1402c55e19b012e66a8398baec2a726f3 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 4 Jan 2013 12:23:21 -0500 +Subject: SUNRPC: Ensure that we free the rpc_task after cleanups are done + +From: Trond Myklebust + +commit c6567ed1402c55e19b012e66a8398baec2a726f3 upstream. + +This patch ensures that we free the rpc_task after the cleanup callbacks +are done in order to avoid a deadlock problem that can be triggered if +the callback needs to wait for another workqueue item to complete. + +Signed-off-by: Trond Myklebust +Cc: Weston Andros Adamson +Cc: Tejun Heo +Cc: Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/sched.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -919,16 +919,35 @@ struct rpc_task *rpc_new_task(const stru + return task; + } + ++/* ++ * rpc_free_task - release rpc task and perform cleanups ++ * ++ * Note that we free up the rpc_task _after_ rpc_release_calldata() ++ * in order to work around a workqueue dependency issue. ++ * ++ * Tejun Heo states: ++ * "Workqueue currently considers two work items to be the same if they're ++ * on the same address and won't execute them concurrently - ie. it ++ * makes a work item which is queued again while being executed wait ++ * for the previous execution to complete. ++ * ++ * If a work function frees the work item, and then waits for an event ++ * which should be performed by another work item and *that* work item ++ * recycles the freed work item, it can create a false dependency loop. ++ * There really is no reliable way to detect this short of verifying ++ * every memory free." ++ * ++ */ + static void rpc_free_task(struct rpc_task *task) + { +- const struct rpc_call_ops *tk_ops = task->tk_ops; +- void *calldata = task->tk_calldata; ++ unsigned short tk_flags = task->tk_flags; + +- if (task->tk_flags & RPC_TASK_DYNAMIC) { ++ rpc_release_calldata(task->tk_ops, task->tk_calldata); ++ ++ if (tk_flags & RPC_TASK_DYNAMIC) { + dprintk("RPC: %5u freeing task\n", task->tk_pid); + mempool_free(task, rpc_task_mempool); + } +- rpc_release_calldata(tk_ops, calldata); + } + + static void rpc_async_release(struct work_struct *work) +From 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 7 Jan 2013 14:30:46 -0500 +Subject: SUNRPC: Ensure we release the socket write lock if the rpc_task exits early + +From: Trond Myklebust + +commit 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 upstream. + +If the rpc_task exits while holding the socket write lock before it has +allocated an rpc slot, then the usual mechanism for releasing the write +lock in xprt_release() is defeated. + +The problem occurs if the call to xprt_lock_write() initially fails, so +that the rpc_task is put on the xprt->sending wait queue. If the task +exits after being assigned the lock by __xprt_lock_write_func, but +before it has retried the call to xprt_lock_and_alloc_slot(), then +it calls xprt_release() while holding the write lock, but will +immediately exit due to the test for task->tk_rqstp != NULL. + +Reported-by: Chris Perl +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/sched.c | 3 +-- + net/sunrpc/xprt.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -957,8 +957,7 @@ static void rpc_async_release(struct wor + + static void rpc_release_resources_task(struct rpc_task *task) + { +- if (task->tk_rqstp) +- xprt_release(task); ++ xprt_release(task); + if (task->tk_msg.rpc_cred) { + put_rpccred(task->tk_msg.rpc_cred); + task->tk_msg.rpc_cred = NULL; +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc + void xprt_release(struct rpc_task *task) + { + struct rpc_xprt *xprt; +- struct rpc_rqst *req; ++ struct rpc_rqst *req = task->tk_rqstp; + +- if (!(req = task->tk_rqstp)) ++ if (req == NULL) { ++ if (task->tk_client) { ++ rcu_read_lock(); ++ xprt = rcu_dereference(task->tk_client->cl_xprt); ++ if (xprt->snd_task == task) ++ xprt_release_write(xprt, task); ++ rcu_read_unlock(); ++ } + return; ++ } + + xprt = req->rq_xprt; + if (task->tk_ops->rpc_count_stats != NULL) +From 2cbba75a56ea78e6876b4e2547a882f10b3fe72b Mon Sep 17 00:00:00 2001 +From: Alexey Khoroshilov +Date: Mon, 5 Nov 2012 22:40:14 +0400 +Subject: jffs2: hold erase_completion_lock on exit + +From: Alexey Khoroshilov + +commit 2cbba75a56ea78e6876b4e2547a882f10b3fe72b upstream. + +Users of jffs2_do_reserve_space() expect they still held +erase_completion_lock after call to it. But there is a path +where jffs2_do_reserve_space() leaves erase_completion_lock unlocked. +The patch fixes it. + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/nodemgmt.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/jffs2/nodemgmt.c ++++ b/fs/jffs2/nodemgmt.c +@@ -417,14 +417,16 @@ static int jffs2_do_reserve_space(struct + spin_unlock(&c->erase_completion_lock); + + ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); +- if (ret) +- return ret; ++ + /* Just lock it again and continue. Nothing much can change because + we hold c->alloc_sem anyway. In fact, it's not entirely clear why + we hold c->erase_completion_lock in the majority of this function... + but that's a question for another (more caffeine-rich) day. */ + spin_lock(&c->erase_completion_lock); + ++ if (ret) ++ return ret; ++ + waste = jeb->free_size; + jffs2_link_node_ref(c, jeb, + (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, +From 999a7c5776a0ed2133645fa7e008bec05bda9254 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 14 Dec 2012 13:10:50 +0000 +Subject: i2400m: add Intel 6150 device IDs + +From: Dan Williams + +commit 999a7c5776a0ed2133645fa7e008bec05bda9254 upstream. + +Add device IDs for WiMAX function of Intel 6150 cards. + +Signed-off-by: Dan Williams +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wimax/i2400m/i2400m-usb.h | 3 +++ + drivers/net/wimax/i2400m/usb.c | 6 ++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/wimax/i2400m/i2400m-usb.h ++++ b/drivers/net/wimax/i2400m/i2400m-usb.h +@@ -152,6 +152,9 @@ enum { + /* Device IDs */ + USB_DEVICE_ID_I6050 = 0x0186, + USB_DEVICE_ID_I6050_2 = 0x0188, ++ USB_DEVICE_ID_I6150 = 0x07d6, ++ USB_DEVICE_ID_I6150_2 = 0x07d7, ++ USB_DEVICE_ID_I6150_3 = 0x07d9, + USB_DEVICE_ID_I6250 = 0x0187, + }; + +--- a/drivers/net/wimax/i2400m/usb.c ++++ b/drivers/net/wimax/i2400m/usb.c +@@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface * + switch (id->idProduct) { + case USB_DEVICE_ID_I6050: + case USB_DEVICE_ID_I6050_2: ++ case USB_DEVICE_ID_I6150: ++ case USB_DEVICE_ID_I6150_2: ++ case USB_DEVICE_ID_I6150_3: + case USB_DEVICE_ID_I6250: + i2400mu->i6050 = 1; + break; +@@ -759,6 +762,9 @@ static + struct usb_device_id i2400mu_id_table[] = { + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, + { USB_DEVICE(0x8086, 0x0181) }, + { USB_DEVICE(0x8086, 0x1403) }, +From 6491d4d02893d9787ba67279595990217177b351 Mon Sep 17 00:00:00 2001 +From: "Woodhouse, David" +Date: Wed, 19 Dec 2012 13:25:35 +0000 +Subject: intel-iommu: Free old page tables before creating superpage + +From: "Woodhouse, David" + +commit 6491d4d02893d9787ba67279595990217177b351 upstream. + +The dma_pte_free_pagetable() function will only free a page table page +if it is asked to free the *entire* 2MiB range that it covers. So if a +page table page was used for one or more small mappings, it's likely to +end up still present in the page tables... but with no valid PTEs. + +This was fine when we'd only be repopulating it with 4KiB PTEs anyway +but the same virtual address range can end up being reused for a +*large-page* mapping. And in that case were were trying to insert the +large page into the second-level page table, and getting a complaint +from the sanity check in __domain_mapping() because there was already a +corresponding entry. This was *relatively* harmless; it led to a memory +leak of the old page table page, but no other ill-effects. + +Fix it by calling dma_pte_clear_range (hopefully redundant) and +dma_pte_free_pagetable() before setting up the new large page. + +Signed-off-by: David Woodhouse +Tested-by: Ravi Murty +Tested-by: Sudeep Dutt +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/intel-iommu.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -1827,10 +1827,17 @@ static int __domain_mapping(struct dmar_ + if (!pte) + return -ENOMEM; + /* It is large page*/ +- if (largepage_lvl > 1) ++ if (largepage_lvl > 1) { + pteval |= DMA_PTE_LARGE_PAGE; +- else ++ /* Ensure that old small page tables are removed to make room ++ for superpage, if they exist. */ ++ dma_pte_clear_range(domain, iov_pfn, ++ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); ++ dma_pte_free_pagetable(domain, iov_pfn, ++ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); ++ } else { + pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; ++ } + + } + /* We don't need lock here, nobody else +From ae133a1129790ec288b429b5f08ab4701633844a Mon Sep 17 00:00:00 2001 +From: Christian König +Date: Tue, 18 Sep 2012 15:30:44 -0400 +Subject: drm/radeon: stop page faults from hanging the system (v2) + +From: Christian König + +commit ae133a1129790ec288b429b5f08ab4701633844a upstream. + +Redirect invalid memory accesses to the default page +instead of locking up the memory controller. Also +enable the invalid memory access interrupts and +start spamming system log with it. + +v2 (agd5f): fix up against 2 level PT changes + +Signed-off-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 10 ++++++++++ + drivers/gpu/drm/radeon/evergreend.h | 3 +++ + drivers/gpu/drm/radeon/ni.c | 16 +++++++++++++--- + drivers/gpu/drm/radeon/nid.h | 11 +++++++++++ + drivers/gpu/drm/radeon/si.c | 25 +++++++++++++++++++++++-- + drivers/gpu/drm/radeon/sid.h | 14 ++++++++++++++ + 6 files changed, 74 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -3093,6 +3093,16 @@ restart_ih: + break; + } + break; ++ case 146: ++ case 147: ++ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); ++ /* reset addr and status */ ++ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); ++ break; + case 176: /* CP_INT in ring buffer */ + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -651,6 +651,7 @@ + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) + #define VM_CONTEXT1_CNTL 0x1414 ++#define VM_CONTEXT1_CNTL2 0x1434 + #define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C + #define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C + #define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C +@@ -672,6 +673,8 @@ + #define CACHE_UPDATE_MODE(x) ((x) << 6) + #define VM_L2_STATUS 0x140C + #define L2_BUSY (1 << 0) ++#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC ++#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC + + #define WAIT_UNTIL 0x8040 + +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -784,10 +784,20 @@ static int cayman_pcie_gart_enable(struc + /* enable context1-7 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); +- WREG32(VM_CONTEXT1_CNTL2, 0); +- WREG32(VM_CONTEXT1_CNTL, 0); ++ WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | +- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | ++ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | ++ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ READ_PROTECTION_FAULT_ENABLE_DEFAULT | ++ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + cayman_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +--- a/drivers/gpu/drm/radeon/nid.h ++++ b/drivers/gpu/drm/radeon/nid.h +@@ -80,7 +80,18 @@ + #define VM_CONTEXT0_CNTL 0x1410 + #define ENABLE_CONTEXT (1 << 0) + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) ++#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) ++#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) ++#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) ++#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) ++#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) ++#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) ++#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) ++#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) + #define VM_CONTEXT1_CNTL 0x1414 + #define VM_CONTEXT0_CNTL2 0x1430 + #define VM_CONTEXT1_CNTL2 0x1434 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -2426,9 +2426,20 @@ static int si_pcie_gart_enable(struct ra + /* enable context1-15 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); +- WREG32(VM_CONTEXT1_CNTL2, 0); ++ WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | +- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | ++ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | ++ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ READ_PROTECTION_FAULT_ENABLE_DEFAULT | ++ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + si_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +@@ -3684,6 +3695,16 @@ restart_ih: + break; + } + break; ++ case 146: ++ case 147: ++ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); ++ /* reset addr and status */ ++ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); ++ break; + case 176: /* RINGID0 CP_INT */ + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; +--- a/drivers/gpu/drm/radeon/sid.h ++++ b/drivers/gpu/drm/radeon/sid.h +@@ -91,7 +91,18 @@ + #define VM_CONTEXT0_CNTL 0x1410 + #define ENABLE_CONTEXT (1 << 0) + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) ++#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) ++#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) ++#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) ++#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) ++#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) ++#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) ++#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) ++#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) + #define VM_CONTEXT1_CNTL 0x1414 + #define VM_CONTEXT0_CNTL2 0x1430 + #define VM_CONTEXT1_CNTL2 0x1434 +@@ -104,6 +115,9 @@ + #define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x1450 + #define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x1454 + ++#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC ++#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC ++ + #define VM_INVALIDATE_REQUEST 0x1478 + #define VM_INVALIDATE_RESPONSE 0x147c + +From a02dc74b317d78298cb0587b9b1f6f741fd5c139 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 13 Nov 2012 18:03:41 -0500 +Subject: drm/radeon/dce32+: use fractional fb dividers for high clocks + +From: Alex Deucher + +commit a02dc74b317d78298cb0587b9b1f6f741fd5c139 upstream. + +Fixes flickering with some high res montiors. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -561,6 +561,8 @@ static u32 atombios_adjust_pll(struct dr + /* use frac fb div on APUs */ + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; ++ if (ASIC_IS_DCE32(rdev) && mode->clock > 165000) ++ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + } else { + radeon_crtc->pll_flags |= RADEON_PLL_LEGACY; + +From 93927f9c1db5f55085457e820f0631064c7bfa34 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 4 Dec 2012 16:50:28 -0500 +Subject: drm/radeon: fix eDP clk and lane setup for scaled modes + +From: Alex Deucher + +commit 93927f9c1db5f55085457e820f0631064c7bfa34 upstream. + +Need to use the adjusted mode since we are sending native +timing and using the scaler for non-native modes. + +Signed-off-by: Alex Deucher +Reviewed-by: Jerome Glisse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/atombios_encoders.c ++++ b/drivers/gpu/drm/radeon/atombios_encoders.c +@@ -340,7 +340,7 @@ static bool radeon_atom_mode_fixup(struc + ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); +- radeon_dp_set_link_config(connector, mode); ++ radeon_dp_set_link_config(connector, adjusted_mode); + } + + return true; +From bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Tue, 11 Dec 2012 11:56:52 -0500 +Subject: drm/radeon: fix amd afusion gpu setup aka sumo v2 + +From: Jerome Glisse + +commit bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a upstream. + +Set the proper number of tile pipe that should be a multiple of +pipe depending on the number of se engine. + +Fix: +https://bugs.freedesktop.org/show_bug.cgi?id=56405 +https://bugs.freedesktop.org/show_bug.cgi?id=56720 + +v2: Don't change sumo2 + +Signed-off-by: Jerome Glisse +Reviewed-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 8 ++++---- + drivers/gpu/drm/radeon/evergreend.h | 2 ++ + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1821,7 +1821,7 @@ static void evergreen_gpu_init(struct ra + case CHIP_SUMO: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; +- rdev->config.evergreen.max_tile_pipes = 2; ++ rdev->config.evergreen.max_tile_pipes = 4; + if (rdev->pdev->device == 0x9648) + rdev->config.evergreen.max_simds = 3; + else if ((rdev->pdev->device == 0x9647) || +@@ -1844,7 +1844,7 @@ static void evergreen_gpu_init(struct ra + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; +- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; ++ gb_addr_config = SUMO_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_SUMO2: + rdev->config.evergreen.num_ses = 1; +@@ -1866,7 +1866,7 @@ static void evergreen_gpu_init(struct ra + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; +- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; ++ gb_addr_config = SUMO2_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_BARTS: + rdev->config.evergreen.num_ses = 2; +@@ -1914,7 +1914,7 @@ static void evergreen_gpu_init(struct ra + break; + case CHIP_CAICOS: + rdev->config.evergreen.num_ses = 1; +- rdev->config.evergreen.max_pipes = 4; ++ rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -45,6 +45,8 @@ + #define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 + #define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 + #define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 ++#define SUMO_GB_ADDR_CONFIG_GOLDEN 0x02010002 ++#define SUMO2_GB_ADDR_CONFIG_GOLDEN 0x02010002 + + /* Registers */ + +From d3493574e267c203836bfdcb9c58d8af46fc0da1 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Fri, 14 Dec 2012 16:20:46 -0500 +Subject: drm/radeon: restore modeset late in GPU reset path + +From: Jerome Glisse + +commit d3493574e267c203836bfdcb9c58d8af46fc0da1 upstream. + +Modeset path seems to conflict sometimes with the memory management +leading to kernel deadlock. This move modesetting reset after GPU +acceleration reset. + +Signed-off-by: Jerome Glisse +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_device.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1337,7 +1337,6 @@ retry: + } + + radeon_restore_bios_scratch_regs(rdev); +- drm_helper_resume_force_mode(rdev->ddev); + + if (!r) { + for (i = 0; i < RADEON_NUM_RINGS; ++i) { +@@ -1362,6 +1361,8 @@ retry: + } + } + ++ drm_helper_resume_force_mode(rdev->ddev); ++ + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (r) { + /* bad news, how to tell it to userspace ? */ +From 76903b96adbfbb38b049765add21e02e44c387a5 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Mon, 17 Dec 2012 10:29:06 -0500 +Subject: drm/radeon: don't leave fence blocked process on failed GPU reset + +From: Jerome Glisse + +commit 76903b96adbfbb38b049765add21e02e44c387a5 upstream. + +Force all fence to signal if GPU reset failed so no process get stuck +on waiting fence. + +Signed-off-by: Jerome Glisse +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon.h | 1 + + drivers/gpu/drm/radeon/radeon_device.c | 1 + + drivers/gpu/drm/radeon/radeon_fence.c | 19 +++++++++++++++++++ + 3 files changed, 21 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -220,6 +220,7 @@ struct radeon_fence { + int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); + int radeon_fence_driver_init(struct radeon_device *rdev); + void radeon_fence_driver_fini(struct radeon_device *rdev); ++void radeon_fence_driver_force_completion(struct radeon_device *rdev); + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); + void radeon_fence_process(struct radeon_device *rdev, int ring); + bool radeon_fence_signaled(struct radeon_fence *fence); +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1356,6 +1356,7 @@ retry: + } + } + } else { ++ radeon_fence_driver_force_completion(rdev); + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + kfree(ring_data[i]); + } +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -868,6 +868,25 @@ void radeon_fence_driver_fini(struct rad + mutex_unlock(&rdev->ring_lock); + } + ++/** ++ * radeon_fence_driver_force_completion - force all fence waiter to complete ++ * ++ * @rdev: radeon device pointer ++ * ++ * In case of GPU reset failure make sure no process keep waiting on fence ++ * that will never complete. ++ */ ++void radeon_fence_driver_force_completion(struct radeon_device *rdev) ++{ ++ int ring; ++ ++ for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { ++ if (!rdev->fence_drv[ring].initialized) ++ continue; ++ radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); ++ } ++} ++ + + /* + * Fence debugfs +From 5f8f635edd8ad5a6416bff4c5ff486500357f473 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Mon, 17 Dec 2012 11:04:32 -0500 +Subject: drm/radeon: avoid deadlock in pm path when waiting for fence + +From: Jerome Glisse + +commit 5f8f635edd8ad5a6416bff4c5ff486500357f473 upstream. + +radeon_fence_wait_empty_locked should not trigger GPU reset as no +place where it's call from would benefit from such thing and it +actually lead to a kernel deadlock in case the reset is triggered +from pm codepath. Instead force ring completion in place where it +makes sense or return early in others. + +Signed-off-by: Jerome Glisse +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon.h | 2 +- + drivers/gpu/drm/radeon/radeon_device.c | 13 +++++++++++-- + drivers/gpu/drm/radeon/radeon_fence.c | 30 ++++++++++++++---------------- + drivers/gpu/drm/radeon/radeon_pm.c | 15 ++++++++++++--- + 4 files changed, 38 insertions(+), 22 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -226,7 +226,7 @@ void radeon_fence_process(struct radeon_ + bool radeon_fence_signaled(struct radeon_fence *fence); + int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); + int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); +-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); ++int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); + int radeon_fence_wait_any(struct radeon_device *rdev, + struct radeon_fence **fences, + bool intr); +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1163,6 +1163,7 @@ int radeon_suspend_kms(struct drm_device + struct drm_crtc *crtc; + struct drm_connector *connector; + int i, r; ++ bool force_completion = false; + + if (dev == NULL || dev->dev_private == NULL) { + return -ENODEV; +@@ -1205,8 +1206,16 @@ int radeon_suspend_kms(struct drm_device + + mutex_lock(&rdev->ring_lock); + /* wait for gpu to finish processing current batch */ +- for (i = 0; i < RADEON_NUM_RINGS; i++) +- radeon_fence_wait_empty_locked(rdev, i); ++ for (i = 0; i < RADEON_NUM_RINGS; i++) { ++ r = radeon_fence_wait_empty_locked(rdev, i); ++ if (r) { ++ /* delay GPU reset to resume */ ++ force_completion = true; ++ } ++ } ++ if (force_completion) { ++ radeon_fence_driver_force_completion(rdev); ++ } + mutex_unlock(&rdev->ring_lock); + + radeon_save_bios_scratch_regs(rdev); +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct + * Returns 0 if the fences have passed, error for all other cases. + * Caller must hold ring lock. + */ +-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) ++int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) + { + uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; ++ int r; + +- while(1) { +- int r; +- r = radeon_fence_wait_seq(rdev, seq, ring, false, false); ++ r = radeon_fence_wait_seq(rdev, seq, ring, false, false); ++ if (r) { + if (r == -EDEADLK) { +- mutex_unlock(&rdev->ring_lock); +- r = radeon_gpu_reset(rdev); +- mutex_lock(&rdev->ring_lock); +- if (!r) +- continue; +- } +- if (r) { +- dev_err(rdev->dev, "error waiting for ring to become" +- " idle (%d)\n", r); ++ return -EDEADLK; + } +- return; ++ dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", ++ ring, r); + } ++ return 0; + } + + /** +@@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct rade + */ + void radeon_fence_driver_fini(struct radeon_device *rdev) + { +- int ring; ++ int ring, r; + + mutex_lock(&rdev->ring_lock); + for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { + if (!rdev->fence_drv[ring].initialized) + continue; +- radeon_fence_wait_empty_locked(rdev, ring); ++ r = radeon_fence_wait_empty_locked(rdev, ring); ++ if (r) { ++ /* no need to trigger GPU reset as we are unloading */ ++ radeon_fence_driver_force_completion(rdev); ++ } + wake_up_all(&rdev->fence_queue); + radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); + rdev->fence_drv[ring].initialized = false; +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -234,7 +234,7 @@ static void radeon_set_power_state(struc + + static void radeon_pm_set_clocks(struct radeon_device *rdev) + { +- int i; ++ int i, r; + + /* no need to take locks, etc. if nothing's going to change */ + if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && +@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct + /* wait for the rings to drain */ + for (i = 0; i < RADEON_NUM_RINGS; i++) { + struct radeon_ring *ring = &rdev->ring[i]; +- if (ring->ready) +- radeon_fence_wait_empty_locked(rdev, i); ++ if (!ring->ready) { ++ continue; ++ } ++ r = radeon_fence_wait_empty_locked(rdev, i); ++ if (r) { ++ /* needs a GPU reset dont reset here */ ++ mutex_unlock(&rdev->ring_lock); ++ up_write(&rdev->pm.mclk_lock); ++ mutex_unlock(&rdev->ddev->struct_mutex); ++ return; ++ } + } + + radeon_unmap_vram_bos(rdev); +From 668bbc81baf0f34df832d8aca5c7d5e19a493c68 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 20 Dec 2012 21:19:32 -0500 +Subject: drm/radeon: add WAIT_UNTIL to evergreen VM safe reg list + +From: Alex Deucher + +commit 668bbc81baf0f34df832d8aca5c7d5e19a493c68 upstream. + +It's used in a recent mesa commit: +http://cgit.freedesktop.org/mesa/mesa/commit/?id=24b1206ab2dcd506aaac3ef656aebc8bc20cd27a +and there may be some other cases in the future where it's required. + +Signed-off-by: Alex Deucher +Reviewed-by: Jerome Glisse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen_cs.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/radeon/evergreen_cs.c ++++ b/drivers/gpu/drm/radeon/evergreen_cs.c +@@ -2724,6 +2724,7 @@ static bool evergreen_vm_reg_valid(u32 r + + /* check config regs */ + switch (reg) { ++ case WAIT_UNTIL: + case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: +From cafa59b9011a7790be4ddd5979419259844a165d Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 20 Dec 2012 16:35:47 -0500 +Subject: drm/radeon: add connector table for Mac G4 Silver + +From: Alex Deucher + +commit cafa59b9011a7790be4ddd5979419259844a165d upstream. + +Apple cards do not provide data tables in the vbios +so we have to hard code the connector parameters +in the driver. + +Reported-by: Albrecht Dreß +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_combios.c | 51 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/radeon/radeon_mode.h | 3 + + 2 files changed, 53 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -1548,6 +1548,9 @@ bool radeon_get_legacy_connector_info_fr + of_machine_is_compatible("PowerBook6,7")) { + /* ibook */ + rdev->mode_info.connector_table = CT_IBOOK; ++ } else if (of_machine_is_compatible("PowerMac3,5")) { ++ /* PowerMac G4 Silver radeon 7500 */ ++ rdev->mode_info.connector_table = CT_MAC_G4_SILVER; + } else if (of_machine_is_compatible("PowerMac4,4")) { + /* emac */ + rdev->mode_info.connector_table = CT_EMAC; +@@ -2210,6 +2213,54 @@ bool radeon_get_legacy_connector_info_fr + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, ++ &hpd); ++ break; ++ case CT_MAC_G4_SILVER: ++ DRM_INFO("Connector Table: %d (mac g4 silver)\n", ++ rdev->mode_info.connector_table); ++ /* DVI-I - tv dac, int tmds */ ++ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); ++ hpd.hpd = RADEON_HPD_1; /* ??? */ ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_DFP1_SUPPORT, ++ 0), ++ ATOM_DEVICE_DFP1_SUPPORT); ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_CRT2_SUPPORT, ++ 2), ++ ATOM_DEVICE_CRT2_SUPPORT); ++ radeon_add_legacy_connector(dev, 0, ++ ATOM_DEVICE_DFP1_SUPPORT | ++ ATOM_DEVICE_CRT2_SUPPORT, ++ DRM_MODE_CONNECTOR_DVII, &ddc_i2c, ++ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, ++ &hpd); ++ /* VGA - primary dac */ ++ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); ++ hpd.hpd = RADEON_HPD_NONE; ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_CRT1_SUPPORT, ++ 1), ++ ATOM_DEVICE_CRT1_SUPPORT); ++ radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, ++ DRM_MODE_CONNECTOR_VGA, &ddc_i2c, ++ CONNECTOR_OBJECT_ID_VGA, ++ &hpd); ++ /* TV - TV DAC */ ++ ddc_i2c.valid = false; ++ hpd.hpd = RADEON_HPD_NONE; ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_TV1_SUPPORT, ++ 2), ++ ATOM_DEVICE_TV1_SUPPORT); ++ radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, ++ DRM_MODE_CONNECTOR_SVIDEO, ++ &ddc_i2c, ++ CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + default: +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -209,7 +209,8 @@ enum radeon_connector_table { + CT_RN50_POWER, + CT_MAC_X800, + CT_MAC_G5_9600, +- CT_SAM440EP ++ CT_SAM440EP, ++ CT_MAC_G4_SILVER + }; + + enum radeon_dvo_chip { +From 0a9069d34918659bc8a89e21e69e60b2b83291a3 Mon Sep 17 00:00:00 2001 +From: Niels Ole Salscheider +Date: Thu, 3 Jan 2013 19:09:28 +0100 +Subject: drm/radeon: Properly handle DDC probe for DP bridges + +From: Niels Ole Salscheider + +commit 0a9069d34918659bc8a89e21e69e60b2b83291a3 upstream. + +DDC information can be accessed using AUX CH + +Fixes failure to probe monitors on some systems with +DP bridge chips. + +agd5f: minor fixes + +Signed-off-by: Niels Ole Salscheider +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_connectors.c | 10 ++++++---- + drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++---- + drivers/gpu/drm/radeon/radeon_i2c.c | 10 ++++++++-- + drivers/gpu/drm/radeon/radeon_mode.h | 2 +- + 4 files changed, 24 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -741,7 +741,7 @@ radeon_vga_detect(struct drm_connector * + ret = connector_status_disconnected; + + if (radeon_connector->ddc_bus) +- dret = radeon_ddc_probe(radeon_connector); ++ dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { +@@ -947,7 +947,7 @@ radeon_dvi_detect(struct drm_connector * + return connector->status; + + if (radeon_connector->ddc_bus) +- dret = radeon_ddc_probe(radeon_connector); ++ dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { +@@ -1401,7 +1401,8 @@ radeon_dp_detect(struct drm_connector *c + if (encoder) { + /* setup ddc on the bridge */ + radeon_atom_ext_encoder_setup_ddc(encoder); +- if (radeon_ddc_probe(radeon_connector)) /* try DDC */ ++ /* bridge chips are always aux */ ++ if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ + ret = connector_status_connected; + else if (radeon_connector->dac_load_detect) { /* try load detection */ + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; +@@ -1419,7 +1420,8 @@ radeon_dp_detect(struct drm_connector *c + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + } else { +- if (radeon_ddc_probe(radeon_connector)) ++ /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ ++ if (radeon_ddc_probe(radeon_connector, false)) + ret = connector_status_connected; + } + } +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -695,10 +695,15 @@ int radeon_ddc_get_modes(struct radeon_c + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + +- if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || +- (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || +- (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != +- ENCODER_OBJECT_ID_NONE)) { ++ if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != ++ ENCODER_OBJECT_ID_NONE) { ++ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; ++ ++ if (dig->dp_i2c_bus) ++ radeon_connector->edid = drm_get_edid(&radeon_connector->base, ++ &dig->dp_i2c_bus->adapter); ++ } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || ++ (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || +--- a/drivers/gpu/drm/radeon/radeon_i2c.c ++++ b/drivers/gpu/drm/radeon/radeon_i2c.c +@@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struc + * radeon_ddc_probe + * + */ +-bool radeon_ddc_probe(struct radeon_connector *radeon_connector) ++bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) + { + u8 out = 0x0; + u8 buf[8]; +@@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_conn + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + +- ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); ++ if (use_aux) { ++ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; ++ ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); ++ } else { ++ ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); ++ } ++ + if (ret != 2) + /* Couldn't find an accessible DDC on this connector */ + return false; +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -559,7 +559,7 @@ extern void radeon_i2c_put_byte(struct r + u8 val); + extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); + extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); +-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); ++extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); + extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); + + extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); +From eda85d6ad490923152544fba0473798b6cc0edf6 Mon Sep 17 00:00:00 2001 +From: Aaro Koskinen +Date: Mon, 31 Dec 2012 03:34:59 +0200 +Subject: drm/nouveau: fix init with agpgart-uninorth + +From: Aaro Koskinen + +commit eda85d6ad490923152544fba0473798b6cc0edf6 upstream. + +Check that the AGP aperture can be mapped. This follows a similar change +done for Radeon (commit 365048ff, drm/radeon: AGP memory is only I/O if +the aperture can be mapped by the CPU.). + +The patch fixes the following error seen on G5 iMac: + + nouveau E[ DRM] failed to create kernel channel, -12 + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58806 +Reviewed-by: Michel Dänzer +Signed-off-by: Aaro Koskinen +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -1279,7 +1279,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo + if (drm->agp.stat == ENABLED) { + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = drm->agp.base; +- mem->bus.is_iomem = true; ++ mem->bus.is_iomem = !dev->agp->cant_use_aperture; + } + #endif + break; +From 13888d78c664a1f61d7b09d282f5916993827a40 Mon Sep 17 00:00:00 2001 +From: Paulo Zanoni +Date: Tue, 20 Nov 2012 13:27:41 -0200 +Subject: drm/i915: make the panel fitter work on pipes B and C on IVB + +From: Paulo Zanoni + +commit 13888d78c664a1f61d7b09d282f5916993827a40 upstream. + +I actually found this problem on Haswell, but then discovered Ivy +Bridge also has it by reading the spec. + +I don't have the hardware to test this. + +Signed-off-by: Paulo Zanoni +Reviewed-by: Damien Lespiau +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_reg.h | 2 ++ + drivers/gpu/drm/i915/intel_display.c | 6 +++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -3315,6 +3315,8 @@ + #define _PFA_CTL_1 0x68080 + #define _PFB_CTL_1 0x68880 + #define PF_ENABLE (1<<31) ++#define PF_PIPE_SEL_MASK_IVB (3<<29) ++#define PF_PIPE_SEL_IVB(pipe) ((pipe)<<29) + #define PF_FILTER_MASK (3<<23) + #define PF_FILTER_PROGRAMMED (0<<23) + #define PF_FILTER_MED_3x3 (1<<23) +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -3225,7 +3225,11 @@ static void ironlake_crtc_enable(struct + * as some pre-programmed values are broken, + * e.g. x201. + */ +- I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); ++ if (IS_IVYBRIDGE(dev)) ++ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | ++ PF_PIPE_SEL_IVB(pipe)); ++ else ++ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); + I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); + I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); + } +From 8fb74b9fb2b182d54beee592350d9ea1f325917a Mon Sep 17 00:00:00 2001 +From: Mel Gorman +Date: Fri, 11 Jan 2013 14:32:16 -0800 +Subject: mm: compaction: partially revert capture of suitable high-order page + +From: Mel Gorman + +commit 8fb74b9fb2b182d54beee592350d9ea1f325917a upstream. + +Eric Wong reported on 3.7 and 3.8-rc2 that ppoll() got stuck when +waiting for POLLIN on a local TCP socket. It was easier to trigger if +there was disk IO and dirty pages at the same time and he bisected it to +commit 1fb3f8ca0e92 ("mm: compaction: capture a suitable high-order page +immediately when it is made available"). + +The intention of that patch was to improve high-order allocations under +memory pressure after changes made to reclaim in 3.6 drastically hurt +THP allocations but the approach was flawed. For Eric, the problem was +that page->pfmemalloc was not being cleared for captured pages leading +to a poor interaction with swap-over-NFS support causing the packets to +be dropped. However, I identified a few more problems with the patch +including the fact that it can increase contention on zone->lock in some +cases which could result in async direct compaction being aborted early. + +In retrospect the capture patch took the wrong approach. What it should +have done is mark the pageblock being migrated as MIGRATE_ISOLATE if it +was allocating for THP and avoided races that way. While the patch was +showing to improve allocation success rates at the time, the benefit is +marginal given the relative complexity and it should be revisited from +scratch in the context of the other reclaim-related changes that have +taken place since the patch was first written and tested. This patch +partially reverts commit 1fb3f8ca0e92 ("mm: compaction: capture a +suitable high-order page immediately when it is made available"). + +Reported-and-tested-by: Eric Wong +Tested-by: Eric Dumazet +Signed-off-by: Mel Gorman +Cc: David Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/compaction.h | 4 - + include/linux/mm.h | 1 + mm/compaction.c | 92 ++++++--------------------------------------- + mm/internal.h | 1 + mm/page_alloc.c | 35 +++-------------- + 5 files changed, 23 insertions(+), 110 deletions(-) + +--- a/include/linux/compaction.h ++++ b/include/linux/compaction.h +@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct + extern int fragmentation_index(struct zone *zone, unsigned int order); + extern unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *mask, +- bool sync, bool *contended, struct page **page); ++ bool sync, bool *contended); + extern int compact_pgdat(pg_data_t *pgdat, int order); + extern void reset_isolation_suitable(pg_data_t *pgdat); + extern unsigned long compaction_suitable(struct zone *zone, int order); +@@ -75,7 +75,7 @@ static inline bool compaction_restarting + #else + static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended, struct page **page) ++ bool sync, bool *contended) + { + return COMPACT_CONTINUE; + } +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pa + + void split_page(struct page *page, unsigned int order); + int split_free_page(struct page *page); +-int capture_free_page(struct page *page, int alloc_order, int migratetype); + + /* + * Compound pages have a destructor function. Provide a +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -214,60 +214,6 @@ static bool suitable_migration_target(st + return false; + } + +-static void compact_capture_page(struct compact_control *cc) +-{ +- unsigned long flags; +- int mtype, mtype_low, mtype_high; +- +- if (!cc->page || *cc->page) +- return; +- +- /* +- * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP +- * regardless of the migratetype of the freelist is is captured from. +- * This is fine because the order for a high-order MIGRATE_MOVABLE +- * allocation is typically at least a pageblock size and overall +- * fragmentation is not impaired. Other allocation types must +- * capture pages from their own migratelist because otherwise they +- * could pollute other pageblocks like MIGRATE_MOVABLE with +- * difficult to move pages and making fragmentation worse overall. +- */ +- if (cc->migratetype == MIGRATE_MOVABLE) { +- mtype_low = 0; +- mtype_high = MIGRATE_PCPTYPES; +- } else { +- mtype_low = cc->migratetype; +- mtype_high = cc->migratetype + 1; +- } +- +- /* Speculatively examine the free lists without zone lock */ +- for (mtype = mtype_low; mtype < mtype_high; mtype++) { +- int order; +- for (order = cc->order; order < MAX_ORDER; order++) { +- struct page *page; +- struct free_area *area; +- area = &(cc->zone->free_area[order]); +- if (list_empty(&area->free_list[mtype])) +- continue; +- +- /* Take the lock and attempt capture of the page */ +- if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc)) +- return; +- if (!list_empty(&area->free_list[mtype])) { +- page = list_entry(area->free_list[mtype].next, +- struct page, lru); +- if (capture_free_page(page, cc->order, mtype)) { +- spin_unlock_irqrestore(&cc->zone->lock, +- flags); +- *cc->page = page; +- return; +- } +- } +- spin_unlock_irqrestore(&cc->zone->lock, flags); +- } +- } +-} +- + /* + * Isolate free pages onto a private freelist. Caller must hold zone->lock. + * If @strict is true, will abort returning 0 on any invalid PFNs or non-free +@@ -831,6 +777,7 @@ static isolate_migrate_t isolate_migrate + static int compact_finished(struct zone *zone, + struct compact_control *cc) + { ++ unsigned int order; + unsigned long watermark; + + if (fatal_signal_pending(current)) +@@ -865,22 +812,16 @@ static int compact_finished(struct zone + return COMPACT_CONTINUE; + + /* Direct compactor: Is a suitable page free? */ +- if (cc->page) { +- /* Was a suitable page captured? */ +- if (*cc->page) ++ for (order = cc->order; order < MAX_ORDER; order++) { ++ struct free_area *area = &zone->free_area[order]; ++ ++ /* Job done if page is free of the right migratetype */ ++ if (!list_empty(&area->free_list[cc->migratetype])) ++ return COMPACT_PARTIAL; ++ ++ /* Job done if allocation would set block type */ ++ if (cc->order >= pageblock_order && area->nr_free) + return COMPACT_PARTIAL; +- } else { +- unsigned int order; +- for (order = cc->order; order < MAX_ORDER; order++) { +- struct free_area *area = &zone->free_area[cc->order]; +- /* Job done if page is free of the right migratetype */ +- if (!list_empty(&area->free_list[cc->migratetype])) +- return COMPACT_PARTIAL; +- +- /* Job done if allocation would set block type */ +- if (cc->order >= pageblock_order && area->nr_free) +- return COMPACT_PARTIAL; +- } + } + + return COMPACT_CONTINUE; +@@ -1018,9 +959,6 @@ static int compact_zone(struct zone *zon + goto out; + } + } +- +- /* Capture a page now if it is a suitable size */ +- compact_capture_page(cc); + } + + out: +@@ -1033,8 +971,7 @@ out: + + static unsigned long compact_zone_order(struct zone *zone, + int order, gfp_t gfp_mask, +- bool sync, bool *contended, +- struct page **page) ++ bool sync, bool *contended) + { + unsigned long ret; + struct compact_control cc = { +@@ -1044,7 +981,6 @@ static unsigned long compact_zone_order( + .migratetype = allocflags_to_migratetype(gfp_mask), + .zone = zone, + .sync = sync, +- .page = page, + }; + INIT_LIST_HEAD(&cc.freepages); + INIT_LIST_HEAD(&cc.migratepages); +@@ -1074,7 +1010,7 @@ int sysctl_extfrag_threshold = 500; + */ + unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended, struct page **page) ++ bool sync, bool *contended) + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + int may_enter_fs = gfp_mask & __GFP_FS; +@@ -1100,7 +1036,7 @@ unsigned long try_to_compact_pages(struc + int status; + + status = compact_zone_order(zone, order, gfp_mask, sync, +- contended, page); ++ contended); + rc = max(status, rc); + + /* If a normal allocation would succeed, stop compacting */ +@@ -1156,7 +1092,6 @@ int compact_pgdat(pg_data_t *pgdat, int + struct compact_control cc = { + .order = order, + .sync = false, +- .page = NULL, + }; + + return __compact_pgdat(pgdat, &cc); +@@ -1167,7 +1102,6 @@ static int compact_node(int nid) + struct compact_control cc = { + .order = -1, + .sync = true, +- .page = NULL, + }; + + return __compact_pgdat(NODE_DATA(nid), &cc); +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -130,7 +130,6 @@ struct compact_control { + int migratetype; /* MOVABLE, RECLAIMABLE etc */ + struct zone *zone; + bool contended; /* True if a lock was contended */ +- struct page **page; /* Page captured of requested size */ + }; + + unsigned long +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1376,14 +1376,8 @@ void split_page(struct page *page, unsig + set_page_refcounted(page + i); + } + +-/* +- * Similar to the split_page family of functions except that the page +- * required at the given order and being isolated now to prevent races +- * with parallel allocators +- */ +-int capture_free_page(struct page *page, int alloc_order, int migratetype) ++static int __isolate_free_page(struct page *page, unsigned int order) + { +- unsigned int order; + unsigned long watermark; + struct zone *zone; + int mt; +@@ -1391,7 +1385,6 @@ int capture_free_page(struct page *page, + BUG_ON(!PageBuddy(page)); + + zone = page_zone(page); +- order = page_order(page); + + /* Obey watermarks as if the page was being allocated */ + watermark = low_wmark_pages(zone) + (1 << order); +@@ -1405,13 +1398,9 @@ int capture_free_page(struct page *page, + + mt = get_pageblock_migratetype(page); + if (unlikely(mt != MIGRATE_ISOLATE)) +- __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); +- +- if (alloc_order != order) +- expand(zone, page, alloc_order, order, +- &zone->free_area[order], migratetype); ++ __mod_zone_freepage_state(zone, -(1UL << order), mt); + +- /* Set the pageblock if the captured page is at least a pageblock */ ++ /* Set the pageblock if the isolated page is at least a pageblock */ + if (order >= pageblock_order - 1) { + struct page *endpage = page + (1 << order) - 1; + for (; page < endpage; page += pageblock_nr_pages) { +@@ -1422,7 +1411,7 @@ int capture_free_page(struct page *page, + } + } + +- return 1UL << alloc_order; ++ return 1UL << order; + } + + /* +@@ -1440,10 +1429,9 @@ int split_free_page(struct page *page) + unsigned int order; + int nr_pages; + +- BUG_ON(!PageBuddy(page)); + order = page_order(page); + +- nr_pages = capture_free_page(page, order, 0); ++ nr_pages = __isolate_free_page(page, order); + if (!nr_pages) + return 0; + +@@ -2148,8 +2136,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m + bool *contended_compaction, bool *deferred_compaction, + unsigned long *did_some_progress) + { +- struct page *page = NULL; +- + if (!order) + return NULL; + +@@ -2161,16 +2147,12 @@ __alloc_pages_direct_compact(gfp_t gfp_m + current->flags |= PF_MEMALLOC; + *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, + nodemask, sync_migration, +- contended_compaction, &page); ++ contended_compaction); + current->flags &= ~PF_MEMALLOC; + +- /* If compaction captured a page, prep and use it */ +- if (page) { +- prep_new_page(page, order, gfp_mask); +- goto got_page; +- } +- + if (*did_some_progress != COMPACT_SKIPPED) { ++ struct page *page; ++ + /* Page migration frees to the PCP lists but we want merging */ + drain_pages(get_cpu()); + put_cpu(); +@@ -2180,7 +2162,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m + alloc_flags & ~ALLOC_NO_WATERMARKS, + preferred_zone, migratetype); + if (page) { +-got_page: + preferred_zone->compact_blockskip_flush = false; + preferred_zone->compact_considered = 0; + preferred_zone->compact_defer_shift = 0; +From e7d841ca03b7ab668620045cd7b428eda9f41601 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 3 Dec 2012 11:36:30 +0000 +Subject: drm/i915: Close race between processing unpin task and queueing the flip + +From: Chris Wilson + +commit e7d841ca03b7ab668620045cd7b428eda9f41601 upstream. + +Before queuing the flip but crucially after attaching the unpin-work to +the crtc, we continue to setup the unpin-work. However, should the +hardware fire early, we see the connected unpin-work and queue the task. +The task then promptly runs and unpins the fb before we finish taking +the required references or even pinning it... Havoc. + +To close the race, we use the flip-pending atomic to indicate when the +flip is finally setup and enqueued. So during the flip-done processing, +we can check more accurately whether the flip was expected. + +v2: Add the appropriate mb() to ensure that the writes to the page-flip +worker are complete prior to marking it active and emitting the MI_FLIP. +On the read side, the mb should be enforced by the spinlocks. + +Signed-off-by: Chris Wilson +[danvet: Review the barriers a bit, we need a write barrier both +before and after updating ->pending. Similarly we need a read barrier +in the interrupt handler both before and after reading ->pending. With +well-ordered irqs only one barrier in each place should be required, +but since this patch explicitly sets out to combat spurious interrupts +with is staged activation of the unpin work we need to go full-bore on +the barriers, too. Discussed with Chris Wilson on irc and changes +acked by him.] +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- + drivers/gpu/drm/i915/i915_irq.c | 4 ++- + drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++++++++++++++------- + drivers/gpu/drm/i915/intel_drv.h | 5 +++- + 4 files changed, 41 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_debugfs.c ++++ b/drivers/gpu/drm/i915/i915_debugfs.c +@@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct + seq_printf(m, "No flip due on pipe %c (plane %c)\n", + pipe, plane); + } else { +- if (!work->pending) { ++ if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { + seq_printf(m, "Flip queued on pipe %c (plane %c)\n", + pipe, plane); + } else { +@@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct + seq_printf(m, "Stall check enabled, "); + else + seq_printf(m, "Stall check waiting for page flip ioctl, "); +- seq_printf(m, "%d prepares\n", work->pending); ++ seq_printf(m, "%d prepares\n", atomic_read(&work->pending)); + + if (work->old_fb_obj) { + struct drm_i915_gem_object *obj = work->old_fb_obj; +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -1464,7 +1464,9 @@ static void i915_pageflip_stall_check(st + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; + +- if (work == NULL || work->pending || !work->enable_stall_check) { ++ if (work == NULL || ++ atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE || ++ !work->enable_stall_check) { + /* Either the pending flip IRQ arrived, or we're too early. Don't check */ + spin_unlock_irqrestore(&dev->event_lock, flags); + return; +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6215,11 +6215,18 @@ static void do_intel_finish_page_flip(st + + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; +- if (work == NULL || !work->pending) { ++ ++ /* Ensure we don't miss a work->pending update ... */ ++ smp_rmb(); ++ ++ if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { + spin_unlock_irqrestore(&dev->event_lock, flags); + return; + } + ++ /* and that the unpin work is consistent wrt ->pending. */ ++ smp_rmb(); ++ + intel_crtc->unpin_work = NULL; + + if (work->event) { +@@ -6272,16 +6279,25 @@ void intel_prepare_page_flip(struct drm_ + to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); + unsigned long flags; + ++ /* NB: An MMIO update of the plane base pointer will also ++ * generate a page-flip completion irq, i.e. every modeset ++ * is also accompanied by a spurious intel_prepare_page_flip(). ++ */ + spin_lock_irqsave(&dev->event_lock, flags); +- if (intel_crtc->unpin_work) { +- if ((++intel_crtc->unpin_work->pending) > 1) +- DRM_ERROR("Prepared flip multiple times\n"); +- } else { +- DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); +- } ++ if (intel_crtc->unpin_work) ++ atomic_inc_not_zero(&intel_crtc->unpin_work->pending); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + ++inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) ++{ ++ /* Ensure that the work item is consistent when activating it ... */ ++ smp_wmb(); ++ atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING); ++ /* and that it is marked active as soon as the irq could fire. */ ++ smp_wmb(); ++} ++ + static int intel_gen2_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, +@@ -6315,6 +6331,8 @@ static int intel_gen2_queue_flip(struct + intel_ring_emit(ring, fb->pitches[0]); + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, 0); /* aux display base address, unused */ ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6355,6 +6373,7 @@ static int intel_gen3_queue_flip(struct + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, MI_NOOP); + ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6401,6 +6420,8 @@ static int intel_gen4_queue_flip(struct + pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + intel_ring_emit(ring, pf | pipesrc); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6443,6 +6464,8 @@ static int intel_gen6_queue_flip(struct + pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + intel_ring_emit(ring, pf | pipesrc); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6497,6 +6520,8 @@ static int intel_gen7_queue_flip(struct + intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, (MI_NOOP)); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -384,7 +384,10 @@ struct intel_unpin_work { + struct drm_i915_gem_object *old_fb_obj; + struct drm_i915_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; +- int pending; ++ atomic_t pending; ++#define INTEL_FLIP_INACTIVE 0 ++#define INTEL_FLIP_PENDING 1 ++#define INTEL_FLIP_COMPLETE 2 + bool enable_stall_check; + }; + +From b4a98e57fc27854b5938fc8b08b68e5e68b91e1f Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 1 Nov 2012 09:26:26 +0000 +Subject: drm/i915: Flush outstanding unpin tasks before pageflipping + +From: Chris Wilson + +commit b4a98e57fc27854b5938fc8b08b68e5e68b91e1f upstream. + +If we accumulate unpin tasks because we are pageflipping faster than the +system can schedule its workers, we can effectively create a +pin-leak. The solution taken here is to limit the number of unpin tasks +we have per-crtc and to flush those outstanding tasks if we accumulate +too many. This should prevent any jitter in the normal case, and also +prevent the hang if we should run too fast. + +Note: It is important that we switch from the system workqueue to our +own dev_priv->wq since all work items on that queue are guaranteed to +only need the dev->struct_mutex and not any modeset resources. For +otherwise if we have a work item ahead in the queue which needs the +modeset lock (like the output detect work used by both polling or +hpd), this work and so the unpin work will never execute since the +pageflip code already holds that lock. Unfortunately there's no +lockdep support for this scenario in the workqueue code. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46991 +Reported-and-tested-by: Tvrtko Ursulin +Signed-off-by: Chris Wilson +[danvet: Added note about workqueu deadlock.] +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56337 +Signed-off-by: Daniel Vetter +Tested-by: Daniel Gnoutcheff +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++------ + drivers/gpu/drm/i915/intel_drv.h | 4 +++- + 2 files changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6187,14 +6187,19 @@ static void intel_unpin_work_fn(struct w + { + struct intel_unpin_work *work = + container_of(__work, struct intel_unpin_work, work); ++ struct drm_device *dev = work->crtc->dev; + +- mutex_lock(&work->dev->struct_mutex); ++ mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(work->old_fb_obj); + drm_gem_object_unreference(&work->pending_flip_obj->base); + drm_gem_object_unreference(&work->old_fb_obj->base); + +- intel_update_fbc(work->dev); +- mutex_unlock(&work->dev->struct_mutex); ++ intel_update_fbc(dev); ++ mutex_unlock(&dev->struct_mutex); ++ ++ BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0); ++ atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count); ++ + kfree(work); + } + +@@ -6249,9 +6254,9 @@ static void do_intel_finish_page_flip(st + + atomic_clear_mask(1 << intel_crtc->plane, + &obj->pending_flip.counter); +- + wake_up(&dev_priv->pending_flip_queue); +- schedule_work(&work->work); ++ ++ queue_work(dev_priv->wq, &work->work); + + trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); + } +@@ -6570,7 +6575,7 @@ static int intel_crtc_page_flip(struct d + return -ENOMEM; + + work->event = event; +- work->dev = crtc->dev; ++ work->crtc = crtc; + intel_fb = to_intel_framebuffer(crtc->fb); + work->old_fb_obj = intel_fb->obj; + INIT_WORK(&work->work, intel_unpin_work_fn); +@@ -6595,6 +6600,9 @@ static int intel_crtc_page_flip(struct d + intel_fb = to_intel_framebuffer(fb); + obj = intel_fb->obj; + ++ if (atomic_read(&intel_crtc->unpin_work_count) >= 2) ++ flush_workqueue(dev_priv->wq); ++ + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto cleanup; +@@ -6613,6 +6621,7 @@ static int intel_crtc_page_flip(struct d + * the flip occurs and the object is no longer visible. + */ + atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); ++ atomic_inc(&intel_crtc->unpin_work_count); + + ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); + if (ret) +@@ -6627,6 +6636,7 @@ static int intel_crtc_page_flip(struct d + return 0; + + cleanup_pending: ++ atomic_dec(&intel_crtc->unpin_work_count); + atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); + drm_gem_object_unreference(&work->old_fb_obj->base); + drm_gem_object_unreference(&obj->base); +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -198,6 +198,8 @@ struct intel_crtc { + struct intel_unpin_work *unpin_work; + int fdi_lanes; + ++ atomic_t unpin_work_count; ++ + /* Display surface base address adjustement for pageflips. Note that on + * gen4+ this only adjusts up to a tile, offsets within a tile are + * handled in the hw itself (with the TILEOFF register). */ +@@ -380,7 +382,7 @@ intel_get_crtc_for_plane(struct drm_devi + + struct intel_unpin_work { + struct work_struct work; +- struct drm_device *dev; ++ struct drm_crtc *crtc; + struct drm_i915_gem_object *old_fb_obj; + struct drm_i915_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; +From b0a2658acb5bf9ca86b4aab011b7106de3af0add Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Tue, 18 Dec 2012 09:37:54 +0100 +Subject: drm/i915: don't disable disconnected outputs + +From: Daniel Vetter + +commit b0a2658acb5bf9ca86b4aab011b7106de3af0add upstream. + +This piece of neat lore has been ported painstakingly and bug-for-bug +compatible from the old crtc helper code. + +Imo it's utter nonsense. + +If you disconnected a cable and before you reconnect it, userspace (or +the kernel) does an set_crtc call, this will result in that connector +getting disabled. Which will result in a nice black screen when +plugging in the cable again. + +There's absolutely no reason the kernel does such policy enforcements +- if userspace tries to set up a mode on something disconnected we +might fail loudly (since the dp link training fails), but silently +adjusting the output configuration behind userspace's back is a recipe +for disaster. Specifically I think that this could explain some of our +MI_WAIT hangs around suspend, where userspace issues a scanline wait +on a disable pipe. This mechanisims here could explain how that pipe +got disabled without userspace noticing. + +Note that this fixes a NULL deref at BIOS takeover when the firmware +sets up a disconnected output in a clone configuration with a +connected output on the 2nd pipe: When doing the full modeset we don't +have a mode for the 2nd pipe and OOPS. On the first pipe this doesn't +matter, since at boot-up the fbdev helpers will set up the choosen +configuration on that on first. Since this is now the umptenth bug +around handling this imo brain-dead semantics correctly, I think it's +time to kill it and see whether there's any userspace out there which +relies on this. + +It also nicely demonstrates that we have a tiny window where DP +hotplug can still kill the driver. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58396 +Tested-by: Peter Ujfalusi +Reviewed-by: Rodrigo Vivi +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -7298,10 +7298,6 @@ intel_modeset_stage_output_state(struct + DRM_DEBUG_KMS("encoder changed, full mode switch\n"); + config->mode_changed = true; + } +- +- /* Disable all disconnected encoders. */ +- if (connector->base.status == connector_status_disconnected) +- connector->new_encoder = NULL; + } + /* connector->new_encoder is now updated for all connectors. */ + +From 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 20 Dec 2012 10:51:09 +1000 +Subject: drm/i915: fix flags in dma buf exporting + +From: Dave Airlie + +commit 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 upstream. + +As pointed out by Seung-Woo Kim this should have been +passing flags like nouveau/radeon have. + +Signed-off-by: Dave Airlie +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c ++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(st + { + struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); + +- return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600); ++ return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags); + } + + static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +From be8a42ae60addd8b6092535c11b42d099d6470ec Mon Sep 17 00:00:00 2001 +From: Seung-Woo Kim +Date: Thu, 27 Sep 2012 15:30:06 +0900 +Subject: drm/prime: drop reference on imported dma-buf come from gem + +From: Seung-Woo Kim + +commit be8a42ae60addd8b6092535c11b42d099d6470ec upstream. + +Increasing ref counts of both dma-buf and gem for imported dma-buf come from gem +makes memory leak. release function of dma-buf cannot be called because f_count +of dma-buf increased by importing gem and gem ref count cannot be decrease +because of exported dma-buf. + +So I add dma_buf_put() for imported gem come from its own gem into each drivers +having prime_import and prime_export capabilities. With this, only gem ref +count is increased if importing gem exported from gem of same driver. + +Signed-off-by: Seung-Woo Kim +Signed-off-by: Kyungmin.park +Cc: Inki Dae +Cc: Daniel Vetter +Cc: Rob Clark +Cc: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 5 +++++ + drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 +++++ + drivers/gpu/drm/nouveau/nouveau_prime.c | 1 + + drivers/gpu/drm/radeon/radeon_prime.c | 1 + + drivers/staging/omapdrm/omap_gem_dmabuf.c | 5 +++++ + 5 files changed, 17 insertions(+) + +--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +@@ -210,7 +210,12 @@ struct drm_gem_object *exynos_dmabuf_pri + + /* is it from our device? */ + if (obj->dev == drm_dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(obj); ++ dma_buf_put(dma_buf); + return obj; + } + } +--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c ++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_im + obj = dma_buf->priv; + /* is it from our device? */ + if (obj->base.dev == dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(&obj->base); ++ dma_buf_put(dma_buf); + return &obj->base; + } + } +--- a/drivers/gpu/drm/nouveau/nouveau_prime.c ++++ b/drivers/gpu/drm/nouveau/nouveau_prime.c +@@ -197,6 +197,7 @@ struct drm_gem_object *nouveau_gem_prime + if (nvbo->gem) { + if (nvbo->gem->dev == dev) { + drm_gem_object_reference(nvbo->gem); ++ dma_buf_put(dma_buf); + return nvbo->gem; + } + } +--- a/drivers/gpu/drm/radeon/radeon_prime.c ++++ b/drivers/gpu/drm/radeon/radeon_prime.c +@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_ + bo = dma_buf->priv; + if (bo->gem_base.dev == dev) { + drm_gem_object_reference(&bo->gem_base); ++ dma_buf_put(dma_buf); + return &bo->gem_base; + } + } +--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c ++++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c +@@ -207,7 +207,12 @@ struct drm_gem_object * omap_gem_prime_i + obj = buffer->priv; + /* is it from our device? */ + if (obj->dev == dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(obj); ++ dma_buf_put(buffer); + return obj; + } + } +From 901593f2bf221659a605bdc1dcb11376ea934163 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 19 Dec 2012 16:51:06 +0000 +Subject: drm: Only evict the blocks required to create the requested hole + +From: Chris Wilson + +commit 901593f2bf221659a605bdc1dcb11376ea934163 upstream. + +Avoid clobbering adjacent blocks if they happen to expire earlier and +amalgamate together to form the requested hole. + +In passing this fixes a regression from +commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c +Author: Daniel Vetter +Date: Fri Feb 18 17:59:12 2011 +0100 + + drm: mm: track free areas implicitly + +which swaps the end address for size (with a potential overflow) and +effectively causes the eviction code to clobber almost all earlier +buffers above the evictee. + +v2: Check the original hole not the adjusted as the coloring may confuse +us when later searching for the overlapping nodes. Also make sure that +we do apply the range restriction and color adjustment in the same +order for both scanning, searching and insertion. + +v3: Send the version that was actually tested. + +Note that this seems to be ducttape of decent quality ot paper over +some of our unbind related gpu hangs reported since 3.7. It is not +fully effective though, and certainly doesn't fix the underlying bug. + +Signed-off-by: Chris Wilson +Cc: Daniel Vetter +[danvet: Added note plus bugzilla link and tested-by.] +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 +Tested-by: Norbert Preining +Acked-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_mm.c | 45 +++++++++++++++++---------------------------- + include/drm/drm_mm.h | 2 +- + 2 files changed, 18 insertions(+), 29 deletions(-) + +--- a/drivers/gpu/drm/drm_mm.c ++++ b/drivers/gpu/drm/drm_mm.c +@@ -213,11 +213,13 @@ static void drm_mm_insert_helper_range(s + + BUG_ON(!hole_node->hole_follows || node->allocated); + +- if (mm->color_adjust) +- mm->color_adjust(hole_node, color, &adj_start, &adj_end); +- + if (adj_start < start) + adj_start = start; ++ if (adj_end > end) ++ adj_end = end; ++ ++ if (mm->color_adjust) ++ mm->color_adjust(hole_node, color, &adj_start, &adj_end); + + if (alignment) { + unsigned tmp = adj_start % alignment; +@@ -489,7 +491,7 @@ void drm_mm_init_scan(struct drm_mm *mm, + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; +- mm->scan_hit_size = 0; ++ mm->scan_hit_end = 0; + mm->scan_check_range = 0; + mm->prev_scanned_node = NULL; + } +@@ -516,7 +518,7 @@ void drm_mm_init_scan_with_range(struct + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; +- mm->scan_hit_size = 0; ++ mm->scan_hit_end = 0; + mm->scan_start = start; + mm->scan_end = end; + mm->scan_check_range = 1; +@@ -535,8 +537,7 @@ int drm_mm_scan_add_block(struct drm_mm_ + struct drm_mm *mm = node->mm; + struct drm_mm_node *prev_node; + unsigned long hole_start, hole_end; +- unsigned long adj_start; +- unsigned long adj_end; ++ unsigned long adj_start, adj_end; + + mm->scanned_blocks++; + +@@ -553,14 +554,8 @@ int drm_mm_scan_add_block(struct drm_mm_ + node->node_list.next = &mm->prev_scanned_node->node_list; + mm->prev_scanned_node = node; + +- hole_start = drm_mm_hole_node_start(prev_node); +- hole_end = drm_mm_hole_node_end(prev_node); +- +- adj_start = hole_start; +- adj_end = hole_end; +- +- if (mm->color_adjust) +- mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); ++ adj_start = hole_start = drm_mm_hole_node_start(prev_node); ++ adj_end = hole_end = drm_mm_hole_node_end(prev_node); + + if (mm->scan_check_range) { + if (adj_start < mm->scan_start) +@@ -569,11 +564,14 @@ int drm_mm_scan_add_block(struct drm_mm_ + adj_end = mm->scan_end; + } + ++ if (mm->color_adjust) ++ mm->color_adjust(prev_node, mm->scan_color, ++ &adj_start, &adj_end); ++ + if (check_free_hole(adj_start, adj_end, + mm->scan_size, mm->scan_alignment)) { + mm->scan_hit_start = hole_start; +- mm->scan_hit_size = hole_end; +- ++ mm->scan_hit_end = hole_end; + return 1; + } + +@@ -609,19 +607,10 @@ int drm_mm_scan_remove_block(struct drm_ + node_list); + + prev_node->hole_follows = node->scanned_preceeds_hole; +- INIT_LIST_HEAD(&node->node_list); + list_add(&node->node_list, &prev_node->node_list); + +- /* Only need to check for containement because start&size for the +- * complete resulting free block (not just the desired part) is +- * stored. */ +- if (node->start >= mm->scan_hit_start && +- node->start + node->size +- <= mm->scan_hit_start + mm->scan_hit_size) { +- return 1; +- } +- +- return 0; ++ return (drm_mm_hole_node_end(node) > mm->scan_hit_start && ++ node->start < mm->scan_hit_end); + } + EXPORT_SYMBOL(drm_mm_scan_remove_block); + +--- a/include/drm/drm_mm.h ++++ b/include/drm/drm_mm.h +@@ -70,7 +70,7 @@ struct drm_mm { + unsigned long scan_color; + unsigned long scan_size; + unsigned long scan_hit_start; +- unsigned scan_hit_size; ++ unsigned long scan_hit_end; + unsigned scanned_blocks; + unsigned long scan_start; + unsigned long scan_end; +From 93be8788e648817d62fda33e2998eb6ca6ebf3a3 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 2 Jan 2013 10:31:22 +0000 +Subject: drm/i915; Only increment the user-pin-count after successfully pinning the bo + +From: Chris Wilson + +commit 93be8788e648817d62fda33e2998eb6ca6ebf3a3 upstream. + +As along the error path we do not correct the user pin-count for the +failure, we may end up with userspace believing that it has a pinned +object at offset 0 (when interrupted by a signal for example). + +Signed-off-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -3511,14 +3511,15 @@ i915_gem_pin_ioctl(struct drm_device *de + goto out; + } + +- obj->user_pin_count++; +- obj->pin_filp = file; +- if (obj->user_pin_count == 1) { ++ if (obj->user_pin_count == 0) { + ret = i915_gem_object_pin(obj, args->alignment, true, false); + if (ret) + goto out; + } + ++ obj->user_pin_count++; ++ obj->pin_filp = file; ++ + /* XXX - flush the CPU caches for pinned objects + * as the X server doesn't manage domains yet + */ +From 93927ca52a55c23e0a6a305e7e9082e8411ac9fa Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Thu, 10 Jan 2013 18:03:00 +0100 +Subject: drm/i915: Revert shrinker changes from "Track unbound pages" + +From: Daniel Vetter + +commit 93927ca52a55c23e0a6a305e7e9082e8411ac9fa upstream. + +This partially reverts + +commit 6c085a728cf000ac1865d66f8c9b52935558b328 +Author: Chris Wilson +Date: Mon Aug 20 11:40:46 2012 +0200 + + drm/i915: Track unbound pages + +Closer inspection of that patch revealed a bunch of unrelated changes +in the shrinker: +- The shrinker count is now in pages instead of objects. +- For counting the shrinkable objects the old code only looked at the + inactive list, the new code looks at all bounds objects (including + pinned ones). That is obviously in addition to the new unbound list. +- The shrinker cound is no longer scaled with + sysctl_vfs_cache_pressure. Note though that with the default tuning + value of vfs_cache_pressue = 100 this doesn't affect the shrinker + behaviour. +- When actually shrinking objects, the old code first dropped + purgeable objects, then normal (inactive) objects. Only then did it, + in a last-ditch effort idle the gpu and evict everything. The new + code omits the intermediate step of evicting normal inactive + objects. + +Safe for the first change, which seems benign, and the shrinker count +scaling, which is a bit a different story, the endresult of all these +changes is that the shrinker is _much_ more likely to fall back to the +last-ditch resort of idling the gpu and evicting everything. The old +code could only do that if something else evicted lots of objects +meanwhile (since without any other changes the nr_to_scan will be +smaller than the object count). + +Reverting the vfs_cache_pressure behaviour itself is a bit bogus: Only +dentry/inode object caches should scale their shrinker counts with +vfs_cache_pressure. Originally I've had that change reverted, too. But +Chris Wilson insisted that it's too bogus and shouldn't again see the +light of day. + +Hence revert all these other changes and restore the old shrinker +behaviour, with the minor adjustment that we now first scan the +unbound list, then the inactive list for each object category +(purgeable or normal). + +A similar patch has been tested by a few people affected by the gen4/5 +hangs which started to appear in 3.7, which some people bisected to +the "drm/i915: Track unbound pages" commit. But just disabling the +unbound logic alone didn't change things at all. + +Note that this patch doesn't fix the referenced bugs, it only hides +the underlying bug(s) well enough to restore pre-3.7 behaviour. The +key to achieve that is to massively reduce the likelyhood of going +into a full gpu stall and evicting everything. + +v2: Reword commit message a bit, taking Chris Wilson's comment into +account. + +v3: On Chris Wilson's insistency, do not reinstate the rather bogus +vfs_cache_pressure change. + +Tested-by: Greg KH +Tested-by: Dave Kleikamp +References: https://bugs.freedesktop.org/show_bug.cgi?id=55984 +References: https://bugs.freedesktop.org/show_bug.cgi?id=57122 +References: https://bugs.freedesktop.org/show_bug.cgi?id=56916 +References: https://bugs.freedesktop.org/show_bug.cgi?id=57136 +Cc: Chris Wilson +Acked-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1718,7 +1718,8 @@ i915_gem_object_put_pages(struct drm_i91 + } + + static long +-i915_gem_purge(struct drm_i915_private *dev_priv, long target) ++__i915_gem_shrink(struct drm_i915_private *dev_priv, long target, ++ bool purgeable_only) + { + struct drm_i915_gem_object *obj, *next; + long count = 0; +@@ -1726,7 +1727,7 @@ i915_gem_purge(struct drm_i915_private * + list_for_each_entry_safe(obj, next, + &dev_priv->mm.unbound_list, + gtt_list) { +- if (i915_gem_object_is_purgeable(obj) && ++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && + i915_gem_object_put_pages(obj) == 0) { + count += obj->base.size >> PAGE_SHIFT; + if (count >= target) +@@ -1737,7 +1738,7 @@ i915_gem_purge(struct drm_i915_private * + list_for_each_entry_safe(obj, next, + &dev_priv->mm.inactive_list, + mm_list) { +- if (i915_gem_object_is_purgeable(obj) && ++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && + i915_gem_object_unbind(obj) == 0 && + i915_gem_object_put_pages(obj) == 0) { + count += obj->base.size >> PAGE_SHIFT; +@@ -1749,6 +1750,12 @@ i915_gem_purge(struct drm_i915_private * + return count; + } + ++static long ++i915_gem_purge(struct drm_i915_private *dev_priv, long target) ++{ ++ return __i915_gem_shrink(dev_priv, target, true); ++} ++ + static void + i915_gem_shrink_all(struct drm_i915_private *dev_priv) + { +@@ -4426,6 +4433,9 @@ i915_gem_inactive_shrink(struct shrinker + if (nr_to_scan) { + nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); + if (nr_to_scan > 0) ++ nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, ++ false); ++ if (nr_to_scan > 0) + i915_gem_shrink_all(dev_priv); + } + +@@ -4433,7 +4443,7 @@ i915_gem_inactive_shrink(struct shrinker + list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) + if (obj->pages_pin_count == 0) + cnt += obj->base.size >> PAGE_SHIFT; +- list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) ++ list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) + if (obj->pin_count == 0 && obj->pages_pin_count == 0) + cnt += obj->base.size >> PAGE_SHIFT; + +From 7d9c199a55200c9b9fcad08e150470d02fb385be Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 20:05:02 +0000 +Subject: RDMA/nes: Fix for crash when registering zero length MR for CQ + +From: Tatyana Nikolova + +commit 7d9c199a55200c9b9fcad08e150470d02fb385be upstream. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes_verbs.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -2559,6 +2559,11 @@ static struct ib_mr *nes_reg_user_mr(str + return ibmr; + case IWNES_MEMREG_TYPE_QP: + case IWNES_MEMREG_TYPE_CQ: ++ if (!region->length) { ++ nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); ++ ib_umem_release(region); ++ return ERR_PTR(-EINVAL); ++ } + nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); + if (!nespbl) { + nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); +From 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 19:58:27 +0000 +Subject: RDMA/nes: Fix for terminate timer crash + +From: Tatyana Nikolova + +commit 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 upstream. + +The terminate timer needs to be initialized just once. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes.h | 1 + + drivers/infiniband/hw/nes/nes_hw.c | 9 ++------- + drivers/infiniband/hw/nes/nes_verbs.c | 4 +++- + 3 files changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/infiniband/hw/nes/nes.h ++++ b/drivers/infiniband/hw/nes/nes.h +@@ -532,6 +532,7 @@ void nes_iwarp_ce_handler(struct nes_dev + int nes_destroy_cqp(struct nes_device *); + int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); + void nes_recheck_link_status(struct work_struct *work); ++void nes_terminate_timeout(unsigned long context); + + /* nes_nic.c */ + struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); +--- a/drivers/infiniband/hw/nes/nes_hw.c ++++ b/drivers/infiniband/hw/nes/nes_hw.c +@@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struc + static void process_critical_error(struct nes_device *nesdev); + static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); + static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); +-static void nes_terminate_timeout(unsigned long context); + static void nes_terminate_start_timer(struct nes_qp *nesqp); + + #ifdef CONFIG_INFINIBAND_NES_DEBUG +@@ -3520,7 +3519,7 @@ static void nes_terminate_received(struc + } + + /* Timeout routine in case terminate fails to complete */ +-static void nes_terminate_timeout(unsigned long context) ++void nes_terminate_timeout(unsigned long context) + { + struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; + +@@ -3530,11 +3529,7 @@ static void nes_terminate_timeout(unsign + /* Set a timer in case hw cannot complete the terminate sequence */ + static void nes_terminate_start_timer(struct nes_qp *nesqp) + { +- init_timer(&nesqp->terminate_timer); +- nesqp->terminate_timer.function = nes_terminate_timeout; +- nesqp->terminate_timer.expires = jiffies + HZ; +- nesqp->terminate_timer.data = (unsigned long)nesqp; +- add_timer(&nesqp->terminate_timer); ++ mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); + } + + /** +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struc + } + + nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); ++ init_timer(&nesqp->terminate_timer); ++ nesqp->terminate_timer.function = nes_terminate_timeout; ++ nesqp->terminate_timer.data = (unsigned long)nesqp; + + /* update the QP table */ + nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; +@@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struc + return &nesqp->ibqp; + } + +- + /** + * nes_clean_cq + */ +From c1a94672a830e01d58c7c7e8de530c3f136d6ff2 Mon Sep 17 00:00:00 2001 +From: Mike Snitzer +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm: disable WRITE SAME + +From: Mike Snitzer + +commit c1a94672a830e01d58c7c7e8de530c3f136d6ff2 upstream. + +WRITE SAME bios are not yet handled correctly by device-mapper so +disable their use on device-mapper devices by setting +max_write_same_sectors to zero. + +As an example, a ciphertext device is incompatible because the data +gets changed according to the location at which it written and so the +dm crypt target cannot support it. + +Signed-off-by: Mike Snitzer +Cc: Milan Broz +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-table.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -1445,6 +1445,8 @@ void dm_table_set_restrictions(struct dm + else + queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); + ++ q->limits.max_write_same_sectors = 0; ++ + dm_table_set_integrity(t); + + /* +From 550929faf89e2e2cdb3e9945ea87d383989274cf Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm persistent data: rename node to btree_node + +From: Mikulas Patocka + +commit 550929faf89e2e2cdb3e9945ea87d383989274cf upstream. + +This patch fixes a compilation failure on sparc32 by renaming struct node. + +struct node is already defined in include/linux/node.h. On sparc32, it +happens to be included through other dependencies and persistent-data +doesn't compile because of conflicting declarations. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/persistent-data/dm-btree-internal.h | 16 ++++---- + drivers/md/persistent-data/dm-btree-remove.c | 50 ++++++++++++------------- + drivers/md/persistent-data/dm-btree-spine.c | 6 +-- + drivers/md/persistent-data/dm-btree.c | 22 +++++------ + 4 files changed, 47 insertions(+), 47 deletions(-) + +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -36,13 +36,13 @@ struct node_header { + __le32 padding; + } __packed; + +-struct node { ++struct btree_node { + struct node_header header; + __le64 keys[0]; + } __packed; + + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); + + int new_block(struct dm_btree_info *info, struct dm_block **result); +@@ -64,7 +64,7 @@ struct ro_spine { + void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); + int exit_ro_spine(struct ro_spine *s); + int ro_step(struct ro_spine *s, dm_block_t new_child); +-struct node *ro_node(struct ro_spine *s); ++struct btree_node *ro_node(struct ro_spine *s); + + struct shadow_spine { + struct dm_btree_info *info; +@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); + /* + * Some inlines. + */ +-static inline __le64 *key_ptr(struct node *n, uint32_t index) ++static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) + { + return n->keys + index; + } + +-static inline void *value_base(struct node *n) ++static inline void *value_base(struct btree_node *n) + { + return &n->keys[le32_to_cpu(n->header.max_entries)]; + } + +-static inline void *value_ptr(struct node *n, uint32_t index) ++static inline void *value_ptr(struct btree_node *n, uint32_t index) + { + uint32_t value_size = le32_to_cpu(n->header.value_size); + return value_base(n) + (value_size * index); +@@ -117,7 +117,7 @@ static inline void *value_ptr(struct nod + /* + * Assumes the values are suitably-aligned and converts to core format. + */ +-static inline uint64_t value64(struct node *n, uint32_t index) ++static inline uint64_t value64(struct btree_node *n, uint32_t index) + { + __le64 *values_le = value_base(n); + +@@ -127,7 +127,7 @@ static inline uint64_t value64(struct no + /* + * Searching for a key within a single node. + */ +-int lower_bound(struct node *n, uint64_t key); ++int lower_bound(struct btree_node *n, uint64_t key); + + extern struct dm_block_validator btree_node_validator; + +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -53,7 +53,7 @@ + /* + * Some little utilities for moving node data around. + */ +-static void node_shift(struct node *n, int shift) ++static void node_shift(struct btree_node *n, int shift) + { + uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); + uint32_t value_size = le32_to_cpu(n->header.value_size); +@@ -79,7 +79,7 @@ static void node_shift(struct node *n, i + } + } + +-static void node_copy(struct node *left, struct node *right, int shift) ++static void node_copy(struct btree_node *left, struct btree_node *right, int shift) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t value_size = le32_to_cpu(left->header.value_size); +@@ -108,7 +108,7 @@ static void node_copy(struct node *left, + /* + * Delete a specific entry from a leaf node. + */ +-static void delete_at(struct node *n, unsigned index) ++static void delete_at(struct btree_node *n, unsigned index) + { + unsigned nr_entries = le32_to_cpu(n->header.nr_entries); + unsigned nr_to_copy = nr_entries - (index + 1); +@@ -128,7 +128,7 @@ static void delete_at(struct node *n, un + n->header.nr_entries = cpu_to_le32(nr_entries - 1); + } + +-static unsigned merge_threshold(struct node *n) ++static unsigned merge_threshold(struct btree_node *n) + { + return le32_to_cpu(n->header.max_entries) / 3; + } +@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct n + struct child { + unsigned index; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + }; + + static struct dm_btree_value_type le64_type = { +@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_t + .equal = NULL + }; + +-static int init_child(struct dm_btree_info *info, struct node *parent, ++static int init_child(struct dm_btree_info *info, struct btree_node *parent, + unsigned index, struct child *result) + { + int r, inc; +@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_in + return dm_tm_unlock(info->tm, c->block); + } + +-static void shift(struct node *left, struct node *right, int count) ++static void shift(struct btree_node *left, struct btree_node *right, int count) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); +@@ -203,11 +203,11 @@ static void shift(struct node *left, str + right->header.nr_entries = cpu_to_le32(nr_right + count); + } + +-static void __rebalance2(struct dm_btree_info *info, struct node *parent, ++static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *r) + { +- struct node *left = l->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *right = r->n; + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); + unsigned threshold = 2 * merge_threshold(left) + 1; +@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent; ++ struct btree_node *parent; + struct child left, right; + + parent = dm_block_data(shadow_current(s)); +@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spin + * in right, then rebalance2. This wastes some cpu, but I want something + * simple atm. + */ +-static void delete_center_node(struct dm_btree_info *info, struct node *parent, ++static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + uint32_t max_entries = le32_to_cpu(left->header.max_entries); +@@ -301,9 +301,9 @@ static void delete_center_node(struct dm + /* + * Redistributes entries among 3 sibling nodes. + */ +-static void redistribute3(struct dm_btree_info *info, struct node *parent, ++static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + int s; +@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btre + *key_ptr(parent, r->index) = right->keys[0]; + } + +-static void __rebalance3(struct dm_btree_info *info, struct node *parent, ++static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r) + { +- struct node *left = l->n; +- struct node *center = c->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *center = c->n; ++ struct btree_node *right = r->n; + + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_center = le32_to_cpu(center->header.nr_entries); +@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent = dm_block_data(shadow_current(s)); ++ struct btree_node *parent = dm_block_data(shadow_current(s)); + struct child left, center, right; + + /* +@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_tran + { + int r; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + + r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); + if (r) +@@ -438,7 +438,7 @@ static int rebalance_children(struct sha + { + int i, r, has_left_sibling, has_right_sibling; + uint32_t child_entries; +- struct node *n; ++ struct btree_node *n; + + n = dm_block_data(shadow_current(s)); + +@@ -483,7 +483,7 @@ static int rebalance_children(struct sha + return r; + } + +-static int do_leaf(struct node *n, uint64_t key, unsigned *index) ++static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) + { + int i = lower_bound(n, key); + +@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spin + uint64_t key, unsigned *index) + { + int i = *index, r; +- struct node *n; ++ struct btree_node *n; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info + unsigned level, last_level = info->levels - 1; + int index = 0, r = 0; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + + init_shadow_spine(&spine, info); + for (level = 0; level < info->levels; level++) { +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -23,7 +23,7 @@ static void node_prepare_for_write(struc + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + + h->blocknr = cpu_to_le64(dm_block_location(b)); +@@ -38,7 +38,7 @@ static int node_check(struct dm_block_va + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + size_t value_size; + __le32 csum_disk; +@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block + return r; + } + +-struct node *ro_node(struct ro_spine *s) ++struct btree_node *ro_node(struct ro_spine *s) + { + struct dm_block *block; + +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -38,7 +38,7 @@ static void array_insert(void *base, siz + /*----------------------------------------------------------------*/ + + /* makes the assumption that no two keys are the same. */ +-static int bsearch(struct node *n, uint64_t key, int want_hi) ++static int bsearch(struct btree_node *n, uint64_t key, int want_hi) + { + int lo = -1, hi = le32_to_cpu(n->header.nr_entries); + +@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint6 + return want_hi ? hi : lo; + } + +-int lower_bound(struct node *n, uint64_t key) ++int lower_bound(struct btree_node *n, uint64_t key) + { + return bsearch(n, key, 0); + } + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt) + { + unsigned i; +@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_ + vt->inc(vt->context, value_ptr(n, i)); + } + +-static int insert_at(size_t value_size, struct node *node, unsigned index, ++static int insert_at(size_t value_size, struct btree_node *node, unsigned index, + uint64_t key, void *value) + __dm_written_to_disk(value) + { +@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info + { + int r; + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + size_t block_size; + uint32_t max_entries; + +@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); + #define MAX_SPINE_DEPTH 64 + struct frame { + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + unsigned level; + unsigned nr_children; + unsigned current_child; +@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); + /*----------------------------------------------------------------*/ + + static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, +- int (*search_fn)(struct node *, uint64_t), ++ int (*search_fn)(struct btree_node *, uint64_t), + uint64_t *result_key, void *v, size_t value_size) + { + int i, r; +@@ -406,7 +406,7 @@ static int btree_split_sibling(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *parent; +- struct node *ln, *rn, *pn; ++ struct btree_node *ln, *rn, *pn; + __le64 location; + + left = shadow_current(s); +@@ -491,7 +491,7 @@ static int btree_split_beneath(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *new_parent; +- struct node *pn, *ln, *rn; ++ struct btree_node *pn, *ln, *rn; + __le64 val; + + new_parent = shadow_current(s); +@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shado + uint64_t key, unsigned *index) + { + int r, i = *index, top = 1; +- struct node *node; ++ struct btree_node *node; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info * + unsigned level, index = -1, last_level = info->levels - 1; + dm_block_t block = root; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + struct dm_btree_value_type le64_type; + + le64_type.context = NULL; +From e910d7ebecd1aac43125944a8641b6cb1a0dfabe Mon Sep 17 00:00:00 2001 +From: Alasdair G Kergon +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm ioctl: prevent unsafe change to dm_ioctl data_size + +From: Alasdair G Kergon + +commit e910d7ebecd1aac43125944a8641b6cb1a0dfabe upstream. + +Abort dm ioctl processing if userspace changes the data_size parameter +after we validated it but before we finished copying the data buffer +from userspace. + +The dm ioctl parameters are processed in the following sequence: + 1. ctl_ioctl() calls copy_params(); + 2. copy_params() makes a first copy of the fixed-sized portion of the + userspace parameters into the local variable "tmp"; + 3. copy_params() then validates tmp.data_size and allocates a new + structure big enough to hold the complete data and copies the whole + userspace buffer there; + 4. ctl_ioctl() reads userspace data the second time and copies the whole + buffer into the pointer "param"; + 5. ctl_ioctl() reads param->data_size without any validation and stores it + in the variable "input_param_size"; + 6. "input_param_size" is further used as the authoritative size of the + kernel buffer. + +The problem is that userspace code could change the contents of user +memory between steps 2 and 4. In particular, the data_size parameter +can be changed to an invalid value after the kernel has validated it. +This lets userspace force the kernel to access invalid kernel memory. + +The fix is to ensure that the size has not changed at step 4. + +This patch shouldn't have a security impact because CAP_SYS_ADMIN is +required to run this code, but it should be fixed anyway. + +Reported-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-ioctl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1566,6 +1566,14 @@ static int copy_params(struct dm_ioctl _ + if (copy_from_user(dmi, user, tmp.data_size)) + goto bad; + ++ /* ++ * Abort if something changed the ioctl data while it was being copied. ++ */ ++ if (dmi->data_size != tmp.data_size) { ++ DMERR("rejecting ioctl: data size modified while processing parameters"); ++ goto bad; ++ } ++ + /* Wipe the user buffer so we do not return it to userspace */ + if (secure_data && clear_user(user, tmp.data_size)) + goto bad; +From b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d Mon Sep 17 00:00:00 2001 +From: Joe Thornber +Date: Fri, 21 Dec 2012 20:23:31 +0000 +Subject: dm thin: replace dm_cell_release_singleton with cell_defer_except + +From: Joe Thornber + +commit b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d upstream. + +Change existing users of the function dm_cell_release_singleton to share +cell_defer_except instead, and then remove the now-unused function. + +Everywhere that calls dm_cell_release_singleton, the bio in question +is the holder of the cell. + +If there are no non-holder entries in the cell then cell_defer_except +behaves exactly like dm_cell_release_singleton. Conversely, if there +*are* non-holder entries then dm_cell_release_singleton must not be used +because those entries would need to be deferred. + +Consequently, it is safe to replace use of dm_cell_release_singleton +with cell_defer_except. + +This patch is a pre-requisite for "dm thin: fix race between +simultaneous io and discards to same block". + +Signed-off-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-bio-prison.c | 25 ------------------------- + drivers/md/dm-bio-prison.h | 1 - + drivers/md/dm-thin.c | 25 ++++++++++++------------- + 3 files changed, 12 insertions(+), 39 deletions(-) + +--- a/drivers/md/dm-bio-prison.c ++++ b/drivers/md/dm-bio-prison.c +@@ -208,31 +208,6 @@ void dm_cell_release(struct dm_bio_priso + EXPORT_SYMBOL_GPL(dm_cell_release); + + /* +- * There are a couple of places where we put a bio into a cell briefly +- * before taking it out again. In these situations we know that no other +- * bio may be in the cell. This function releases the cell, and also does +- * a sanity check. +- */ +-static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +-{ +- BUG_ON(cell->holder != bio); +- BUG_ON(!bio_list_empty(&cell->bios)); +- +- __cell_release(cell, NULL); +-} +- +-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +-{ +- unsigned long flags; +- struct dm_bio_prison *prison = cell->prison; +- +- spin_lock_irqsave(&prison->lock, flags); +- __cell_release_singleton(cell, bio); +- spin_unlock_irqrestore(&prison->lock, flags); +-} +-EXPORT_SYMBOL_GPL(dm_cell_release_singleton); +- +-/* + * Sometimes we don't want the holder, just the additional bios. + */ + static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) +--- a/drivers/md/dm-bio-prison.h ++++ b/drivers/md/dm-bio-prison.h +@@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison * + struct bio *inmate, struct dm_bio_prison_cell **ref); + + void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); +-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed + void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); + void dm_cell_error(struct dm_bio_prison_cell *cell); + +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -513,8 +513,7 @@ static void cell_defer(struct thin_c *tc + } + + /* +- * Same as cell_defer above, except it omits one particular detainee, +- * a write bio that covers the block and has already been processed. ++ * Same as cell_defer except it omits the original holder of the cell. + */ + static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) + { +@@ -936,7 +935,7 @@ static void process_discard(struct thin_ + */ + build_data_key(tc->td, lookup_result.block, &key2); + if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + break; + } + +@@ -967,8 +966,8 @@ static void process_discard(struct thin_ + * a block boundary. So we submit the discard of a + * partial block appropriately. + */ +- dm_cell_release_singleton(cell, bio); +- dm_cell_release_singleton(cell2, bio); ++ cell_defer_except(tc, cell); ++ cell_defer_except(tc, cell2); + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else +@@ -980,13 +979,13 @@ static void process_discard(struct thin_ + /* + * It isn't provisioned, just forget it. + */ +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_endio(bio, 0); + break; + + default: + DMERR("discard: find block unexpectedly returned %d", r); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_io_error(bio); + break; + } +@@ -1041,7 +1040,7 @@ static void process_shared_bio(struct th + + h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); + +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_and_issue(tc, bio, lookup_result->block); + } + } +@@ -1056,7 +1055,7 @@ static void provision_block(struct thin_ + * Remap empty bios (flushes) immediately, without provisioning. + */ + if (!bio->bi_size) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_and_issue(tc, bio, 0); + return; + } +@@ -1066,7 +1065,7 @@ static void provision_block(struct thin_ + */ + if (bio_data_dir(bio) == READ) { + zero_fill_bio(bio); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_endio(bio, 0); + return; + } +@@ -1120,7 +1119,7 @@ static void process_bio(struct thin_c *t + * TODO: this will probably have to change when discard goes + * back in. + */ +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + + if (lookup_result.shared) + process_shared_bio(tc, bio, block, &lookup_result); +@@ -1130,7 +1129,7 @@ static void process_bio(struct thin_c *t + + case -ENODATA: + if (bio_data_dir(bio) == READ && tc->origin_dev) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_to_origin_and_issue(tc, bio); + } else + provision_block(tc, bio, block, cell); +@@ -1138,7 +1137,7 @@ static void process_bio(struct thin_c *t + + default: + DMERR("dm_thin_find_block() failed, error = %d", r); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_io_error(bio); + break; + } +From ab1dd9963137a1e122004d5378a581bf16ae9bc8 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 7 Oct 2012 08:27:00 +0100 +Subject: staging: vt6656: [BUG] out of bound array reference in RFbSetPower. + +From: Malcolm Priestley + +commit ab1dd9963137a1e122004d5378a581bf16ae9bc8 upstream. + +Calling RFbSetPower with uCH zero value will cause out of bound array reference. + +This causes 64 bit kernels to oops on boot. + +Note: Driver does not function on 64 bit kernels and should be +blacklisted on them. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/rf.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/vt6656/rf.c ++++ b/drivers/staging/vt6656/rf.c +@@ -769,6 +769,9 @@ BYTE byPwr = pDevice->byCCKPwr; + return TRUE; + } + ++ if (uCH == 0) ++ return -EINVAL; ++ + switch (uRATE) { + case RATE_1M: + case RATE_2M: +From a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:32:05 +0000 +Subject: staging: vt6656: 64 bit fixes: use u32 for QWORD definition. + +From: Malcolm Priestley + +commit a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 upstream. + +Size of long issues replace with u32. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/ttype.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/staging/vt6656/ttype.h ++++ b/drivers/staging/vt6656/ttype.h +@@ -29,6 +29,8 @@ + #ifndef __TTYPE_H__ + #define __TTYPE_H__ + ++#include ++ + /******* Common definitions and typedefs ***********************************/ + + typedef int BOOL; +@@ -51,8 +53,8 @@ typedef unsigned long DWORD; + // which is NOT really a floating point number. + typedef union tagUQuadWord { + struct { +- DWORD dwLowDword; +- DWORD dwHighDword; ++ u32 dwLowDword; ++ u32 dwHighDword; + } u; + double DoNotUseThisField; + } UQuadWord; +From 7730492855a2f9c828599bcd8d62760f96d319e4 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:41:25 +0000 +Subject: staging: vt6656: 64 bit fixes : correct all type sizes + +From: Malcolm Priestley + +commit 7730492855a2f9c828599bcd8d62760f96d319e4 upstream. + +After this patch all BYTE/WORD/DWORD types can be replaced with the appropriate u sizes. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/ttype.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/staging/vt6656/ttype.h ++++ b/drivers/staging/vt6656/ttype.h +@@ -44,9 +44,9 @@ typedef int BOOL; + + /****** Simple typedefs ***************************************************/ + +-typedef unsigned char BYTE; // 8-bit +-typedef unsigned short WORD; // 16-bit +-typedef unsigned long DWORD; // 32-bit ++typedef u8 BYTE; ++typedef u16 WORD; ++typedef u32 DWORD; + + // QWORD is for those situation that we want + // an 8-byte-aligned 8 byte long structure +@@ -62,8 +62,8 @@ typedef UQuadWord QWORD; + + /****** Common pointer types ***********************************************/ + +-typedef unsigned long ULONG_PTR; // 32-bit +-typedef unsigned long DWORD_PTR; // 32-bit ++typedef u32 ULONG_PTR; ++typedef u32 DWORD_PTR; + + // boolean pointer + +From b4dc03af5513774277c9c36b12a25cd3f25f4404 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:45:52 +0000 +Subject: staging: vt6656: 64 bit fixes: fix long warning messages. + +From: Malcolm Priestley + +commit b4dc03af5513774277c9c36b12a25cd3f25f4404 upstream. + +Fixes long warning messages from patch +[PATCH 08/14] staging: vt6656: 64 bit fixes : correct all type sizes + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/dpc.c | 4 +-- + drivers/staging/vt6656/key.c | 47 +++++++++++++++++++++++++++++------------- + drivers/staging/vt6656/mac.c | 6 +++-- + drivers/staging/vt6656/rxtx.c | 18 ++++++++++------ + 4 files changed, 51 insertions(+), 24 deletions(-) + +--- a/drivers/staging/vt6656/dpc.c ++++ b/drivers/staging/vt6656/dpc.c +@@ -1238,7 +1238,7 @@ static BOOL s_bHandleRxEncryption ( + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { +@@ -1349,7 +1349,7 @@ static BOOL s_bHostWepRxEncryption ( + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); +--- a/drivers/staging/vt6656/key.c ++++ b/drivers/staging/vt6656/key.c +@@ -235,7 +235,8 @@ BOOL KeybSetKey( + PSKeyItem pKey; + unsigned int uKeyIdx; + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Enter KeybSetKey: %X\n", dwKeyIndex); + + j = (MAX_KEY_TABLE-1); + for (i=0;i<(MAX_KEY_TABLE-1);i++) { +@@ -261,7 +262,9 @@ BOOL KeybSetKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[i].dwGTKeyIndex, i); + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); +@@ -302,9 +305,12 @@ BOOL KeybSetKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", ++ pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", ++ pKey->wTSC15_0); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -326,7 +332,9 @@ BOOL KeybSetKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(N)[%X]: %d\n", ++ pTable->KeyTable[j].dwGTKeyIndex, j); + } + pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); +@@ -367,9 +375,11 @@ BOOL KeybSetKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", ++ pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", ++ pTable->KeyTable[i].dwGTKeyIndex); + + return (TRUE); + } +@@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, ++ MAX_KEY_TABLE-1); + + } + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed +@@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", ++ pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey( + PSKeyItem pKey; + unsigned int uKeyIdx; + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", ++ dwKeyIndex); + + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key +@@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[i].dwGTKeyIndex, i); + + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed +--- a/drivers/staging/vt6656/mac.c ++++ b/drivers/staging/vt6656/mac.c +@@ -260,7 +260,8 @@ BYTE pbyData[24]; + dwData1 <<= 16; + dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ ++ " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); +@@ -277,7 +278,8 @@ BYTE pbyData[24]; + dwData2 <<= 8; + dwData2 |= *(pbyAddr+0); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", ++ wOffset, dwData2); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); +--- a/drivers/staging/vt6656/rxtx.c ++++ b/drivers/staging/vt6656/rxtx.c +@@ -375,7 +375,8 @@ s_vFillTxKey ( + *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + // Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", ++ *pdwExtIV); + + } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + pTransmitKey->wTSC15_0++; +@@ -1751,7 +1752,8 @@ s_bPacketToWirelessUsb( + MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", ++ dwMICKey0, dwMICKey1); + + /////////////////////////////////////////////////////////////////// + +@@ -2633,7 +2635,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct + MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ ++ " %X, %X\n", dwMICKey0, dwMICKey1); + + uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; + +@@ -2653,7 +2656,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", ++ *pdwMIC_L, *pdwMIC_R); + + } + +@@ -3027,7 +3031,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); + } + else { +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", ++ pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } +@@ -3041,7 +3046,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un + if (pDevice->bEnableHostWEP) { + if ((uNodeIndex != 0) && + (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", ++ pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } +From c0d05b305b00c698b0a8c1b3d46c9380bce9db45 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:49:59 +0000 +Subject: staging: vt6656: 64bit fixes: key.c/h change unsigned long to u32 + +From: Malcolm Priestley + +commit c0d05b305b00c698b0a8c1b3d46c9380bce9db45 upstream. + +Fixes long issues. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/key.c | 6 +++--- + drivers/staging/vt6656/key.h | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/staging/vt6656/key.c ++++ b/drivers/staging/vt6656/key.c +@@ -223,7 +223,7 @@ BOOL KeybSetKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -675,7 +675,7 @@ BOOL KeybSetDefaultKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -791,7 +791,7 @@ BOOL KeybSetAllGroupKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +--- a/drivers/staging/vt6656/key.h ++++ b/drivers/staging/vt6656/key.h +@@ -58,7 +58,7 @@ + typedef struct tagSKeyItem + { + BOOL bKeyValid; +- unsigned long uKeyLength; ++ u32 uKeyLength; + BYTE abyKey[MAX_KEY_LEN]; + QWORD KeyRSC; + DWORD dwTSC47_16; +@@ -107,7 +107,7 @@ BOOL KeybSetKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +From 70e227790d4ee4590023d8041a3485f8053593fc Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 16:07:57 +0000 +Subject: staging: vt6656: 64bit fixes: vCommandTimerWait change calculation of timer. + +From: Malcolm Priestley + +commit 70e227790d4ee4590023d8041a3485f8053593fc upstream. + +The timer appears to run too fast/race on 64 bit systems. + +Using msecs_to_jiffies seems to cause a deadlock on 64 bit. + +A calculation of (MSecond * HZ) / 1000 appears to run satisfactory. + +Change BSSIDInfoCount to u32. + +After this patch the driver can be successfully connect on little endian 64/32 bit systems. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/wcmd.c | 20 +++++++++++--------- + drivers/staging/vt6656/wpa2.h | 4 ++-- + 2 files changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/staging/vt6656/wcmd.c ++++ b/drivers/staging/vt6656/wcmd.c +@@ -316,17 +316,19 @@ s_MgrMakeProbeRequest( + return pTxPacket; + } + +-void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond) ++void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond) + { +- PSDevice pDevice = (PSDevice)hDeviceContext; ++ PSDevice pDevice = (PSDevice)hDeviceContext; + +- init_timer(&pDevice->sTimerCommand); +- pDevice->sTimerCommand.data = (unsigned long)pDevice; +- pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; +- // RUN_AT :1 msec ~= (HZ/1024) +- pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); +- add_timer(&pDevice->sTimerCommand); +- return; ++ init_timer(&pDevice->sTimerCommand); ++ ++ pDevice->sTimerCommand.data = (unsigned long)pDevice; ++ pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; ++ pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); ++ ++ add_timer(&pDevice->sTimerCommand); ++ ++ return; + } + + void vRunCommand(void *hDeviceContext) +--- a/drivers/staging/vt6656/wpa2.h ++++ b/drivers/staging/vt6656/wpa2.h +@@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo { + } PMKIDInfo, *PPMKIDInfo; + + typedef struct tagSPMKIDCache { +- unsigned long BSSIDInfoCount; +- PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; ++ u32 BSSIDInfoCount; ++ PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; + } SPMKIDCache, *PSPMKIDCache; + + +From 0602934f302e016e2ea5dc6951681bfac77455ef Mon Sep 17 00:00:00 2001 +From: Chris Verges +Date: Fri, 21 Dec 2012 01:58:34 -0800 +Subject: hwmon: (lm73} Detect and report i2c bus errors + +From: Chris Verges + +commit 0602934f302e016e2ea5dc6951681bfac77455ef upstream. + +If an LM73 device does not exist on an I2C bus, attempts to communicate +with the device result in an error code returned from the i2c read/write +functions. The current lm73 driver casts that return value from a s32 +type to a s16 type, then converts it to a temperature in celsius. +Because negative temperatures are valid, it is difficult to distinguish +between an error code printed to the response buffer and a negative +temperature recorded by the sensor. + +The solution is to evaluate the return value from the i2c functions +before performing any temperature calculations. If the i2c function did +not succeed, the error code should be passed back through the virtual +file system layer instead of being printed into the response buffer. + +Before: + + $ cat /sys/class/hwmon/hwmon0/device/temp1_input + -46 + +After: + + $ cat /sys/class/hwmon/hwmon0/device/temp1_input + cat: read error: No such device or address + +Signed-off-by: Chris Verges +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/lm73.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/hwmon/lm73.c ++++ b/drivers/hwmon/lm73.c +@@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *d + struct i2c_client *client = to_i2c_client(dev); + long temp; + short value; ++ s32 err; + + int status = kstrtol(buf, 10, &temp); + if (status < 0) +@@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *d + /* Write value */ + value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), + (LM73_TEMP_MAX*4)) << 5; +- i2c_smbus_write_word_swapped(client, attr->index, value); +- return count; ++ err = i2c_smbus_write_word_swapped(client, attr->index, value); ++ return (err < 0) ? err : count; + } + + static ssize_t show_temp(struct device *dev, struct device_attribute *da, +@@ -66,11 +67,16 @@ static ssize_t show_temp(struct device * + { + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); ++ int temp; ++ ++ s32 err = i2c_smbus_read_word_swapped(client, attr->index); ++ if (err < 0) ++ return err; ++ + /* use integer division instead of equivalent right shift to + guarantee arithmetic shift and preserve the sign */ +- int temp = ((s16) (i2c_smbus_read_word_swapped(client, +- attr->index))*250) / 32; +- return sprintf(buf, "%d\n", temp); ++ temp = (((s16) err) * 250) / 32; ++ return scnprintf(buf, PAGE_SIZE, "%d\n", temp); + } + + +From 7b9205bd775afc4439ed86d617f9042ee9e76a71 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 11 Jan 2013 14:32:05 -0800 +Subject: audit: create explicit AUDIT_SECCOMP event type + +From: Kees Cook + +commit 7b9205bd775afc4439ed86d617f9042ee9e76a71 upstream. + +The seccomp path was using AUDIT_ANOM_ABEND from when seccomp mode 1 +could only kill a process. While we still want to make sure an audit +record is forced on a kill, this should use a separate record type since +seccomp mode 2 introduces other behaviors. + +In the case of "handled" behaviors (process wasn't killed), only emit a +record if the process is under inspection. This change also fixes +userspace examination of seccomp audit events, since it was considered +malformed due to missing fields of the AUDIT_ANOM_ABEND event type. + +Signed-off-by: Kees Cook +Cc: Al Viro +Cc: Eric Paris +Cc: Jeff Layton +Cc: "Eric W. Biederman" +Cc: Julien Tinnes +Acked-by: Will Drewry +Acked-by: Steve Grubb +Cc: Andrea Arcangeli +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/audit.h | 3 ++- + include/uapi/linux/audit.h | 1 + + kernel/auditsc.c | 14 +++++++++++--- + 3 files changed, 14 insertions(+), 4 deletions(-) + +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -157,7 +157,8 @@ void audit_core_dumps(long signr); + + static inline void audit_seccomp(unsigned long syscall, long signr, int code) + { +- if (unlikely(!audit_dummy_context())) ++ /* Force a record to be reported if a signal was delivered. */ ++ if (signr || unlikely(!audit_dummy_context())) + __audit_seccomp(syscall, signr, code); + } + +--- a/include/uapi/linux/audit.h ++++ b/include/uapi/linux/audit.h +@@ -106,6 +106,7 @@ + #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ + #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ + #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ ++#define AUDIT_SECCOMP 1326 /* Secure Computing event */ + + #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ + #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -2735,7 +2735,7 @@ void __audit_mmap_fd(int fd, int flags) + context->type = AUDIT_MMAP; + } + +-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) ++static void audit_log_task(struct audit_buffer *ab) + { + kuid_t auid, uid; + kgid_t gid; +@@ -2753,6 +2753,11 @@ static void audit_log_abend(struct audit + audit_log_task_context(ab); + audit_log_format(ab, " pid=%d comm=", current->pid); + audit_log_untrustedstring(ab, current->comm); ++} ++ ++static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) ++{ ++ audit_log_task(ab); + audit_log_format(ab, " reason="); + audit_log_string(ab, reason); + audit_log_format(ab, " sig=%ld", signr); +@@ -2783,8 +2788,11 @@ void __audit_seccomp(unsigned long sysca + { + struct audit_buffer *ab; + +- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); +- audit_log_abend(ab, "seccomp", signr); ++ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); ++ if (unlikely(!ab)) ++ return; ++ audit_log_task(ab); ++ audit_log_format(ab, " sig=%ld", signr); + audit_log_format(ab, " syscall=%ld", syscall); + audit_log_format(ab, " compat=%d", is_compat_task()); + audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); +From d9a58a782e396a0f04e8445b7ba3763c8a48c7fe Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Mon, 7 Jan 2013 05:32:06 +0000 +Subject: xen/netfront: improve truesize tracking + +From: Ian Campbell + +commit d9a58a782e396a0f04e8445b7ba3763c8a48c7fe upstream. + +Using RX_COPY_THRESHOLD is incorrect if the SKB is actually smaller +than that. We have already accounted for this in +NETFRONT_SKB_CB(skb)->pull_to so use that instead. + +Fixes WARN_ON from skb_try_coalesce. + +Signed-off-by: Ian Campbell +Cc: Sander Eikelenboom +Cc: Konrad Rzeszutek Wilk +Cc: annie li +Cc: xen-devel@lists.xen.org +Cc: netdev@vger.kernel.org +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/xen-netfront.c | 27 ++++----------------------- + 1 file changed, 4 insertions(+), 23 deletions(-) + +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -1015,29 +1015,10 @@ err: + i = xennet_fill_frags(np, skb, &tmpq); + + /* +- * Truesize approximates the size of true data plus +- * any supervisor overheads. Adding hypervisor +- * overheads has been shown to significantly reduce +- * achievable bandwidth with the default receive +- * buffer size. It is therefore not wise to account +- * for it here. +- * +- * After alloc_skb(RX_COPY_THRESHOLD), truesize is set +- * to RX_COPY_THRESHOLD + the supervisor +- * overheads. Here, we add the size of the data pulled +- * in xennet_fill_frags(). +- * +- * We also adjust for any unused space in the main +- * data area by subtracting (RX_COPY_THRESHOLD - +- * len). This is especially important with drivers +- * which split incoming packets into header and data, +- * using only 66 bytes of the main data area (see the +- * e1000 driver for example.) On such systems, +- * without this last adjustement, our achievable +- * receive throughout using the standard receive +- * buffer size was cut by 25%(!!!). +- */ +- skb->truesize += skb->data_len - RX_COPY_THRESHOLD; ++ * Truesize is the actual allocation size, even if the ++ * allocation is only partially used. ++ */ ++ skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags; + skb->len += skb->data_len; + + if (rx->flags & XEN_NETRXF_csum_blank) +From 92638e2facc5330475c7d558acec77721c3214e4 Mon Sep 17 00:00:00 2001 +From: Sivaram Nair +Date: Tue, 18 Dec 2012 13:52:54 +0100 +Subject: cpuidle / coupled: fix ready counter decrement + +From: Sivaram Nair + +commit 92638e2facc5330475c7d558acec77721c3214e4 upstream. + +The ready_waiting_counts atomic variable is compared against the wrong +online cpu count. The latter is computed incorrectly using logical-OR +instead of bit-OR. This patch fixes that. + +Signed-off-by: Sivaram Nair +Acked-by: Santosh Shilimkar +Acked-by: Colin Cross +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpuidle/coupled.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/cpuidle/coupled.c ++++ b/drivers/cpuidle/coupled.c +@@ -209,7 +209,7 @@ inline int cpuidle_coupled_set_not_ready + int all; + int ret; + +- all = coupled->online_count || (coupled->online_count << WAITING_BITS); ++ all = coupled->online_count | (coupled->online_count << WAITING_BITS); + ret = atomic_add_unless(&coupled->ready_waiting_counts, + -MAX_WAITING_CPUS, all); + +From 619c5a9ad54e6bbdafd16d1cdc6c049403710540 Mon Sep 17 00:00:00 2001 +From: Hante Meuleman +Date: Wed, 2 Jan 2013 15:12:39 +0100 +Subject: brcmfmac: fix parsing rsn ie for ap mode. + +From: Hante Meuleman + +commit 619c5a9ad54e6bbdafd16d1cdc6c049403710540 upstream. + +RSN IEs got incorrectly parsed and therefore ap mode using WPA2 +security was not working. + +Reviewed-by: Arend Van Spriel +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Hante Meuleman +Signed-off-by: Arend van Spriel +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +@@ -3730,10 +3730,11 @@ brcmf_configure_wpaie(struct net_device + + len = wpa_ie->len + TLV_HDR_LEN; + data = (u8 *)wpa_ie; +- offset = 0; ++ offset = TLV_HDR_LEN; + if (!is_rsn_ie) + offset += VS_IE_FIXED_HDR_LEN; +- offset += WPA_IE_VERSION_LEN; ++ else ++ offset += WPA_IE_VERSION_LEN; + + /* check for multicast cipher suite */ + if (offset + WPA_IE_MIN_OUI_LEN > len) { +From 6c1ecba8d84841277d68140ef485335d5be28485 Mon Sep 17 00:00:00 2001 +From: Lothar Waßmann +Date: Thu, 22 Nov 2012 13:49:14 +0100 +Subject: video: mxsfb: fix crash when unblanking the display +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lothar Waßmann + +commit 6c1ecba8d84841277d68140ef485335d5be28485 upstream. + +The VDCTRL4 register does not provide the MXS SET/CLR/TOGGLE feature. +The write in mxsfb_disable_controller() sets the data_cnt for the LCD +DMA to 0 which obviously means the max. count for the LCD DMA and +leads to overwriting arbitrary memory when the display is unblanked. + +Signed-off-by: Lothar Waßmann +Acked-by: Juergen Beisert +Tested-by: Lauri Hintsala +Signed-off-by: Shawn Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/mxsfb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/video/mxsfb.c ++++ b/drivers/video/mxsfb.c +@@ -369,7 +369,8 @@ static void mxsfb_disable_controller(str + loop--; + } + +- writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR); ++ reg = readl(host->base + LCDC_VDCTRL4); ++ writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); + + clk_disable_unprepare(host->clk); + +From e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Wed, 5 Dec 2012 16:08:33 -0600 +Subject: samsung-laptop: Add quirk for broken acpi_video backlight on N250P + +From: Seth Forshee + +commit e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 upstream. + +BugLink: http://bugs.launchpad.net/bugs/1086921 +Signed-off-by: Seth Forshee +Signed-off-by: Matthew Garrett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/samsung-laptop.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -1523,6 +1523,16 @@ static struct dmi_system_id __initdata s + }, + .driver_data = &samsung_broken_acpi_video, + }, ++ { ++ .callback = samsung_dmi_matched, ++ .ident = "N250P", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), ++ DMI_MATCH(DMI_BOARD_NAME, "N250P"), ++ }, ++ .driver_data = &samsung_broken_acpi_video, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); +From 9f6d8f6ab26b42620a914d67f29822f9bba90233 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Sat, 22 Dec 2012 23:59:01 +0100 +Subject: PM: Move disabling/enabling runtime PM to late suspend/early resume + +From: "Rafael J. Wysocki" + +commit 9f6d8f6ab26b42620a914d67f29822f9bba90233 upstream. + +Currently, the PM core disables runtime PM for all devices right +after executing subsystem/driver .suspend() callbacks for them +and re-enables it right before executing subsystem/driver .resume() +callbacks for them. This may lead to problems when there are +two devices such that the .suspend() callback executed for one of +them depends on runtime PM working for the other. In that case, +if runtime PM has already been disabled for the second device, +the first one's .suspend() won't work correctly (and analogously +for resume). + +To make those issues go away, make the PM core disable runtime PM +for devices right before executing subsystem/driver .suspend_late() +callbacks for them and enable runtime PM for them right after +executing subsystem/driver .resume_early() callbacks for them. This +way the potential conflitcs between .suspend_late()/.resume_early() +and their runtime PM counterparts are still prevented from happening, +but the subtle ordering issues related to disabling/enabling runtime +PM for devices during system suspend/resume are much easier to avoid. + +Reported-and-tested-by: Jan-Matthias Braun +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Ulf Hansson +Reviewed-by: Kevin Hilman +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/power/runtime_pm.txt | 9 +++++---- + drivers/base/power/main.c | 9 ++++----- + 2 files changed, 9 insertions(+), 9 deletions(-) + +--- a/Documentation/power/runtime_pm.txt ++++ b/Documentation/power/runtime_pm.txt +@@ -642,12 +642,13 @@ out the following operations: + * During system suspend it calls pm_runtime_get_noresume() and + pm_runtime_barrier() for every device right before executing the + subsystem-level .suspend() callback for it. In addition to that it calls +- pm_runtime_disable() for every device right after executing the +- subsystem-level .suspend() callback for it. ++ __pm_runtime_disable() with 'false' as the second argument for every device ++ right before executing the subsystem-level .suspend_late() callback for it. + + * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync() +- for every device right before and right after executing the subsystem-level +- .resume() callback for it, respectively. ++ for every device right after executing the subsystem-level .resume_early() ++ callback and right after executing the subsystem-level .resume() callback ++ for it, respectively. + + 7. Generic subsystem callbacks + +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -513,6 +513,8 @@ static int device_resume_early(struct de + + Out: + TRACE_RESUME(error); ++ ++ pm_runtime_enable(dev); + return error; + } + +@@ -589,8 +591,6 @@ static int device_resume(struct device * + if (!dev->power.is_suspended) + goto Unlock; + +- pm_runtime_enable(dev); +- + if (dev->pm_domain) { + info = "power domain "; + callback = pm_op(&dev->pm_domain->ops, state); +@@ -930,6 +930,8 @@ static int device_suspend_late(struct de + pm_callback_t callback = NULL; + char *info = NULL; + ++ __pm_runtime_disable(dev, false); ++ + if (dev->power.syscore) + return 0; + +@@ -1133,11 +1135,8 @@ static int __device_suspend(struct devic + + Complete: + complete_all(&dev->power.completion); +- + if (error) + async_error = error; +- else if (dev->power.is_suspended) +- __pm_runtime_disable(dev, false); + + return error; + } +From c36575e663e302dbaa4d16b9c72d2c9a913a9aef Mon Sep 17 00:00:00 2001 +From: Forrest Liu +Date: Mon, 17 Dec 2012 09:55:39 -0500 +Subject: ext4: fix extent tree corruption caused by hole punch + +From: Forrest Liu + +commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream. + +When depth of extent tree is greater than 1, logical start value of +interior node is not correctly updated in ext4_ext_rm_idx. + +Signed-off-by: Forrest Liu +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Ashish Sangwan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2190,13 +2190,14 @@ errout: + * removes index from the index block. + */ + static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, +- struct ext4_ext_path *path) ++ struct ext4_ext_path *path, int depth) + { + int err; + ext4_fsblk_t leaf; + + /* free index block */ +- path--; ++ depth--; ++ path = path + depth; + leaf = ext4_idx_pblock(path->p_idx); + if (unlikely(path->p_hdr->eh_entries == 0)) { + EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); +@@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *han + + ext4_free_blocks(handle, inode, NULL, leaf, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); ++ ++ while (--depth >= 0) { ++ if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) ++ break; ++ path--; ++ err = ext4_ext_get_access(handle, inode, path); ++ if (err) ++ break; ++ path->p_idx->ei_block = (path+1)->p_idx->ei_block; ++ err = ext4_ext_dirty(handle, inode, path); ++ if (err) ++ break; ++ } + return err; + } + +@@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struc + /* if this leaf is free, then we should + * remove it from index block above */ + if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) +- err = ext4_ext_rm_idx(handle, inode, path + depth); ++ err = ext4_ext_rm_idx(handle, inode, path, depth); + + out: + return err; +@@ -2760,7 +2774,7 @@ again: + /* index is empty, remove it; + * handle must be already prepared by the + * truncatei_leaf() */ +- err = ext4_ext_rm_idx(handle, inode, path + i); ++ err = ext4_ext_rm_idx(handle, inode, path, i); + } + /* root level has p_bh == NULL, brelse() eats this */ + brelse(path[i].p_bh); +From 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 20 Dec 2012 00:07:18 -0500 +Subject: ext4: check dioread_nolock on remount + +From: Jan Kara + +commit 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 upstream. + +Currently we allow enabling dioread_nolock mount option on remount for +filesystems where blocksize < PAGE_CACHE_SIZE. This isn't really +supported so fix the bug by moving the check for blocksize != +PAGE_CACHE_SIZE into parse_options(). Change the original PAGE_SIZE to +PAGE_CACHE_SIZE along the way because that's what we are really +interested in. + +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Eric Sandeen +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1650,9 +1650,7 @@ static int parse_options(char *options, + unsigned int *journal_ioprio, + int is_remount) + { +-#ifdef CONFIG_QUOTA + struct ext4_sb_info *sbi = EXT4_SB(sb); +-#endif + char *p; + substring_t args[MAX_OPT_ARGS]; + int token; +@@ -1701,6 +1699,16 @@ static int parse_options(char *options, + } + } + #endif ++ if (test_opt(sb, DIOREAD_NOLOCK)) { ++ int blocksize = ++ BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); ++ ++ if (blocksize < PAGE_CACHE_SIZE) { ++ ext4_msg(sb, KERN_ERR, "can't mount with " ++ "dioread_nolock if block size != PAGE_SIZE"); ++ return 0; ++ } ++ } + return 1; + } + +@@ -3446,15 +3454,6 @@ static int ext4_fill_super(struct super_ + clear_opt(sb, DELALLOC); + } + +- blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); +- if (test_opt(sb, DIOREAD_NOLOCK)) { +- if (blocksize < PAGE_SIZE) { +- ext4_msg(sb, KERN_ERR, "can't mount with " +- "dioread_nolock if block size != PAGE_SIZE"); +- goto failed_mount; +- } +- } +- + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); + +@@ -3496,6 +3495,7 @@ static int ext4_fill_super(struct super_ + if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) + goto failed_mount; + ++ blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); + if (blocksize < EXT4_MIN_BLOCK_SIZE || + blocksize > EXT4_MAX_BLOCK_SIZE) { + ext4_msg(sb, KERN_ERR, +From d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 21 Dec 2012 00:15:51 -0500 +Subject: jbd2: fix assertion failure in jbd2_journal_flush() + +From: Jan Kara + +commit d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a upstream. + +The following race is possible between start_this_handle() and someone +calling jbd2_journal_flush(). + +Process A Process B +start_this_handle(). + if (journal->j_barrier_count) # false + if (!journal->j_running_transaction) { #true + read_unlock(&journal->j_state_lock); + jbd2_journal_lock_updates() + jbd2_journal_flush() + write_lock(&journal->j_state_lock); + if (journal->j_running_transaction) { + # false + ... wait for committing trans ... + write_unlock(&journal->j_state_lock); + ... + write_lock(&journal->j_state_lock); + if (!journal->j_running_transaction) { # true + jbd2_get_transaction(journal, new_transaction); + write_unlock(&journal->j_state_lock); + goto repeat; # eventually blocks on j_barrier_count > 0 + ... + J_ASSERT(!journal->j_running_transaction); + # fails + +We fix the race by rechecking j_barrier_count after reacquiring j_state_lock +in exclusive mode. + +Reported-by: yjwsignal@empal.com +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -209,7 +209,8 @@ repeat: + if (!new_transaction) + goto alloc_transaction; + write_lock(&journal->j_state_lock); +- if (!journal->j_running_transaction) { ++ if (!journal->j_running_transaction && ++ !journal->j_barrier_count) { + jbd2_get_transaction(journal, new_transaction); + new_transaction = NULL; + } +From d096ad0f79a782935d2e06ae8fb235e8c5397775 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Tue, 25 Dec 2012 14:08:16 -0500 +Subject: ext4: do not try to write superblock on ro remount w/o journal + +From: Michael Tokarev + +commit d096ad0f79a782935d2e06ae8fb235e8c5397775 upstream. + +When a journal-less ext4 filesystem is mounted on a read-only block +device (blockdev --setro will do), each remount (for other, unrelated, +flags, like suid=>nosuid etc) results in a series of scary messages +from kernel telling about I/O errors on the device. + +This is becauese of the following code ext4_remount(): + + if (sbi->s_journal == NULL) + ext4_commit_super(sb, 1); + +at the end of remount procedure, which forces writing (flushing) of +a superblock regardless whenever it is dirty or not, if the filesystem +is readonly or not, and whenever the device itself is readonly or not. + +We only need call ext4_commit_super when the file system had been +previously mounted read/write. + +Thanks to Eric Sandeen for help in diagnosing this issue. + +Signed-off-By: Michael Tokarev +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4729,7 +4729,7 @@ static int ext4_remount(struct super_blo + } + + ext4_setup_system_zone(sb); +- if (sbi->s_journal == NULL) ++ if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) + ext4_commit_super(sb, 1); + + #ifdef CONFIG_QUOTA +From 721e3eba21e43532e438652dd8f1fcdfce3187e7 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:48 -0500 +Subject: ext4: lock i_mutex when truncating orphan inodes + +From: Theodore Ts'o + +commit 721e3eba21e43532e438652dd8f1fcdfce3187e7 upstream. + +Commit c278531d39 added a warning when ext4_flush_unwritten_io() is +called without i_mutex being taken. It had previously not been taken +during orphan cleanup since races weren't possible at that point in +the mount process, but as a result of this c278531d39, we will now see +a kernel WARN_ON in this case. Take the i_mutex in +ext4_orphan_cleanup() to suppress this warning. + +Reported-by: Alexander Beregalov +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2225,7 +2225,9 @@ static void ext4_orphan_cleanup(struct s + __func__, inode->i_ino, inode->i_size); + jbd_debug(2, "truncating inode %lu to %lld bytes\n", + inode->i_ino, inode->i_size); ++ mutex_lock(&inode->i_mutex); + ext4_truncate(inode); ++ mutex_unlock(&inode->i_mutex); + nr_truncates++; + } else { + ext4_msg(sb, KERN_DEBUG, +From 0e9a9a1ad619e7e987815d20262d36a2f95717ca Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:50 -0500 +Subject: ext4: avoid hang when mounting non-journal filesystems with orphan list + +From: Theodore Ts'o + +commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. + +When trying to mount a file system which does not contain a journal, +but which does have a orphan list containing an inode which needs to +be truncated, the mount call with hang forever in +ext4_orphan_cleanup() because ext4_orphan_del() will return +immediately without removing the inode from the orphan list, leading +to an uninterruptible loop in kernel code which will busy out one of +the CPU's on the system. + +This can be trivially reproduced by trying to mount the file system +found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs +source tree. If a malicious user were to put this on a USB stick, and +mount it on a Linux desktop which has automatic mounts enabled, this +could be considered a potential denial of service attack. (Not a big +deal in practice, but professional paranoids worry about such things, +and have even been known to allocate CVE numbers for such problems.) + +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2498,7 +2498,8 @@ int ext4_orphan_del(handle_t *handle, st + struct ext4_iloc iloc; + int err = 0; + +- if (!EXT4_SB(inode->i_sb)->s_journal) ++ if ((!EXT4_SB(inode->i_sb)->s_journal) && ++ !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) + return 0; + + mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); +From 0ecaef0644973e9006fdbc6974301047aaff9bc6 Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Sun, 6 Jan 2013 23:38:47 -0500 +Subject: ext4: release buffer in failed path in dx_probe() + +From: Guo Chao + +commit 0ecaef0644973e9006fdbc6974301047aaff9bc6 upstream. + +If checksum fails, we should also release the buffer +read from previous iteration. + +Signed-off-by: Guo Chao +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Darrick J. Wong - +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -725,7 +725,7 @@ dx_probe(const struct qstr *d_name, stru + ext4_warning(dir->i_sb, "Node failed checksum"); + brelse(bh); + *err = ERR_BAD_DX_DIR; +- goto fail; ++ goto fail2; + } + set_buffer_verified(bh); + +From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 +From: Ed Cashin +Date: Mon, 17 Dec 2012 16:03:58 -0800 +Subject: aoe: remove vestigial request queue allocation + +From: Ed Cashin + +commit 0a41409c518083133e79015092585d68915865be upstream. + +Before the aoe driver was an I/O request handler, it was a +make_request-style block driver. Even so, there was a problem where +sysfs expected a request queue to exist, so one was provided in commit +7135a71b19be ("aoe: allocate unused request_queue for sysfs"). + +During the transition to the request-handler style, a patch was merged +that was based on a driver without the noop queue, and the noop queue +remained in place after the patch was merged, even though a new +functional queue was introduced by the patch, allocated through +blk_init_queue. + +The user impact is a memory leak proportional to the number of AoE +targets discovered. This patch removes the memory leak and cleans up +vestiges of the old do-nothing queue from the aoeblk_gdalloc function. + +Signed-off-by: Ed Cashin +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/aoe/aoeblk.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/block/aoe/aoeblk.c ++++ b/drivers/block/aoe/aoeblk.c +@@ -231,18 +231,12 @@ aoeblk_gdalloc(void *vp) + if (q == NULL) { + pr_err("aoe: cannot allocate block queue for %ld.%d\n", + d->aoemajor, d->aoeminor); +- mempool_destroy(mp); +- goto err_disk; ++ goto err_mempool; + } + +- d->blkq = blk_alloc_queue(GFP_KERNEL); +- if (!d->blkq) +- goto err_mempool; +- d->blkq->backing_dev_info.name = "aoe"; +- if (bdi_init(&d->blkq->backing_dev_info)) +- goto err_blkq; + spin_lock_irqsave(&d->lock, flags); +- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); ++ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); ++ q->backing_dev_info.name = "aoe"; + q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; + d->bufpool = mp; + d->blkq = gd->queue = q; +@@ -265,11 +259,8 @@ aoeblk_gdalloc(void *vp) + aoedisk_add_sysfs(d); + return; + +-err_blkq: +- blk_cleanup_queue(d->blkq); +- d->blkq = NULL; + err_mempool: +- mempool_destroy(d->bufpool); ++ mempool_destroy(mp); + err_disk: + put_disk(gd); + err: +From 2fb7d99d0de3fd8ae869f35ab682581d8455887a Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 10 Oct 2012 00:08:56 +0900 +Subject: udf: fix memory leak while allocating blocks during write + +From: Namjae Jeon + +commit 2fb7d99d0de3fd8ae869f35ab682581d8455887a upstream. + +Need to brelse the buffer_head stored in cur_epos and next_epos. + +Signed-off-by: Namjae Jeon +Signed-off-by: Ashish Sangwan +Signed-off-by: Jan Kara +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/inode.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -765,6 +765,8 @@ static sector_t inode_getblk(struct inod + goal, err); + if (!newblocknum) { + brelse(prev_epos.bh); ++ brelse(cur_epos.bh); ++ brelse(next_epos.bh); + *err = -ENOSPC; + return 0; + } +@@ -795,6 +797,8 @@ static sector_t inode_getblk(struct inod + udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); + + brelse(prev_epos.bh); ++ brelse(cur_epos.bh); ++ brelse(next_epos.bh); + + newblock = udf_get_pblock(inode->i_sb, newblocknum, + iinfo->i_location.partitionReferenceNum, 0); +From fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 10 Oct 2012 00:09:12 +0900 +Subject: udf: don't increment lenExtents while writing to a hole + +From: Namjae Jeon + +commit fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 upstream. + +Incrementing lenExtents even while writing to a hole is bad +for performance as calls to udf_discard_prealloc and +udf_truncate_tail_extent would not return from start if +isize != lenExtents + +Signed-off-by: Namjae Jeon +Signed-off-by: Ashish Sangwan +Signed-off-by: Jan Kara +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/inode.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -601,6 +601,7 @@ static sector_t inode_getblk(struct inod + struct udf_inode_info *iinfo = UDF_I(inode); + int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; + int lastblock = 0; ++ bool isBeyondEOF; + + *err = 0; + *new = 0; +@@ -680,7 +681,7 @@ static sector_t inode_getblk(struct inod + /* Are we beyond EOF? */ + if (etype == -1) { + int ret; +- ++ isBeyondEOF = 1; + if (count) { + if (c) + laarr[0] = laarr[1]; +@@ -723,6 +724,7 @@ static sector_t inode_getblk(struct inod + endnum = c + 1; + lastblock = 1; + } else { ++ isBeyondEOF = 0; + endnum = startnum = ((count > 2) ? 2 : count); + + /* if the current extent is in position 0, +@@ -770,7 +772,8 @@ static sector_t inode_getblk(struct inod + *err = -ENOSPC; + return 0; + } +- iinfo->i_lenExtents += inode->i_sb->s_blocksize; ++ if (isBeyondEOF) ++ iinfo->i_lenExtents += inode->i_sb->s_blocksize; + } + + /* if the extent the requsted block is located in contains multiple +From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Tue, 4 Dec 2012 23:23:16 +0100 +Subject: ACPI : do not use Lid and Sleep button for S5 wakeup + +From: Zhang Rui + +commit b7e383046c2c7c13ad928cd7407eafff758ddd4b upstream. + +When system enters power off, the _PSW of Lid device is enabled. +But this may cause the system to reboot instead of power off. + +A proper way to fix this is to always disable lid wakeup capability for S5. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 +Signed-off-by: Zhang Rui +Signed-off-by: Rafael J. Wysocki +Cc: Joseph Salisbury +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/scan.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -859,8 +859,8 @@ acpi_bus_extract_wakeup_device_power_pac + static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + { + struct acpi_device_id button_device_ids[] = { +- {"PNP0C0D", 0}, + {"PNP0C0C", 0}, ++ {"PNP0C0D", 0}, + {"PNP0C0E", 0}, + {"", 0}, + }; +@@ -872,6 +872,11 @@ static void acpi_bus_set_run_wake_flags( + /* Power button, Lid switch always enable wakeup */ + if (!acpi_match_device_ids(device, button_device_ids)) { + device->wakeup.flags.run_wake = 1; ++ if (!acpi_match_device_ids(device, &button_device_ids[1])) { ++ /* Do not use Lid/sleep button for S5 wakeup */ ++ if (device->wakeup.sleep_state == ACPI_STATE_S5) ++ device->wakeup.sleep_state = ACPI_STATE_S4; ++ } + device_set_wakeup_capable(&device->dev, true); + return; + } +From db04328c167ff8e7c57f4a3532214aeada3a82fd Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 11 Dec 2012 01:14:11 +0900 +Subject: regmap: debugfs: Avoid overflows for very small reads + +From: Mark Brown + +commit db04328c167ff8e7c57f4a3532214aeada3a82fd upstream. + +If count is less than the size of a register then we may hit integer +wraparound when trying to move backwards to check if we're still in +the buffer. Instead move the position forwards to check if it's still +in the buffer, we are unlikely to be able to allocate a buffer +sufficiently big to overflow here. + +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org + +--- + drivers/base/regmap/regmap-debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -90,7 +90,7 @@ static ssize_t regmap_map_read_file(stru + /* If we're in the region the user is trying to read */ + if (p >= *ppos) { + /* ...but not beyond it */ +- if (buf_pos >= count - 1 - tot_len) ++ if (buf_pos + 1 + tot_len >= count) + break; + + /* Format the register */ +From 128dd1759d96ad36c379240f8b9463e8acfd37a1 Mon Sep 17 00:00:00 2001 +From: Eric Wong +Date: Tue, 1 Jan 2013 21:20:27 +0000 +Subject: epoll: prevent missed events on EPOLL_CTL_MOD + +From: Eric Wong + +commit 128dd1759d96ad36c379240f8b9463e8acfd37a1 upstream. + +EPOLL_CTL_MOD sets the interest mask before calling f_op->poll() to +ensure events are not missed. Since the modifications to the interest +mask are not protected by the same lock as ep_poll_callback, we need to +ensure the change is visible to other CPUs calling ep_poll_callback. + +We also need to ensure f_op->poll() has an up-to-date view of past +events which occured before we modified the interest mask. So this +barrier also pairs with the barrier in wq_has_sleeper(). + +This should guarantee either ep_poll_callback or f_op->poll() (or both) +will notice the readiness of a recently-ready/modified item. + +This issue was encountered by Andreas Voellmy and Junchang(Jason) Wang in: +http://thread.gmane.org/gmane.linux.kernel/1408782/ + +Signed-off-by: Eric Wong +Cc: Hans Verkuil +Cc: Jiri Olsa +Cc: Jonathan Corbet +Cc: Al Viro +Cc: Davide Libenzi +Cc: Hans de Goede +Cc: Mauro Carvalho Chehab +Cc: David Miller +Cc: Eric Dumazet +Cc: Andrew Morton +Cc: Andreas Voellmy +Tested-by: "Junchang(Jason) Wang" +Cc: netdev@vger.kernel.org +Cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/eventpoll.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1285,7 +1285,7 @@ static int ep_modify(struct eventpoll *e + * otherwise we might miss an event that happens between the + * f_op->poll() call and the new event set registering. + */ +- epi->event.events = event->events; ++ epi->event.events = event->events; /* need barrier below */ + pt._key = event->events; + epi->event.data = event->data; /* protected by mtx */ + if (epi->event.events & EPOLLWAKEUP) { +@@ -1296,6 +1296,26 @@ static int ep_modify(struct eventpoll *e + } + + /* ++ * The following barrier has two effects: ++ * ++ * 1) Flush epi changes above to other CPUs. This ensures ++ * we do not miss events from ep_poll_callback if an ++ * event occurs immediately after we call f_op->poll(). ++ * We need this because we did not take ep->lock while ++ * changing epi above (but ep_poll_callback does take ++ * ep->lock). ++ * ++ * 2) We also need to ensure we do not miss _past_ events ++ * when calling f_op->poll(). This barrier also ++ * pairs with the barrier in wq_has_sleeper (see ++ * comments for wq_has_sleeper). ++ * ++ * This barrier will now guarantee ep_poll_callback or f_op->poll ++ * (or both) will notice the readiness of an item. ++ */ ++ smp_mb(); ++ ++ /* + * Get current event bits. We can safely use the file* here because + * its usage count has been increased by the caller of this function. + */ +From 436136cec650d661eb662fcb508a99878606d050 Mon Sep 17 00:00:00 2001 +From: Marek Vasut +Date: Sat, 24 Nov 2012 06:15:57 +0100 +Subject: HID: add quirk for Freescale i.MX23 ROM recovery + +From: Marek Vasut + +commit 436136cec650d661eb662fcb508a99878606d050 upstream. + +The USB recovery mode present in i.MX23 ROM emulates USB HID. It needs this +quirk to behave properly. + +Even if the official branding of the chip is Freescale i.MX23, I named it +Sigmatel STMP3780 since that's what the chip really is and it even reports +itself as STMP3780. + +Signed-off-by: Marek Vasut +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/usbhid/hid-quirks.c | 1 + + 2 files changed, 4 insertions(+) + +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -696,6 +696,9 @@ + #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f + #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 + ++#define USB_VENDOR_ID_SIGMATEL 0x066F ++#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 ++ + #define USB_VENDOR_ID_SKYCABLE 0x1223 + #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 + +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -79,6 +79,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, +From a8c02db029385fb4426e0396e108ab23cd08f384 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 18 Dec 2012 14:05:01 +0000 +Subject: ASoC: arizona: Correct FLL source definitions + +From: Mark Brown + +commit a8c02db029385fb4426e0396e108ab23cd08f384 upstream. + +The FLL source constants were numbered as a simple enumeration but were +being used in the code as direct values to be written to the registers. +Renumber the constants to reflect the usage. + +Reported-by: Ryo Tsutsui +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/sound/soc/codecs/arizona.h ++++ b/sound/soc/codecs/arizona.h +@@ -32,15 +32,15 @@ + + #define ARIZONA_FLL_SRC_MCLK1 0 + #define ARIZONA_FLL_SRC_MCLK2 1 +-#define ARIZONA_FLL_SRC_SLIMCLK 2 +-#define ARIZONA_FLL_SRC_FLL1 3 +-#define ARIZONA_FLL_SRC_FLL2 4 +-#define ARIZONA_FLL_SRC_AIF1BCLK 5 +-#define ARIZONA_FLL_SRC_AIF2BCLK 6 +-#define ARIZONA_FLL_SRC_AIF3BCLK 7 +-#define ARIZONA_FLL_SRC_AIF1LRCLK 8 +-#define ARIZONA_FLL_SRC_AIF2LRCLK 9 +-#define ARIZONA_FLL_SRC_AIF3LRCLK 10 ++#define ARIZONA_FLL_SRC_SLIMCLK 3 ++#define ARIZONA_FLL_SRC_FLL1 4 ++#define ARIZONA_FLL_SRC_FLL2 5 ++#define ARIZONA_FLL_SRC_AIF1BCLK 8 ++#define ARIZONA_FLL_SRC_AIF2BCLK 9 ++#define ARIZONA_FLL_SRC_AIF3BCLK 10 ++#define ARIZONA_FLL_SRC_AIF1LRCLK 12 ++#define ARIZONA_FLL_SRC_AIF2LRCLK 13 ++#define ARIZONA_FLL_SRC_AIF3LRCLK 14 + + #define ARIZONA_MIXER_VOL_MASK 0x00FE + #define ARIZONA_MIXER_VOL_SHIFT 1 +From 7110a287ff2b1f3780905d1686a1a4edccb95133 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Thu, 20 Dec 2012 23:29:42 +0800 +Subject: ASoC: arizona: Do proper shift for setting AIF rate + +From: Axel Lin + +commit 7110a287ff2b1f3780905d1686a1a4edccb95133 upstream. + +ARIZONA_AIF1_RATE_MASK is 0x7800 /* AIF1_RATE - [14:11] */ +Thus we need left shift ARIZONA_AIF1_RATE_SHIFT when setting aif1 rate. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/sound/soc/codecs/arizona.c ++++ b/sound/soc/codecs/arizona.c +@@ -677,7 +677,8 @@ static int arizona_hw_params(struct snd_ + snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, + ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); + snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, +- ARIZONA_AIF1_RATE_MASK, 8); ++ ARIZONA_AIF1_RATE_MASK, ++ 8 << ARIZONA_AIF1_RATE_SHIFT); + break; + default: + arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); +From d71753e22b24548911b377db28f80870cf50d07b Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 10:48:02 +0000 +Subject: ASoC: arizona: Remove DSP B and left justified AIF modes + +From: Mark Brown + +commit d71753e22b24548911b377db28f80870cf50d07b upstream. + +These are not supported. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/arizona.c ++++ b/sound/soc/codecs/arizona.c +@@ -409,15 +409,9 @@ static int arizona_set_fmt(struct snd_so + case SND_SOC_DAIFMT_DSP_A: + mode = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- mode = 1; +- break; + case SND_SOC_DAIFMT_I2S: + mode = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- mode = 3; +- break; + default: + arizona_aif_err(dai, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 21:18:12 +0000 +Subject: ASoC: wm2000: Fix sense of speech clarity enable + +From: Mark Brown + +commit 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa upstream. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2000.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/codecs/wm2000.c ++++ b/sound/soc/codecs/wm2000.c +@@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_cl + + ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); + if (wm2000->speech_clarity) +- ret &= ~WM2000_SPEECH_CLARITY; +- else + ret |= WM2000_SPEECH_CLARITY; ++ else ++ ret &= ~WM2000_SPEECH_CLARITY; + wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); + + wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); +From 2a5f431592343b78896013b055582f94c12a5049 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 21 Dec 2012 16:28:37 +0800 +Subject: ASoC: wm2200: Fix setting dai format in wm2200_set_fmt + +From: Axel Lin + +commit 2a5f431592343b78896013b055582f94c12a5049 upstream. + +According to the defines in wm2200.h: +/* + * R1284 (0x504) - Audio IF 1_5 + */ + +We should not left shift 1 bit for fmt_val when setting dai format. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2200.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/codecs/wm2200.c ++++ b/sound/soc/codecs/wm2200.c +@@ -1440,7 +1440,7 @@ static int wm2200_set_fmt(struct snd_soc + WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, + lrclk); + snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, +- WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); ++ WM2200_AIF1_FMT_MASK, fmt_val); + + return 0; + } +From 0cc411b934c4317b363d1af993549f391852b980 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 10:48:10 +0000 +Subject: ASoC: wm2200: Remove DSP B and left justified AIF modes + +From: Mark Brown + +commit 0cc411b934c4317b363d1af993549f391852b980 upstream. + +These are not supported. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2200.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/wm2200.c ++++ b/sound/soc/codecs/wm2200.c +@@ -1380,15 +1380,9 @@ static int wm2200_set_fmt(struct snd_soc + case SND_SOC_DAIFMT_DSP_A: + fmt_val = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- fmt_val = 1; +- break; + case SND_SOC_DAIFMT_I2S: + fmt_val = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- fmt_val = 3; +- break; + default: + dev_err(codec->dev, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From ad1937cdd59c412097ec2bb8f38c12a5640f1f9a Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Thu, 20 Dec 2012 16:17:25 +0800 +Subject: ASoC: sta529: Fix update register bits in sta529_set_dai_fmt + +From: Axel Lin + +commit ad1937cdd59c412097ec2bb8f38c12a5640f1f9a upstream. + +Both the mask and mode settings are wrong in current code. + +According to the datasheet: + +S2PCFG0 (0x0A) +BIT[3:1] DATA_FORMAT + serial interface protocol format: + 000: left Justified + 001: I2S (default) + 010: right justified + 100: PCM no delay + 101: PCM delay + 111: DSP + +Thus fixes the defines for LEFT_J_DATA_FORMAT, I2S_DATA_FORMAT, and +RIGHT_J_DATA_FORMAT. +Also adds define for DATA_FORMAT_MSK. + +Signed-off-by: Axel Lin +Acked-by: Rajeev Kumar +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/sta529.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/sound/soc/codecs/sta529.c ++++ b/sound/soc/codecs/sta529.c +@@ -74,9 +74,10 @@ + SNDRV_PCM_FMTBIT_S32_LE) + #define S2PC_VALUE 0x98 + #define CLOCK_OUT 0x60 +-#define LEFT_J_DATA_FORMAT 0x10 +-#define I2S_DATA_FORMAT 0x12 +-#define RIGHT_J_DATA_FORMAT 0x14 ++#define DATA_FORMAT_MSK 0x0E ++#define LEFT_J_DATA_FORMAT 0x00 ++#define I2S_DATA_FORMAT 0x02 ++#define RIGHT_J_DATA_FORMAT 0x04 + #define CODEC_MUTE_VAL 0x80 + + #define POWER_CNTLMSAK 0x40 +@@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd + return -EINVAL; + } + +- snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); ++ snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); + + return 0; + } +From 08b27848da620f206a8b6d80f26184485dd7aa40 Mon Sep 17 00:00:00 2001 +From: Patrick Lai +Date: Wed, 19 Dec 2012 19:36:02 -0800 +Subject: ASoC: pcm: allow backend hardware to be freed in pause state + +From: Patrick Lai + +commit 08b27848da620f206a8b6d80f26184485dd7aa40 upstream. + +When front-end PCM session is in paused state, back-end +PCM session will be put in paused state as well if given +front-end PCM session is the only client of given back-end. +Then, application closes front-end PCM session, DPCM +framework will not allow back-end enters HW_FREE state +so back-end will never get shutdown completely. + +Signed-off-by: Patrick Lai +Acked-by: Liam Girdwood +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/soc-pcm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1240,6 +1240,7 @@ static int dpcm_be_dai_hw_free(struct sn + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && ++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + continue; + +From 5f960294e2031d12f10c8488c3446fecbf59628d Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 21:06:08 +0000 +Subject: ASoC: wm5100: Remove DSP B and left justified formats + +From: Mark Brown + +commit 5f960294e2031d12f10c8488c3446fecbf59628d upstream. + +These are not supported + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm5100.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/wm5100.c ++++ b/sound/soc/codecs/wm5100.c +@@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc + case SND_SOC_DAIFMT_DSP_A: + mask = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- mask = 1; +- break; + case SND_SOC_DAIFMT_I2S: + mask = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- mask = 3; +- break; + default: + dev_err(codec->dev, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From c930812fe5ebe725760422c9c351d1f6fde1502d Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:56 +0100 +Subject: udldrmfb: Fix EDID not working with monitors with EDID + extension blocks + +From: Hans de Goede + +commit c930812fe5ebe725760422c9c351d1f6fde1502d upstream. + +udldrmfb only reads the main EDID block, and if that advertises extensions +the drm_edid code expects them to be present, and starts reading beyond the +buffer udldrmfb passes it. + +Although it may be possible to read more EDID info with the udl we simpy don't +know how, and even if trial and error gets it working on one device, that is +no guarantee it will work on other revisions. So this patch does a simple fix +in the form of patching the EDID info to report 0 extension blocks, this +fixes udldrmfb only doing 1024x768 on monitors with EDID extension blocks. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -57,6 +57,14 @@ static int udl_get_modes(struct drm_conn + + edid = (struct edid *)udl_get_edid(udl); + ++ /* ++ * We only read the main block, but if the monitor reports extension ++ * blocks then the drm edid code expects them to be present, so patch ++ * the extension count to 0. ++ */ ++ edid->checksum += edid->extensions; ++ edid->extensions = 0; ++ + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); +From 242187b362555849e8c971dfbbfd55f8bd9fa717 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:57 +0100 +Subject: udldrmfb: udl_get_edid: usb_control_msg buffer must not be on the stack + +From: Hans de Goede + +commit 242187b362555849e8c971dfbbfd55f8bd9fa717 upstream. + +The buffer passed to usb_control_msg may end up in scatter-gather list, and +may thus not be on the stack. Having it on the stack usually works on x86, but +not on other archs. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -22,13 +22,17 @@ + static u8 *udl_get_edid(struct udl_device *udl) + { + u8 *block; +- char rbuf[3]; ++ char *rbuf; + int ret, i; + + block = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (block == NULL) + return NULL; + ++ rbuf = kmalloc(2, GFP_KERNEL); ++ if (rbuf == NULL) ++ goto error; ++ + for (i = 0; i < EDID_LENGTH; i++) { + ret = usb_control_msg(udl->ddev->usbdev, + usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), +@@ -42,10 +46,12 @@ static u8 *udl_get_edid(struct udl_devic + block[i] = rbuf[1]; + } + ++ kfree(rbuf); + return block; + + error: + kfree(block); ++ kfree(rbuf); + return NULL; + } + +From 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:58 +0100 +Subject: udldrmfb: udl_get_edid: drop unneeded i-- + +From: Hans de Goede + +commit 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 upstream. + +This is a left-over from when udl_get_edid returned the amount of bytes +successfully read, which it no longer does. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -40,7 +40,6 @@ static u8 *udl_get_edid(struct udl_devic + HZ); + if (ret < 1) { + DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); +- i--; + goto error; + } + block[i] = rbuf[1]; +From 6d283dba3721cc43be014b50a1acc2f35860a65a Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 14 Jan 2013 13:17:50 -0800 +Subject: vfs: add missing virtual cache flush after editing partial pages + +From: Linus Torvalds + +commit 6d283dba3721cc43be014b50a1acc2f35860a65a upstream. + +Andrew Morton pointed this out a month ago, and then I completely forgot +about it. + +If we read a partial last page of a block device, we will zero out the +end of the page, but since that page can then be mapped into user space, +we should also make sure to flush the cache on architectures that have +virtual caches. We have the flush_dcache_page() function for this, so +use it. + +Now, in practice this really never matters, because nobody sane uses +virtual caches to begin with, and they largely exist on old broken RISC +arhitectures. + +And even if you did run on one of those obsolete CPU's, the whole "mmap +and access the last partial page of a block device" behavior probably +doesn't actually exist. The normal IO functions (read/write) will never +see the zeroed-out part of the page that migth not be coherent in the +cache, because they honor the size of the device. + +So I'm marking this for stable (3.7 only), but I'm not sure anybody will +ever care. + +Pointed-out-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/buffer.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2939,6 +2939,7 @@ static void guard_bh_eod(int rw, struct + void *kaddr = kmap_atomic(bh->b_page); + memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); + kunmap_atomic(kaddr); ++ flush_dcache_page(bh->b_page); + } + } + +From 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 Mon Sep 17 00:00:00 2001 +From: David Henningsson +Date: Wed, 19 Dec 2012 09:44:47 +0100 +Subject: Revert "ALSA: hda - Shut up pins at power-saving mode with Conexnat codecs" + +From: David Henningsson + +commit 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 upstream. + +This reverts commit 697c373e34613609cb5450f98b91fefb6e910588. + +The original patch was meant to remove clicking, but in fact caused even +more clicking instead. + +Thanks to c4pp4 for doing most of the work with this bug. + +BugLink: https://bugs.launchpad.net/bugs/886975 +Signed-off-by: David Henningsson +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_conexant.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -553,24 +553,12 @@ static int conexant_build_controls(struc + return 0; + } + +-#ifdef CONFIG_PM +-static int conexant_suspend(struct hda_codec *codec) +-{ +- snd_hda_shutup_pins(codec); +- return 0; +-} +-#endif +- + static const struct hda_codec_ops conexant_patch_ops = { + .build_controls = conexant_build_controls, + .build_pcms = conexant_build_pcms, + .init = conexant_init, + .free = conexant_free, + .set_power_state = conexant_set_power, +-#ifdef CONFIG_PM +- .suspend = conexant_suspend, +-#endif +- .reboot_notify = snd_hda_shutup_pins, + }; + + #ifdef CONFIG_SND_HDA_INPUT_BEEP +@@ -4393,10 +4381,6 @@ static const struct hda_codec_ops cx_aut + .init = cx_auto_init, + .free = conexant_free, + .unsol_event = snd_hda_jack_unsol_event, +-#ifdef CONFIG_PM +- .suspend = conexant_suspend, +-#endif +- .reboot_notify = snd_hda_shutup_pins, + }; + + /* +From d7dab4dbbb2d1b0c903378d6bade2e4ae161804e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 8 Jan 2013 13:51:30 +0100 +Subject: ALSA: hda - Disable runtime D3 for Intel CPT & co + +From: Takashi Iwai + +commit d7dab4dbbb2d1b0c903378d6bade2e4ae161804e upstream. + +We've got a few bug reports that the runtime D3 results in the dead +HD-audio controller. It seems that the problem is in a deeper level +than the sound driver itself, so as a temporal solution, disable the +feature for these controllers again. + +Reported-and-tested-by: Vincent Blut +Reported-and-tested-by: Maurizio Avogadro +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_intel.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -559,9 +559,12 @@ enum { + #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ + + /* quirks for Intel PCH */ +-#define AZX_DCAPS_INTEL_PCH \ ++#define AZX_DCAPS_INTEL_PCH_NOPM \ + (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ +- AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) ++ AZX_DCAPS_COUNT_LPIB_DELAY) ++ ++#define AZX_DCAPS_INTEL_PCH \ ++ (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) + + /* quirks for ATI SB / AMD Hudson */ + #define AZX_DCAPS_PRESET_ATI_SB \ +@@ -3448,13 +3451,13 @@ static void __devexit azx_remove(struct + static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + /* CPT */ + { PCI_DEVICE(0x8086, 0x1c20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* PBG */ + { PCI_DEVICE(0x8086, 0x1d20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Panther Point */ + { PCI_DEVICE(0x8086, 0x1e20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, +From 41b645c8624df6ace020a8863ad1449d69140f7d Mon Sep 17 00:00:00 2001 +From: Mike Dunn +Date: Mon, 7 Jan 2013 13:55:12 -0800 +Subject: ALSA: pxa27x: fix ac97 cold reset + +From: Mike Dunn + +commit 41b645c8624df6ace020a8863ad1449d69140f7d upstream. + +Cold reset on the pxa27x currently fails and + + pxa2xx_ac97_try_cold_reset: cold reset timeout (GSR=0x44) + +appears in the kernel log. Through trial-and-error (the pxa270 developer's +manual is mostly incoherent on the topic of ac97 reset), I got cold reset to +complete by setting the WARM_RST bit in the GCR register (and later noticed that +pxa3xx does this for cold reset as well). Also, a timeout loop is needed to +wait for the reset to complete. + +Tested on a palm treo 680 machine. + +Signed-off-by: Mike Dunn +Acked-by: Igor Grinberg +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/arm/pxa2xx-ac97-lib.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/sound/arm/pxa2xx-ac97-lib.c ++++ b/sound/arm/pxa2xx-ac97-lib.c +@@ -148,6 +148,8 @@ static inline void pxa_ac97_warm_pxa27x( + + static inline void pxa_ac97_cold_pxa27x(void) + { ++ unsigned int timeout; ++ + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ + GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + +@@ -157,8 +159,10 @@ static inline void pxa_ac97_cold_pxa27x( + clk_enable(ac97conf_clk); + udelay(5); + clk_disable(ac97conf_clk); +- GCR = GCR_COLD_RST; +- udelay(50); ++ GCR = GCR_COLD_RST | GCR_WARM_RST; ++ timeout = 100; /* wait for the codec-ready bit to be set */ ++ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) ++ mdelay(1); + } + #endif + +From 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd Mon Sep 17 00:00:00 2001 +From: Mike Dunn +Date: Mon, 7 Jan 2013 13:55:13 -0800 +Subject: ALSA: pxa27x: fix ac97 warm reset + +From: Mike Dunn + +commit 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd upstream. + +This patch fixes some code that implements a work-around to a hardware bug in +the ac97 controller on the pxa27x. A bug in the controller's warm reset +functionality requires that the mfp used by the controller as the AC97_nRESET +line be temporarily reconfigured as a generic output gpio (AF0) and manually +held high for the duration of the warm reset cycle. This is what was done in +the original code, but it was broken long ago by commit fb1bf8cd + ([ARM] pxa: introduce processor specific pxa27x_assert_ac97reset()) +which changed the mfp to a GPIO input instead of a high output. + +The fix requires the ac97 controller to obtain the gpio via gpio_request_one(), +with arguments that configure the gpio as an output initially driven high. + +Tested on a palm treo 680 machine. Reportedly, this broken code only prevents a +warm reset on hardware that lacks a pull-up on the line, which appears to be the +case for me. + +Signed-off-by: Mike Dunn +Signed-off-by: Igor Grinberg +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 +++ + arch/arm/mach-pxa/pxa27x.c | 4 ++-- + sound/arm/pxa2xx-ac97-lib.c | 18 +++++++++++++++++- + 3 files changed, 22 insertions(+), 3 deletions(-) + +--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h ++++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +@@ -463,6 +463,9 @@ + GPIO76_LCD_PCLK, \ + GPIO77_LCD_BIAS + ++/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ ++#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) ++#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) + + extern int keypad_set_wake(unsigned int on); + #endif /* __ASM_ARCH_MFP_PXA27X_H */ +--- a/arch/arm/mach-pxa/pxa27x.c ++++ b/arch/arm/mach-pxa/pxa27x.c +@@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) + EXPORT_SYMBOL(pxa27x_clear_otgph); + + static unsigned long ac97_reset_config[] = { +- GPIO113_GPIO, ++ GPIO113_AC97_nRESET_GPIO_HIGH, + GPIO113_AC97_nRESET, +- GPIO95_GPIO, ++ GPIO95_AC97_nRESET_GPIO_HIGH, + GPIO95_AC97_nRESET, + }; + +--- a/sound/arm/pxa2xx-ac97-lib.c ++++ b/sound/arm/pxa2xx-ac97-lib.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -344,8 +345,21 @@ int __devinit pxa2xx_ac97_hw_probe(struc + } + + if (cpu_is_pxa27x()) { +- /* Use GPIO 113 as AC97 Reset on Bulverde */ ++ /* ++ * This gpio is needed for a work-around to a bug in the ac97 ++ * controller during warm reset. The direction and level is set ++ * here so that it is an output driven high when switching from ++ * AC97_nRESET alt function to generic gpio. ++ */ ++ ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, ++ "pxa27x ac97 reset"); ++ if (ret < 0) { ++ pr_err("%s: gpio_request_one() failed: %d\n", ++ __func__, ret); ++ goto err_conf; ++ } + pxa27x_assert_ac97reset(reset_gpio, 0); ++ + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); + if (IS_ERR(ac97conf_clk)) { + ret = PTR_ERR(ac97conf_clk); +@@ -388,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); + + void pxa2xx_ac97_hw_remove(struct platform_device *dev) + { ++ if (cpu_is_pxa27x()) ++ gpio_free(reset_gpio); + GCR |= GCR_ACLINK_OFF; + free_irq(IRQ_AC97, NULL); + if (ac97conf_clk) { +From 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Tue, 4 Dec 2012 15:59:55 +0000 +Subject: staging: comedi: prevent auto-unconfig of manually configured devices + +From: Ian Abbott + +commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c upstream. + +When a low-level comedi driver auto-configures a device, a `struct +comedi_dev_file_info` is allocated (as well as a `struct +comedi_device`) by `comedi_alloc_board_minor()`. A pointer to the +hardware `struct device` is stored as a cookie in the `struct +comedi_dev_file_info`. When the low-level comedi driver +auto-unconfigures the device, `comedi_auto_unconfig()` uses the cookie +to find the `struct comedi_dev_file_info` so it can detach the comedi +device from the driver, clean it up and free it. + +A problem arises if the user manually unconfigures and reconfigures the +comedi device using the `COMEDI_DEVCONFIG` ioctl so that is no longer +associated with the original hardware device. The problem is that the +cookie is not cleared, so that a call to `comedi_auto_unconfig()` from +the low-level driver will still find it, detach it, clean it up and free +it. + +Stop this problem occurring by always clearing the `hardware_device` +cookie in the `struct comedi_dev_file_info` whenever the +`COMEDI_DEVCONFIG` ioctl call is successful. + +Signed-off-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/comedi_fops.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/comedi/comedi_fops.c ++++ b/drivers/staging/comedi/comedi_fops.c +@@ -1546,6 +1546,9 @@ static long comedi_unlocked_ioctl(struct + if (cmd == COMEDI_DEVCONFIG) { + rc = do_devconfig_ioctl(dev, + (struct comedi_devconfig __user *)arg); ++ if (rc == 0) ++ /* Evade comedi_auto_unconfig(). */ ++ dev_file_info->hardware_device = NULL; + goto done; + } + +From 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 Mon Sep 17 00:00:00 2001 +From: Éric Piel +Date: Wed, 19 Dec 2012 13:03:13 +0100 +Subject: staging: comedi: fix minimum AO period for NI 625x and NI 628x + +From: Éric Piel + +commit 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 upstream. + +The minimum period was set to 357 ns, while the divider for these boards is 50 +ns. This prevented to output at maximum speed as ni_ao_cmdtest() would return +357 but would not accept it. + +Not sure why it was set to 357 ns (this was done before the git history, +which starts 5 years ago). My guess is that it comes from reading the +specification stating a 2.8 MHz rate (~ 357 ns). The latest +specification states a 2.86 MHz rate (~ 350 ns), which makes a lot +more sense. + +Tested on a pci-6251. + +Signed-off-by: Éric Piel +Acked-By: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/ni_pcimio.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/staging/comedi/drivers/ni_pcimio.c ++++ b/drivers/staging/comedi/drivers/ni_pcimio.c +@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +From 34ffb33e09132401872fe79e95c30824ce194d23 Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Thu, 3 Jan 2013 12:15:26 +0000 +Subject: staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC + +From: Ian Abbott + +commit 34ffb33e09132401872fe79e95c30824ce194d23 upstream. + +The 'ni_at_a2150' module links to `cfc_write_to_buffer` in the +'comedi_fc' module, so selecting 'COMEDI_NI_AT_A2150' in the kernel config +needs to also select 'COMEDI_FC'. + +Signed-off-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/staging/comedi/Kconfig ++++ b/drivers/staging/comedi/Kconfig +@@ -444,6 +444,7 @@ config COMEDI_ADQ12B + + config COMEDI_NI_AT_A2150 + tristate "NI AT-A2150 ISA card support" ++ select COMEDI_FC + depends on VIRT_TO_BUS + ---help--- + Enable support for National Instruments AT-A2150 cards +From c0729eeefdcd76db338f635162bf0739fd2c5f6f Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Fri, 4 Jan 2013 11:33:21 +0000 +Subject: staging: comedi: comedi_test: fix race when cancelling command + +From: Ian Abbott + +commit c0729eeefdcd76db338f635162bf0739fd2c5f6f upstream. + +Éric Piel reported a kernel oops in the "comedi_test" module. It was a +NULL pointer dereference within `waveform_ai_interrupt()` (actually a +timer function) that sometimes occurred when a running asynchronous +command is cancelled (either by the `COMEDI_CANCEL` ioctl or by closing +the device file). + +This seems to be a race between the caller of `waveform_ai_cancel()` +which on return from that function goes and tears down the running +command, and the timer function which uses the command. In particular, +`async->cmd.chanlist` gets freed (and the pointer set to NULL) by +`do_become_nonbusy()` in "comedi_fops.c" but a previously scheduled +`waveform_ai_interrupt()` timer function will dereference that pointer +regardless, leading to the oops. + +Fix it by replacing the `del_timer()` call in `waveform_ai_cancel()` +with `del_timer_sync()`. + +Signed-off-by: Ian Abbott +Reported-by: Éric Piel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/comedi_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/comedi/drivers/comedi_test.c ++++ b/drivers/staging/comedi/drivers/comedi_test.c +@@ -372,7 +372,7 @@ static int waveform_ai_cancel(struct com + struct waveform_private *devpriv = dev->private; + + devpriv->timer_running = 0; +- del_timer(&devpriv->timer); ++ del_timer_sync(&devpriv->timer); + return 0; + } + +From da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sat, 29 Dec 2012 11:36:53 -0600 +Subject: staging: r8712u: Add new device ID + +From: Larry Finger + +commit da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 upstream. + +The ISY IWL 1000 USB WLAN stick with USB ID 050d:11f1 is a clone of +the Belkin F7D1101 V1 device. + +Reported-by: Thomas Hartmann +Signed-off-by: Larry Finger +Cc: Thomas Hartmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/rtl8712/usb_intf.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/staging/rtl8712/usb_intf.c ++++ b/drivers/staging/rtl8712/usb_intf.c +@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_ + {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ + /* Belkin */ + {USB_DEVICE(0x050D, 0x945A)}, ++ /* ISY IWL - Belkin clone */ ++ {USB_DEVICE(0x050D, 0x11F1)}, + /* Corega */ + {USB_DEVICE(0x07AA, 0x0047)}, + /* D-Link */ +From ae428655b826f2755a8101b27beda42a275ef8ad Mon Sep 17 00:00:00 2001 +From: Nickolai Zeldovich +Date: Sat, 5 Jan 2013 14:17:45 -0500 +Subject: staging: speakup: avoid out-of-range access in synth_init() + +From: Nickolai Zeldovich + +commit ae428655b826f2755a8101b27beda42a275ef8ad upstream. + +Check that array index is in-bounds before accessing the synths[] array. + +Signed-off-by: Nickolai Zeldovich +Cc: Samuel Thibault +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/speakup/synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/speakup/synth.c ++++ b/drivers/staging/speakup/synth.c +@@ -342,7 +342,7 @@ int synth_init(char *synth_name) + + mutex_lock(&spk_mutex); + /* First, check if we already have it loaded. */ +- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) ++ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + if (strcmp(synths[i]->name, synth_name) == 0) + synth = synths[i]; + +From 6102c48bd421074a33e102f2ebda3724e8d275f9 Mon Sep 17 00:00:00 2001 +From: Samuel Thibault +Date: Mon, 7 Jan 2013 22:03:51 +0100 +Subject: staging: speakup: avoid out-of-range access in synth_add() + +From: Samuel Thibault + +commit 6102c48bd421074a33e102f2ebda3724e8d275f9 upstream. + +Check that array index is in-bounds before accessing the synths[] array. + +Signed-off-by: Samuel Thibault +Cc: Nickolai Zeldovich +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/speakup/synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/speakup/synth.c ++++ b/drivers/staging/speakup/synth.c +@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth + int i; + int status = 0; + mutex_lock(&spk_mutex); +- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) ++ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + /* synth_remove() is responsible for rotating the array down */ + if (in_synth == synths[i]) { + mutex_unlock(&spk_mutex); +From 37b51fdddf64e7ba0971d070428655f8d6f36578 Mon Sep 17 00:00:00 2001 +From: Sergey Senozhatsky +Date: Tue, 30 Oct 2012 22:40:23 +0300 +Subject: staging: zram: factor-out zram_decompress_page() function + +From: Sergey Senozhatsky + +commit 37b51fdddf64e7ba0971d070428655f8d6f36578 upstream. + +zram_bvec_read() shared decompress functionality with zram_read_before_write() function. +Factor-out and make commonly used zram_decompress_page() function, which also simplified +error handling in zram_bvec_read(). + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Nitin Gupta +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/zram/zram_drv.c | 113 ++++++++++++++++------------------------ + 1 file changed, 48 insertions(+), 65 deletions(-) + +--- a/drivers/staging/zram/zram_drv.c ++++ b/drivers/staging/zram/zram_drv.c +@@ -183,62 +183,25 @@ static inline int is_partial_io(struct b + return bvec->bv_len != PAGE_SIZE; + } + +-static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, +- u32 index, int offset, struct bio *bio) ++static int zram_decompress_page(struct zram *zram, char *mem, u32 index) + { +- int ret; +- size_t clen; +- struct page *page; +- unsigned char *user_mem, *cmem, *uncmem = NULL; +- +- page = bvec->bv_page; +- +- if (zram_test_flag(zram, index, ZRAM_ZERO)) { +- handle_zero_page(bvec); +- return 0; +- } ++ int ret = LZO_E_OK; ++ size_t clen = PAGE_SIZE; ++ unsigned char *cmem; ++ unsigned long handle = zram->table[index].handle; + +- /* Requested page is not present in compressed area */ +- if (unlikely(!zram->table[index].handle)) { +- pr_debug("Read before write: sector=%lu, size=%u", +- (ulong)(bio->bi_sector), bio->bi_size); +- handle_zero_page(bvec); ++ if (!handle || zram_test_flag(zram, index, ZRAM_ZERO)) { ++ memset(mem, 0, PAGE_SIZE); + return 0; + } + +- if (is_partial_io(bvec)) { +- /* Use a temporary buffer to decompress the page */ +- uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); +- if (!uncmem) { +- pr_info("Error allocating temp memory!\n"); +- return -ENOMEM; +- } +- } +- +- user_mem = kmap_atomic(page); +- if (!is_partial_io(bvec)) +- uncmem = user_mem; +- clen = PAGE_SIZE; +- +- cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, +- ZS_MM_RO); +- +- if (zram->table[index].size == PAGE_SIZE) { +- memcpy(uncmem, cmem, PAGE_SIZE); +- ret = LZO_E_OK; +- } else { ++ cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); ++ if (zram->table[index].size == PAGE_SIZE) ++ memcpy(mem, cmem, PAGE_SIZE); ++ else + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, +- uncmem, &clen); +- } +- +- if (is_partial_io(bvec)) { +- memcpy(user_mem + bvec->bv_offset, uncmem + offset, +- bvec->bv_len); +- kfree(uncmem); +- } +- +- zs_unmap_object(zram->mem_pool, zram->table[index].handle); +- kunmap_atomic(user_mem); ++ mem, &clen); ++ zs_unmap_object(zram->mem_pool, handle); + + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { +@@ -247,36 +210,56 @@ static int zram_bvec_read(struct zram *z + return ret; + } + +- flush_dcache_page(page); +- + return 0; + } + +-static int zram_read_before_write(struct zram *zram, char *mem, u32 index) ++static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, ++ u32 index, int offset, struct bio *bio) + { + int ret; +- size_t clen = PAGE_SIZE; +- unsigned char *cmem; +- unsigned long handle = zram->table[index].handle; ++ struct page *page; ++ unsigned char *user_mem, *uncmem = NULL; + +- if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) { +- memset(mem, 0, PAGE_SIZE); ++ page = bvec->bv_page; ++ ++ if (unlikely(!zram->table[index].handle) || ++ zram_test_flag(zram, index, ZRAM_ZERO)) { ++ handle_zero_page(bvec); + return 0; + } + +- cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); +- ret = lzo1x_decompress_safe(cmem, zram->table[index].size, +- mem, &clen); +- zs_unmap_object(zram->mem_pool, handle); ++ user_mem = kmap_atomic(page); ++ if (is_partial_io(bvec)) ++ /* Use a temporary buffer to decompress the page */ ++ uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ else ++ uncmem = user_mem; ++ ++ if (!uncmem) { ++ pr_info("Unable to allocate temp memory\n"); ++ ret = -ENOMEM; ++ goto out_cleanup; ++ } + ++ ret = zram_decompress_page(zram, uncmem, index); + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { + pr_err("Decompression failed! err=%d, page=%u\n", ret, index); + zram_stat64_inc(zram, &zram->stats.failed_reads); +- return ret; ++ goto out_cleanup; + } + +- return 0; ++ if (is_partial_io(bvec)) ++ memcpy(user_mem + bvec->bv_offset, uncmem + offset, ++ bvec->bv_len); ++ ++ flush_dcache_page(page); ++ ret = 0; ++out_cleanup: ++ kunmap_atomic(user_mem); ++ if (is_partial_io(bvec)) ++ kfree(uncmem); ++ return ret; + } + + static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, +@@ -302,7 +285,7 @@ static int zram_bvec_write(struct zram * + ret = -ENOMEM; + goto out; + } +- ret = zram_read_before_write(zram, uncmem, index); ++ ret = zram_decompress_page(zram, uncmem, index); + if (ret) { + kfree(uncmem); + goto out; +From 397c60668aa5ae7130b5ad4e73870d7b8a787085 Mon Sep 17 00:00:00 2001 +From: Nitin Gupta +Date: Wed, 2 Jan 2013 08:53:41 -0800 +Subject: staging: zram: fix invalid memory references during disk write + +From: Nitin Gupta + +commit 397c60668aa5ae7130b5ad4e73870d7b8a787085 upstream. + +Fixes a bug introduced by commit c8f2f0db1 ("zram: Fix handling +of incompressible pages") which caused invalid memory references +during disk write. Invalid references could occur in two cases: + - Incoming data expands on compression: In this case, reference was +made to kunmap()'ed bio page. + - Partial (non PAGE_SIZE) write with incompressible data: In this +case, reference was made to a kfree()'ed buffer. + +Fixes bug 50081: +https://bugzilla.kernel.org/show_bug.cgi?id=50081 + +Signed-off-by: Nitin Gupta +Reported-by: Mihail Kasadjikov +Reported-by: Tomas M +Reviewed-by: Minchan Kim +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/zram/zram_drv.c | 39 ++++++++++++++++++++++++--------------- + 1 file changed, 24 insertions(+), 15 deletions(-) + +--- a/drivers/staging/zram/zram_drv.c ++++ b/drivers/staging/zram/zram_drv.c +@@ -265,7 +265,7 @@ out_cleanup: + static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + int offset) + { +- int ret; ++ int ret = 0; + size_t clen; + unsigned long handle; + struct page *page; +@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram * + goto out; + } + ret = zram_decompress_page(zram, uncmem, index); +- if (ret) { +- kfree(uncmem); ++ if (ret) + goto out; +- } + } + + /* +@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram * + + user_mem = kmap_atomic(page); + +- if (is_partial_io(bvec)) ++ if (is_partial_io(bvec)) { + memcpy(uncmem + offset, user_mem + bvec->bv_offset, + bvec->bv_len); +- else ++ kunmap_atomic(user_mem); ++ user_mem = NULL; ++ } else { + uncmem = user_mem; ++ } + + if (page_zero_filled(uncmem)) { +- kunmap_atomic(user_mem); +- if (is_partial_io(bvec)) +- kfree(uncmem); ++ if (!is_partial_io(bvec)) ++ kunmap_atomic(user_mem); + zram_stat_inc(&zram->stats.pages_zero); + zram_set_flag(zram, index, ZRAM_ZERO); + ret = 0; +@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram * + ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, + zram->compress_workmem); + +- kunmap_atomic(user_mem); +- if (is_partial_io(bvec)) +- kfree(uncmem); ++ if (!is_partial_io(bvec)) { ++ kunmap_atomic(user_mem); ++ user_mem = NULL; ++ uncmem = NULL; ++ } + + if (unlikely(ret != LZO_E_OK)) { + pr_err("Compression failed! err=%d\n", ret); +@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram * + + if (unlikely(clen > max_zpage_size)) { + zram_stat_inc(&zram->stats.bad_compress); +- src = uncmem; + clen = PAGE_SIZE; ++ src = NULL; ++ if (is_partial_io(bvec)) ++ src = uncmem; + } + + handle = zs_malloc(zram->mem_pool, clen); +@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram * + } + cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); + ++ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) ++ src = kmap_atomic(page); + memcpy(cmem, src, clen); ++ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) ++ kunmap_atomic(src); + + zs_unmap_object(zram->mem_pool, handle); + +@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram * + if (clen <= PAGE_SIZE / 2) + zram_stat_inc(&zram->stats.good_compress); + +- return 0; +- + out: ++ if (is_partial_io(bvec)) ++ kfree(uncmem); ++ + if (ret) + zram_stat64_inc(zram, &zram->stats.failed_writes); + return ret; +From 51861d4eebc2ddc25c77084343d060fa79f6e291 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Tue, 8 Jan 2013 18:41:01 -0500 +Subject: radeon/kms: force rn50 chip to always report connected on analog output + +From: Jerome Glisse + +commit 51861d4eebc2ddc25c77084343d060fa79f6e291 upstream. + +Those rn50 chip are often connected to console remoting hw and load +detection often fails with those. Just don't try to load detect and +report connect. + +Signed-off-by: Jerome Glisse +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c ++++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_ + enum drm_connector_status found = connector_status_disconnected; + bool color = true; + ++ /* just don't bother on RN50 those chip are often connected to remoting ++ * console hw and often we get failure to load detect those. So to make ++ * everyone happy report the encoder as always connected. ++ */ ++ if (ASIC_IS_RN50(rdev)) { ++ return connector_status_connected; ++ } ++ + /* save the regs we need */ + vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); +From 392d4cad7907f6cb4ffc85e135a01abfddc89027 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 27 Dec 2012 21:37:04 +0100 +Subject: iwlwifi: fix PCIe interrupt handle return value + +From: Johannes Berg + +commit 392d4cad7907f6cb4ffc85e135a01abfddc89027 upstream. + +By accident, commit eb6476441bc2fecf6232a87d0313a85f8e3da7f4 +("iwlwifi: protect use_ict with irq_lock") changed the return +value of the iwl_pcie_isr() function in case it handles an +interrupt -- it now returns IRQ_NONE instead of IRQ_HANDLED. + +Put back the correct return value. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/rx.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c +@@ -971,6 +971,7 @@ static irqreturn_t iwl_isr(int irq, void + else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); ++ return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. */ +From f590dcec944552f9a4a61155810f3abd17d6465d Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Mon, 31 Dec 2012 09:26:10 +0200 +Subject: iwlwifi: fix the reclaimed packet tracking upon flush queue + +From: Emmanuel Grumbach + +commit f590dcec944552f9a4a61155810f3abd17d6465d upstream. + +There's a bug in the currently released firmware version, +the sequence control in the Tx response isn't updated in +all cases. Take it from the packet as a workaround. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/dvm/tx.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -1154,13 +1154,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + next_reclaimed = ssn; + } + +- if (tid != IWL_TID_NON_QOS) { +- priv->tid_data[sta_id][tid].next_reclaimed = +- next_reclaimed; +- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", +- next_reclaimed); +- } +- + iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); + + iwlagn_check_ratid_empty(priv, sta_id, tid); +@@ -1211,11 +1204,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + if (!is_agg) + iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); + ++ /* ++ * W/A for FW bug - the seq_ctl isn't updated when the ++ * queues are flushed. Fetch it from the packet itself ++ */ ++ if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { ++ next_reclaimed = le16_to_cpu(hdr->seq_ctrl); ++ next_reclaimed = ++ SEQ_TO_SN(next_reclaimed + 0x10); ++ } ++ + is_offchannel_skb = + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); + freed++; + } + ++ if (tid != IWL_TID_NON_QOS) { ++ priv->tid_data[sta_id][tid].next_reclaimed = ++ next_reclaimed; ++ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", ++ next_reclaimed); ++ } ++ + WARN_ON(!is_agg && freed != 1); + + /* +From 34bcf71502413f8903ade93746f2d0f04b937a78 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Tue, 11 Dec 2012 10:48:23 +0100 +Subject: mac80211: fix ibss scanning + +From: Stanislaw Gruszka + +commit 34bcf71502413f8903ade93746f2d0f04b937a78 upstream. + +Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this +can trigger Microcode errors on iwlwifi and iwlegacy drivers. + +Also rename ieee80211_request_internal_scan() function since it is only +used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). + +This patch should address: +https://bugzilla.redhat.com/show_bug.cgi?id=883414 +https://bugzilla.kernel.org/show_bug.cgi?id=49411 + +Reported-by: Jesse Kahtava +Reported-by: Mikko Rapeli +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/ibss.c | 9 ++++----- + net/mac80211/ieee80211_i.h | 6 +++--- + net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- + 3 files changed, 31 insertions(+), 18 deletions(-) + +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(str + sdata_info(sdata, + "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, ++ NULL); + } + + static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(stru + IEEE80211_SCAN_INTERVAL)) { + sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, +- ifibss->fixed_channel ? ifibss->channel : NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ++ ifibss->ssid_len, chan); + } else { + int interval = IEEE80211_SCAN_INTERVAL; + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struc + + /* scan/BSS handling */ + void ieee80211_scan_work(struct work_struct *work); +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan); ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan); + int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req); + void ieee80211_scan_cancel(struct ieee80211_local *local); +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80 + return res; + } + +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan) ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan) + { + struct ieee80211_local *local = sdata->local; + int ret = -EBUSY; +@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(stru + + /* fill internal scan request */ + if (!chan) { +- int i, nchan = 0; ++ int i, max_n; ++ int n_ch = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; +- for (i = 0; +- i < local->hw.wiphy->bands[band]->n_channels; +- i++) { +- local->int_scan_req->channels[nchan] = ++ ++ max_n = local->hw.wiphy->bands[band]->n_channels; ++ for (i = 0; i < max_n; i++) { ++ struct ieee80211_channel *tmp_ch = + &local->hw.wiphy->bands[band]->channels[i]; +- nchan++; ++ ++ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED)) ++ continue; ++ ++ local->int_scan_req->channels[n_ch] = tmp_ch; ++ n_ch++; + } + } + +- local->int_scan_req->n_channels = nchan; ++ if (WARN_ON_ONCE(n_ch == 0)) ++ goto unlock; ++ ++ local->int_scan_req->n_channels = n_ch; + } else { ++ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED))) ++ goto unlock; ++ + local->int_scan_req->channels[0] = chan; + local->int_scan_req->n_channels = 1; + } +From 97f97b1f5fe0878b35c8e314f98591771696321b Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 13 Dec 2012 22:54:58 +0100 +Subject: mac80211: fix station destruction in AP/mesh modes + +From: Johannes Berg + +commit 97f97b1f5fe0878b35c8e314f98591771696321b upstream. + +Unfortunately, commit b22cfcfcae5b, intended to speed up roaming +by avoiding the synchronize_rcu() broke AP/mesh modes as it moved +some code into that work item that will still call into the driver +at a time where it's no longer expected to handle this: after the +AP or mesh has been stopped. + +To fix this problem remove the per-station work struct, maintain a +station cleanup list instead and flush this list when stations are +flushed. To keep this patch smaller for stable, do this when the +stations are flushed (sta_info_flush()). This unfortunately brings +back the original roaming delay; I'll fix that again in a separate +patch. + +Also, Ben reported that the original commit could sometimes (with +many interfaces) cause long delays when an interface is set down, +due to blocking on flush_workqueue(). Since we now maintain the +cleanup list, this particular change of the original patch can be +reverted. + +Reported-by: Ben Greear +Tested-by: Ben Greear +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/ieee80211_i.h | 4 ++++ + net/mac80211/iface.c | 28 ++++++++++++++++------------ + net/mac80211/sta_info.c | 44 ++++++++++++++++++++++++++++++++++++++++---- + net/mac80211/sta_info.h | 3 ++- + 4 files changed, 62 insertions(+), 17 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -730,6 +730,10 @@ struct ieee80211_sub_if_data { + u32 mntr_flags; + } u; + ++ spinlock_t cleanup_stations_lock; ++ struct list_head cleanup_stations; ++ struct work_struct cleanup_stations_wk; ++ + #ifdef CONFIG_MAC80211_DEBUGFS + struct { + struct dentry *dir; +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -793,20 +793,11 @@ static void ieee80211_do_stop(struct iee + flush_work(&sdata->work); + /* + * When we get here, the interface is marked down. +- * Call rcu_barrier() to wait both for the RX path ++ * Call synchronize_rcu() to wait for the RX path + * should it be using the interface and enqueuing +- * frames at this very time on another CPU, and +- * for the sta free call_rcu callbacks. ++ * frames at this very time on another CPU. + */ +- rcu_barrier(); +- +- /* +- * free_sta_rcu() enqueues a work for the actual +- * sta cleanup, so we need to flush it while +- * sdata is still valid. +- */ +- flush_workqueue(local->workqueue); +- ++ synchronize_rcu(); + skb_queue_purge(&sdata->skb_queue); + + /* +@@ -1432,6 +1423,15 @@ static void ieee80211_assign_perm_addr(s + mutex_unlock(&local->iflist_mtx); + } + ++static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ ++ sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); ++ ++ ieee80211_cleanup_sdata_stas(sdata); ++} ++ + int ieee80211_if_add(struct ieee80211_local *local, const char *name, + struct wireless_dev **new_wdev, enum nl80211_iftype type, + struct vif_params *params) +@@ -1507,6 +1507,10 @@ int ieee80211_if_add(struct ieee80211_lo + + INIT_LIST_HEAD(&sdata->key_list); + ++ spin_lock_init(&sdata->cleanup_stations_lock); ++ INIT_LIST_HEAD(&sdata->cleanup_stations); ++ INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); ++ + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + struct ieee80211_supported_band *sband; + sband = local->hw.wiphy->bands[i]; +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee + return -ENOENT; + } + +-static void free_sta_work(struct work_struct *wk) ++static void cleanup_single_sta(struct sta_info *sta) + { +- struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); + int ac, i; + struct tid_ampdu_tx *tid_tx; + struct ieee80211_sub_if_data *sdata = sta->sdata; +@@ -148,11 +147,35 @@ static void free_sta_work(struct work_st + sta_info_free(local, sta); + } + ++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) ++{ ++ struct sta_info *sta; ++ ++ spin_lock_bh(&sdata->cleanup_stations_lock); ++ while (!list_empty(&sdata->cleanup_stations)) { ++ sta = list_first_entry(&sdata->cleanup_stations, ++ struct sta_info, list); ++ list_del(&sta->list); ++ spin_unlock_bh(&sdata->cleanup_stations_lock); ++ ++ cleanup_single_sta(sta); ++ ++ spin_lock_bh(&sdata->cleanup_stations_lock); ++ } ++ ++ spin_unlock_bh(&sdata->cleanup_stations_lock); ++} ++ + static void free_sta_rcu(struct rcu_head *h) + { + struct sta_info *sta = container_of(h, struct sta_info, rcu_head); ++ struct ieee80211_sub_if_data *sdata = sta->sdata; + +- ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); ++ spin_lock(&sdata->cleanup_stations_lock); ++ list_add_tail(&sta->list, &sdata->cleanup_stations); ++ spin_unlock(&sdata->cleanup_stations_lock); ++ ++ ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); + } + + /* protected by RCU */ +@@ -305,7 +328,6 @@ struct sta_info *sta_info_alloc(struct i + + spin_lock_init(&sta->lock); + INIT_WORK(&sta->drv_unblock_wk, sta_unblock); +- INIT_WORK(&sta->free_sta_wk, free_sta_work); + INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); + mutex_init(&sta->ampdu_mlme.mtx); + +@@ -877,6 +899,20 @@ int sta_info_flush(struct ieee80211_loca + } + mutex_unlock(&local->sta_mtx); + ++ rcu_barrier(); ++ ++ if (sdata) { ++ ieee80211_cleanup_sdata_stas(sdata); ++ cancel_work_sync(&sdata->cleanup_stations_wk); ++ } else { ++ mutex_lock(&local->iflist_mtx); ++ list_for_each_entry(sdata, &local->interfaces, list) { ++ ieee80211_cleanup_sdata_stas(sdata); ++ cancel_work_sync(&sdata->cleanup_stations_wk); ++ } ++ mutex_unlock(&local->iflist_mtx); ++ } ++ + return ret; + } + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -298,7 +298,6 @@ struct sta_info { + spinlock_t lock; + + struct work_struct drv_unblock_wk; +- struct work_struct free_sta_wk; + + u16 listen_interval; + +@@ -558,4 +557,6 @@ void ieee80211_sta_ps_deliver_wakeup(str + void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); + void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); + ++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); ++ + #endif /* STA_INFO_H */ +From a56f992cdabc63f56b4b142885deebebf936ff76 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 13 Dec 2012 23:08:52 +0100 +Subject: mac80211: use del_timer_sync for final sta cleanup timer deletion + +From: Johannes Berg + +commit a56f992cdabc63f56b4b142885deebebf936ff76 upstream. + +This is a very old bug, but there's nothing that prevents the +timer from running while the module is being removed when we +only do del_timer() instead of del_timer_sync(). + +The timer should normally not be running at this point, but +it's not clearly impossible (or we could just remove this.) + +Tested-by: Ben Greear +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/sta_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -870,7 +870,7 @@ void sta_info_init(struct ieee80211_loca + + void sta_info_stop(struct ieee80211_local *local) + { +- del_timer(&local->sta_cleanup); ++ del_timer_sync(&local->sta_cleanup); + sta_info_flush(local, NULL); + } + +From 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 Mon Sep 17 00:00:00 2001 +From: Bing Zhao +Date: Wed, 2 Jan 2013 16:07:35 -0800 +Subject: mwifiex: check wait_event_interruptible return value + +From: Bing Zhao + +commit 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 upstream. + +wait_event_interruptible function returns -ERESTARTSYS if it's +interrupted by a signal. Driver should check the return value +and handle this case properly. + +In mwifiex_wait_queue_complete() routine, as we are now checking +wait_event_interruptible return value, the condition check is not +required. Also, we have removed mwifiex_cancel_pending_ioctl() +call to avoid a chance of sending second command to FW by other path +as soon as we clear current command node. FW can not handle two +commands simultaneously. + +Signed-off-by: Bing Zhao +Signed-off-by: Amitkumar Karwar +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/mwifiex/sta_ioctl.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/mwifiex/sta_ioctl.c ++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c +@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifi + */ + int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) + { +- bool cancel_flag = false; + int status; + struct cmd_ctrl_node *cmd_queued; + +@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct m + atomic_inc(&adapter->cmd_pending); + + /* Wait for completion */ +- wait_event_interruptible(adapter->cmd_wait_q.wait, +- *(cmd_queued->condition)); +- if (!*(cmd_queued->condition)) +- cancel_flag = true; +- +- if (cancel_flag) { +- mwifiex_cancel_pending_ioctl(adapter); +- dev_dbg(adapter->dev, "cmd cancel\n"); ++ status = wait_event_interruptible(adapter->cmd_wait_q.wait, ++ *(cmd_queued->condition)); ++ if (status) { ++ dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); ++ return status; + } + + status = adapter->cmd_wait_q.status; +@@ -480,8 +476,11 @@ int mwifiex_enable_hs(struct mwifiex_ada + return false; + } + +- wait_event_interruptible(adapter->hs_activate_wait_q, +- adapter->hs_activate_wait_q_woken); ++ if (wait_event_interruptible(adapter->hs_activate_wait_q, ++ adapter->hs_activate_wait_q_woken)) { ++ dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); ++ return false; ++ } + + return true; + } +From 5e20a4b53094651d80f856ff55a916b999dbb57a Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Thu, 20 Dec 2012 15:55:01 -0600 +Subject: b43: Fix firmware loading when driver is built into the kernel + +From: Larry Finger + +commit 5e20a4b53094651d80f856ff55a916b999dbb57a upstream. + +Recent versions of udev cause synchronous firmware loading from the +probe routine to fail because the request to user space would time +out. The original fix for b43 (commit 6b6fa58) moved the firmware +load from the probe routine to a work queue, but it still used synchronous +firmware loading. This method is OK when b43 is built as a module; +however, it fails when the driver is compiled into the kernel. + +This version changes the code to load the initial firmware file +using request_firmware_nowait(). A completion event is used to +hold the work queue until that file is available. This driver +reads several firmware files - the remainder can be read synchronously. +On some test systems, the async read fails; however, a following synch +read works, thus the async failure falls through to the sync try. + +Reported-and-Tested by: Felix Janda +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/b43/b43.h | 5 +++ + drivers/net/wireless/b43/main.c | 54 ++++++++++++++++++++++++++++++---------- + drivers/net/wireless/b43/main.h | 5 +-- + 3 files changed, 48 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/b43/b43.h ++++ b/drivers/net/wireless/b43/b43.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + + #include "debugfs.h" +@@ -722,6 +723,10 @@ enum b43_firmware_file_type { + struct b43_request_fw_context { + /* The device we are requesting the fw for. */ + struct b43_wldev *dev; ++ /* a completion event structure needed if this call is asynchronous */ ++ struct completion fw_load_complete; ++ /* a pointer to the firmware object */ ++ const struct firmware *blob; + /* The type of firmware to request. */ + enum b43_firmware_file_type req_type; + /* Error messages for each firmware type. */ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct + b43warn(wl, text); + } + ++static void b43_fw_cb(const struct firmware *firmware, void *context) ++{ ++ struct b43_request_fw_context *ctx = context; ++ ++ ctx->blob = firmware; ++ complete(&ctx->fw_load_complete); ++} ++ + int b43_do_request_fw(struct b43_request_fw_context *ctx, + const char *name, +- struct b43_firmware_file *fw) ++ struct b43_firmware_file *fw, bool async) + { +- const struct firmware *blob; + struct b43_fw_header *hdr; + u32 size; + int err; +@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request + B43_WARN_ON(1); + return -ENOSYS; + } +- err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); ++ if (async) { ++ /* do this part asynchronously */ ++ init_completion(&ctx->fw_load_complete); ++ err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, ++ ctx->dev->dev->dev, GFP_KERNEL, ++ ctx, b43_fw_cb); ++ if (err < 0) { ++ pr_err("Unable to load firmware\n"); ++ return err; ++ } ++ /* stall here until fw ready */ ++ wait_for_completion(&ctx->fw_load_complete); ++ if (ctx->blob) ++ goto fw_ready; ++ /* On some ARM systems, the async request will fail, but the next sync ++ * request works. For this reason, we dall through here ++ */ ++ } ++ err = request_firmware(&ctx->blob, ctx->fwname, ++ ctx->dev->dev->dev); + if (err == -ENOENT) { + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), +- "Firmware file \"%s\" not found\n", ctx->fwname); ++ "Firmware file \"%s\" not found\n", ++ ctx->fwname); + return err; + } else if (err) { + snprintf(ctx->errors[ctx->req_type], +@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request + ctx->fwname, err); + return err; + } +- if (blob->size < sizeof(struct b43_fw_header)) ++fw_ready: ++ if (ctx->blob->size < sizeof(struct b43_fw_header)) + goto err_format; +- hdr = (struct b43_fw_header *)(blob->data); ++ hdr = (struct b43_fw_header *)(ctx->blob->data); + switch (hdr->type) { + case B43_FW_TYPE_UCODE: + case B43_FW_TYPE_PCM: + size = be32_to_cpu(hdr->size); +- if (size != blob->size - sizeof(struct b43_fw_header)) ++ if (size != ctx->blob->size - sizeof(struct b43_fw_header)) + goto err_format; + /* fallthrough */ + case B43_FW_TYPE_IV: +@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request + goto err_format; + } + +- fw->data = blob; ++ fw->data = ctx->blob; + fw->filename = name; + fw->type = ctx->req_type; + +@@ -2172,7 +2200,7 @@ err_format: + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), + "Firmware file \"%s\" format error.\n", ctx->fwname); +- release_firmware(blob); ++ release_firmware(ctx->blob); + + return -EPROTO; + } +@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43 + goto err_no_ucode; + } + } +- err = b43_do_request_fw(ctx, filename, &fw->ucode); ++ err = b43_do_request_fw(ctx, filename, &fw->ucode, true); + if (err) + goto err_load; + +@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43 + else + goto err_no_pcm; + fw->pcm_request_failed = false; +- err = b43_do_request_fw(ctx, filename, &fw->pcm); ++ err = b43_do_request_fw(ctx, filename, &fw->pcm, false); + if (err == -ENOENT) { + /* We did not find a PCM file? Not fatal, but + * core rev <= 10 must do without hwcrypto then. */ +@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43 + default: + goto err_no_initvals; + } +- err = b43_do_request_fw(ctx, filename, &fw->initvals); ++ err = b43_do_request_fw(ctx, filename, &fw->initvals, false); + if (err) + goto err_load; + +@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43 + default: + goto err_no_initvals; + } +- err = b43_do_request_fw(ctx, filename, &fw->initvals_band); ++ err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); + if (err) + goto err_load; + +--- a/drivers/net/wireless/b43/main.h ++++ b/drivers/net/wireless/b43/main.h +@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wl + + + struct b43_request_fw_context; +-int b43_do_request_fw(struct b43_request_fw_context *ctx, +- const char *name, +- struct b43_firmware_file *fw); ++int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, ++ struct b43_firmware_file *fw, bool async); + void b43_do_release_fw(struct b43_firmware_file *fw); + + #endif /* B43_MAIN_H_ */ +From ad86e58661b38b279b7519d4e49c7a19dc1654bb Mon Sep 17 00:00:00 2001 +From: Dzianis Kahanovich +Date: Mon, 3 Dec 2012 16:06:26 +0300 +Subject: USB: option: add Nexpring NP10T terminal id + +From: Dzianis Kahanovich + +commit ad86e58661b38b279b7519d4e49c7a19dc1654bb upstream. + +Hyundai Petatel Inc. Nexpring NP10T terminal (EV-DO rev.A USB modem) ID + +Signed-off-by: Denis Kaganovich +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -442,6 +442,10 @@ static void option_instat_callback(struc + #define CELLIENT_VENDOR_ID 0x2692 + #define CELLIENT_PRODUCT_MEN200 0x9005 + ++/* Hyundai Petatel Inc. products */ ++#define PETATEL_VENDOR_ID 0x1ff4 ++#define PETATEL_PRODUCT_NP10T 0x600e ++ + /* some devices interfaces need special handling due to a number of reasons */ + enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, +@@ -1296,6 +1300,7 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, ++ { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +From fab38246f318edcd0dcb8fd3852a47cf8938878a Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Wed, 19 Dec 2012 15:15:17 +0100 +Subject: USB: option: blacklist network interface on ZTE MF880 + +From: Bjørn Mork + +commit fab38246f318edcd0dcb8fd3852a47cf8938878a upstream. + +The driver description files gives these names to the vendor specific +functions on this modem: + + diag: VID_19D2&PID_0284&MI_00 + nmea: VID_19D2&PID_0284&MI_01 + at: VID_19D2&PID_0284&MI_02 + mdm: VID_19D2&PID_0284&MI_03 + net: VID_19D2&PID_0284&MI_04 + +Signed-off-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -928,7 +928,8 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +From 94a85b633829b946eef53fc1825d526312fb856f Mon Sep 17 00:00:00 2001 +From: "Quentin.Li" +Date: Wed, 26 Dec 2012 16:58:22 +0800 +Subject: USB: option: Add new MEDIATEK PID support + +From: "Quentin.Li" + +commit 94a85b633829b946eef53fc1825d526312fb856f upstream. + +In option.c, add some new MEDIATEK PIDs support for MEDIATEK new products. This +is a MEDIATEK inc. release patch. + +Signed-off-by: Quentin.Li +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -430,9 +430,12 @@ static void option_instat_callback(struc + #define MEDIATEK_VENDOR_ID 0x0e8d + #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 + #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 ++#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 + #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 + #define MEDIATEK_PRODUCT_7208_1COM 0x7101 + #define MEDIATEK_PRODUCT_7208_2COM 0x7102 ++#define MEDIATEK_PRODUCT_7103_2COM 0x7103 ++#define MEDIATEK_PRODUCT_7106_2COM 0x7106 + #define MEDIATEK_PRODUCT_FP_1COM 0x0003 + #define MEDIATEK_PRODUCT_FP_2COM 0x0023 + #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 +@@ -1300,6 +1303,10 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, + { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { } /* Terminating entry */ +From 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Fri, 28 Dec 2012 17:29:52 +0100 +Subject: USB: option: add Telekom Speedstick LTE II + +From: Bjørn Mork + +commit 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf upstream. + +also known as Alcatel One Touch L100V LTE + +The driver description files gives these names to the vendor specific +functions on this modem: + + Application1: VID_1BBB&PID_011E&MI_00 + Application2: VID_1BBB&PID_011E&MI_01 + Modem: VID_1BBB&PID_011E&MI_03 + Ethernet: VID_1BBB&PID_011E&MI_04 + +Reported-by: Thomas Schäfer +Signed-off-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -289,6 +289,7 @@ static void option_instat_callback(struc + #define ALCATEL_VENDOR_ID 0x1bbb + #define ALCATEL_PRODUCT_X060S_X200 0x0000 + #define ALCATEL_PRODUCT_X220_X500D 0x0017 ++#define ALCATEL_PRODUCT_L100V 0x011e + + #define PIRELLI_VENDOR_ID 0x1266 + #define PIRELLI_PRODUCT_C100_1 0x1002 +@@ -1199,6 +1200,8 @@ static const struct usb_device_id option + .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist + }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, ++ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, + { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), +From 8cf65dc386f3634a43312f436cc7a935476a40c4 Mon Sep 17 00:00:00 2001 +From: Tomasz Mloduchowski +Date: Sun, 13 Jan 2013 23:32:53 +0100 +Subject: usb: ftdi_sio: Crucible Technologies COMET Caller ID - pid added + +From: Tomasz Mloduchowski + +commit 8cf65dc386f3634a43312f436cc7a935476a40c4 upstream. + +Simple fix to add support for Crucible Technologies COMET Caller ID +USB decoder - a device containing FTDI USB/Serial converter chip, +handling 1200bps CallerID messages decoded from the phone line - +adding correct USB PID is sufficient. + +Tested to apply cleanly and work flawlessly against 3.6.9, 3.7.0-rc8 +and 3.8.0-rc3 on both amd64 and x86 arches. + +Signed-off-by: Tomasz Mloduchowski +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 2 ++ + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -876,6 +876,8 @@ static struct usb_device_id id_table_com + { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, ++ /* Crucible Devices */ ++ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, + { }, /* Optional parameter entry */ + { } /* Terminating entry */ + }; +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -1259,3 +1259,9 @@ + * ATI command output: Cinterion MC55i + */ + #define FTDI_CINTERION_MC55I_PID 0xA951 ++ ++/* ++ * Product: Comet Caller ID decoder ++ * Manufacturer: Crucible Technologies ++ */ ++#define FTDI_CT_COMET_PID 0x8e08 +From 036915a7a402753c05b8d0529f5fd08805ab46d0 Mon Sep 17 00:00:00 2001 +From: Denis N Ladin +Date: Wed, 26 Dec 2012 18:29:44 +0500 +Subject: USB: cdc-acm: Add support for "PSC Scanning, Magellan 800i" + +From: Denis N Ladin + +commit 036915a7a402753c05b8d0529f5fd08805ab46d0 upstream. + +Adding support "PSC Scanning, Magellan 800i" in cdc-acm + +Very simple, but very necessary. +Suitable for all versions of the kernel > 2.6 + +Signed-off-by: Denis N Ladin +Acked-by: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_id + { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ + .driver_info = NO_UNION_NORMAL, + }, ++ { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ ++ .driver_info = NO_UNION_NORMAL, ++ }, + { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ + }, +From 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Tue, 20 Nov 2012 13:23:15 +0100 +Subject: usb: gadget: dummy: fix enumeration with g_multi + +From: Sebastian Andrzej Siewior + +commit 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 upstream. + +If we do have endpoints named like "ep-a" then bEndpointAddress is +counted internally by the gadget framework. + +If we do have endpoints named like "ep-1" then bEndpointAddress is +assigned from the digit after "ep-". + +If we do have both, then it is likely that after we used up the +"generic" endpoints we will use the digits and thus assign one +bEndpointAddress to multiple endpoints. + +This theory can be proofed by using the completely enabled g_multi. +Without this patch, the mass storage won't enumerate and times out +because it shares endpoints with RNDIS. + +This patch also adds fills up the endpoints list so we have in total +endpoints 1 to 15 in + out available while some of them are restricted +to certain types like BULK or ISO. Without this change the nokia gadget +won't load because the system does not provide enough (BULK) endpoints +but it did before ep-a - ep-f were removed. + +Signed-off-by: Sebastian Andrzej Siewior +Acked-by: Alan Stern +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/dummy_hcd.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/usb/gadget/dummy_hcd.c ++++ b/drivers/usb/gadget/dummy_hcd.c +@@ -126,10 +126,7 @@ static const char ep0name[] = "ep0"; + static const char *const ep_name[] = { + ep0name, /* everyone has ep0 */ + +- /* act like a net2280: high speed, six configurable endpoints */ +- "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", +- +- /* or like pxa250: fifteen fixed function endpoints */ ++ /* act like a pxa250: fifteen fixed function endpoints */ + "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", + "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", + "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", +@@ -137,6 +134,10 @@ static const char *const ep_name[] = { + + /* or like sa1100: two fixed function endpoints */ + "ep1out-bulk", "ep2in-bulk", ++ ++ /* and now some generic EPs so we have enough in multi config */ ++ "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", ++ "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", + }; + #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) + +From 2ac788f705e5118dd45204e7a5bc8d5bb6873835 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 14 Nov 2012 18:49:50 +0300 +Subject: usb: musb: core: print new line in the driver banner again + +From: Sergei Shtylyov + +commit 2ac788f705e5118dd45204e7a5bc8d5bb6873835 upstream. + +Commit 5c8a86e10a7c164f44537fabdc169fd8b4e7a440 (usb: musb: drop unneeded +musb_debug trickery) erroneously removed '\n' from the driver's banner. +Concatenate all the banner substrings while adding it back... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/musb/musb_core.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2351,10 +2351,7 @@ static int __init musb_init(void) + if (usb_disabled()) + return 0; + +- pr_info("%s: version " MUSB_VERSION ", " +- "?dma?" +- ", " +- "otg (peripheral+host)", ++ pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", + musb_driver_name); + return platform_driver_register(&musb_driver); + } +From f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Tue, 25 Dec 2012 18:13:22 +0100 +Subject: drm/nv17-50: restore fence buffer on resume + +From: Marcin Slusarz + +commit f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 upstream. + +Since commit 5e120f6e4b3f35b741c5445dfc755f50128c3c44 "drm/nouveau/fence: +convert to exec engine, and improve channel sync" nouveau fence sync +implementation for nv17-50 and nvc0+ started to rely on state of fence buffer +left by previous sync operation. But as pinned bo's (where fence state is +stored) are not saved+restored across suspend/resume, we need to do it +manually. + +nvc0+ was fixed by commit d6ba6d215a538a58f0f0026f0961b0b9125e8042 +"drm/nvc0/fence: restore pre-suspend fence buffer context on resume". + +Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=50121 + +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_fence.h | 1 + + drivers/gpu/drm/nouveau/nv10_fence.c | 8 ++++++++ + drivers/gpu/drm/nouveau/nv50_fence.c | 1 + + 3 files changed, 10 insertions(+) + +--- a/drivers/gpu/drm/nouveau/nouveau_fence.h ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.h +@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_chan + void nv10_fence_context_del(struct nouveau_channel *); + void nv10_fence_destroy(struct nouveau_drm *); + int nv10_fence_create(struct nouveau_drm *); ++void nv17_fence_resume(struct nouveau_drm *drm); + + int nv50_fence_create(struct nouveau_drm *); + int nv84_fence_create(struct nouveau_drm *); +--- a/drivers/gpu/drm/nouveau/nv10_fence.c ++++ b/drivers/gpu/drm/nouveau/nv10_fence.c +@@ -160,6 +160,13 @@ nv10_fence_destroy(struct nouveau_drm *d + kfree(priv); + } + ++void nv17_fence_resume(struct nouveau_drm *drm) ++{ ++ struct nv10_fence_priv *priv = drm->fence; ++ ++ nouveau_bo_wr32(priv->bo, 0, priv->sequence); ++} ++ + int + nv10_fence_create(struct nouveau_drm *drm) + { +@@ -192,6 +199,7 @@ nv10_fence_create(struct nouveau_drm *dr + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; ++ priv->base.resume = nv17_fence_resume; + } + } + +--- a/drivers/gpu/drm/nouveau/nv50_fence.c ++++ b/drivers/gpu/drm/nouveau/nv50_fence.c +@@ -119,6 +119,7 @@ nv50_fence_create(struct nouveau_drm *dr + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; ++ priv->base.resume = nv17_fence_resume; + } + + if (ret) +From 92441b2263866c27ef48137be5aa6c8c692652fc Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Tue, 18 Dec 2012 20:30:47 +0100 +Subject: drm/nouveau: fix blank LVDS screen regression on pre-nv50 cards + +From: Marcin Slusarz + +commit 92441b2263866c27ef48137be5aa6c8c692652fc upstream. + +Commit 2a44e499 ("drm/nouveau/disp: introduce proper init/fini, separate +from create/destroy") started to call display init routines on pre-nv50 +hardware on module load. But LVDS init code sets driver state in a way +which prevents modesetting code from operating properly. + +nv04_display_init calls nv04_dfp_restore, which sets encoder->last_dpms to +NV_DPMS_CLEARED. + +drm_crtc_helper_set_mode + nv04_dfp_prepare + nv04_lvds_dpms(DRM_MODE_DPMS_OFF) + +nv04_lvds_dpms checks last_dpms mode (which is NV_DPMS_CLEARED) and wrongly +assumes it's a "powersaving mode", the new one (DRM_MODE_DPMS_OFF) is too, +so it skips calling some crucial lvds scripts. + +Reported-by: Chris Paulson-Ellis +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nv04_dfp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nv04_dfp.c ++++ b/drivers/gpu/drm/nouveau/nv04_dfp.c +@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(st + + static inline bool is_powersaving_dpms(int mode) + { +- return (mode != DRM_MODE_DPMS_ON); ++ return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; + } + + static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) +From 4c4101d29fb6c63f78791d02c437702b11e1d4f0 Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Sun, 2 Dec 2012 12:56:22 +0100 +Subject: drm/nouveau: add locking around instobj list operations + +From: Marcin Slusarz + +commit 4c4101d29fb6c63f78791d02c437702b11e1d4f0 upstream. + +Fixes memory corruptions, oopses, etc. when multiple gpuobjs are +simultaneously created or destroyed. + +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | 35 ++++++++++++++++----- + 1 file changed, 27 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_o + if (ret) + return ret; + ++ mutex_lock(&imem->base.mutex); + list_add(&iobj->head, &imem->list); ++ mutex_unlock(&imem->base.mutex); + return 0; + } + + void + nouveau_instobj_destroy(struct nouveau_instobj *iobj) + { +- if (iobj->head.prev) +- list_del(&iobj->head); ++ struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); ++ ++ mutex_lock(&subdev->mutex); ++ list_del(&iobj->head); ++ mutex_unlock(&subdev->mutex); ++ + return nouveau_object_destroy(&iobj->base); + } + +@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_inst + if (ret) + return ret; + ++ mutex_lock(&imem->base.mutex); ++ + list_for_each_entry(iobj, &imem->list, head) { + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) +@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_inst + } + } + ++ mutex_unlock(&imem->base.mutex); ++ + return 0; + } + +@@ -104,17 +114,26 @@ int + nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) + { + struct nouveau_instobj *iobj; +- int i; ++ int i, ret = 0; + + if (suspend) { ++ mutex_lock(&imem->base.mutex); ++ + list_for_each_entry(iobj, &imem->list, head) { + iobj->suspend = vmalloc(iobj->size); +- if (iobj->suspend) { +- for (i = 0; i < iobj->size; i += 4) +- iobj->suspend[i / 4] = nv_ro32(iobj, i); +- } else +- return -ENOMEM; ++ if (!iobj->suspend) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ for (i = 0; i < iobj->size; i += 4) ++ iobj->suspend[i / 4] = nv_ro32(iobj, i); + } ++ ++ mutex_unlock(&imem->base.mutex); ++ ++ if (ret) ++ return ret; + } + + return nouveau_subdev_fini(&imem->base, suspend); +From d19528a9e4f220519c2cb3f56ef0c84ead3ee440 Mon Sep 17 00:00:00 2001 +From: Aleksi Torhamo +Date: Fri, 4 Jan 2013 18:39:13 +0200 +Subject: drm/nouveau/clock: fix support for more than 2 monitors on nve0 + +From: Aleksi Torhamo + +commit d19528a9e4f220519c2cb3f56ef0c84ead3ee440 upstream. + +Fixes regression introduced in commit 70790f4f +"drm/nouveau/clock: pull in the implementation from all over the place" + +When code was moved from nv50_crtc_set_clock to nvc0_clock_pll_set, +the PLLs it is used for got limited to only the first two VPLLs. + +nv50_crtc_set_clock was only called to change VPLLs, so it didn't +limit what it was used for in any way. Since nvc0_clock_pll_set is +used for all PLLs, it has to specify which PLLs the code is used for, +and only listed the first two VPLLs. + +Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=58735 + +This patch is a -stable candidate for 3.7. + +Signed-off-by: Aleksi Torhamo +Tested-by: Aleksi Torhamo +Tested-by: Sean Santos +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | 2 ++ + drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h ++++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +@@ -38,6 +38,8 @@ enum nvbios_pll_type { + PLL_UNK42 = 0x42, + PLL_VPLL0 = 0x80, + PLL_VPLL1 = 0x81, ++ PLL_VPLL2 = 0x82, ++ PLL_VPLL3 = 0x83, + PLL_MAX = 0xff + }; + +--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: ++ case PLL_VPLL2: ++ case PLL_VPLL3: + nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); + nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); + nv_wr32(priv, info.reg + 0x10, fN << 16); +From 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 Mon Sep 17 00:00:00 2001 +From: Aleksi Torhamo +Date: Wed, 9 Jan 2013 20:08:48 +0200 +Subject: drm/nvc0/fb: fix crash when different mutex is used to protect same list + +From: Aleksi Torhamo + +commit 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 upstream. + +Fixes regression introduced in commit 861d2107 +"drm/nouveau/fb: merge fb/vram and port to subdev interfaces" + +nv50_fb_vram_{new,del} functions were changed to use +nouveau_subdev->mutex instead of the old nouveau_mm->mutex. +nvc0_fb_vram_new still uses the nouveau_mm->mutex, but nvc0 doesn't +have its own fb_vram_del function, using nv50_fb_vram_del instead. +Because of this, on nvc0 a different mutex ends up being used to protect +additions and deletions to the same list. + +This patch is a -stable candidate for 3.7. + +Signed-off-by: Aleksi Torhamo +Reported-by: Roy Spliet +Tested-by: Roy Spliet +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +@@ -86,14 +86,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, + mem->memtype = type; + mem->size = size; + +- mutex_lock(&mm->mutex); ++ mutex_lock(&pfb->base.mutex); + do { + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); + if (ret) { +- mutex_unlock(&mm->mutex); ++ mutex_unlock(&pfb->base.mutex); + pfb->ram.put(pfb, &mem); + return ret; + } +@@ -101,7 +101,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); +- mutex_unlock(&mm->mutex); ++ mutex_unlock(&pfb->base.mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; +From 1c7439c61fa6516419c32a9824976334ea969d47 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 15:58:52 -0800 +Subject: USB: Handle auto-transition from hot to warm reset. + +From: Sarah Sharp + +commit 1c7439c61fa6516419c32a9824976334ea969d47 upstream. + +USB 3.0 hubs and roothubs will automatically transition a failed hot +reset to a warm (BH) reset. In that case, the warm reset change bit +will be set, and the link state change bit may also be set. Change +hub_port_finish_reset to unconditionally clear those change bits for USB +3.0 hubs. If these bits are not cleared, we may lose port change events +from the roothub. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2541,16 +2541,16 @@ static void hub_port_finish_reset(struct + clear_port_feature(hub->hdev, + port1, USB_PORT_FEAT_C_RESET); + /* FIXME need disconnect() for NOTATTACHED device */ +- if (warm) { ++ if (hub_is_superspeed(hub->hdev)) { + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); +- } else { ++ } ++ if (!warm) + usb_set_device_state(udev, *status + ? USB_STATE_NOTATTACHED + : USB_STATE_DEFAULT); +- } + break; + } + } +From bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 Mon Sep 17 00:00:00 2001 +From: Andreas Fleig +Date: Wed, 5 Dec 2012 16:17:49 +0100 +Subject: USB: Add device quirk for Microsoft VX700 webcam + +From: Andreas Fleig + +commit bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 upstream. + +Add device quirk for Microsoft Lifecam VX700 v2.0 webcams. +Fixes squeaking noise of the microphone. + +Signed-off-by: Andreas Fleig +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -43,6 +43,9 @@ static const struct usb_device_id usb_qu + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Microsoft LifeCam-VX700 v2.0 */ ++ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Quickcam Fusion */ + { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, + +From 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 16:10:49 -0800 +Subject: USB: Ignore xHCI Reset Device status. + +From: Sarah Sharp + +commit 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a upstream. + +When the USB core finishes reseting a USB device, the xHCI driver sends +a Reset Device command to the host. The xHC then updates its internal +representation of the USB device to the 'Default' device state. If the +device was already in the Default state, the xHC will complete the +command with an error status. + +If a device needs to be reset several times during enumeration, the +second reset will always fail because of the xHCI Reset Device command. +This can cause issues during enumeration. + +For example, usb_reset_and_verify_device calls into hub_port_init in a +loop. Say that on the first call into hub_port_init, the device is +successfully reset, but doesn't respond to several set address control +transfers. Then the port will be disabled, but the udev will remain in +tact. usb_reset_and_verify_device will call into hub_port_init again. + +On the second call into hub_port_init, the device will be reset, and the +xHCI driver will issue a Reset Device command. This command will fail +(because the device is already in the Default state), and +usb_reset_and_verify_device will fail. The port will be disabled, and +the device won't be able to enumerate. + +Fix this by ignoring the return value of the HCD reset_device callback. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2526,14 +2526,11 @@ static void hub_port_finish_reset(struct + msleep(10 + 40); + update_devnum(udev, 0); + hcd = bus_to_hcd(udev->bus); +- if (hcd->driver->reset_device) { +- *status = hcd->driver->reset_device(hcd, udev); +- if (*status < 0) { +- dev_err(&udev->dev, "Cannot reset " +- "HCD device state\n"); +- break; +- } +- } ++ /* The xHC may think the device is already reset, ++ * so ignore the status. ++ */ ++ if (hcd->driver->reset_device) ++ hcd->driver->reset_device(hcd, udev); + } + /* FALL THROUGH */ + case -ENOTCONN: +From 41e7e056cdc662f704fa9262e5c6e213b4ab45dd Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 16:42:32 -0800 +Subject: USB: Allow USB 3.0 ports to be disabled. + +From: Sarah Sharp + +commit 41e7e056cdc662f704fa9262e5c6e213b4ab45dd upstream. + +If hot and warm reset fails, or a port remains in the Compliance Mode, +the USB core needs to be able to disable a USB 3.0 port. Unlike USB 2.0 +ports, once the port is placed into the Disabled link state, it will not +report any new device connects. To get device connect notifications, we +need to put the link into the Disabled state, and then the RxDetect +state. + +The xHCI driver needs to atomically clear all change bits on USB 3.0 +port disable, so that we get Port Status Change Events for future port +changes. We could technically do this in the USB core instead of in the +xHCI roothub code, since the port state machine can't advance out of the +disabled state until we set the link state to RxDetect. However, +external USB 3.0 hubs don't need this code. They are level-triggered, +not edge-triggered like xHCI, so they will continue to send interrupt +events when any change bit is set. Therefore it doesn't make sense to +put this code in the USB core. + +This patch is part of a series to fix several reports of infinite loops +on device enumeration failure. This includes John, when he boots with +a USB 3.0 device (Roseweil eusb3 enclosure) attached to his NEC 0.96 +host controller. The fix requires warm reset support, so it does not +make sense to backport this patch to stable kernels without warm reset +support. + +This patch should be backported to kernels as old as 3.2, contain the +commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm +reset logic" + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 63 ++++++++++++++++++++++++++++++++++++++++++-- + drivers/usb/host/xhci-hub.c | 31 ++++++++++++++++++++- + 2 files changed, 90 insertions(+), 4 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -876,6 +876,60 @@ static int hub_hub_status(struct usb_hub + return ret; + } + ++static int hub_set_port_link_state(struct usb_hub *hub, int port1, ++ unsigned int link_status) ++{ ++ return set_port_feature(hub->hdev, ++ port1 | (link_status << 3), ++ USB_PORT_FEAT_LINK_STATE); ++} ++ ++/* ++ * If USB 3.0 ports are placed into the Disabled state, they will no longer ++ * detect any device connects or disconnects. This is generally not what the ++ * USB core wants, since it expects a disabled port to produce a port status ++ * change event when a new device connects. ++ * ++ * Instead, set the link state to Disabled, wait for the link to settle into ++ * that state, clear any change bits, and then put the port into the RxDetect ++ * state. ++ */ ++static int hub_usb3_port_disable(struct usb_hub *hub, int port1) ++{ ++ int ret; ++ int total_time; ++ u16 portchange, portstatus; ++ ++ if (!hub_is_superspeed(hub->hdev)) ++ return -EINVAL; ++ ++ ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); ++ if (ret) { ++ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", ++ port1, ret); ++ return ret; ++ } ++ ++ /* Wait for the link to enter the disabled state. */ ++ for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { ++ ret = hub_port_status(hub, port1, &portstatus, &portchange); ++ if (ret < 0) ++ return ret; ++ ++ if ((portstatus & USB_PORT_STAT_LINK_STATE) == ++ USB_SS_PORT_LS_SS_DISABLED) ++ break; ++ if (total_time >= HUB_DEBOUNCE_TIMEOUT) ++ break; ++ msleep(HUB_DEBOUNCE_STEP); ++ } ++ if (total_time >= HUB_DEBOUNCE_TIMEOUT) ++ dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", ++ port1, total_time); ++ ++ return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); ++} ++ + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) + { + struct usb_device *hdev = hub->hdev; +@@ -884,8 +938,13 @@ static int hub_port_disable(struct usb_h + if (hub->ports[port1 - 1]->child && set_state) + usb_set_device_state(hub->ports[port1 - 1]->child, + USB_STATE_NOTATTACHED); +- if (!hub->error && !hub_is_superspeed(hub->hdev)) +- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); ++ if (!hub->error) { ++ if (hub_is_superspeed(hub->hdev)) ++ ret = hub_usb3_port_disable(hub, port1); ++ else ++ ret = clear_port_feature(hdev, port1, ++ USB_PORT_FEAT_ENABLE); ++ } + if (ret) + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd + break; + case USB_PORT_FEAT_LINK_STATE: + temp = xhci_readl(xhci, port_array[wIndex]); ++ ++ /* Disable port */ ++ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { ++ xhci_dbg(xhci, "Disable port %d\n", wIndex); ++ temp = xhci_port_state_to_neutral(temp); ++ /* ++ * Clear all change bits, so that we get a new ++ * connection event. ++ */ ++ temp |= PORT_CSC | PORT_PEC | PORT_WRC | ++ PORT_OCC | PORT_RC | PORT_PLC | ++ PORT_CEC; ++ xhci_writel(xhci, temp | PORT_PE, ++ port_array[wIndex]); ++ temp = xhci_readl(xhci, port_array[wIndex]); ++ break; ++ } ++ ++ /* Put link in RxDetect (enable port) */ ++ if (link_state == USB_SS_PORT_LS_RX_DETECT) { ++ xhci_dbg(xhci, "Enable port %d\n", wIndex); ++ xhci_set_link_state(xhci, port_array, wIndex, ++ link_state); ++ temp = xhci_readl(xhci, port_array[wIndex]); ++ break; ++ } ++ + /* Software should not attempt to set +- * port link state above '5' (Rx.Detect) and the port ++ * port link state above '3' (U3) and the port + * must be enabled. + */ + if ((temp & PORT_PE) == 0 || +- (link_state > USB_SS_PORT_LS_RX_DETECT)) { ++ (link_state > USB_SS_PORT_LS_U3)) { + xhci_warn(xhci, "Cannot set link state.\n"); + goto error; + } +From 77c7f072c87fa951e9a74805febf26466f31170c Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 17:16:52 -0800 +Subject: USB: Increase reset timeout. + +From: Sarah Sharp + +commit 77c7f072c87fa951e9a74805febf26466f31170c upstream. + +John's NEC 0.96 xHCI host controller needs a longer timeout for a warm +reset to complete. The logs show it takes 650ms to complete the warm +reset, so extend the hub reset timeout to 800ms to be on the safe side. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2460,7 +2460,7 @@ static unsigned hub_is_wusb(struct usb_h + #define HUB_SHORT_RESET_TIME 10 + #define HUB_BH_RESET_TIME 50 + #define HUB_LONG_RESET_TIME 200 +-#define HUB_RESET_TIMEOUT 500 ++#define HUB_RESET_TIMEOUT 800 + + static int hub_port_reset(struct usb_hub *hub, int port1, + struct usb_device *udev, unsigned int delay, bool warm); +From 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Thu, 15 Nov 2012 14:58:04 -0800 +Subject: USB: Ignore port state until reset completes. + +From: Sarah Sharp + +commit 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 upstream. + +The port reset code bails out early if the current connect status is +cleared (device disconnected). If we're issuing a hot reset, it may +also look at the link state before the reset is finished. + +Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the +Error state or Resetting state, the port connection bit retains the +value from the previous state. Therefore we can't trust it until the +reset finishes. Also, the xHCI spec section 4.19.1.2.5 says software +shall ignore the link state while the port is resetting, as it can be in +an unknown state. + +The port state during reset is also unknown for USB 2.0 hubs. The hub +sends a reset signal by driving the bus into an SE0 state. This +overwhelms the "connect" signal from the device, so the port can't tell +whether anything is connected or not. + +Fix the port reset code to ignore the port link state and current +connect bit until the reset finishes, and USB_PORT_STAT_RESET is +cleared. + +Remove the check for USB_PORT_STAT_C_BH_RESET in the warm reset case, +because it's redundant. When the warm reset finishes, the port reset +bit will be cleared at the same time USB_PORT_STAT_C_BH_RESET is set. +Remove the now-redundant check for a cleared USB_PORT_STAT_RESET bit +in the code to deal with the finished reset. + +This patch should be backported to all stable kernels. + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2495,6 +2495,10 @@ static int hub_port_wait_reset(struct us + if (ret < 0) + return ret; + ++ /* The port state is unknown until the reset completes. */ ++ if ((portstatus & USB_PORT_STAT_RESET)) ++ goto delay; ++ + /* + * Some buggy devices require a warm reset to be issued even + * when the port appears not to be connected. +@@ -2540,11 +2544,7 @@ static int hub_port_wait_reset(struct us + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + return -ENOTCONN; + +- /* if we`ve finished resetting, then break out of +- * the loop +- */ +- if (!(portstatus & USB_PORT_STAT_RESET) && +- (portstatus & USB_PORT_STAT_ENABLE)) { ++ if ((portstatus & USB_PORT_STAT_ENABLE)) { + if (hub_is_wusb(hub)) + udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeed(hub->hdev)) +@@ -2558,10 +2558,10 @@ static int hub_port_wait_reset(struct us + return 0; + } + } else { +- if (portchange & USB_PORT_STAT_C_BH_RESET) +- return 0; ++ return 0; + } + ++delay: + /* switch to the long delay after two short delay failures */ + if (delay_time >= 2 * HUB_SHORT_RESET_TIME) + delay = HUB_LONG_RESET_TIME; +From 65bdac5effd15d6af619b3b7218627ef4d84ed6a Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 17:58:04 -0800 +Subject: USB: Handle warm reset failure on empty port. + +From: Sarah Sharp + +commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a upstream. + +An empty port can transition to either Inactive or Compliance Mode if a +newly connected USB 3.0 device fails to link train. In that case, we +issue a warm reset. Some devices, such as John's Roseweil eusb3 +enclosure, slip back into Compliance Mode after the warm reset. + +The current warm reset code does not check for device connect status on +warm reset completion, and it incorrectly reports the warm reset +succeeded. This causes the USB core to attempt to send a Set Address +control transfer to a port in Compliance Mode, which will always fail. + +Make hub_port_wait_reset check the current connect status and link state +after the warm reset completes. Return a failure status if the device +is disconnected or the link state is Compliance Mode or SS.Inactive. + +Make hub_events disable the port if warm reset fails. This will disable +the port, and then bring it back into the RxDetect state. Make the USB +core ignore the connect change until the device reconnects. + +Note that this patch does NOT handle connected devices slipping into the +Inactive state very well. This is a concern, because devices can go +into the Inactive state on U1/U2 exit failure. However, the fix for +that case is too large for stable, so it will be submitted in a separate +patch. + +This patch should be backported to kernels as old as 3.2, contain the +commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm +reset logic" + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2558,6 +2558,11 @@ static int hub_port_wait_reset(struct us + return 0; + } + } else { ++ if (!(portstatus & USB_PORT_STAT_CONNECTION) || ++ hub_port_warm_reset_required(hub, ++ portstatus)) ++ return -ENOTCONN; ++ + return 0; + } + +@@ -4628,9 +4633,14 @@ static void hub_events(void) + * SS.Inactive state. + */ + if (hub_port_warm_reset_required(hub, portstatus)) { ++ int status; ++ + dev_dbg(hub_dev, "warm reset port %d\n", i); +- hub_port_reset(hub, i, NULL, ++ status = hub_port_reset(hub, i, NULL, + HUB_BH_RESET_TIME, true); ++ if (status < 0) ++ hub_port_disable(hub, i, 1); ++ connect_change = 0; + } + + if (connect_change) +From c52804a472649b2e5005342308739434cbd51119 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Tue, 27 Nov 2012 12:30:23 -0800 +Subject: xhci: Avoid "dead ports", add roothub port polling. + +From: Sarah Sharp + +commit c52804a472649b2e5005342308739434cbd51119 upstream. + +The USB core hub thread (khubd) is designed with external USB hubs in +mind. It expects that if a port status change bit is set, the hub will +continue to send a notification through the hub status data transfer. +Basically, it expects hub notifications to be level-triggered. + +The xHCI host controller is designed to be edge-triggered on the logical +'OR' of all the port status change bits. When all port status change +bits are clear, and a new change bit is set, the xHC will generate a +Port Status Change Event. If another change bit is set in the same port +status register before the first bit is cleared, it will not send +another event. + +This means that the hub code may lose port status changes because of +race conditions between clearing change bits. The user sees this as a +"dead port" that doesn't react to device connects. + +The fix is to turn on port polling whenever a new change bit is set. +Once the USB core issues a hub status request that shows that no change +bits are set in any USB ports, turn off port polling. + +We can't allow the USB core to poll the roothub for port events during +host suspend because if the PCI host is in D3cold, the port registers +will be all f's. Instead, stop the port polling timer, and +unconditionally restart it when the host resumes. If there are no port +change bits set after the resume, the first call to hub_status_data will +disable polling. + +This patch should be backported to stable kernels with the first xHCI +support, 2.6.31 and newer, that include the commit +0f2a79300a1471cf92ab43af165ea13555c8b0a5 "USB: xhci: Root hub support." +There will be merge conflicts because the check for HC_STATE_SUSPENDED +was moved into xhci_suspend in 3.8. + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-hub.c | 7 +++++++ + drivers/usb/host/xhci-ring.c | 9 +++++++++ + drivers/usb/host/xhci.c | 10 ++++++++++ + 3 files changed, 26 insertions(+) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -984,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd + int max_ports; + __le32 __iomem **port_array; + struct xhci_bus_state *bus_state; ++ bool reset_change = false; + + max_ports = xhci_get_ports(hcd, &port_array); + bus_state = &xhci->bus_state[hcd_index(hcd)]; +@@ -1015,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd + buf[(i + 1) / 8] |= 1 << (i + 1) % 8; + status = 1; + } ++ if ((temp & PORT_RC)) ++ reset_change = true; ++ } ++ if (!status && !reset_change) { ++ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); ++ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + } + spin_unlock_irqrestore(&xhci->lock, flags); + return status ? retval : 0; +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1725,6 +1725,15 @@ cleanup: + if (bogus_port_status) + return; + ++ /* ++ * xHCI port-status-change events occur when the "or" of all the ++ * status-change bits in the portsc register changes from 0 to 1. ++ * New status changes won't cause an event if any other change ++ * bits are still set. When an event occurs, switch over to ++ * polling to avoid losing status changes. ++ */ ++ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); ++ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + spin_unlock(&xhci->lock); + /* Pass this up to the core */ + usb_hcd_poll_rh_status(hcd); +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -880,6 +880,11 @@ int xhci_suspend(struct xhci_hcd *xhci) + struct usb_hcd *hcd = xhci_to_hcd(xhci); + u32 command; + ++ /* Don't poll the roothubs on bus suspend. */ ++ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); ++ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); ++ del_timer_sync(&hcd->rh_timer); ++ + spin_lock_irq(&xhci->lock); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); +@@ -1064,6 +1069,11 @@ int xhci_resume(struct xhci_hcd *xhci, b + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + ++ /* Re-enable port polling. */ ++ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); ++ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); ++ usb_hcd_poll_rh_status(hcd); ++ + return retval; + } + #endif /* CONFIG_PM */ +From 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 29 Nov 2012 15:05:57 +0100 +Subject: USB: hub: handle claim of enabled remote wakeup after reset + +From: Oliver Neukum + +commit 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 upstream. + +Some touchscreens have buggy firmware which claims +remote wakeup to be enabled after a reset. They nevertheless +crash if the feature is cleared by the host. +Add a check for reset resume before checking for +an enabled remote wakeup feature. On compliant +devices the feature must be cleared after a reset anyway. + +Signed-off-by: Oliver Neukum +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2960,7 +2960,7 @@ int usb_port_suspend(struct usb_device * + static int finish_port_resume(struct usb_device *udev) + { + int status = 0; +- u16 devstatus; ++ u16 devstatus = 0; + + /* caller owns the udev device lock */ + dev_dbg(&udev->dev, "%s\n", +@@ -3005,7 +3005,13 @@ static int finish_port_resume(struct usb + if (status) { + dev_dbg(&udev->dev, "gone after usb resume? status %d\n", + status); +- } else if (udev->actconfig) { ++ /* ++ * There are a few quirky devices which violate the standard ++ * by claiming to have remote wakeup enabled after a reset, ++ * which crash if the feature is cleared, hence check for ++ * udev->reset_resume ++ */ ++ } else if (udev->actconfig && !udev->reset_resume) { + le16_to_cpus(&devstatus); + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { + status = usb_control_msg(udev, +From 55c1945edaac94c5338a3647bc2e85ff75d9cf36 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 17 Dec 2012 14:12:35 -0800 +Subject: xhci: Handle HS bulk/ctrl endpoints that don't NAK. + +From: Sarah Sharp + +commit 55c1945edaac94c5338a3647bc2e85ff75d9cf36 upstream. + +A high speed control or bulk endpoint may have bInterval set to zero, +which means it does not NAK. If bInterval is non-zero, it means the +endpoint NAKs at a rate of 2^(bInterval - 1). + +The xHCI code to compute the NAK interval does not handle the special +case of zero properly. The current code unconditionally subtracts one +from bInterval and uses it as an exponent. This causes a very large +bInterval to be used, and warning messages like these will be printed: + +usb 1-1: ep 0x1 - rounding interval to 32768 microframes, ep desc says 0 microframes + +This may cause the xHCI host hardware to reject the Configure Endpoint +command, which means the HS device will be unusable under xHCI ports. + +This patch should be backported to kernels as old as 2.6.31, that contain +commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in +xhci_get_endpoint_interval()". + +Reported-by: Vincent Pelletier +Suggested-by: Alan Stern +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_ + static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) + { ++ if (ep->desc.bInterval == 0) ++ return 0; + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval, 0, 15); + } +From 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Wed, 19 Dec 2012 16:15:56 +0000 +Subject: USB: ehci: make debug port in-use detection functional again + +From: Jan Beulich + +commit 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe upstream. + +Debug port in-use determination must be done before the controller gets +reset the first time, i.e. before the call to ehci_setup() as of commit +1a49e2ac9651df7349867a5cf44e2c83de1046af. That commit effectively +rendered commit 9fa5780beea1274d498a224822397100022da7d4 useless. + +While moving that code around, also fix the BAR determination - the +respective capability field is a 3- rather than a 2-bit one -, and use +PCI_CAP_ID_DBG instead of the literal 0x0a. + +It's unclear to me whether the debug port functionality is important +enough to warrant fixing this in stable kernels too. + +Signed-off-by: Jan Beulich +Cc: Konrad Rzeszutek Wilk +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-pci.c | 39 ++++++++++++++++++++------------------- + 1 file changed, 20 insertions(+), 19 deletions(-) + +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -192,6 +192,26 @@ static int ehci_pci_setup(struct usb_hcd + break; + } + ++ /* optional debug port, normally in the first BAR */ ++ temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); ++ if (temp) { ++ pci_read_config_dword(pdev, temp, &temp); ++ temp >>= 16; ++ if (((temp >> 13) & 7) == 1) { ++ u32 hcs_params = ehci_readl(ehci, ++ &ehci->caps->hcs_params); ++ ++ temp &= 0x1fff; ++ ehci->debug = hcd->regs + temp; ++ temp = ehci_readl(ehci, &ehci->debug->control); ++ ehci_info(ehci, "debug port %d%s\n", ++ HCS_DEBUG_PORT(hcs_params), ++ (temp & DBGP_ENABLED) ? " IN USE" : ""); ++ if (!(temp & DBGP_ENABLED)) ++ ehci->debug = NULL; ++ } ++ } ++ + retval = ehci_setup(hcd); + if (retval) + return retval; +@@ -226,25 +246,6 @@ static int ehci_pci_setup(struct usb_hcd + break; + } + +- /* optional debug port, normally in the first BAR */ +- temp = pci_find_capability(pdev, 0x0a); +- if (temp) { +- pci_read_config_dword(pdev, temp, &temp); +- temp >>= 16; +- if ((temp & (3 << 13)) == (1 << 13)) { +- temp &= 0x1fff; +- ehci->debug = hcd->regs + temp; +- temp = ehci_readl(ehci, &ehci->debug->control); +- ehci_info(ehci, "debug port %d%s\n", +- HCS_DEBUG_PORT(ehci->hcs_params), +- (temp & DBGP_ENABLED) +- ? " IN USE" +- : ""); +- if (!(temp & DBGP_ENABLED)) +- ehci->debug = NULL; +- } +- } +- + /* at least the Genesys GL880S needs fixup here */ + temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); + temp &= 0x0f; +From bc3b7756b5ff66828acf7bc24f148d28b8d61108 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 28 Dec 2012 17:09:03 +0800 +Subject: regulator: max8997: Use uV in voltage_map_desc + +From: Axel Lin + +commit bc3b7756b5ff66828acf7bc24f148d28b8d61108 upstream. + +Current code does integer division (min_vol = min_uV / 1000) before pass +min_vol to max8997_get_voltage_proper_val(). +So it is possible min_vol is truncated to a smaller value. + +For example, if the request min_uV is 800900 for ldo. +min_vol = 800900 / 1000 = 800 (mV) +Then max8997_get_voltage_proper_val returns 800 mV for this case which is lower +than the requested voltage. + +Use uV rather than mV in voltage_map_desc to prevent truncation by integer +division. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8997.c | 36 +++++++++++++++++------------------- + 1 file changed, 17 insertions(+), 19 deletions(-) + +--- a/drivers/regulator/max8997.c ++++ b/drivers/regulator/max8997.c +@@ -69,26 +69,26 @@ struct voltage_map_desc { + int step; + }; + +-/* Voltage maps in mV */ ++/* Voltage maps in uV */ + static const struct voltage_map_desc ldo_voltage_map_desc = { +- .min = 800, .max = 3950, .step = 50, ++ .min = 800000, .max = 3950000, .step = 50000, + }; /* LDO1 ~ 18, 21 all */ + + static const struct voltage_map_desc buck1245_voltage_map_desc = { +- .min = 650, .max = 2225, .step = 25, ++ .min = 650000, .max = 2225000, .step = 25000, + }; /* Buck1, 2, 4, 5 */ + + static const struct voltage_map_desc buck37_voltage_map_desc = { +- .min = 750, .max = 3900, .step = 50, ++ .min = 750000, .max = 3900000, .step = 50000, + }; /* Buck3, 7 */ + +-/* current map in mA */ ++/* current map in uA */ + static const struct voltage_map_desc charger_current_map_desc = { +- .min = 200, .max = 950, .step = 50, ++ .min = 200000, .max = 950000, .step = 50000, + }; + + static const struct voltage_map_desc topoff_current_map_desc = { +- .min = 50, .max = 200, .step = 10, ++ .min = 50000, .max = 200000, .step = 10000, + }; + + static const struct voltage_map_desc *reg_voltage_map[] = { +@@ -192,7 +192,7 @@ static int max8997_list_voltage(struct r + if (val > desc->max) + return -EINVAL; + +- return val * 1000; ++ return val; + } + + static int max8997_get_enable_register(struct regulator_dev *rdev, +@@ -483,7 +483,6 @@ static int max8997_set_voltage_ldobuck(s + { + struct max8997_data *max8997 = rdev_get_drvdata(rdev); + struct i2c_client *i2c = max8997->iodev->i2c; +- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; + const struct voltage_map_desc *desc; + int rid = rdev_get_id(rdev); + int i, reg, shift, mask, ret; +@@ -507,7 +506,7 @@ static int max8997_set_voltage_ldobuck(s + + desc = reg_voltage_map[rid]; + +- i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); ++ i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); + if (i < 0) + return i; + +@@ -555,7 +554,7 @@ static int max8997_set_voltage_ldobuck_t + case MAX8997_BUCK4: + case MAX8997_BUCK5: + return DIV_ROUND_UP(desc->step * (new_selector - old_selector), +- max8997->ramp_delay); ++ max8997->ramp_delay * 1000); + } + + return 0; +@@ -654,7 +653,6 @@ static int max8997_set_voltage_buck(stru + const struct voltage_map_desc *desc; + int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; + bool gpio_dvs_mode = false; +- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; + + if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) + return -EINVAL; +@@ -679,7 +677,7 @@ static int max8997_set_voltage_buck(stru + selector); + + desc = reg_voltage_map[rid]; +- new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); ++ new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); + if (new_val < 0) + return new_val; + +@@ -977,8 +975,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck1_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck1_voltage[i] / 1000, +- pdata->buck1_voltage[i] / 1000 + ++ pdata->buck1_voltage[i], ++ pdata->buck1_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +@@ -986,8 +984,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck2_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck2_voltage[i] / 1000, +- pdata->buck2_voltage[i] / 1000 + ++ pdata->buck2_voltage[i], ++ pdata->buck2_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +@@ -995,8 +993,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck5_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck5_voltage[i] / 1000, +- pdata->buck5_voltage[i] / 1000 + ++ pdata->buck5_voltage[i], ++ pdata->buck5_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +From adf6178ad5552a7f2f742a8c85343c50f080c412 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 28 Dec 2012 17:10:20 +0800 +Subject: regulator: max8998: Use uV in voltage_map_desc + +From: Axel Lin + +commit adf6178ad5552a7f2f742a8c85343c50f080c412 upstream. + +Integer division may truncate. +This happens when pdata->buckx_voltagex setting is not align with 1000 uV. +Thus use uV in voltage_map_desc, this ensures the selected voltage won't less +than pdata buckx_voltagex settings. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8998.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +--- a/drivers/regulator/max8998.c ++++ b/drivers/regulator/max8998.c +@@ -51,39 +51,39 @@ struct voltage_map_desc { + int step; + }; + +-/* Voltage maps */ ++/* Voltage maps in uV*/ + static const struct voltage_map_desc ldo23_voltage_map_desc = { +- .min = 800, .step = 50, .max = 1300, ++ .min = 800000, .step = 50000, .max = 1300000, + }; + static const struct voltage_map_desc ldo456711_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc ldo8_voltage_map_desc = { +- .min = 3000, .step = 100, .max = 3600, ++ .min = 3000000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc ldo9_voltage_map_desc = { +- .min = 2800, .step = 100, .max = 3100, ++ .min = 2800000, .step = 100000, .max = 3100000, + }; + static const struct voltage_map_desc ldo10_voltage_map_desc = { +- .min = 950, .step = 50, .max = 1300, ++ .min = 95000, .step = 50000, .max = 1300000, + }; + static const struct voltage_map_desc ldo1213_voltage_map_desc = { +- .min = 800, .step = 100, .max = 3300, ++ .min = 800000, .step = 100000, .max = 3300000, + }; + static const struct voltage_map_desc ldo1415_voltage_map_desc = { +- .min = 1200, .step = 100, .max = 3300, ++ .min = 1200000, .step = 100000, .max = 3300000, + }; + static const struct voltage_map_desc ldo1617_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc buck12_voltage_map_desc = { +- .min = 750, .step = 25, .max = 1525, ++ .min = 750000, .step = 25000, .max = 1525000, + }; + static const struct voltage_map_desc buck3_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc buck4_voltage_map_desc = { +- .min = 800, .step = 100, .max = 2300, ++ .min = 800000, .step = 100000, .max = 2300000, + }; + + static const struct voltage_map_desc *ldo_voltage_map[] = { +@@ -445,7 +445,7 @@ static int max8998_set_voltage_buck_time + if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) + return 0; + +- difference = (new_selector - old_selector) * desc->step; ++ difference = (new_selector - old_selector) * desc->step / 1000; + if (difference > 0) + return difference / ((val & 0x0f) + 1); + +@@ -702,7 +702,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage1 / 1000)) ++ < pdata->buck1_voltage1) + i++; + max8998->buck1_vol[0] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); +@@ -713,7 +713,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage2 / 1000)) ++ < pdata->buck1_voltage2) + i++; + + max8998->buck1_vol[1] = i; +@@ -725,7 +725,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage3 / 1000)) ++ < pdata->buck1_voltage3) + i++; + + max8998->buck1_vol[2] = i; +@@ -737,7 +737,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage4 / 1000)) ++ < pdata->buck1_voltage4) + i++; + + max8998->buck1_vol[3] = i; +@@ -763,7 +763,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck2_voltage1 / 1000)) ++ < pdata->buck2_voltage1) + i++; + max8998->buck2_vol[0] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); +@@ -774,7 +774,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck2_voltage2 / 1000)) ++ < pdata->buck2_voltage2) + i++; + max8998->buck2_vol[1] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); +@@ -792,8 +792,8 @@ static __devinit int max8998_pmic_probe( + int count = (desc->max - desc->min) / desc->step + 1; + + regulators[index].n_voltages = count; +- regulators[index].min_uV = desc->min * 1000; +- regulators[index].uV_step = desc->step * 1000; ++ regulators[index].min_uV = desc->min; ++ regulators[index].uV_step = desc->step; + } + + config.dev = max8998->dev; +From 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Wed, 9 Jan 2013 19:34:57 +0800 +Subject: regulator: max8998: Ensure enough delay time for max8998_set_voltage_buck_time_sel + +From: Axel Lin + +commit 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 upstream. + +Use DIV_ROUND_UP to prevent truncation by integer division issue. +This ensures we return enough delay time. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8998.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/max8998.c ++++ b/drivers/regulator/max8998.c +@@ -447,7 +447,7 @@ static int max8998_set_voltage_buck_time + + difference = (new_selector - old_selector) * desc->step / 1000; + if (difference > 0) +- return difference / ((val & 0x0f) + 1); ++ return DIV_ROUND_UP(difference, (val & 0x0f) + 1); + + return 0; + } +From 9120963578320532dfb3a9a7947e8d05b39900b5 Mon Sep 17 00:00:00 2001 +From: Ralf Baechle +Date: Thu, 20 Dec 2012 12:47:51 +0100 +Subject: Revert "MIPS: Optimise TLB handlers for MIPS32/64 R2 cores." + +From: Ralf Baechle + +commit 9120963578320532dfb3a9a7947e8d05b39900b5 upstream. + +This reverts commit ff401e52100dcdc85e572d1ad376d3307b3fe28e. + +This breaks on MIPS64 R2 cores such as Broadcom's. + +Signed-off-by: Jayachandran C +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/mm/tlbex.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -952,13 +952,6 @@ build_get_pgde32(u32 **p, unsigned int t + #endif + uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ + uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); +- +- if (cpu_has_mips_r2) { +- uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT)); +- uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT)); +- return; +- } +- + uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ + uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); + uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ +@@ -994,15 +987,6 @@ static void __cpuinit build_adjust_conte + + static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) + { +- if (cpu_has_mips_r2) { +- /* PTE ptr offset is obtained from BadVAddr */ +- UASM_i_MFC0(p, tmp, C0_BADVADDR); +- UASM_i_LW(p, ptr, 0, ptr); +- uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1); +- uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1); +- return; +- } +- + /* + * Bug workaround for the Nevada. It seems as if under certain + * circumstances the move from cp0_context might produce a +From e8088073c9610af017fd47fddd104a2c3afb32e8 Mon Sep 17 00:00:00 2001 +From: Joe Thornber +Date: Fri, 21 Dec 2012 20:23:31 +0000 +Subject: dm thin: fix race between simultaneous io and discards to same block + +From: Joe Thornber + +commit e8088073c9610af017fd47fddd104a2c3afb32e8 upstream. + +There is a race when discard bios and non-discard bios are issued +simultaneously to the same block. + +Discard support is expensive for all thin devices precisely because you +have to be careful to quiesce the area you're discarding. DM thin must +handle this conflicting IO pattern (simultaneous non-discard vs discard) +even though a sane application shouldn't be issuing such IO. + +The race manifests as follows: + +1. A non-discard bio is mapped in thin_bio_map. + This doesn't lock out parallel activity to the same block. + +2. A discard bio is issued to the same block as the non-discard bio. + +3. The discard bio is locked in a dm_bio_prison_cell in process_discard + to lock out parallel activity against the same block. + +4. The non-discard bio's mapping continues and its all_io_entry is + incremented so the bio is accounted for in the thin pool's all_io_ds + which is a dm_deferred_set used to track time locality of non-discard IO. + +5. The non-discard bio is finally locked in a dm_bio_prison_cell in + process_bio. + +The race can result in deadlock, leaving the block layer hanging waiting +for completion of a discard bio that never completes, e.g.: + +INFO: task ruby:15354 blocked for more than 120 seconds. +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +ruby D ffffffff8160f0e0 0 15354 15314 0x00000000 + ffff8802fb08bc58 0000000000000082 ffff8802fb08bfd8 0000000000012900 + ffff8802fb08a010 0000000000012900 0000000000012900 0000000000012900 + ffff8802fb08bfd8 0000000000012900 ffff8803324b9480 ffff88032c6f14c0 +Call Trace: + [] schedule+0x29/0x70 + [] schedule_timeout+0x195/0x220 + [] ? _dm_request+0x111/0x160 [dm_mod] + [] wait_for_common+0x11e/0x190 + [] ? try_to_wake_up+0x2b0/0x2b0 + [] wait_for_completion+0x1d/0x20 + [] blkdev_issue_discard+0x219/0x260 + [] blkdev_ioctl+0x6e9/0x7b0 + [] block_ioctl+0x3c/0x40 + [] do_vfs_ioctl+0x8c/0x340 + [] ? block_llseek+0x67/0xb0 + [] sys_ioctl+0xa1/0xb0 + [] ? sys_rt_sigprocmask+0x86/0xd0 + [] system_call_fastpath+0x16/0x1b + +The thinp-test-suite's test_discard_random_sectors reliably hits this +deadlock on fast SSD storage. + +The fix for this race is that the all_io_entry for a bio must be +incremented whilst the dm_bio_prison_cell is held for the bio's +associated virtual and physical blocks. That cell locking wasn't +occurring early enough in thin_bio_map. This patch fixes this. + +Care is taken to always call the new function inc_all_io_entry() with +the relevant cells locked, but they are generally unlocked before +calling issue() to try to avoid holding the cells locked across +generic_submit_request. + +Also, now that thin_bio_map may lock bios in a cell, process_bio() is no +longer the only thread that will do so. Because of this we must be sure +to use cell_defer_except() to release all non-holder entries, that +were added by the other thread, because they must be deferred. + +This patch depends on "dm thin: replace dm_cell_release_singleton with +cell_defer_except". + +Signed-off-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-thin.c | 84 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 59 insertions(+), 25 deletions(-) + +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -368,6 +368,17 @@ static int bio_triggers_commit(struct th + dm_thin_changed_this_transaction(tc->td); + } + ++static void inc_all_io_entry(struct pool *pool, struct bio *bio) ++{ ++ struct dm_thin_endio_hook *h; ++ ++ if (bio->bi_rw & REQ_DISCARD) ++ return; ++ ++ h = dm_get_mapinfo(bio)->ptr; ++ h->all_io_entry = dm_deferred_entry_inc(pool->all_io_ds); ++} ++ + static void issue(struct thin_c *tc, struct bio *bio) + { + struct pool *pool = tc->pool; +@@ -596,13 +607,15 @@ static void process_prepared_discard_pas + { + struct thin_c *tc = m->tc; + ++ inc_all_io_entry(tc->pool, m->bio); ++ cell_defer_except(tc, m->cell); ++ cell_defer_except(tc, m->cell2); ++ + if (m->pass_discard) + remap_and_issue(tc, m->bio, m->data_block); + else + bio_endio(m->bio, 0); + +- cell_defer_except(tc, m->cell); +- cell_defer_except(tc, m->cell2); + mempool_free(m, tc->pool->mapping_pool); + } + +@@ -710,6 +723,7 @@ static void schedule_copy(struct thin_c + h->overwrite_mapping = m; + m->bio = bio; + save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); ++ inc_all_io_entry(pool, bio); + remap_and_issue(tc, bio, data_dest); + } else { + struct dm_io_region from, to; +@@ -779,6 +793,7 @@ static void schedule_zero(struct thin_c + h->overwrite_mapping = m; + m->bio = bio; + save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); ++ inc_all_io_entry(pool, bio); + remap_and_issue(tc, bio, data_block); + } else { + int r; +@@ -961,13 +976,15 @@ static void process_discard(struct thin_ + wake_worker(pool); + } + } else { ++ inc_all_io_entry(pool, bio); ++ cell_defer_except(tc, cell); ++ cell_defer_except(tc, cell2); ++ + /* + * The DM core makes sure that the discard doesn't span + * a block boundary. So we submit the discard of a + * partial block appropriately. + */ +- cell_defer_except(tc, cell); +- cell_defer_except(tc, cell2); + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else +@@ -1039,8 +1056,9 @@ static void process_shared_bio(struct th + struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; + + h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); +- ++ inc_all_io_entry(pool, bio); + cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, lookup_result->block); + } + } +@@ -1055,7 +1073,9 @@ static void provision_block(struct thin_ + * Remap empty bios (flushes) immediately, without provisioning. + */ + if (!bio->bi_size) { ++ inc_all_io_entry(tc->pool, bio); + cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, 0); + return; + } +@@ -1110,26 +1130,22 @@ static void process_bio(struct thin_c *t + r = dm_thin_find_block(tc->td, block, 1, &lookup_result); + switch (r) { + case 0: +- /* +- * We can release this cell now. This thread is the only +- * one that puts bios into a cell, and we know there were +- * no preceding bios. +- */ +- /* +- * TODO: this will probably have to change when discard goes +- * back in. +- */ +- cell_defer_except(tc, cell); +- +- if (lookup_result.shared) ++ if (lookup_result.shared) { + process_shared_bio(tc, bio, block, &lookup_result); +- else ++ cell_defer_except(tc, cell); ++ } else { ++ inc_all_io_entry(tc->pool, bio); ++ cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, lookup_result.block); ++ } + break; + + case -ENODATA: + if (bio_data_dir(bio) == READ && tc->origin_dev) { ++ inc_all_io_entry(tc->pool, bio); + cell_defer_except(tc, cell); ++ + remap_to_origin_and_issue(tc, bio); + } else + provision_block(tc, bio, block, cell); +@@ -1155,8 +1171,10 @@ static void process_bio_read_only(struct + case 0: + if (lookup_result.shared && (rw == WRITE) && bio->bi_size) + bio_io_error(bio); +- else ++ else { ++ inc_all_io_entry(tc->pool, bio); + remap_and_issue(tc, bio, lookup_result.block); ++ } + break; + + case -ENODATA: +@@ -1166,6 +1184,7 @@ static void process_bio_read_only(struct + } + + if (tc->origin_dev) { ++ inc_all_io_entry(tc->pool, bio); + remap_to_origin_and_issue(tc, bio); + break; + } +@@ -1346,7 +1365,7 @@ static struct dm_thin_endio_hook *thin_h + + h->tc = tc; + h->shared_read_entry = NULL; +- h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds); ++ h->all_io_entry = NULL; + h->overwrite_mapping = NULL; + + return h; +@@ -1363,6 +1382,8 @@ static int thin_bio_map(struct dm_target + dm_block_t block = get_bio_block(tc, bio); + struct dm_thin_device *td = tc->td; + struct dm_thin_lookup_result result; ++ struct dm_bio_prison_cell *cell1, *cell2; ++ struct dm_cell_key key; + + map_context->ptr = thin_hook_bio(tc, bio); + +@@ -1399,12 +1420,25 @@ static int thin_bio_map(struct dm_target + * shared flag will be set in their case. + */ + thin_defer_bio(tc, bio); +- r = DM_MAPIO_SUBMITTED; +- } else { +- remap(tc, bio, result.block); +- r = DM_MAPIO_REMAPPED; ++ return DM_MAPIO_SUBMITTED; + } +- break; ++ ++ build_virtual_key(tc->td, block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1)) ++ return DM_MAPIO_SUBMITTED; ++ ++ build_data_key(tc->td, result.block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2)) { ++ cell_defer_except(tc, cell1); ++ return DM_MAPIO_SUBMITTED; ++ } ++ ++ inc_all_io_entry(tc->pool, bio); ++ cell_defer_except(tc, cell2); ++ cell_defer_except(tc, cell1); ++ ++ remap(tc, bio, result.block); ++ return DM_MAPIO_REMAPPED; + + case -ENODATA: + if (get_pool_mode(tc->pool) == PM_READ_ONLY) { +From ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 3 Dec 2012 12:59:04 +0100 +Subject: Revert: "rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails" + +From: Stanislaw Gruszka + +commit ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e upstream. + +This revert: + +commit be03d4a45c09ee5100d3aaaedd087f19bc20d01f +Author: Andreas Hartmann +Date: Tue Apr 17 00:25:28 2012 +0200 + + rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails + +To fix problem workaround by above commit use +IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL flag (see change log for +"mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL" patch). + +Resolve: https://bugzilla.kernel.org/show_bug.cgi?id=42828 +Bisected-by: Francisco Pina Martins +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + drivers/net/wireless/rt2x00/rt2x00dev.c | 7 +++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -5036,7 +5036,8 @@ static int rt2800_probe_hw_mode(struct r + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_AMPDU_AGGREGATION | +- IEEE80211_HW_REPORTS_TX_ACK_STATUS; ++ IEEE80211_HW_REPORTS_TX_ACK_STATUS | ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL; + + /* + * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -391,10 +391,9 @@ void rt2x00lib_txdone(struct queue_entry + tx_info->flags |= IEEE80211_TX_STAT_AMPDU; + tx_info->status.ampdu_len = 1; + tx_info->status.ampdu_ack_len = success ? 1 : 0; +- /* +- * TODO: Need to tear down BA session here +- * if not successful. +- */ ++ ++ if (!success) ++ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + } + + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { +From 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov +Date: Fri, 14 Dec 2012 15:03:10 +0400 +Subject: EDAC: Fix kernel panic on module unloading + +From: Konstantin Khlebnikov + +commit 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 upstream. + +This patch fixes use-after-free and double-free bugs in +edac_mc_sysfs_exit(). mci_pdev has single reference and put_device() +calls mc_attr_release() which calls kfree(). The following +device_del() works with already released memory. An another kfree() in +edac_mc_sysfs_exit() releses the same memory again. Great. + +Signed-off-by: Konstantin Khlebnikov +Cc: Denis Kirjanov +Cc: Mauro Carvalho Chehab +Link: http://lkml.kernel.org/r/20121214110310.11019.21098.stgit@zurg +Signed-off-by: Borislav Petkov +[ a partial 3.7.y backport ] +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/edac/edac_mc_sysfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -1145,7 +1145,7 @@ int __init edac_mc_sysfs_init(void) + + void __exit edac_mc_sysfs_exit(void) + { +- put_device(mci_pdev); + device_del(mci_pdev); ++ put_device(mci_pdev); + edac_put_sysfs_subsys(); + } +From 539526b4137bc0e7a8806c38c8522f226814a0e6 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sat, 8 Dec 2012 12:58:33 +0100 +Subject: drm/i915: disable cpt phase pointer fdi rx workaround + +From: Daniel Vetter + +commit 539526b4137bc0e7a8806c38c8522f226814a0e6 upstream. + +We've originally added this in + +commit 291427f5fdadec6e4be2924172e83588880e1539 +Author: Jesse Barnes +Date: Fri Jul 29 12:42:37 2011 -0700 + + drm/i915: apply phase pointer override on SNB+ too + +and then copy-pasted it over to ivb/ppt. The w/a was originally added +for ilk/ibx in + +commit 5b2adf897146edeac6a1e438fb67b5a53dbbdf34 +Author: Jesse Barnes +Date: Thu Oct 7 16:01:15 2010 -0700 + + drm/i915: add Ironlake clock gating workaround for FDI link training + +and fixed up a bit in + +commit 6f06ce184c765fd8d50669a8d12fdd566c920859 +Author: Jesse Barnes +Date: Tue Jan 4 15:09:38 2011 -0800 + + drm/i915: set phase sync pointer override enable before setting phase sync pointer + +It turns out that this w/a isn't actually required on cpt/ppt and +positively harmful on ivb/ppt when using fdi B/C links - it results in +a black screen occasionally, with seemingfully everything working as +it should. The only failure indication I've found in the hw is that +eventually (but not right after the modeset completes) a pipe underrun +is signalled. + +Big thanks to Arthur Runyan for all the ideas for registers to check +and changes to test, otherwise I couldn't ever have tracked this down! + +Cc: "Runyan, Arthur J" +Cc: stable@vger.kernel.org +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 31 ------------------------------- + 1 file changed, 31 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -2302,18 +2302,6 @@ static void intel_fdi_normal_train(struc + FDI_FE_ERRC_ENABLE); + } + +-static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- u32 flags = I915_READ(SOUTH_CHICKEN1); +- +- flags |= FDI_PHASE_SYNC_OVR(pipe); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ +- flags |= FDI_PHASE_SYNC_EN(pipe); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ +- POSTING_READ(SOUTH_CHICKEN1); +-} +- + /* The FDI link training functions for ILK/Ibexpeak. */ + static void ironlake_fdi_link_train(struct drm_crtc *crtc) + { +@@ -2464,9 +2452,6 @@ static void gen6_fdi_link_train(struct d + POSTING_READ(reg); + udelay(150); + +- if (HAS_PCH_CPT(dev)) +- cpt_phase_pointer_enable(dev, pipe); +- + for (i = 0; i < 4; i++) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); +@@ -2593,9 +2578,6 @@ static void ivb_manual_fdi_link_train(st + POSTING_READ(reg); + udelay(150); + +- if (HAS_PCH_CPT(dev)) +- cpt_phase_pointer_enable(dev, pipe); +- + for (i = 0; i < 4; i++) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); +@@ -2737,17 +2719,6 @@ static void ironlake_fdi_pll_disable(str + udelay(100); + } + +-static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- u32 flags = I915_READ(SOUTH_CHICKEN1); +- +- flags &= ~(FDI_PHASE_SYNC_EN(pipe)); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ +- flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ +- POSTING_READ(SOUTH_CHICKEN1); +-} + static void ironlake_fdi_disable(struct drm_crtc *crtc) + { + struct drm_device *dev = crtc->dev; +@@ -2777,8 +2748,6 @@ static void ironlake_fdi_disable(struct + I915_WRITE(FDI_RX_CHICKEN(pipe), + I915_READ(FDI_RX_CHICKEN(pipe) & + ~FDI_RX_PHASE_SYNC_POINTER_EN)); +- } else if (HAS_PCH_CPT(dev)) { +- cpt_phase_pointer_disable(dev, pipe); + } + + /* still set train pattern 1 */ +From e43a028752fed049e4bd94ef895542f96d79fa74 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Sat, 6 Oct 2012 03:56:35 +0200 +Subject: KVM: PPC: 44x: fix DCR read/write + +From: Alexander Graf + +commit e43a028752fed049e4bd94ef895542f96d79fa74 upstream. + +When remembering the direction of a DCR transaction, we should write +to the same variable that we interpret on later when doing vcpu_run +again. + +Signed-off-by: Alexander Graf +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kvm/44x_emulate.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/powerpc/kvm/44x_emulate.c ++++ b/arch/powerpc/kvm/44x_emulate.c +@@ -76,6 +76,7 @@ int kvmppc_core_emulate_op(struct kvm_ru + run->dcr.dcrn = dcrn; + run->dcr.data = 0; + run->dcr.is_write = 0; ++ vcpu->arch.dcr_is_write = 0; + vcpu->arch.io_gpr = rt; + vcpu->arch.dcr_needed = 1; + kvmppc_account_exit(vcpu, DCR_EXITS); +@@ -94,6 +95,7 @@ int kvmppc_core_emulate_op(struct kvm_ru + run->dcr.dcrn = dcrn; + run->dcr.data = kvmppc_get_gpr(vcpu, rs); + run->dcr.is_write = 1; ++ vcpu->arch.dcr_is_write = 1; + vcpu->arch.dcr_needed = 1; + kvmppc_account_exit(vcpu, DCR_EXITS); + emulated = EMULATE_DO_DCR; +From 3751809df766c05bcce372fcfa4a886b9aaca44b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 7 Dec 2012 19:50:07 -0600 +Subject: libceph: socket can close in any connection state + +From: Alex Elder + +(cherry picked from commit 7bb21d68c535ad8be38e14a715632ae398b37ac1) + +A connection's socket can close for any reason, independent of the +state of the connection (and without irrespective of the connection +mutex). As a result, the connectino can be in pretty much any state +at the time its socket is closed. + +Handle those other cases at the top of con_work(). Pull this whole +block of code into a separate function to reduce the clutter. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 47 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 17 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2262,6 +2262,35 @@ static void queue_con(struct ceph_connec + } + } + ++static bool con_sock_closed(struct ceph_connection *con) ++{ ++ if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) ++ return false; ++ ++#define CASE(x) \ ++ case CON_STATE_ ## x: \ ++ con->error_msg = "socket closed (con state " #x ")"; \ ++ break; ++ ++ switch (con->state) { ++ CASE(CLOSED); ++ CASE(PREOPEN); ++ CASE(CONNECTING); ++ CASE(NEGOTIATING); ++ CASE(OPEN); ++ CASE(STANDBY); ++ default: ++ pr_warning("%s con %p unrecognized state %lu\n", ++ __func__, con, con->state); ++ con->error_msg = "unrecognized con state"; ++ BUG(); ++ break; ++ } ++#undef CASE ++ ++ return true; ++} ++ + /* + * Do some work on a connection. Drop a connection ref when we're done. + */ +@@ -2273,24 +2302,8 @@ static void con_work(struct work_struct + + mutex_lock(&con->mutex); + restart: +- if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { +- switch (con->state) { +- case CON_STATE_CONNECTING: +- con->error_msg = "connection failed"; +- break; +- case CON_STATE_NEGOTIATING: +- con->error_msg = "negotiation failed"; +- break; +- case CON_STATE_OPEN: +- con->error_msg = "socket closed"; +- break; +- default: +- dout("unrecognized con state %d\n", (int)con->state); +- con->error_msg = "unrecognized con state"; +- BUG(); +- } ++ if (con_sock_closed(con)) + goto fault; +- } + + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { + dout("con_work %p backing off\n", con); +From 5f64737fb44ee280362a1be280f26adb38c689e4 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 14 Dec 2012 16:47:41 -0600 +Subject: libceph: report connection fault with warning + +From: Alex Elder + +(cherry picked from commit 28362986f8743124b3a0fda20a8ed3e80309cce1) + +When a connection's socket disconnects, or if there's a protocol +error of some kind on the connection, a fault is signaled and +the connection is reset (closed and reopened, basically). We +currently get an error message on the log whenever this occurs. + +A ceph connection will attempt to reestablish a socket connection +repeatedly if a fault occurs. This means that these error messages +will get repeatedly added to the log, which is undesirable. + +Change the error message to be a warning, so they don't get +logged by default. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2369,7 +2369,7 @@ fault: + static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) + { +- pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ++ pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), + ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); +From d49d943a24d4addbb5c6d1e4feb45bb98b2885fa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: init osd->o_node in create_osd() + +From: Alex Elder + +(cherry picked from commit f407731d12214e7686819018f3a1e9d7b6f83a02) + +The red-black node node in the ceph osd structure is not initialized +in create_osd(). Because this node can be the subject of a +RB_EMPTY_NODE() call later on, we should ensure the node is +initialized properly for that. Add a call to RB_CLEAR_NODE() +initialize it. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -647,6 +647,7 @@ static struct ceph_osd *create_osd(struc + atomic_set(&osd->o_ref, 1); + osd->o_osdc = osdc; + osd->o_osd = onum; ++ RB_CLEAR_NODE(&osd->o_node); + INIT_LIST_HEAD(&osd->o_requests); + INIT_LIST_HEAD(&osd->o_linger_requests); + INIT_LIST_HEAD(&osd->o_osd_lru); +From b4c0c6243efad1ae18a8aa17694952fd6c13bbaa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: init event->node in ceph_osdc_create_event() + +From: Alex Elder + +(cherry picked from commit 3ee5234df68d253c415ba4f2db72ad250d9c21a9) + +The red-black node node in the ceph osd event structure is not +initialized in create_osdc_create_event(). Because this node can +be the subject of a RB_EMPTY_NODE() call later on, we should ensure +the node is initialized properly for that. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1600,6 +1600,7 @@ int ceph_osdc_create_event(struct ceph_o + event->data = data; + event->osdc = osdc; + INIT_LIST_HEAD(&event->osd_node); ++ RB_CLEAR_NODE(&event->node); + kref_init(&event->kref); /* one ref for us */ + kref_get(&event->kref); /* one ref for the caller */ + init_completion(&event->completion); +From f660813d76b3634c39c2b3ed8715af7e9db14f9c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: don't use rb_init_node() in ceph_osdc_alloc_request() + +From: Alex Elder + +(cherry picked from commit a978fa20fb657548561dddbfb605fe43654f0825) + +The red-black node in the ceph osd request structure is initialized +in ceph_osdc_alloc_request() using rbd_init_node(). We do need to +initialize this, because in __unregister_request() we call +RB_EMPTY_NODE(), which expects the node it's checking to have +been initialized. But rb_init_node() is apparently overkill, and +may in fact be on its way out. So use RB_CLEAR_NODE() instead. + +For a little more background, see this commit: + 4c199a93 rbtree: empty nodes have no color" + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc + kref_init(&req->r_kref); + init_completion(&req->r_completion); + init_completion(&req->r_safe_completion); ++ RB_CLEAR_NODE(&req->r_node); + INIT_LIST_HEAD(&req->r_unsafe_item); + INIT_LIST_HEAD(&req->r_linger_item); + INIT_LIST_HEAD(&req->r_linger_osd); +From c9ddd2cac5e5e9bf278a9c08976592972a2d15c1 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: register request before unregister linger + +From: Alex Elder + +(cherry picked from commit c89ce05e0c5a01a256100ac6a6019f276bdd1ca6) + +In kick_requests(), we need to register the request before we +unregister the linger request. Otherwise the unregister will +reset the request's osd pointer to NULL. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1366,8 +1366,8 @@ static void kick_requests(struct ceph_os + + dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); +- __unregister_linger_request(osdc, req); + __register_request(osdc, req); ++ __unregister_linger_request(osdc, req); + } + mutex_unlock(&osdc->request_mutex); + +From d92a42b79c755e911495bd36316d2573804293ea Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 19 Dec 2012 15:52:36 -0600 +Subject: libceph: move linger requests sooner in kick_requests() + +From: Alex Elder + +(cherry picked from commit ab60b16d3c31b9bd9fd5b39f97dc42c52a50b67d) + +The kick_requests() function is called by ceph_osdc_handle_map() +when an osd map change has been indicated. Its purpose is to +re-queue any request whose target osd is different from what it +was when it was originally sent. + +It is structured as two loops, one for incomplete but registered +requests, and a second for handling completed linger requests. +As a special case, in the first loop if a request marked to linger +has not yet completed, it is moved from the request list to the +linger list. This is as a quick and dirty way to have the second +loop handle sending the request along with all the other linger +requests. + +Because of the way it's done now, however, this quick and dirty +solution can result in these incomplete linger requests never +getting re-sent as desired. The problem lies in the fact that +the second loop only arranges for a linger request to be sent +if it appears its target osd has changed. This is the proper +handling for *completed* linger requests (it avoids issuing +the same linger request twice to the same osd). + +But although the linger requests added to the list in the first loop +may have been sent, they have not yet completed, so they need to be +re-sent regardless of whether their target osd has changed. + +The first required fix is we need to avoid calling __map_request() +on any incomplete linger request. Otherwise the subsequent +__map_request() call in the second loop will find the target osd +has not changed and will therefore not re-send the request. + +Second, we need to be sure that a sent but incomplete linger request +gets re-sent. If the target osd is the same with the new osd map as +it was when the request was originally sent, this won't happen. +This can be fixed through careful handling when we move these +requests from the request list to the linger list, by unregistering +the request *before* it is registered as a linger request. This +works because a side-effect of unregistering the request is to make +the request's r_osd pointer be NULL, and *that* will ensure the +second loop actually re-sends the linger request. + +Processing of such a request is done at that point, so continue with +the next one once it's been moved. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1322,6 +1322,24 @@ static void kick_requests(struct ceph_os + for (p = rb_first(&osdc->requests); p; ) { + req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); ++ ++ /* ++ * For linger requests that have not yet been ++ * registered, move them to the linger list; they'll ++ * be sent to the osd in the loop below. Unregister ++ * the request before re-registering it as a linger ++ * request to ensure the __map_request() below ++ * will decide it needs to be sent. ++ */ ++ if (req->r_linger && list_empty(&req->r_linger_item)) { ++ dout("%p tid %llu restart on osd%d\n", ++ req, req->r_tid, ++ req->r_osd ? req->r_osd->o_osd : -1); ++ __unregister_request(osdc, req); ++ __register_linger_request(osdc, req); ++ continue; ++ } ++ + err = __map_request(osdc, req, force_resend); + if (err < 0) + continue; /* error */ +@@ -1336,17 +1354,6 @@ static void kick_requests(struct ceph_os + req->r_flags |= CEPH_OSD_FLAG_RETRY; + } + } +- if (req->r_linger && list_empty(&req->r_linger_item)) { +- /* +- * register as a linger so that we will +- * re-submit below and get a new tid +- */ +- dout("%p tid %llu restart on osd%d\n", +- req, req->r_tid, +- req->r_osd ? req->r_osd->o_osd : -1); +- __register_linger_request(osdc, req); +- __unregister_request(osdc, req); +- } + } + + list_for_each_entry_safe(req, nreq, &osdc->req_linger, +@@ -1354,6 +1361,7 @@ static void kick_requests(struct ceph_os + dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); + + err = __map_request(osdc, req, force_resend); ++ dout("__map_request returned %d\n", err); + if (err == 0) + continue; /* no change and no osd was specified */ + if (err < 0) +From 8cc1491a5d9e720f0b6f69244fc1548597bb868b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 14:31:40 -0600 +Subject: libceph: always reset osds when kicking + +From: Alex Elder + +(cherry picked from commit e6d50f67a6b1a6252a616e6e629473b5c4277218) + +When ceph_osdc_handle_map() is called to process a new osd map, +kick_requests() is called to ensure all affected requests are +updated if necessary to reflect changes in the osd map. This +happens in two cases: whenever an incremental map update is +processed; and when a full map update (or the last one if there is +more than one) gets processed. + +In the former case, the kick_requests() call is followed immediately +by a call to reset_changed_osds() to ensure any connections to osds +affected by the map change are reset. But for full map updates +this isn't done. + +Both cases should be doing this osd reset. + +Rather than duplicating the reset_changed_osds() call, move it into +the end of kick_requests(). + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1308,7 +1308,7 @@ static void reset_changed_osds(struct ce + * Requeue requests whose mapping to an OSD has changed. If requests map to + * no osd, request a new map. + * +- * Caller should hold map_sem for read and request_mutex. ++ * Caller should hold map_sem for read. + */ + static void kick_requests(struct ceph_osd_client *osdc, int force_resend) + { +@@ -1383,6 +1383,7 @@ static void kick_requests(struct ceph_os + dout("%d requests for down osds, need new map\n", needmap); + ceph_monc_request_next_osdmap(&osdc->client->monc); + } ++ reset_changed_osds(osdc); + } + + +@@ -1439,7 +1440,6 @@ void ceph_osdc_handle_map(struct ceph_os + osdc->osdmap = newmap; + } + kick_requests(osdc, 0); +- reset_changed_osds(osdc); + } else { + dout("ignoring incremental map %u len %d\n", + epoch, maplen); +From b95ad0140dc8d2375bff4b0f30f6832cbb29e17c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 10:43:57 -0600 +Subject: libceph: WARN, don't BUG on unexpected connection states + +From: Alex Elder + +(cherry picked from commit 122070a2ffc91f87fe8e8493eb0ac61986c5557c) + +A number of assertions in the ceph messenger are implemented with +BUG_ON(), killing the system if connection's state doesn't match +what's expected. At this point our state model is (evidently) not +well understood enough for these assertions to trigger a BUG(). +Convert all BUG_ON(con->state...) calls to be WARN_ON(con->state...) +so we learn about these issues without killing the machine. + +We now recognize that a connection fault can occur due to a socket +closure at any time, regardless of the state of the connection. So +there is really nothing we can assert about the state of the +connection at that point so eliminate that assertion. + +Reported-by: Ugis +Tested-by: Ugis +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -561,7 +561,7 @@ void ceph_con_open(struct ceph_connectio + mutex_lock(&con->mutex); + dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); + +- BUG_ON(con->state != CON_STATE_CLOSED); ++ WARN_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; + + con->peer_name.type = (__u8) entity_type; +@@ -1509,7 +1509,7 @@ static int process_banner(struct ceph_co + static void fail_protocol(struct ceph_connection *con) + { + reset_connection(con); +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_CLOSED; + } + +@@ -1635,7 +1635,7 @@ static int process_connect(struct ceph_c + return -1; + } + +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); +@@ -2132,7 +2132,6 @@ more: + if (ret < 0) + goto out; + +- BUG_ON(con->state != CON_STATE_CONNECTING); + con->state = CON_STATE_NEGOTIATING; + + /* +@@ -2160,7 +2159,7 @@ more: + goto more; + } + +- BUG_ON(con->state != CON_STATE_OPEN); ++ WARN_ON(con->state != CON_STATE_OPEN); + + if (con->in_base_pos < 0) { + /* +@@ -2374,7 +2373,7 @@ static void ceph_fault(struct ceph_conne + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); + +- BUG_ON(con->state != CON_STATE_CONNECTING && ++ WARN_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); + +From 48e858340dae43189a4e55647f6eac736766f828 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Mon, 7 Jan 2013 10:27:13 +0100 +Subject: Revert "drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13" + +From: Daniel Vetter + +commit 48e858340dae43189a4e55647f6eac736766f828 upstream. + +This reverts commit 9756fe38d10b2bf90c81dc4d2f17d5632e135364. + +The bogus lvds output is actually a lvds->hdmi bridge, which we don't +really support. But unconditionally disabling it breaks some existing +setups. + +Reported-by: John Tapsell +References: http://permalink.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/17237 +Signed-off-by: Daniel Vetter +Cc: Luis Henriques +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/gpu/drm/i915/intel_lvds.c | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -763,14 +763,6 @@ static const struct dmi_system_id intel_ + }, + { + .callback = intel_no_lvds_dmi_callback, +- .ident = "ZOTAC ZBOXSD-ID12/ID13", +- .matches = { +- DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), +- DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), +- }, +- }, +- { +- .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), +From f10a18433a1b3192e71eecffeaeca5f5f1694016 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Thu, 27 Dec 2012 20:27:04 -0600 +Subject: libceph: fix protocol feature mismatch failure path + + +From: Sage Weil + +(cherry picked from commit 0fa6ebc600bc8e830551aee47a0e929e818a1868) + +We should not set con->state to CLOSED here; that happens in +ceph_fault() in the caller, where it first asserts that the state +is not yet CLOSED. Avoids a BUG when the features don't match. + +Since the fail_protocol() has become a trivial wrapper, replace +calls to it with direct calls to reset_connection(). + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -506,6 +506,7 @@ static void reset_connection(struct ceph + { + /* reset connection, out_queue, msg_ and connect_seq */ + /* discard existing out_queue and msg_seq */ ++ dout("reset_connection %p\n", con); + ceph_msg_remove_list(&con->out_queue); + ceph_msg_remove_list(&con->out_sent); + +@@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_co + return 0; + } + +-static void fail_protocol(struct ceph_connection *con) +-{ +- reset_connection(con); +- WARN_ON(con->state != CON_STATE_NEGOTIATING); +- con->state = CON_STATE_CLOSED; +-} +- + static int process_connect(struct ceph_connection *con) + { + u64 sup_feat = con->msgr->supported_features; +@@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_c + ceph_pr_addr(&con->peer_addr.in_addr), + sup_feat, server_feat, server_feat & ~sup_feat); + con->error_msg = "missing required protocol features"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + + case CEPH_MSGR_TAG_BADPROTOVER: +@@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_c + le32_to_cpu(con->out_connect.protocol_version), + le32_to_cpu(con->in_reply.protocol_version)); + con->error_msg = "protocol version mismatch"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + + case CEPH_MSGR_TAG_BADAUTHORIZER: +@@ -1631,7 +1625,7 @@ static int process_connect(struct ceph_c + ceph_pr_addr(&con->peer_addr.in_addr), + req_feat, server_feat, req_feat & ~server_feat); + con->error_msg = "missing required protocol features"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + } + +From 71630f053c8da3b7d8e52c99ff2592f44dd28979 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Mon, 29 Oct 2012 11:01:42 -0700 +Subject: libceph: fix osdmap decode error paths + + +From: Sage Weil + +(cherry picked from commit 0ed7285e0001b960c888e5455ae982025210ed3d) + +Ensure that we set the err value correctly so that we do not pass a 0 +value to ERR_PTR and confuse the calling code. (In particular, +osd_client.c handle_map() will BUG(!newmap)). + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osdmap.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/net/ceph/osdmap.c ++++ b/net/ceph/osdmap.c +@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void * + ceph_decode_32_safe(p, end, max, bad); + while (max--) { + ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); ++ err = -ENOMEM; + pi = kzalloc(sizeof(*pi), GFP_NOFS); + if (!pi) + goto bad; + pi->id = ceph_decode_32(p); ++ err = -EINVAL; + ev = ceph_decode_8(p); /* encoding version */ + if (ev > CEPH_PG_POOL_VERSION) { + pr_warning("got unknown v %d > %d of ceph_pg_pool\n", +@@ -664,8 +666,13 @@ struct ceph_osdmap *osdmap_decode(void * + __insert_pg_pool(&map->pg_pools, pi); + } + +- if (version >= 5 && __decode_pool_names(p, end, map) < 0) +- goto bad; ++ if (version >= 5) { ++ err = __decode_pool_names(p, end, map); ++ if (err < 0) { ++ dout("fail to decode pool names"); ++ goto bad; ++ } ++ } + + ceph_decode_32_safe(p, end, map->pool_max, bad); + +@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void * + return map; + + bad: +- dout("osdmap_decode fail\n"); ++ dout("osdmap_decode fail err %d\n", err); + ceph_osdmap_destroy(map); + return ERR_PTR(err); + } +@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_increme + if (ev > CEPH_PG_POOL_VERSION) { + pr_warning("got unknown v %d > %d of ceph_pg_pool\n", + ev, CEPH_PG_POOL_VERSION); ++ err = -EINVAL; + goto bad; + } + pi = __lookup_pg_pool(&map->pg_pools, pool); +@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_increme + if (err < 0) + goto bad; + } +- if (version >= 5 && __decode_pool_names(p, end, map) < 0) +- goto bad; ++ if (version >= 5) { ++ err = __decode_pool_names(p, end, map); ++ if (err < 0) ++ goto bad; ++ } + + /* old_pool */ + ceph_decode_32_safe(p, end, len, bad); +@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_increme + (void) __remove_pg_mapping(&map->pg_temp, pgid); + + /* insert */ +- if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { +- err = -EINVAL; ++ err = -EINVAL; ++ if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; +- } ++ err = -ENOMEM; + pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); +- if (!pg) { +- err = -ENOMEM; ++ if (!pg) + goto bad; +- } + pg->pgid = pgid; + pg->len = pglen; + for (j = 0; j < pglen; j++) +From f4a3fea610cb6a9fc9cb722a0765194e19b82e7b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 7 Dec 2012 09:57:58 -0600 +Subject: libceph: avoid using freed osd in __kick_osd_requests() + + +From: Alex Elder + +(cherry picked from commit 685a7555ca69030739ddb57a47f0ea8ea80196a4) + +If an osd has no requests and no linger requests, __reset_osd() +will just remove it with a call to __remove_osd(). That drops +a reference to the osd, and therefore the osd may have been free +by the time __reset_osd() returns. That function offers no +indication this may have occurred, and as a result the osd will +continue to be used even when it's no longer valid. + +Change__reset_osd() so it returns an error (ENODEV) when it +deletes the osd being reset. And change __kick_osd_requests() so it +returns immediately (before referencing osd again) if __reset_osd() +returns *any* error. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -581,7 +581,7 @@ static void __kick_osd_requests(struct c + + dout("__kick_osd_requests osd%d\n", osd->o_osd); + err = __reset_osd(osdc, osd); +- if (err == -EAGAIN) ++ if (err) + return; + + list_for_each_entry(req, &osd->o_requests, r_osd_item) { +@@ -752,6 +752,7 @@ static int __reset_osd(struct ceph_osd_c + if (list_empty(&osd->o_requests) && + list_empty(&osd->o_linger_requests)) { + __remove_osd(osdc, osd); ++ ret = -ENODEV; + } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], + &osd->o_con.peer_addr, + sizeof(osd->o_con.peer_addr)) == 0 && +From aa852ff17166b53b1d29388af472bb9c32297f05 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Wed, 28 Nov 2012 12:28:24 -0800 +Subject: libceph: remove 'osdtimeout' option + + +From: Sage Weil + +(cherry picked from commit 83aff95eb9d60aff5497e9f44a2ae906b86d8e88) + +This would reset a connection with any OSD that had an outstanding +request that was taking more than N seconds. The idea was that if the +OSD was buggy, the client could compensate by resending the request. + +In reality, this only served to hide server bugs, and we haven't +actually seen such a bug in quite a while. Moreover, the userspace +client code never did this. + +More importantly, often the request is taking a long time because the +OSD is trying to recover, or overloaded, and killing the connection +and retrying would only make the situation worse by giving the OSD +more work to do. + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/super.c | 2 - + include/linux/ceph/libceph.h | 2 - + net/ceph/ceph_common.c | 3 -- + net/ceph/osd_client.c | 47 +++---------------------------------------- + 4 files changed, 5 insertions(+), 49 deletions(-) + +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -403,8 +403,6 @@ static int ceph_show_options(struct seq_ + seq_printf(m, ",mount_timeout=%d", opt->mount_timeout); + if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) + seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl); +- if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT) +- seq_printf(m, ",osdtimeout=%d", opt->osd_timeout); + if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) + seq_printf(m, ",osdkeepalivetimeout=%d", + opt->osd_keepalive_timeout); +--- a/include/linux/ceph/libceph.h ++++ b/include/linux/ceph/libceph.h +@@ -43,7 +43,6 @@ struct ceph_options { + struct ceph_entity_addr my_addr; + int mount_timeout; + int osd_idle_ttl; +- int osd_timeout; + int osd_keepalive_timeout; + + /* +@@ -63,7 +62,6 @@ struct ceph_options { + * defaults + */ + #define CEPH_MOUNT_TIMEOUT_DEFAULT 60 +-#define CEPH_OSD_TIMEOUT_DEFAULT 60 /* seconds */ + #define CEPH_OSD_KEEPALIVE_DEFAULT 5 + #define CEPH_OSD_IDLE_TTL_DEFAULT 60 + +--- a/net/ceph/ceph_common.c ++++ b/net/ceph/ceph_common.c +@@ -305,7 +305,6 @@ ceph_parse_options(char *options, const + + /* start with defaults */ + opt->flags = CEPH_OPT_DEFAULT; +- opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; + opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; + opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ + opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ +@@ -391,7 +390,7 @@ ceph_parse_options(char *options, const + + /* misc */ + case Opt_osdtimeout: +- opt->osd_timeout = intval; ++ pr_warning("ignoring deprecated osdtimeout option\n"); + break; + case Opt_osdkeepalivetimeout: + opt->osd_keepalive_timeout = intval; +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -608,14 +608,6 @@ static void __kick_osd_requests(struct c + } + } + +-static void kick_osd_requests(struct ceph_osd_client *osdc, +- struct ceph_osd *kickosd) +-{ +- mutex_lock(&osdc->request_mutex); +- __kick_osd_requests(osdc, kickosd); +- mutex_unlock(&osdc->request_mutex); +-} +- + /* + * If the osd connection drops, we need to resubmit all requests. + */ +@@ -629,7 +621,9 @@ static void osd_reset(struct ceph_connec + dout("osd_reset osd%d\n", osd->o_osd); + osdc = osd->o_osdc; + down_read(&osdc->map_sem); +- kick_osd_requests(osdc, osd); ++ mutex_lock(&osdc->request_mutex); ++ __kick_osd_requests(osdc, osd); ++ mutex_unlock(&osdc->request_mutex); + send_queued(osdc); + up_read(&osdc->map_sem); + } +@@ -1093,12 +1087,10 @@ static void handle_timeout(struct work_s + { + struct ceph_osd_client *osdc = + container_of(work, struct ceph_osd_client, timeout_work.work); +- struct ceph_osd_request *req, *last_req = NULL; ++ struct ceph_osd_request *req; + struct ceph_osd *osd; +- unsigned long timeout = osdc->client->options->osd_timeout * HZ; + unsigned long keepalive = + osdc->client->options->osd_keepalive_timeout * HZ; +- unsigned long last_stamp = 0; + struct list_head slow_osds; + dout("timeout\n"); + down_read(&osdc->map_sem); +@@ -1108,37 +1100,6 @@ static void handle_timeout(struct work_s + mutex_lock(&osdc->request_mutex); + + /* +- * reset osds that appear to be _really_ unresponsive. this +- * is a failsafe measure.. we really shouldn't be getting to +- * this point if the system is working properly. the monitors +- * should mark the osd as failed and we should find out about +- * it from an updated osd map. +- */ +- while (timeout && !list_empty(&osdc->req_lru)) { +- req = list_entry(osdc->req_lru.next, struct ceph_osd_request, +- r_req_lru_item); +- +- /* hasn't been long enough since we sent it? */ +- if (time_before(jiffies, req->r_stamp + timeout)) +- break; +- +- /* hasn't been long enough since it was acked? */ +- if (req->r_request->ack_stamp == 0 || +- time_before(jiffies, req->r_request->ack_stamp + timeout)) +- break; +- +- BUG_ON(req == last_req && req->r_stamp == last_stamp); +- last_req = req; +- last_stamp = req->r_stamp; +- +- osd = req->r_osd; +- BUG_ON(!osd); +- pr_warning(" tid %llu timed out on osd%d, will reset osd\n", +- req->r_tid, osd->o_osd); +- __kick_osd_requests(osdc, osd); +- } +- +- /* + * ping osds that are a bit slow. this ensures that if there + * is a break in the TCP connection we will notice, and reopen + * a connection with that osd (from the fault callback). +From a6bbcd6741d53b326a2a3a7edef6e15334de6ea3 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 29 Nov 2012 08:37:03 -0600 +Subject: ceph: don't reference req after put + + +From: Alex Elder + +(cherry picked from commit 7d5f24812bd182a2471cb69c1c2baf0648332e1f) + +In __unregister_request(), there is a call to list_del_init() +referencing a request that was the subject of a call to +ceph_osdc_put_request() on the previous line. This is not +safe, because the request structure could have been freed +by the time we reach the list_del_init(). + +Fix this by reversing the order of these lines. + +Signed-off-by: Alex Elder +Reviewed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -873,9 +873,9 @@ static void __unregister_request(struct + req->r_osd = NULL; + } + ++ list_del_init(&req->r_req_lru_item); + ceph_osdc_put_request(req); + +- list_del_init(&req->r_req_lru_item); + if (osdc->num_requests == 0) { + dout(" no requests, canceling timeout\n"); + __cancel_osd_timeout(osdc); +From 8824d0eb9dee3bad29e9dba796d5d7953cab6719 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 10 Oct 2012 21:19:13 -0700 +Subject: rbd: fix bug in rbd_dev_id_put() + + +From: Alex Elder + +(cherry picked from commit b213e0b1a62637b2a9395a34349b13d73ca2b90a) + +In rbd_dev_id_put(), there's a loop that's intended to determine +the maximum device id in use. But it isn't doing that at all, +the effect of how it's written is to simply use the just-put id +number, which ignores whole purpose of this function. + +Fix the bug. + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -2621,8 +2621,8 @@ static void rbd_dev_id_put(struct rbd_de + struct rbd_device *rbd_dev; + + rbd_dev = list_entry(tmp, struct rbd_device, node); +- if (rbd_id > max_id) +- max_id = rbd_id; ++ if (rbd_dev->dev_id > max_id) ++ max_id = rbd_dev->dev_id; + } + spin_unlock(&rbd_dev_list_lock); + +From cc8b5fcd343b3c99468fc9f0b4c3e03a7eafa7fc Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 10 Oct 2012 21:19:13 -0700 +Subject: rbd: zero return code in rbd_dev_image_id() + + +From: Alex Elder + +(cherry picked from commit a0ea3a40fd20b8c66381f747c454f89d6d1f50d4) + +When rbd_dev_probe() calls rbd_dev_image_id() it expects to get +a 0 return code if successful, but it is getting a positive value. + +The reason is that rbd_dev_image_id() returns the value it gets from +rbd_req_sync_exec(), which returns the number of bytes read in as a +result of the request. (This ultimately comes from +ceph_copy_from_page_vector() in rbd_req_sync_op()). + +Force the return value to 0 when successful in rbd_dev_image_id(). +Do the same in rbd_dev_v2_object_prefix(). + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Reviewed-by: Dan Mick +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -2189,6 +2189,7 @@ static int rbd_dev_v2_object_prefix(stru + dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); + if (ret < 0) + goto out; ++ ret = 0; /* rbd_req_sync_exec() can return positive */ + + p = reply_buf; + rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, +@@ -2841,6 +2842,7 @@ static int rbd_dev_image_id(struct rbd_d + dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); + if (ret < 0) + goto out; ++ ret = 0; /* rbd_req_sync_exec() can return positive */ + + p = response; + rbd_dev->image_id = ceph_extract_encoded_string(&p, +From 9aca7b487cf1c996a13ff5abf0ea4ac560ea1dd4 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 22 Oct 2012 11:31:26 -0500 +Subject: rbd: fix read-only option name + + +From: Alex Elder + +(cherry picked from commit be466c1cc36621590ef17b05a6d342dfd33f7280) + +The name of the "read-only" mapping option was inadvertently changed +in this commit: + + f84344f3 rbd: separate mapping info in rbd_dev + +Revert that hunk to return it to what it should be. + +Signed-off-by: Alex Elder +Reviewed-by: Dan Mick +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -388,7 +388,7 @@ enum { + static match_table_t rbd_opts_tokens = { + /* int args above */ + /* string args above */ +- {Opt_read_only, "mapping.read_only"}, ++ {Opt_read_only, "read_only"}, + {Opt_read_only, "ro"}, /* Alternate spelling */ + {Opt_read_write, "read_write"}, + {Opt_read_write, "rw"}, /* Alternate spelling */ +From 1306be442fda1b7a92b879ab18a535f56da5ab0a Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Tue, 3 Jul 2012 16:01:19 -0500 +Subject: rbd: increase maximum snapshot name length + + +From: Alex Elder + +(cherry picked from commit d4b125e9eb43babd14538ba61718e3db71a98d29) + +Change RBD_MAX_SNAP_NAME_LEN to be based on NAME_MAX. That is a +practical limit for the length of a snapshot name (based on the +presence of a directory using the name under /sys/bus/rbd to +represent the snapshot). + +The /sys entry is created by prefixing it with "snap_"; define that +prefix symbolically, and take its length into account in defining +the snapshot name length limit. + +Enforce the limit in rbd_add_parse_args(). Also delete a dout() +call in that function that was not meant to be committed. + +Signed-off-by: Alex Elder +Reviewed-by: Dan Mick +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -61,7 +61,10 @@ + + #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ + +-#define RBD_MAX_SNAP_NAME_LEN 32 ++#define RBD_SNAP_DEV_NAME_PREFIX "snap_" ++#define RBD_MAX_SNAP_NAME_LEN \ ++ (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) ++ + #define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */ + #define RBD_MAX_OPT_LEN 1024 + +@@ -2073,7 +2076,7 @@ static int rbd_register_snap_dev(struct + dev->type = &rbd_snap_device_type; + dev->parent = parent; + dev->release = rbd_snap_dev_release; +- dev_set_name(dev, "snap_%s", snap->name); ++ dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name); + dout("%s: registering device for snapshot %s\n", __func__, snap->name); + + ret = device_register(dev); +@@ -2766,8 +2769,13 @@ static char *rbd_add_parse_args(struct r + if (!rbd_dev->image_name) + goto out_err; + +- /* Snapshot name is optional */ ++ /* Snapshot name is optional; default is to use "head" */ ++ + len = next_token(&buf); ++ if (len > RBD_MAX_SNAP_NAME_LEN) { ++ err_ptr = ERR_PTR(-ENAMETOOLONG); ++ goto out_err; ++ } + if (!len) { + buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */ + len = sizeof (RBD_SNAP_HEAD_NAME) - 1; +@@ -2778,8 +2786,6 @@ static char *rbd_add_parse_args(struct r + memcpy(snap_name, buf, len); + *(snap_name + len) = '\0'; + +-dout(" SNAP_NAME is <%s>, len is %zd\n", snap_name, len); +- + return snap_name; + + out_err: +From 21bc037520c252304c04d3bb8131fb3d4ba5b2c5 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 25 Oct 2012 23:34:40 -0500 +Subject: rbd: remove snapshots on error in rbd_add() + + +From: Alex Elder + +(cherry picked from commit 41f38c2b2f8b66b176a0e548ef06294343a7bfa2) + +If rbd_dev_snaps_update() has ever been called for an rbd device +structure there could be snapshot structures on its snaps list. +In rbd_add(), this function is called but a subsequent error +path neglected to clean up any of these snapshots. + +Add a call to rbd_remove_all_snaps() in the appropriate spot to +remedy this. Change a couple of error labels to be a little +clearer while there. + +Drop the leading underscores from the function name; there's nothing +special about that function that they might signify. As suggested +in review, the leading underscores in __rbd_remove_snap_dev() have +been removed as well. + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -221,7 +221,7 @@ static int rbd_dev_snaps_update(struct r + static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); + + static void rbd_dev_release(struct device *dev); +-static void __rbd_remove_snap_dev(struct rbd_snap *snap); ++static void rbd_remove_snap_dev(struct rbd_snap *snap); + + static ssize_t rbd_add(struct bus_type *bus, const char *buf, + size_t count); +@@ -1710,13 +1710,13 @@ static int rbd_read_header(struct rbd_de + return ret; + } + +-static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) ++static void rbd_remove_all_snaps(struct rbd_device *rbd_dev) + { + struct rbd_snap *snap; + struct rbd_snap *next; + + list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) +- __rbd_remove_snap_dev(snap); ++ rbd_remove_snap_dev(snap); + } + + /* +@@ -2060,7 +2060,7 @@ static bool rbd_snap_registered(struct r + return ret; + } + +-static void __rbd_remove_snap_dev(struct rbd_snap *snap) ++static void rbd_remove_snap_dev(struct rbd_snap *snap) + { + list_del(&snap->node); + if (device_is_registered(&snap->dev)) +@@ -2442,7 +2442,7 @@ static int rbd_dev_snaps_update(struct r + + if (rbd_dev->mapping.snap_id == snap->id) + rbd_dev->mapping.snap_exists = false; +- __rbd_remove_snap_dev(snap); ++ rbd_remove_snap_dev(snap); + dout("%ssnap id %llu has been removed\n", + rbd_dev->mapping.snap_id == snap->id ? + "mapped " : "", +@@ -3053,11 +3053,11 @@ static ssize_t rbd_add(struct bus_type * + /* no need to lock here, as rbd_dev is not registered yet */ + rc = rbd_dev_snaps_update(rbd_dev); + if (rc) +- goto err_out_header; ++ goto err_out_probe; + + rc = rbd_dev_set_mapping(rbd_dev, snap_name); + if (rc) +- goto err_out_header; ++ goto err_out_snaps; + + /* generate unique id: find highest unique id, add one */ + rbd_dev_id_get(rbd_dev); +@@ -3121,7 +3121,9 @@ err_out_blkdev: + unregister_blkdev(rbd_dev->major, rbd_dev->name); + err_out_id: + rbd_dev_id_put(rbd_dev); +-err_out_header: ++err_out_snaps: ++ rbd_remove_all_snaps(rbd_dev); ++err_out_probe: + rbd_header_free(&rbd_dev->header); + err_out_client: + kfree(rbd_dev->header_name); +@@ -3219,7 +3221,7 @@ static ssize_t rbd_remove(struct bus_typ + goto done; + } + +- __rbd_remove_all_snaps(rbd_dev); ++ rbd_remove_all_snaps(rbd_dev); + rbd_bus_del_dev(rbd_dev); + + done: +From 730406993ec6d044a81115fc19091ba6abfcbb15 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 16 Nov 2012 09:29:16 -0600 +Subject: rbd: do not allow remove of mounted-on image + + +From: Alex Elder + +(cherry picked from commit 42382b709bd1d143b9f0fa93e0a3a1f2f4210707) + +There is no check in rbd_remove() to see if anybody holds open the +image being removed. That's not cool. + +Add a simple open count that goes up and down with opens and closes +(releases) of the device, and don't allow an rbd image to be removed +if the count is non-zero. + +Protect the updates of the open count value with ctl_mutex to ensure +the underlying rbd device doesn't get removed while concurrently +being opened. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -207,6 +207,7 @@ struct rbd_device { + + /* sysfs related */ + struct device dev; ++ unsigned long open_count; + }; + + static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ +@@ -280,8 +281,11 @@ static int rbd_open(struct block_device + if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only) + return -EROFS; + ++ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->mapping.read_only); ++ rbd_dev->open_count++; ++ mutex_unlock(&ctl_mutex); + + return 0; + } +@@ -290,7 +294,11 @@ static int rbd_release(struct gendisk *d + { + struct rbd_device *rbd_dev = disk->private_data; + ++ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); ++ rbd_assert(rbd_dev->open_count > 0); ++ rbd_dev->open_count--; + rbd_put_dev(rbd_dev); ++ mutex_unlock(&ctl_mutex); + + return 0; + } +@@ -3221,6 +3229,11 @@ static ssize_t rbd_remove(struct bus_typ + goto done; + } + ++ if (rbd_dev->open_count) { ++ ret = -EBUSY; ++ goto done; ++ } ++ + rbd_remove_all_snaps(rbd_dev); + rbd_bus_del_dev(rbd_dev); + +From 965f03ad3d796d03ec16f9809cb0096a64f6523d Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 9 Nov 2012 15:05:54 -0600 +Subject: rbd: get rid of RBD_MAX_SEG_NAME_LEN + + +From: Alex Elder + +(cherry picked from commit 2fd82b9e92c2a718ae81fc987b4468ceeee6979b) + +RBD_MAX_SEG_NAME_LEN represents the maximum length of an rbd object +name (i.e., one of the objects providing storage backing an rbd +image). + +Another symbol, MAX_OBJ_NAME_SIZE, is used in the osd client code to +define the maximum length of any object name in an osd request. + +Right now they disagree, with RBD_MAX_SEG_NAME_LEN being too big. + +There's no real benefit at this point to defining the rbd object +name length limit separate from any other object name, so just +get rid of RBD_MAX_SEG_NAME_LEN and use MAX_OBJ_NAME_SIZE in its +place. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 6 +++--- + drivers/block/rbd_types.h | 2 -- + 2 files changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -706,13 +706,13 @@ static char *rbd_segment_name(struct rbd + u64 segment; + int ret; + +- name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); ++ name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO); + if (!name) + return NULL; + segment = offset >> rbd_dev->header.obj_order; +- ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx", ++ ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx", + rbd_dev->header.object_prefix, segment); +- if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) { ++ if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { + pr_err("error formatting segment name for #%llu (%d)\n", + segment, ret); + kfree(name); +--- a/drivers/block/rbd_types.h ++++ b/drivers/block/rbd_types.h +@@ -46,8 +46,6 @@ + #define RBD_MIN_OBJ_ORDER 16 + #define RBD_MAX_OBJ_ORDER 30 + +-#define RBD_MAX_SEG_NAME_LEN 128 +- + #define RBD_COMP_NONE 0 + #define RBD_CRYPT_NONE 0 + +From 942784e7a6e2ef8f861043f65b054eb3ef10b2fd Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 09:37:23 -0600 +Subject: rbd: remove linger unconditionally + + +From: Alex Elder + +(cherry picked from commit 61c74035626beb25a39b0273ccf7d75510bc36a1) + +In __unregister_linger_request(), the request is being removed +from the osd client's req_linger list only when the request +has a non-null osd pointer. It should be done whether or not +the request currently has an osd. + +This is most likely a non-issue because I believe the request +will always have an osd when this function is called. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -907,8 +907,8 @@ static void __unregister_linger_request( + struct ceph_osd_request *req) + { + dout("__unregister_linger_request %p\n", req); ++ list_del_init(&req->r_linger_item); + if (req->r_osd) { +- list_del_init(&req->r_linger_item); + list_del_init(&req->r_linger_osd); + + if (list_empty(&req->r_osd->o_requests) && +From 76c834d784c36bda3a8d56f5cdf3e1282b0979f9 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:04 +0800 +Subject: ceph: Don't update i_max_size when handling non-auth cap + + +From: "Yan, Zheng" + +(cherry picked from commit 5e62ad30157d0da04cf40c6d1a2f4bc840948b9c) + +The cap from non-auth mds doesn't have a meaningful max_size value. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2388,7 +2388,7 @@ static void handle_cap_grant(struct inod + &atime); + + /* max size increase? */ +- if (max_size != ci->i_max_size) { ++ if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { + dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); + ci->i_max_size = max_size; + if (max_size >= ci->i_wanted_max_size) { +From 0fd2af5e838e87cf449c657b6e19535b64da6c4c Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:06 +0800 +Subject: ceph: Fix infinite loop in __wake_requests + + +From: "Yan, Zheng" + +(cherry picked from commit ed75ec2cd19b47efcd292b6e23f58e56f4c5bc34) + +__wake_requests() will enter infinite loop if we use it to wake +requests in the session->s_waiting list. __wake_requests() deletes +requests from the list and __do_request() adds requests back to +the list. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/mds_client.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1876,9 +1876,14 @@ finish: + static void __wake_requests(struct ceph_mds_client *mdsc, + struct list_head *head) + { +- struct ceph_mds_request *req, *nreq; ++ struct ceph_mds_request *req; ++ LIST_HEAD(tmp_list); + +- list_for_each_entry_safe(req, nreq, head, r_wait) { ++ list_splice_init(head, &tmp_list); ++ ++ while (!list_empty(&tmp_list)) { ++ req = list_entry(tmp_list.next, ++ struct ceph_mds_request, r_wait); + list_del_init(&req->r_wait); + __do_request(mdsc, req); + } +From f409f158fb190ab9915fd94dce367e462a0c02f6 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:07 +0800 +Subject: ceph: Don't add dirty inode to dirty list if caps is in migration + + +From: "Yan, Zheng" + +(cherry picked from commit 0685235ffd9dbdb9ccbda587f8a3c83ad1d5a921) + +Add dirty inode to cap_dirty_migrating list instead, this can avoid +ceph_flush_dirty_caps() entering infinite loop. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_i + if (!ci->i_head_snapc) + ci->i_head_snapc = ceph_get_snap_context( + ci->i_snap_realm->cached_context); +- dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode, +- ci->i_head_snapc); ++ dout(" inode %p now dirty snapc %p auth cap %p\n", ++ &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); + BUG_ON(!list_empty(&ci->i_dirty_item)); + spin_lock(&mdsc->cap_dirty_lock); +- list_add(&ci->i_dirty_item, &mdsc->cap_dirty); ++ if (ci->i_auth_cap) ++ list_add(&ci->i_dirty_item, &mdsc->cap_dirty); ++ else ++ list_add(&ci->i_dirty_item, ++ &mdsc->cap_dirty_migrating); + spin_unlock(&mdsc->cap_dirty_lock); + if (ci->i_flushing_caps == 0) { + ihold(inode); +From 0e6789acaba2e40768a778a1e553c92723a19a30 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:08 +0800 +Subject: ceph: Fix __ceph_do_pending_vmtruncate + + +From: "Yan, Zheng" + +(cherry picked from commit a85f50b6ef93fbbb2ae932ce9b2376509d172796) + +we should set i_truncate_pending to 0 after page cache is truncated +to i_truncate_size + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/inode.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct + { + struct ceph_inode_info *ci = ceph_inode(inode); + u64 to; +- int wrbuffer_refs, wake = 0; ++ int wrbuffer_refs, finish = 0; + + retry: + spin_lock(&ci->i_ceph_lock); +@@ -1498,15 +1498,18 @@ retry: + truncate_inode_pages(inode->i_mapping, to); + + spin_lock(&ci->i_ceph_lock); +- ci->i_truncate_pending--; +- if (ci->i_truncate_pending == 0) +- wake = 1; ++ if (to == ci->i_truncate_size) { ++ ci->i_truncate_pending = 0; ++ finish = 1; ++ } + spin_unlock(&ci->i_ceph_lock); ++ if (!finish) ++ goto retry; + + if (wrbuffer_refs == 0) + ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); +- if (wake) +- wake_up_all(&ci->i_cap_wq); ++ ++ wake_up_all(&ci->i_cap_wq); + } + + +From 0747d15ddb5eac0e83376e2722e3654ae01d252f Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:09 +0800 +Subject: ceph: call handle_cap_grant() for cap import message + + +From: "Yan, Zheng" + +(cherry picked from commit 0e5e1774a92e6fe9c511585de8f078b4c4c68dbb) + +If client sends cap message that requests new max size during +exporting caps, the exporting MDS will drop the message quietly. +So the client may wait for the reply that updates the max size +forever. call handle_cap_grant() for cap import message can +avoid this issue. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2749,6 +2749,7 @@ static void handle_cap_import(struct cep + + /* make sure we re-request max_size, if necessary */ + spin_lock(&ci->i_ceph_lock); ++ ci->i_wanted_max_size = 0; /* reset */ + ci->i_requested_max_size = 0; + spin_unlock(&ci->i_ceph_lock); + } +@@ -2844,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_se + case CEPH_CAP_OP_IMPORT: + handle_cap_import(mdsc, inode, h, session, + snaptrace, snaptrace_len); +- ceph_check_caps(ceph_inode(inode), 0, session); +- goto done_unlocked; + } + + /* the rest require a cap */ +@@ -2862,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_se + switch (op) { + case CEPH_CAP_OP_REVOKE: + case CEPH_CAP_OP_GRANT: ++ case CEPH_CAP_OP_IMPORT: + handle_cap_grant(inode, h, session, cap, msg->middle); + goto done_unlocked; + +From 9fa5ba96f32fbea354457fc7ece06b2ee81b1b71 Mon Sep 17 00:00:00 2001 +From: David Zafman +Date: Mon, 3 Dec 2012 19:14:05 -0800 +Subject: libceph: Unlock unprocessed pages in start_read() error path + + +From: David Zafman + +(cherry picked from commit 8884d53dd63b1d9315b343564fcbe1ede004a99e) + +Function start_read() can get an error before processing all pages. +It must not only release the remaining pages, but unlock them too. + +This fixes http://tracker.newdream.net/issues/3370 + +Signed-off-by: David Zafman +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/addr.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_ + kfree(req->r_pages); + } + ++static void ceph_unlock_page_vector(struct page **pages, int num_pages) ++{ ++ int i; ++ ++ for (i = 0; i < num_pages; i++) ++ unlock_page(pages[i]); ++} ++ + /* + * start an async read(ahead) operation. return nr_pages we submitted + * a read for on success, or negative error code. +@@ -347,6 +355,7 @@ static int start_read(struct inode *inod + return nr_pages; + + out_pages: ++ ceph_unlock_page_vector(pages, nr_pages); + ceph_release_page_vector(pages, nr_pages); + out: + ceph_osdc_put_request(req); +From 45e2b5f640b3766da3eda48f6c35f088155c06f3 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Fri, 23 Nov 2012 18:16:34 +0100 +Subject: drm/i915: force restore on lid open + +From: Daniel Vetter + +commit 45e2b5f640b3766da3eda48f6c35f088155c06f3 upstream. + +There seem to be indeed some awkwards machines around, mostly those +without OpRegion support, where the firmware changes the display hw +state behind our backs when closing the lid. + +This force-restore logic has been originally introduced in + +commit c1c7af60892070e4b82ad63bbfb95ae745056de0 +Author: Jesse Barnes +Date: Thu Sep 10 15:28:03 2009 -0700 + + drm/i915: force mode set at lid open time + +but after the modeset-rework we've disabled it in the vain hope that +it's no longer required: + +commit 3b7a89fce3e3dc96b549d6d829387b4439044d0d +Author: Daniel Vetter +Date: Mon Sep 17 22:27:21 2012 +0200 + + drm/i915: fix OOPS in lid_notify + +Alas, no. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54677 +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 +Tested-by: Krzysztof Mazur +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_drv.c | 2 +- + drivers/gpu/drm/i915/i915_drv.h | 3 ++- + drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++--- + drivers/gpu/drm/i915/intel_lvds.c | 2 +- + 4 files changed, 16 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -552,7 +552,7 @@ static int i915_drm_thaw(struct drm_devi + mutex_unlock(&dev->struct_mutex); + + intel_modeset_init_hw(dev); +- intel_modeset_setup_hw_state(dev); ++ intel_modeset_setup_hw_state(dev, false); + drm_mode_config_reset(dev); + drm_irq_install(dev); + } +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1595,7 +1595,8 @@ extern void intel_modeset_init(struct dr + extern void intel_modeset_gem_init(struct drm_device *dev); + extern void intel_modeset_cleanup(struct drm_device *dev); + extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); +-extern void intel_modeset_setup_hw_state(struct drm_device *dev); ++extern void intel_modeset_setup_hw_state(struct drm_device *dev, ++ bool force_restore); + extern bool intel_fbc_enabled(struct drm_device *dev); + extern void intel_disable_fbc(struct drm_device *dev); + extern bool ironlake_set_drps(struct drm_device *dev, u8 val); +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -8250,7 +8250,8 @@ static void intel_sanitize_encoder(struc + + /* Scan out the current hw modeset state, sanitizes it and maps it into the drm + * and i915 state tracking structures. */ +-void intel_modeset_setup_hw_state(struct drm_device *dev) ++void intel_modeset_setup_hw_state(struct drm_device *dev, ++ bool force_restore) + { + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe; +@@ -8321,7 +8322,15 @@ void intel_modeset_setup_hw_state(struct + intel_sanitize_crtc(crtc); + } + +- intel_modeset_update_staged_output_state(dev); ++ if (force_restore) { ++ for_each_pipe(pipe) { ++ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); ++ intel_set_mode(&crtc->base, &crtc->base.mode, ++ crtc->base.x, crtc->base.y, crtc->base.fb); ++ } ++ } else { ++ intel_modeset_update_staged_output_state(dev); ++ } + + intel_modeset_check_state(dev); + } +@@ -8332,7 +8341,7 @@ void intel_modeset_gem_init(struct drm_d + + intel_setup_overlay(dev); + +- intel_modeset_setup_hw_state(dev); ++ intel_modeset_setup_hw_state(dev, false); + } + + void intel_modeset_cleanup(struct drm_device *dev) +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -526,7 +526,7 @@ static int intel_lid_notify(struct notif + dev_priv->modeset_on_lid = 0; + + mutex_lock(&dev->mode_config.mutex); +- intel_modeset_check_state(dev); ++ intel_modeset_setup_hw_state(dev, true); + mutex_unlock(&dev->mode_config.mutex); + + return NOTIFY_OK; +From 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 Mon Sep 17 00:00:00 2001 +From: Krzysztof Mazur +Date: Wed, 19 Dec 2012 11:03:41 +0100 +Subject: i915: ensure that VGA plane is disabled + +From: Krzysztof Mazur + +commit 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 upstream. + +Some broken systems (like HP nc6120) in some cases, usually after LID +close/open, enable VGA plane, making display unusable (black screen on LVDS, +some strange mode on VGA output). We used to disable VGA plane only once at +startup. Now we also check, if VGA plane is still disabled while changing +mode, and fix that if something changed it. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 +Signed-off-by: Krzysztof Mazur +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -8248,6 +8248,23 @@ static void intel_sanitize_encoder(struc + * the crtc fixup. */ + } + ++static void i915_redisable_vga(struct drm_device *dev) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ u32 vga_reg; ++ ++ if (HAS_PCH_SPLIT(dev)) ++ vga_reg = CPU_VGACNTRL; ++ else ++ vga_reg = VGACNTRL; ++ ++ if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { ++ DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); ++ I915_WRITE(vga_reg, VGA_DISP_DISABLE); ++ POSTING_READ(vga_reg); ++ } ++} ++ + /* Scan out the current hw modeset state, sanitizes it and maps it into the drm + * and i915 state tracking structures. */ + void intel_modeset_setup_hw_state(struct drm_device *dev, +@@ -8328,6 +8345,8 @@ void intel_modeset_setup_hw_state(struct + intel_set_mode(&crtc->base, &crtc->base.mode, + crtc->base.x, crtc->base.y, crtc->base.fb); + } ++ ++ i915_redisable_vga(dev); + } else { + intel_modeset_update_staged_output_state(dev); + } +From 3490ea5de6ac4af309c3df8a26a5cca61306334c Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 7 Jan 2013 10:11:40 +0000 +Subject: drm/i915: Treat crtc->mode.clock == 0 as disabled + +From: Chris Wilson + +commit 3490ea5de6ac4af309c3df8a26a5cca61306334c upstream. + +Prevent a divide-by-zero by consistently treating an 'active' CRTC +without a mode set as actually disabled. + +This looks to have been first introduced with + +commit 24929352481f085c5f85d4d4cbc919ddf106d381 +Author: Daniel Vetter +Date: Mon Jul 2 20:28:59 2012 +0200 + + drm/i915: read out the modeset hw state at load and resume time + +but then combined with + +commit b0a2658acb5bf9ca86b4aab011b7106de3af0add +Author: Daniel Vetter +Date: Tue Dec 18 09:37:54 2012 +0100 + + drm/i915: don't disable disconnected outputs + +it finally started oopsing. + +Signed-off-by: Chris Wilson +Reported-and-tested-by: Alexey Zaytsev +Tested-by: Sedat Dilek +Cc: Daniel Vetter +Cc: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_pm.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -44,6 +44,14 @@ + * i915.i915_enable_fbc parameter + */ + ++static bool intel_crtc_active(struct drm_crtc *crtc) ++{ ++ /* Be paranoid as we can arrive here with only partial ++ * state retrieved from the hardware during setup. ++ */ ++ return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; ++} ++ + static void i8xx_disable_fbc(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device + * - going to an unsupported config (interlace, pixel multiply, etc.) + */ + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { +- if (tmp_crtc->enabled && +- !to_intel_crtc(tmp_crtc)->primary_disabled && +- tmp_crtc->fb) { ++ if (intel_crtc_active(tmp_crtc) && ++ !to_intel_crtc(tmp_crtc)->primary_disabled) { + if (crtc) { + DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); + dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; +@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_c + struct drm_crtc *crtc, *enabled = NULL; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- if (crtc->enabled && crtc->fb) { ++ if (intel_crtc_active(crtc)) { + if (enabled) + return NULL; + enabled = crtc; +@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_d + int entries, tlb_miss; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) { ++ if (!intel_crtc_active(crtc)) { + *cursor_wm = cursor->guard_size; + *plane_wm = display->guard_size; + return false; +@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(st + int entries; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) ++ if (!intel_crtc_active(crtc)) + return false; + + clock = crtc->mode.clock; /* VESA DOT Clock */ +@@ -1478,7 +1485,7 @@ static void i9xx_update_wm(struct drm_de + + fifo_size = dev_priv->display.get_fifo_size(dev, 1); + crtc = intel_get_crtc_for_plane(dev, 1); +- if (crtc->enabled && crtc->fb) { ++ if (intel_crtc_active(crtc)) { + planeb_wm = intel_calculate_wm(crtc->mode.clock, + wm_info, fifo_size, + crtc->fb->bits_per_pixel / 8, +@@ -1923,7 +1930,7 @@ sandybridge_compute_sprite_wm(struct drm + int entries, tlb_miss; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) { ++ if (!intel_crtc_active(crtc)) { + *sprite_wm = display->guard_size; + return false; + } diff --git a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch deleted file mode 100644 index f6e997c41..000000000 --- a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +++ /dev/null @@ -1,46 +0,0 @@ -From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 -From: Zhang Rui -Date: Tue, 4 Dec 2012 23:23:16 +0100 -Subject: [PATCH] ACPI : do not use Lid and Sleep button for S5 wakeup - -When system enters power off, the _PSW of Lid device is enabled. -But this may cause the system to reboot instead of power off. - -A proper way to fix this is to always disable lid wakeup capability for S5. - -References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 -Signed-off-by: Zhang Rui -Signed-off-by: Rafael J. Wysocki ---- - drivers/acpi/scan.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c -index d0b38ab..bd523bf 100644 ---- a/drivers/acpi/scan.c -+++ b/drivers/acpi/scan.c -@@ -917,8 +917,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, - static void acpi_bus_set_run_wake_flags(struct acpi_device *device) - { - struct acpi_device_id button_device_ids[] = { -- {"PNP0C0D", 0}, - {"PNP0C0C", 0}, -+ {"PNP0C0D", 0}, - {"PNP0C0E", 0}, - {"", 0}, - }; -@@ -930,6 +930,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) - /* Power button, Lid switch always enable wakeup */ - if (!acpi_match_device_ids(device, button_device_ids)) { - device->wakeup.flags.run_wake = 1; -+ if (!acpi_match_device_ids(device, &button_device_ids[1])) { -+ /* Do not use Lid/sleep button for S5 wakeup */ -+ if (device->wakeup.sleep_state == ACPI_STATE_S5) -+ device->wakeup.sleep_state = ACPI_STATE_S4; -+ } - device_set_wakeup_capable(&device->dev, true); - return; - } --- -1.8.0.1 - diff --git a/aoe-remove-vestigial-request-queue-allocation.patch b/aoe-remove-vestigial-request-queue-allocation.patch deleted file mode 100644 index fa4ad1ac8..000000000 --- a/aoe-remove-vestigial-request-queue-allocation.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 -From: Ed Cashin -Date: Mon, 17 Dec 2012 16:03:58 -0800 -Subject: [PATCH] aoe: remove vestigial request queue allocation - -Before the aoe driver was an I/O request handler, it was a -make_request-style block driver. Even so, there was a problem where -sysfs expected a request queue to exist, so one was provided in commit -7135a71b19be ("aoe: allocate unused request_queue for sysfs"). - -During the transition to the request-handler style, a patch was merged -that was based on a driver without the noop queue, and the noop queue -remained in place after the patch was merged, even though a new -functional queue was introduced by the patch, allocated through -blk_init_queue. - -The user impact is a memory leak proportional to the number of AoE -targets discovered. This patch removes the memory leak and cleans up -vestiges of the old do-nothing queue from the aoeblk_gdalloc function. - -Signed-off-by: Ed Cashin -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - drivers/block/aoe/aoeblk.c | 17 ++++------------- - 1 file changed, 4 insertions(+), 13 deletions(-) - -diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c -index 7ba0fcf..57ac72c 100644 ---- a/drivers/block/aoe/aoeblk.c -+++ b/drivers/block/aoe/aoeblk.c -@@ -278,18 +278,12 @@ aoeblk_gdalloc(void *vp) - if (q == NULL) { - pr_err("aoe: cannot allocate block queue for %ld.%d\n", - d->aoemajor, d->aoeminor); -- mempool_destroy(mp); -- goto err_disk; -+ goto err_mempool; - } - -- d->blkq = blk_alloc_queue(GFP_KERNEL); -- if (!d->blkq) -- goto err_mempool; -- d->blkq->backing_dev_info.name = "aoe"; -- if (bdi_init(&d->blkq->backing_dev_info)) -- goto err_blkq; - spin_lock_irqsave(&d->lock, flags); -- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); -+ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); -+ q->backing_dev_info.name = "aoe"; - q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; - d->bufpool = mp; - d->blkq = gd->queue = q; -@@ -314,11 +308,8 @@ aoeblk_gdalloc(void *vp) - aoedisk_add_sysfs(d); - return; - --err_blkq: -- blk_cleanup_queue(d->blkq); -- d->blkq = NULL; - err_mempool: -- mempool_destroy(d->bufpool); -+ mempool_destroy(mp); - err_disk: - put_disk(gd); - err: --- -1.8.0.1 - diff --git a/config-x86-generic b/config-x86-generic index b3d19ea45..2bcd498eb 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -45,7 +45,7 @@ CONFIG_FB_EFI=y CONFIG_INTEL_IOMMU=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_INTEL_IOMMU_FLOPPY_WA=y -CONFIG_INTEL_IOMMU_DEFAULT_ON=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y diff --git a/kernel.spec b/kernel.spec index 71033f5e7..e58f8cbeb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -780,17 +780,8 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 883414 -Patch21234: mac80211-fix-ibss-scanning.patch - -#rhbz 873107 -Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch - -#rhbz 853064 -Patch21239: aoe-remove-vestigial-request-queue-allocation.patch - -#rhbz 890547 -Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +#3.7.3 stable queue +Patch2150: 3.7.3-stable-queue.patch # END OF PATCH DEFINITIONS @@ -1511,18 +1502,8 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 883414 -ApplyPatch mac80211-fix-ibss-scanning.patch - -#rhbz 873107 -ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch - -#rhbz 853064 -ApplyPatch aoe-remove-vestigial-request-queue-allocation.patch - -#rhbz 890547 -ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch - +#3.7.3 stable qeueu +ApplyPatch 3.7.3-stable-queue.patch # END OF PATCH APPLICATIONS @@ -2396,6 +2377,10 @@ fi # ||----w | # || || %changelog +* Tue Jan 15 2013 Justin M. Forbes 3.7.2-203 +- Turn off Intel IOMMU by default +- Stable queue from 3.7.3 with many relevant fixes + * Tue Jan 15 2013 Josh Boyer - Enable CONFIG_DVB_USB_V2 (rhbz 895460) diff --git a/mac80211-fix-ibss-scanning.patch b/mac80211-fix-ibss-scanning.patch deleted file mode 100644 index c2bc698a0..000000000 --- a/mac80211-fix-ibss-scanning.patch +++ /dev/null @@ -1,132 +0,0 @@ -Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this -can trigger Microcode errors on iwlwifi and iwlegacy drivers. - -Also rename ieee80211_request_internal_scan() function since it is only -used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). - -This patch should address: -https://bugzilla.redhat.com/show_bug.cgi?id=883414 -https://bugzilla.kernel.org/show_bug.cgi?id=49411 - -Reported-by: Jesse Kahtava -Reported-by: Mikko Rapeli -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - net/mac80211/ibss.c | 9 ++++----- - net/mac80211/ieee80211_i.h | 6 +++--- - net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- - 3 files changed, 31 insertions(+), 18 deletions(-) - -diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c -index c21e33d..d9df6b8 100644 ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) - sdata_info(sdata, - "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, -+ NULL); - } - - static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) -@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) - IEEE80211_SCAN_INTERVAL)) { - sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, -- ifibss->fixed_channel ? ifibss->channel : NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, -+ ifibss->ssid_len, chan); - } else { - int interval = IEEE80211_SCAN_INTERVAL; - -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 156e583..bc48d4d 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, - - /* scan/BSS handling */ - void ieee80211_scan_work(struct work_struct *work); --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan); -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan); - int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req); - void ieee80211_scan_cancel(struct ieee80211_local *local); -diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c -index 43e60b5..fab706f 100644 ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - return res; - } - --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan) -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan) - { - struct ieee80211_local *local = sdata->local; - int ret = -EBUSY; -@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - - /* fill internal scan request */ - if (!chan) { -- int i, nchan = 0; -+ int i, max_n; -+ int n_ch = 0; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!local->hw.wiphy->bands[band]) - continue; -- for (i = 0; -- i < local->hw.wiphy->bands[band]->n_channels; -- i++) { -- local->int_scan_req->channels[nchan] = -+ -+ max_n = local->hw.wiphy->bands[band]->n_channels; -+ for (i = 0; i < max_n; i++) { -+ struct ieee80211_channel *tmp_ch = - &local->hw.wiphy->bands[band]->channels[i]; -- nchan++; -+ -+ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED)) -+ continue; -+ -+ local->int_scan_req->channels[n_ch] = tmp_ch; -+ n_ch++; - } - } - -- local->int_scan_req->n_channels = nchan; -+ if (WARN_ON_ONCE(n_ch == 0)) -+ goto unlock; -+ -+ local->int_scan_req->n_channels = n_ch; - } else { -+ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED))) -+ goto unlock; -+ - local->int_scan_req->channels[0] = chan; - local->int_scan_req->n_channels = 1; - } --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From d613208152f65406b3459b2863b8c6d778783fd5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 16 Jan 2013 08:29:18 -0500 Subject: [PATCH 146/492] Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) --- iwlegacy-fix-IBSS-cleanup.patch | 104 ++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 iwlegacy-fix-IBSS-cleanup.patch diff --git a/iwlegacy-fix-IBSS-cleanup.patch b/iwlegacy-fix-IBSS-cleanup.patch new file mode 100644 index 000000000..5533aed75 --- /dev/null +++ b/iwlegacy-fix-IBSS-cleanup.patch @@ -0,0 +1,104 @@ +From 658f1bd2dd632209df00ec66349e15941ffdd83b Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Wed, 16 Jan 2013 10:28:09 +0000 +Subject: [PATCH 3.8] iwlegacy: fix IBSS cleanup + +We do not correctly change interface type when switching from +IBSS mode to STA mode, that results in microcode errors. + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=886946 + +Reported-by: Jaroslav Skarvada +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/common.c | 35 ++++++++++++++-------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c +index 7e16d10..90b8970 100644 +--- a/drivers/net/wireless/iwlegacy/common.c ++++ b/drivers/net/wireless/iwlegacy/common.c +@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) + + memset(&il->staging, 0, sizeof(il->staging)); + +- if (!il->vif) { ++ switch (il->iw_mode) { ++ case NL80211_IFTYPE_UNSPECIFIED: + il->staging.dev_type = RXON_DEV_TYPE_ESS; +- } else if (il->vif->type == NL80211_IFTYPE_STATION) { ++ break; ++ case NL80211_IFTYPE_STATION: + il->staging.dev_type = RXON_DEV_TYPE_ESS; + il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; +- } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { ++ break; ++ case NL80211_IFTYPE_ADHOC: + il->staging.dev_type = RXON_DEV_TYPE_IBSS; + il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.filter_flags = + RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; +- } else { ++ break; ++ default: + IL_ERR("Unsupported interface type %d\n", il->vif->type); + return; + } +@@ -4550,8 +4554,7 @@ out: + EXPORT_SYMBOL(il_mac_add_interface); + + static void +-il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, +- bool mode_change) ++il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) + { + lockdep_assert_held(&il->mutex); + +@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, + il_force_scan_end(il); + } + +- if (!mode_change) +- il_set_mode(il); +- ++ il_set_mode(il); + } + + void +@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) + + WARN_ON(il->vif != vif); + il->vif = NULL; +- +- il_teardown_interface(il, vif, false); ++ il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; ++ il_teardown_interface(il, vif); + memset(il->bssid, 0, ETH_ALEN); + + D_MAC80211("leave\n"); +@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + } + + /* success */ +- il_teardown_interface(il, vif, true); + vif->type = newtype; + vif->p2p = false; +- err = il_set_mode(il); +- WARN_ON(err); +- /* +- * We've switched internally, but submitting to the +- * device may have failed for some reason. Mask this +- * error, because otherwise mac80211 will not switch +- * (and set the interface type back) and we'll be +- * out of sync with it. +- */ ++ il->iw_mode = newtype; ++ il_teardown_interface(il, vif); + err = 0; + + out: +-- +1.8.0.2 + diff --git a/kernel.spec b/kernel.spec index e58f8cbeb..d3d2022b0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -783,6 +783,9 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #3.7.3 stable queue Patch2150: 3.7.3-stable-queue.patch +#rhbz 886946 +Patch21234: iwlegacy-fix-IBSS-cleanup.patch + # END OF PATCH DEFINITIONS %endif @@ -1505,6 +1508,9 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #3.7.3 stable qeueu ApplyPatch 3.7.3-stable-queue.patch +#rhbz 886948 +ApplyPatch iwlegacy-fix-IBSS-cleanup.patch + # END OF PATCH APPLICATIONS %endif @@ -2377,6 +2383,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 16 2013 Josh Boyer +- Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) + * Tue Jan 15 2013 Justin M. Forbes 3.7.2-203 - Turn off Intel IOMMU by default - Stable queue from 3.7.3 with many relevant fixes From e4e27aa5113b4a0b82ac2ef4cff57b72764604ff Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 16 Jan 2013 09:57:24 -0600 Subject: [PATCH 147/492] Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) --- kernel.spec | 9 +++ ...-corruption-in-xen_failsafe_callback.patch | 62 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 xen-fix-stack-corruption-in-xen_failsafe_callback.patch diff --git a/kernel.spec b/kernel.spec index d3d2022b0..dfd024981 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,6 +786,9 @@ Patch2150: 3.7.3-stable-queue.patch #rhbz 886946 Patch21234: iwlegacy-fix-IBSS-cleanup.patch +#rhbz 896051 896038 CVE-2013-0190 +Patch21250: xen-fix-stack-corruption-in-xen_failsafe_callback.patch + # END OF PATCH DEFINITIONS %endif @@ -1511,6 +1514,9 @@ ApplyPatch 3.7.3-stable-queue.patch #rhbz 886948 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch +#rhbz 896051 896038 CVE-2013-0190 +ApplyPatch xen-fix-stack-corruption-in-xen_failsafe_callback.patch + # END OF PATCH APPLICATIONS %endif @@ -2383,6 +2389,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 16 2013 Justin M. Forbes 3.7.2-204 +- Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) + * Wed Jan 16 2013 Josh Boyer - Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) diff --git a/xen-fix-stack-corruption-in-xen_failsafe_callback.patch b/xen-fix-stack-corruption-in-xen_failsafe_callback.patch new file mode 100644 index 000000000..9d83ea0c9 --- /dev/null +++ b/xen-fix-stack-corruption-in-xen_failsafe_callback.patch @@ -0,0 +1,62 @@ +From 38174c8c07ad638cd18285ba402b59076849dc21 Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Thu, 10 Jan 2013 17:16:30 +0000 +Subject: [PATCH] xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests. + +There has been an error on the xen_failsafe_callback path for failed +iret, which causes the stack pointer to be wrong when entering the +iret_exc error path. This can result in the kernel crashing. + +In the classic kernel case, the relevant code looked a little like: + + popl %eax # Error code from hypervisor + jz 5f + addl $16,%esp + jmp iret_exc # Hypervisor said iret fault +5: addl $16,%esp + # Hypervisor said segment selector fault + +Here, there are two identical addls on either option of a branch which +appears to have been optimised by hoisting it above the jz, and +converting it to an lea, which leaves the flags register unaffected. + +In the PVOPS case, the code looks like: + + popl_cfi %eax # Error from the hypervisor + lea 16(%esp),%esp # Add $16 before choosing fault path + CFI_ADJUST_CFA_OFFSET -16 + jz 5f + addl $16,%esp # Incorrectly adjust %esp again + jmp iret_exc + +It is possible unprivileged userspace applications to cause this +behaviour, for example by loading an LDT code selector, then changing +the code selector to be not-present. At this point, there is a race +condition where it is possible for the hypervisor to return back to +userspace from an interrupt, fault on its own iret, and inject a +failsafe_callback into the kernel. + +This bug has been present since the introduction of Xen PVOPS support +in commit 5ead97c84 (xen: Core Xen implementation), in 2.6.23. + +Signed-off-by: Frediano Ziglio +Signed-off-by: Andrew Cooper +--- + arch/x86/kernel/entry_32.S | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S +index ff84d54..6ed91d9 100644 +--- a/arch/x86/kernel/entry_32.S ++++ b/arch/x86/kernel/entry_32.S +@@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback) + lea 16(%esp),%esp + CFI_ADJUST_CFA_OFFSET -16 + jz 5f +- addl $16,%esp + jmp iret_exc + 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ + SAVE_ALL +-- +1.7.2.5 + From 202608877d88faba8f114c079c25f6d04075d10b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 16 Jan 2013 22:08:34 -0500 Subject: [PATCH 148/492] Fix power management sysfs on non-secure boot machines (rhbz 896243) --- kernel.spec | 5 +++- secure-boot-20121212.patch | 48 ++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/kernel.spec b/kernel.spec index dfd024981..46c06cdd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 205 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2389,6 +2389,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 16 2013 Josh Boyer +- Fix power management sysfs on non-secure boot machines (rhbz 896243) + * Wed Jan 16 2013 Justin M. Forbes 3.7.2-204 - Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) diff --git a/secure-boot-20121212.patch b/secure-boot-20121212.patch index 387302b90..61f796e85 100644 --- a/secure-boot-20121212.patch +++ b/secure-boot-20121212.patch @@ -1318,10 +1318,10 @@ index 0000000..76a5a34 1.8.0.1 -From 7d5629a2000d9dc92da91d2f1258af748e89cfd7 Mon Sep 17 00:00:00 2001 +From e45330362517d08579cdaddc718febe68e2cae06 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH 19/20] hibernate: Disable in a Secure Boot environment +Subject: [PATCH] hibernate: Disable in a Secure Boot environment There is currently no way to verify the resume image when returning from hibernate. This might compromise the secure boot trust model, @@ -1330,16 +1330,24 @@ a Secure Boot environment. Signed-off-by: Josh Boyer --- - kernel/power/hibernate.c | 14 +++++++++++++- - kernel/power/main.c | 4 +++- + kernel/power/hibernate.c | 15 ++++++++++++++- + kernel/power/main.c | 7 ++++++- kernel/power/user.c | 3 +++ - 3 files changed, 19 insertions(+), 2 deletions(-) + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index b26f5f1..f04343b 100644 +index b26f5f1..26bdfa8 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c -@@ -632,6 +632,10 @@ int hibernate(void) +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -632,6 +633,10 @@ int hibernate(void) { int error; @@ -1350,7 +1358,7 @@ index b26f5f1..f04343b 100644 lock_system_sleep(); /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -@@ -723,7 +727,7 @@ static int software_resume(void) +@@ -723,7 +728,7 @@ static int software_resume(void) /* * If the user said "noresume".. bail out early. */ @@ -1359,11 +1367,11 @@ index b26f5f1..f04343b 100644 return 0; /* -@@ -889,6 +893,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, +@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, int i; char *start = buf; -+ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ if (secure_boot_enabled) { + buf += sprintf(buf, "[%s]\n", "disabled"); + return buf-start; + } @@ -1371,7 +1379,7 @@ index b26f5f1..f04343b 100644 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { if (!hibernation_modes[i]) continue; -@@ -923,6 +932,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, +@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, char *p; int mode = HIBERNATION_INVALID; @@ -1382,16 +1390,26 @@ index b26f5f1..f04343b 100644 len = p ? p - buf : n; diff --git a/kernel/power/main.c b/kernel/power/main.c -index f458238..72580c1 100644 +index 1c16f91..8e3456d 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c -@@ -301,7 +301,9 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, } #endif #ifdef CONFIG_HIBERNATION - s += sprintf(s, "%s\n", "disk"); -+ if (capable(CAP_COMPROMISE_KERNEL)) { ++ if (!secure_boot_enabled) { + s += sprintf(s, "%s\n", "disk"); ++ } else { ++ s += sprintf(s, "\n"); + } #else if (s != buf) @@ -1411,7 +1429,7 @@ index 4ed81e7..b11a0f4 100644 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -- -1.8.0.1 +1.8.0.2 From 81adc779dba0f45f10b5ff307bd55832305f1112 Mon Sep 17 00:00:00 2001 From 0f008535c88de63df9fec3c6dfb11500f361daba Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Fri, 18 Jan 2013 15:54:38 +0000 Subject: [PATCH 149/492] Merge 3.7 ARM kernel including unified kernel, Drop separate IMX and highbank kernels, Disable ARM PL310 errata that crash highbank --- Makefile.config | 32 +--- config-arm-generic | 1 + config-arm-highbank | 65 -------- config-arm-imx | 119 --------------- config-armv7 | 353 ++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 63 ++------ 6 files changed, 376 insertions(+), 257 deletions(-) delete mode 100644 config-arm-highbank delete mode 100644 config-arm-imx create mode 100644 config-armv7 diff --git a/Makefile.config b/Makefile.config index af6dd73f2..777b30283 100644 --- a/Makefile.config +++ b/Makefile.config @@ -11,15 +11,13 @@ CONFIGFILES = \ $(CFG)-s390x.config \ $(CFG)-armv5tel-kirkwood.config \ $(CFG)-armv7l.config $(CFG)-armv7hl.config \ - $(CFG)-armv7l-imx.config $(CFG)-armv7hl-imx.config \ $(CFG)-armv7l-omap.config $(CFG)-armv7hl-omap.config \ $(CFG)-armv7l-tegra.config $(CFG)-armv7hl-tegra.config \ - $(CFG)-armv7l-highbank.config $(CFG)-armv7hl-highbank.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64p7.config $(CFG)-ppc64-debug.config -PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x sparc64 +PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x sparc64 arm TEMPFILES = $(addprefix temp-, $(addsuffix -generic, $(PLATFORMS))) configs: $(CONFIGFILES) @@ -37,10 +35,10 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic -temp-arm-generic: config-arm-generic temp-generic - perl merge.pl $^ > $@ +temp-armv7: config-armv7 temp-generic + perl merge.pl $^ > $@ -temp-armv7l-versatile: config-arm-versatile temp-arm-generic +temp-arm-generic: config-arm-generic temp-generic perl merge.pl $^ > $@ temp-armv7l-omap: config-arm-omap temp-arm-generic @@ -52,12 +50,6 @@ temp-armv7l-tegra: config-arm-tegra temp-arm-generic temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic perl merge.pl $^ > $@ -temp-armv7l-imx: config-arm-imx temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv7l-highbank: config-arm-highbank temp-arm-generic - perl merge.pl $^ > $@ - temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ @@ -130,13 +122,7 @@ kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7l.config: /dev/null temp-armv7l-versatile - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-imx.config: /dev/null temp-armv7l-imx - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-highbank.config: /dev/null temp-armv7l-highbank +kernel-$(VERSION)-armv7l.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap @@ -145,13 +131,7 @@ kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7hl.config: /dev/null temp-armv7l-versatile - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-imx.config: /dev/null temp-armv7l-imx - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-highbank.config: /dev/null temp-armv7l-highbank +kernel-$(VERSION)-armv7hl.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap diff --git a/config-arm-generic b/config-arm-generic index 89fc4356a..d268b4d73 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -251,6 +251,7 @@ CONFIG_HW_RANDOM_EXYNOS=m # Device tree CONFIG_OF=y CONFIG_USE_OF=y +CONFIG_OF_DEVICE=y CONFIG_OF_IRQ=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y diff --git a/config-arm-highbank b/config-arm-highbank deleted file mode 100644 index ca27f65cb..000000000 --- a/config-arm-highbank +++ /dev/null @@ -1,65 +0,0 @@ -CONFIG_ARCH_HIGHBANK=y -# CONFIG_ARM_LPAE is not set -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_PL310_ERRATA_769419 is not set - -# CONFIG_THUMB2_KERNEL is not set - -CONFIG_ARM_TIMER_SP804=y - -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -CONFIG_SATA_AHCI_PLATFORM=y -CONFIG_ATA_SFF=y - -CONFIG_NET_CALXEDA_XGMAC=y - -CONFIG_EDAC_HIGHBANK_MC=m -CONFIG_EDAC_HIGHBANK_L2=m - -CONFIG_GPIO_PL061=y - -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - -CONFIG_RTC_DRV_PL030=y -CONFIG_RTC_DRV_PL031=y - -CONFIG_SATA_HIGHBANK=m - -CONFIG_OC_ETM=y - -# CONFIG_NET_VENDOR_BROADCOM is not set -# these were all requested to be disabled on highbank kernels by calxeda -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_CAIF is not set -# CONFIG_NFC is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -# CONFIG_ATM_DRIVERS is not set -# CONFIG_WAN is not set -# CONFIG_ISDN is not set -# CONFIG_MEDIA_SUPPORT is not set -# CONFIG_DRM is not set -# CONFIG_SND is not set -# CONFIG_ARCH_MULTI_V4 is not set -# CONFIG_ARCH_MULTI_V4T is not set -# CONFIG_ARCH_MULTI_V6 is not set -# end of list of requested disabled options diff --git a/config-arm-imx b/config-arm-imx deleted file mode 100644 index 8ffd96559..000000000 --- a/config-arm-imx +++ /dev/null @@ -1,119 +0,0 @@ -CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX51=y - -CONFIG_VFP=y -CONFIG_NEON=y -# CONFIG_SWP_EMULATE is not set -# CONFIG_THUMB2_KERNEL is not set -CONFIG_CPU_FREQ_IMX=y - -CONFIG_SOC_IMX53=y -CONFIG_SOC_IMX6Q=y - -CONFIG_MACH_ARMADILLO5X0=y -CONFIG_MACH_BUG=y -CONFIG_MACH_EUKREA_CPUIMX35=y -CONFIG_MACH_EUKREA_CPUIMX35SD=y -CONFIG_MACH_EUKREA_CPUIMX51=y -CONFIG_MACH_EUKREA_CPUIMX51SD=y -CONFIG_MACH_IMX31_DT=y -CONFIG_MACH_IMX51_DT=y -CONFIG_MACH_IMX53_DT=y -CONFIG_MACH_KZM_ARM11_01=y -CONFIG_MACH_MX31_3DS=y -CONFIG_MACH_MX31ADS=y -CONFIG_MACH_MX31LILLY=y -CONFIG_MACH_MX31LITE=y -CONFIG_MACH_MX31MOBOARD=y -CONFIG_MACH_MX35_3DS=y -CONFIG_MACH_MX51_3DS=y -CONFIG_MACH_MX51_BABBAGE=y -CONFIG_MACH_MX51_EFIKAMX=y -CONFIG_MACH_MX51_EFIKASB=y -CONFIG_MACH_MX53_EVK=y -CONFIG_MACH_MX53_SMD=y -CONFIG_MACH_MX53_LOCO=y -CONFIG_MACH_MX53_ARD=y -CONFIG_MACH_PCM037=y -CONFIG_MACH_PCM037_EET=y -CONFIG_MACH_PCM043=y -CONFIG_MACH_QONG=y -CONFIG_MACH_VPR200=y - -CONFIG_W1_MASTER_MXC=m -CONFIG_DMA_CACHE_RWFO=y -CONFIG_IMX_DMA=y -CONFIG_IMX_SDMA=y -CONFIG_MXS_DMA=y -CONFIG_MXC_IRQ_PRIOR=y -CONFIG_MXC_PWM=m -CONFIG_MXC_DEBUG_BOARD=y - -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_ERRATA_326103=y -CONFIG_ARM_ERRATA_411920=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_ARM_ERRATA_364296=y - -CONFIG_PATA_IMX=m -CONFIG_NET_VENDOR_FREESCALE=y -CONFIG_FEC=y -CONFIG_KEYBOARD_IMX=m -CONFIG_SERIAL_IMX=y -CONFIG_HW_RANDOM_MXC_RNGA=m -CONFIG_I2C_IMX=m -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MCP23S08=m -# CONFIG_GPIO_MC9S08DZ60 is not set -CONFIG_PINCTRL_IMX35=y -CONFIG_PINCTRL_IMX51=y -CONFIG_PINCTRL_IMX53=y -CONFIG_USB_EHCI_MXC=y -CONFIG_USB_MXS_PHY=m -# CONFIG_USB_IMX21_HCD is not set -CONFIG_MMC_SDHCI_ESDHC_IMX=m -CONFIG_MMC_MXC=m -CONFIG_RTC_MXC=y -CONFIG_RTC_DRV_MXC=m - -CONFIG_DRM_IMX=m -CONFIG_DRM_IMX_FB_HELPER=m -CONFIG_DRM_IMX_PARALLEL_DISPLAY=m -CONFIG_DRM_IMX_IPUV3_CORE=m -CONFIG_DRM_IMX_IPUV3=m -CONFIG_VIDEO_CODA=m -CONFIG_BACKLIGHT_PWM=m -CONFIG_LEDS_PWM=m - -# CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set -CONFIG_MXC_USE_EPIT=y -CONFIG_HAVE_EPIT=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_CAN_FLEXCAN=m -CONFIG_MTD_NAND_MXC=m -CONFIG_MTD_NAND_GPMI_NAND=y -CONFIG_INPUT_PWM_BEEPER=m -CONFIG_SERIAL_IMX_CONSOLE=y -CONFIG_IMX2_WDT=m - -CONFIG_SND_IMX_SOC=m -CONFIG_SND_SOC_PHYCORE_AC97=m -CONFIG_SND_SOC_EUKREA_TLV320=m -CONFIG_SND_SOC_IMX_SGTL5000=m - -CONFIG_PL310_ERRATA_769419=y -CONFIG_LEDS_RENESAS_TPU=y - -CONFIG_MFD_MAX8907=m - -CONFIG_FB_IMX=m - -# CONFIG_NET_VENDOR_BROADCOM is not set diff --git a/config-armv7 b/config-armv7 new file mode 100644 index 000000000..f143f3dee --- /dev/null +++ b/config-armv7 @@ -0,0 +1,353 @@ +# ARM unified arch kernel +CONFIG_CPU_V7=y +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_HIGHBANK=y +CONFIG_ARCH_PICOXCELL=y +CONFIG_ARCH_SOCFPGA=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +CONFIG_ARCH_VEXPRESS_DT=y + +CONFIG_MACH_ARMADA_370_XP=y +CONFIG_MACH_ARMADA_370=y +CONFIG_MACH_ARMADA_XP=y + +# generic ARM config options +CONFIG_CMDLINE="" +CONFIG_ARM_ARCH_TIMER=y +CONFIG_AEABI=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_UNWIND=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_GIC=y +CONFIG_ARM_ASM_UNIFIED=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_SWP_EMULATE=y +CONFIG_CPU_BPREDICT_DISABLE=y +CONFIG_CACHE_L2X0=y +CONFIG_HIGHPTE=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ATAGS is not set +# CONFIG_ATAGS_PROC is not set +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_DMA_CACHE_RWFO is not set +# CONFIG_ARM_LPAE is not set +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_XEN is not set +CONFIG_HVC_DCC=y + +# CONFIG_ARM_VIRT_EXT is not set + +# errata +# v5/v6 +# CONFIG_ARM_ERRATA_326103 is not set +# CONFIG_ARM_ERRATA_411920 is not set +# Cortex-A8 +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# Cortex-A9 +CONFIG_ARM_ERRATA_742230=y +CONFIG_ARM_ERRATA_742231=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +# Disabled due to causing highbank to crash +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +CONFIG_PL310_ERRATA_769419=y + +# generic that deviates from or should be merged into config-generic +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_SMP_ON_UP=y +CONFIG_HIGHMEM=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y + +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 + +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_GOV_LADDER is not set +CONFIG_CPU_IDLE_GOV_MENU=y + +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +CONFIG_SECCOMP=y +CONFIG_STRICT_DEVMEM=y + +CONFIG_PM=y +CONFIG_PM_STD_PARTITION="" +CONFIG_SUSPEND=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_CPU_TOPOLOGY=y + +CONFIG_LOCAL_TIMERS=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_CC_STACKPROTECTOR=y + +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set + +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y + +CONFIG_PINCTRL=y +CONFIG_PINCONF=y + +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_EARLY_PRINTK=y + +CONFIG_LBDAF=y + +CONFIG_COMMON_CLK=y + +# Versatile and highbank +CONFIG_ARM_TIMER_SP804=y + +CONFIG_SERIO_AMBAKMI=m +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + +CONFIG_RTC_DRV_PL030=y +CONFIG_RTC_DRV_PL031=y + +CONFIG_PL330_DMA=y +CONFIG_AMBA_PL08X=y +CONFIG_ARM_SP805_WATCHDOG=m + +# highbank +CONFIG_EDAC_HIGHBANK_MC=m +CONFIG_EDAC_HIGHBANK_L2=m + +CONFIG_OC_ETM=y + +CONFIG_SATA_HIGHBANK=m + +# versatile +CONFIG_FB_ARMCLCD=m +CONFIG_I2C_VERSATILE=m +CONFIG_OC_ETM=y +CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y + +# unknown and needs review +CONFIG_ARM_AMBA=y + +# mvebu +CONFIG_MV_XOR=y +CONFIG_RTC_DRV_88PM80X=m +CONFIG_CRYPTO_DEV_MV_CESA=m +CONFIG_MV643XX_ETH=m +CONFIG_I2C_MV64XXX=m +CONFIG_PINCTRL_MVEBU=y + +# exynos +# CONFIG_DRM_EXYNOS is not set + +# picoxcell +CONFIG_CRYPTO_DEV_PICOXCELL=m + +# ST Ericsson +# CONFIG_I2C_NOMADIK is not set + +# General ARM drivers +# Device tree +CONFIG_OF=y +CONFIG_USE_OF=y +CONFIG_OF_DEVICE=y +CONFIG_OF_IRQ=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_OF_GPIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_OF_MDIO=m + +CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_GPIOLIB=y + +# MMC/SD +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SPI=m +CONFIG_MMC_DW=m +CONFIG_MMC_DW_PLTFM=m +CONFIG_MMC_DW_PCI=m +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_IDMAC is not set +CONFIG_MMC_TMIO=m +CONFIG_MMC_SDHCI_PXAV3=m +CONFIG_MMC_SDHCI_PXAV2=m +CONFIG_MMC_MVSDIO=m + +# usb +CONFIG_USB_ULPI=y +CONFIG_AX88796=m +CONFIG_AX88796_93CX6=y +CONFIG_SMC91X=m +CONFIG_SMC911X=m +CONFIG_SMSC911X=m +CONFIG_USB_ISP1760_HCD=m + +# HW crypto and rng +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m +CONFIG_HW_RANDOM_ATMEL=m +CONFIG_HW_RANDOM_EXYNOS=m + +# Sound +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=m +CONFIG_SND_SOC=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SND_SOC_CACHE_LZO=y +CONFIG_SND_SOC_ALL_CODECS=m + +# EDAC +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_LEGACY_SYSFS=y + +# Watchdog +CONFIG_MPCORE_WATCHDOG=m + +# Multi function devices +CONFIG_MFD_T7L66XB=y +CONFIG_MFD_TC6387XB=y +CONFIG_MFD_SYSCON=y +CONFIG_MFD_MAX8907=m +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_SMSC is not set + +# RTC +CONFIG_RTC_DRV_SNVS=m + +# Pin stuff +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_SINGLE=m +# CONFIG_PINCTRL_SAMSUNG is not set +# CONFIG_PINCTRL_EXYNOS4 is not set + +# GPIO +CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_GPIO_EM=m +CONFIG_GPIO_ADNP=m +CONFIG_GPIO_MCP23S08=m +CONFIG_RFKILL_GPIO=m +CONFIG_SERIAL_8250_EM=m +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_MDIO_BUS_MUX_MMIOREG=m + +# MTD +CONFIG_MTD_OF_PARTS=y +# CONFIG_MG_DISK is not set + +# Regulator drivers +CONFIG_REGULATOR_FAN53555=m +# Needs work/investigation + +# CONFIG_ARM_CHARLCD is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_BPF_JIT is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_COMMON_CLK_DEBUG is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_PINCTRL is not set + +# CONFIG_CS89x0 is not set +# CONFIG_DM9000 is not set + +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_LEDS_RENESAS_TPU is not set + +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +CONFIG_THERMAL=y +# CONFIG_PATA_PLATFORM is not set +CONFIG_PERF_EVENTS=y + +# Defined config options we don't use yet +# CONFIG_PINCTRL_IMX35 is not set +# CONFIG_DRM_IMX_FB_HELPER is not set +# CONFIG_DRM_IMX_PARALLEL_DISPLAY is not set +# CONFIG_DRM_IMX_IPUV3_CORE is not set +# CONFIG_DRM_IMX_IPUV3 is not set +# CONFIG_REGULATOR_ANATOP is not set + +# CONFIG_GPIO_TWL6040 is not set +# CONFIG_SND_OMAP_SOC_OMAP_TWL4030 is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_PANEL_TAAL is not set +# CONFIG_IR_RX51 is not set + +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set +# CONFIG_GPIO_TWL6040 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_IR_RX51 is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_PANEL_TAAL is not set +# CONFIG_SND_OMAP_SOC_OMAP_TWL4030 is not set + +# CONFIG_DVB_USB_PCTV452E is not set +# We need to fix these as they should be either generic includes or kconfig fixes +# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set diff --git a/kernel.spec b/kernel.spec index 46c06cdd0..3f33e9c61 100644 --- a/kernel.spec +++ b/kernel.spec @@ -138,10 +138,6 @@ Summary: The Linux kernel %define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} # kernel-kirkwood (only valid for arm) %define with_kirkwood %{?_without_kirkwood: 0} %{?!_without_kirkwood: 1} -# kernel-imx (only valid for arm) -%define with_imx %{?_without_imx: 0} %{?!_without_imx: 1} -# kernel-highbank (only valid for arm) -%define with_highbank %{?_without_highbank: 0} %{?!_without_highbank: 1} # # Additional options for user-friendly one-off kernel building: # @@ -258,10 +254,8 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel up (versatile express), tegra, omap, imx and highbank are only built on armv7 hfp/sfp +# kernel up (versatile express), tegra and omap are only built on armv7 hfp/sfp %ifnarch armv7hl armv7l -%define with_imx 0 -%define with_highbank 0 %define with_omap 0 %define with_tegra 0 %endif @@ -534,6 +528,11 @@ ExclusiveOS: Linux %kernel_reqprovconf +%ifarch %{arm} +Obsoletes: kernel-highbank +Obsoletes: kernel-imx +%endif + # # List the packages used during the kernel build # @@ -599,13 +598,14 @@ Source70: config-s390x Source90: config-sparc64-generic -Source100: config-arm-generic +# Unified ARM kernels +Source100: config-armv7 + +# Legacy ARM kernels +Source105: config-arm-generic Source110: config-arm-omap Source111: config-arm-tegra Source112: config-arm-kirkwood -Source113: config-arm-imx -Source114: config-arm-highbank -Source115: config-arm-versatile # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -752,12 +752,6 @@ Patch21004: arm-tegra-nvec-kconfig.patch Patch21005: arm-tegra-usb-no-reset-linux33.patch Patch21006: arm-tegra-sdhci-module-fix.patch -# ARM highbank patches - -# ARM exynos4 -Patch21020: arm-smdk310-regulator-fix.patch -Patch21021: arm-origen-regulator-fix.patch - #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1074,18 +1068,6 @@ on kernel bugs, as some of these options impact performance noticably. This package includes a version of the Linux kernel with support for marvell kirkwood based systems, i.e., guruplug, sheevaplug -%define variant_summary The Linux kernel compiled for freescale boards -%kernel_variant_package imx -%description imx -This package includes a version of the Linux kernel with support for -freescale based systems, i.e., efika smartbook. - -%define variant_summary The Linux kernel compiled for Calxeda boards -%kernel_variant_package highbank -%description highbank -This package includes a version of the Linux kernel with support for -Calxeda based systems, i.e., HP arm servers. - %define variant_summary The Linux kernel compiled for TI-OMAP boards %kernel_variant_package omap %description omap @@ -1368,8 +1350,6 @@ ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch ApplyPatch arm-alignment-faults.patch -ApplyPatch arm-smdk310-regulator-fix.patch -ApplyPatch arm-origen-regulator-fix.patch # # bugfixes to drivers and filesystems @@ -1871,14 +1851,6 @@ BuildKernel %make_target %kernel_image PAE BuildKernel %make_target %kernel_image kirkwood %endif -%if %{with_imx} -BuildKernel %make_target %kernel_image imx -%endif - -%if %{with_highbank} -BuildKernel %make_target %kernel_image highbank -%endif - %if %{with_omap} BuildKernel %make_target %kernel_image omap %endif @@ -2218,12 +2190,6 @@ fi}\ %kernel_variant_preun kirkwood %kernel_variant_post -v kirkwood -%kernel_variant_preun imx -%kernel_variant_post -v imx - -%kernel_variant_preun highbank -%kernel_variant_post -v highbank - %kernel_variant_preun omap %kernel_variant_post -v omap @@ -2371,8 +2337,6 @@ fi %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug %kernel_variant_files %{with_kirkwood} kirkwood -%kernel_variant_files %{with_imx} imx -%kernel_variant_files %{with_highbank} highbank %kernel_variant_files %{with_omap} omap %kernel_variant_files %{with_tegra} tegra @@ -2389,6 +2353,11 @@ fi # ||----w | # || || %changelog +* Thu Jan 17 2013 Peter Robinson +- Merge 3.7 ARM kernel including unified kernel +- Drop separate IMX and highbank kernels +- Disable ARM PL310 errata that crash highbank + * Wed Jan 16 2013 Josh Boyer - Fix power management sysfs on non-secure boot machines (rhbz 896243) From 6f5f5295ba337872086d99355b316f06710c49f3 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Fri, 18 Jan 2013 15:59:51 +0000 Subject: [PATCH 150/492] drop obsolete arm patches --- arm-origen-regulator-fix.patch | 12 ----------- arm-smdk310-regulator-fix.patch | 36 --------------------------------- 2 files changed, 48 deletions(-) delete mode 100644 arm-origen-regulator-fix.patch delete mode 100644 arm-smdk310-regulator-fix.patch diff --git a/arm-origen-regulator-fix.patch b/arm-origen-regulator-fix.patch deleted file mode 100644 index c91bfb84c..000000000 --- a/arm-origen-regulator-fix.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c -index 4e574c2..5028fee 100644 ---- a/arch/arm/mach-exynos/mach-origen.c -+++ b/arch/arm/mach-exynos/mach-origen.c -@@ -121,6 +121,7 @@ static struct regulator_consumer_supply __initdata ldo14_consumer[] = { - }; - static struct regulator_consumer_supply __initdata ldo17_consumer[] = { - REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */ -+ REGULATOR_SUPPLY("vmmc", NULL), - }; - static struct regulator_consumer_supply __initdata buck1_consumer[] = { - REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */ diff --git a/arm-smdk310-regulator-fix.patch b/arm-smdk310-regulator-fix.patch deleted file mode 100644 index 0e0be1e4d..000000000 --- a/arm-smdk310-regulator-fix.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- linus.orig/arch/arm/mach-exynos/mach-smdkv310.c -+++ linus/arch/arm/mach-exynos/mach-smdkv310.c -@@ -14,6 +14,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -380,6 +382,14 @@ static void __init smdkv310_reserve(void - s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20); - } - -+static struct regulator_consumer_supply vddmmc_consumers[] __devinitdata = { -+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"), -+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"), -+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), -+ REGULATOR_SUPPLY("vdd33a", "smsc911x"), -+ REGULATOR_SUPPLY("vddvario", "smsc911x"), -+}; -+ - static void __init smdkv310_machine_init(void) - { - s3c_i2c1_set_platdata(NULL); -@@ -387,6 +397,9 @@ static void __init smdkv310_machine_init - - smdkv310_smsc911x_init(); - -+ regulator_register_always_on(0, "fixed-3.3V", vddmmc_consumers, -+ ARRAY_SIZE(vddmmc_consumers), 3300000); -+ - s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata); - s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata); - s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); From c7c083e5a7342f26a05bbe8a56a04cd19c3ea927 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 18 Jan 2013 12:08:21 -0600 Subject: [PATCH 151/492] Linux v3.7.3 --- kernel.spec | 13 +++++-------- sources | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3f33e9c61..07f96cf16 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 205 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -774,9 +774,6 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#3.7.3 stable queue -Patch2150: 3.7.3-stable-queue.patch - #rhbz 886946 Patch21234: iwlegacy-fix-IBSS-cleanup.patch @@ -1488,9 +1485,6 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#3.7.3 stable qeueu -ApplyPatch 3.7.3-stable-queue.patch - #rhbz 886948 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch @@ -2353,6 +2347,9 @@ fi # ||----w | # || || %changelog +* Fri Jan 18 2013 Justin M. Forbes 3.7.3-201 +- Linux v3.7.3 + * Thu Jan 17 2013 Peter Robinson - Merge 3.7 ARM kernel including unified kernel - Drop separate IMX and highbank kernels diff --git a/sources b/sources index 764eb4a60..df992bd44 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -132211742278e18b8f4808754d85e66c patch-3.7.2.xz +d4aa39ec9610e9fbd7bb4f5aff2c5db8 patch-3.7.3.xz From bcc94bf2746790e8fb6858ffc4bbc48bd13d10bc Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 18 Jan 2013 14:06:45 -0600 Subject: [PATCH 152/492] Remove stable queue patch --- 3.7.3-stable-queue.patch | 15769 ------------------------------------- 1 file changed, 15769 deletions(-) delete mode 100644 3.7.3-stable-queue.patch diff --git a/3.7.3-stable-queue.patch b/3.7.3-stable-queue.patch deleted file mode 100644 index e9b57d5a5..000000000 --- a/3.7.3-stable-queue.patch +++ /dev/null @@ -1,15769 +0,0 @@ -From 13ae633cf729b0ecb677b75b04886ff8fada8fad Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Tue, 20 Nov 2012 10:02:06 +0900 -Subject: regulator: wm831x: Set the new rather than old value for DVS VSEL - -From: Mark Brown - -commit 13ae633cf729b0ecb677b75b04886ff8fada8fad upstream. - -Reported-by: Guennadi Liakhovetski -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/regulator/wm831x-dcdc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/regulator/wm831x-dcdc.c -+++ b/drivers/regulator/wm831x-dcdc.c -@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel( - if (vsel > dcdc->dvs_vsel) { - ret = wm831x_set_bits(wm831x, dvs_reg, - WM831X_DC1_DVS_VSEL_MASK, -- dcdc->dvs_vsel); -+ vsel); - if (ret == 0) - dcdc->dvs_vsel = vsel; - else -From 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Mon, 10 Dec 2012 16:40:41 +0100 -Subject: ath5k: fix tx path skb leaks - -From: Felix Fietkau - -commit 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c upstream. - -ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for -tx packets passed to the driver from mac80211 - -Signed-off-by: Felix Fietkau -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath5k/base.c | 4 ++-- - drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/ath/ath5k/base.c -+++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -848,7 +848,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah - return; - dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, - DMA_TO_DEVICE); -- dev_kfree_skb_any(bf->skb); -+ ieee80211_free_txskb(ah->hw, bf->skb); - bf->skb = NULL; - bf->skbaddr = 0; - bf->desc->ds_data = 0; -@@ -1575,7 +1575,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, - return; - - drop_packet: -- dev_kfree_skb_any(skb); -+ ieee80211_free_txskb(hw, skb); - } - - static void ---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c -+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c -@@ -62,7 +62,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct - u16 qnum = skb_get_queue_mapping(skb); - - if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { -- dev_kfree_skb_any(skb); -+ ieee80211_free_txskb(hw, skb); - return; - } - -From 25a172655f837bdb032e451f95441bb4acec51bb Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Wed, 28 Nov 2012 10:51:34 +0200 -Subject: iwlwifi: don't handle masked interrupt - -From: Emmanuel Grumbach - -commit 25a172655f837bdb032e451f95441bb4acec51bb upstream. - -This can lead to a panic if the driver isn't ready to -handle them. Since our interrupt line is shared, we can get -an interrupt at any time (and CONFIG_DEBUG_SHIRQ checks -that even when the interrupt is being freed). - -If the op_mode has gone away, we musn't call it. To avoid -this the transport disables the interrupts when the hw is -stopped and the op_mode is leaving. -If there is an event that would cause an interrupt the INTA -register is updated regardless of the enablement of the -interrupts: even if the interrupts are disabled, the INTA -will be changed, but the device won't issue an interrupt. -But the ISR can be called at any time, so we ought ignore -the value in the INTA otherwise we can call the op_mode -after it was freed. - -I found this bug when the op_mode_start failed, and called -iwl_trans_stop_hw(trans, true). Then I played with the -RFKILL button, and removed the module. -While removing the module, the IRQ is freed, and the ISR is -called (CONFIG_DEBUG_SHIRQ enabled). Panic. - -Signed-off-by: Emmanuel Grumbach -Reviewed-by: Gregory Greenman -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/iwlwifi/pcie/rx.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/iwlwifi/pcie/rx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c -@@ -927,12 +927,20 @@ static irqreturn_t iwl_isr(int irq, void - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ -- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ -+ inta_mask = iwl_read32(trans, CSR_INT_MASK); - iwl_write32(trans, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(trans, CSR_INT); - -+ if (inta & (~inta_mask)) { -+ IWL_DEBUG_ISR(trans, -+ "We got a masked interrupt (0x%08x)...Ack and ignore\n", -+ inta & (~inta_mask)); -+ iwl_write32(trans, CSR_INT, inta & (~inta_mask)); -+ inta &= inta_mask; -+ } -+ - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ -@@ -1015,7 +1023,7 @@ irqreturn_t iwl_isr_ict(int irq, void *d - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. - */ -- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ -+ inta_mask = iwl_read32(trans, CSR_INT_MASK); - iwl_write32(trans, CSR_INT_MASK, 0x00000000); - - -From 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Sun, 2 Dec 2012 09:56:44 +0200 -Subject: iwlwifi: silently ignore fw flaws in Tx path - -From: Emmanuel Grumbach - -commit 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 upstream. - -We know that we have issues with the fw in the reclaim path. -This is why iwl_reclaim doesn't complain too loud when it -happens since it is recoverable. Somehow, the caller of -iwl_reclaim however WARNed when it happens. This doesn't -make any sense. - -When I digged into the history of that code, I discovered -that this bug occurs only when we receive a BA notification. -So move the W/A in the BA notification handling code where -it was before. - -This patch addresses: -http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2387 - -Reported-by: Florian Reitmeir -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/iwlwifi/dvm/tx.c | 49 ++++++++++++---------------------- - 1 file changed, 18 insertions(+), 31 deletions(-) - ---- a/drivers/net/wireless/iwlwifi/dvm/tx.c -+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c -@@ -1100,29 +1100,6 @@ static void iwl_check_abort_status(struc - } - } - --static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid, -- int txq_id, int ssn, struct sk_buff_head *skbs) --{ -- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && -- tid != IWL_TID_NON_QOS && -- txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) { -- /* -- * FIXME: this is a uCode bug which need to be addressed, -- * log the information and return for now. -- * Since it is can possibly happen very often and in order -- * not to fill the syslog, don't use IWL_ERR or IWL_WARN -- */ -- IWL_DEBUG_TX_QUEUES(priv, -- "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", -- txq_id, sta_id, tid, -- priv->tid_data[sta_id][tid].agg.txq_id); -- return 1; -- } -- -- iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs); -- return 0; --} -- - int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, - struct iwl_device_cmd *cmd) - { -@@ -1184,9 +1161,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv * - next_reclaimed); - } - -- /*we can free until ssn % q.n_bd not inclusive */ -- WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid, -- txq_id, ssn, &skbs)); -+ iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); -+ - iwlagn_check_ratid_empty(priv, sta_id, tid); - freed = 0; - -@@ -1311,16 +1287,27 @@ int iwlagn_rx_reply_compressed_ba(struct - return 0; - } - -+ if (unlikely(scd_flow != agg->txq_id)) { -+ /* -+ * FIXME: this is a uCode bug which need to be addressed, -+ * log the information and return for now. -+ * Since it is can possibly happen very often and in order -+ * not to fill the syslog, don't use IWL_ERR or IWL_WARN -+ */ -+ IWL_DEBUG_TX_QUEUES(priv, -+ "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", -+ scd_flow, sta_id, tid, agg->txq_id); -+ spin_unlock(&priv->sta_lock); -+ return 0; -+ } -+ - __skb_queue_head_init(&reclaimed_skbs); - - /* Release all TFDs before the SSN, i.e. all TFDs in front of - * block-ack window (we assume that they've been successfully - * transmitted ... if not, it's too late anyway). */ -- if (iwl_reclaim(priv, sta_id, tid, scd_flow, -- ba_resp_scd_ssn, &reclaimed_skbs)) { -- spin_unlock(&priv->sta_lock); -- return 0; -- } -+ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn, -+ &reclaimed_skbs); - - IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " - "sta_id = %d\n", -From cbbc0138efe1dcd5426b8fc5d87741f5057aee72 Mon Sep 17 00:00:00 2001 -From: Rafał Miłecki -Date: Mon, 10 Dec 2012 07:53:56 +0100 -Subject: bcma: mips: fix clearing device IRQ - -From: Rafał Miłecki - -commit cbbc0138efe1dcd5426b8fc5d87741f5057aee72 upstream. - -We were using wrong IRQ number so clearing wasn't working at all. -Depending on a platform this could result in a one device having two -interrupts assigned. On BCM4706 this resulted in all IRQs being broken. - -Signed-off-by: Rafał Miłecki -Cc: Hauke Mehrtens -Acked-by: Hauke Mehrtens -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/bcma/driver_mips.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/bcma/driver_mips.c -+++ b/drivers/bcma/driver_mips.c -@@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struc - bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & - ~(1 << irqflag)); - else -- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); -+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); - - /* assign the new one */ - if (irq == 0) { -From f5685ba675449b072feab6a5391a9ef9f604bc94 Mon Sep 17 00:00:00 2001 -From: Helmut Schaa -Date: Mon, 3 Dec 2012 22:35:39 +0100 -Subject: rt2x00: Only specify interface combinations if more then one interface is possible - -From: Helmut Schaa - -commit f5685ba675449b072feab6a5391a9ef9f604bc94 upstream. - -Otherwise rt2500* triggers a warning in cfg80211, from net/wireless/core.c: - - /* Combinations with just one interface aren't real */ - if (WARN_ON(c->max_interfaces < 2)) - -This was introduced in commit 55d2e9da744ba11eae900b4bfc2da72eace3c1e1: -rt2x00: Replace open coded interface checking with interface combinations. - -Reported-by: Stefan Lippers-Hollmann -Tested-by: Stefan Lippers-Hollmann -Signed-off-by: Helmut Schaa -Acked-by: Gertjan van Wingerde -Acked-by: Stanislaw Gruszka -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/rt2x00/rt2x00dev.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -1123,6 +1123,9 @@ static inline void rt2x00lib_set_if_comb - struct ieee80211_iface_limit *if_limit; - struct ieee80211_iface_combination *if_combination; - -+ if (rt2x00dev->ops->max_ap_intf < 2) -+ return; -+ - /* - * Build up AP interface limits structure. - */ -From 87cac8f879a5ecd7109dbe688087e8810b3364eb Mon Sep 17 00:00:00 2001 -From: Christian Borntraeger -Date: Tue, 2 Oct 2012 16:25:38 +0200 -Subject: s390/kvm: dont announce RRBM support - -From: Christian Borntraeger - -commit 87cac8f879a5ecd7109dbe688087e8810b3364eb upstream. - -Newer kernels (linux-next with the transparent huge page patches) -use rrbm if the feature is announced via feature bit 66. -RRBM will cause intercepts, so KVM does not handle it right now, -causing an illegal instruction in the guest. -The easy solution is to disable the feature bit for the guest. - -This fixes bugs like: -Kernel BUG at 0000000000124c2a [verbose debug info unavailable] -illegal operation: 0001 [#1] SMP -Modules linked in: virtio_balloon virtio_net ipv6 autofs4 -CPU: 0 Not tainted 3.5.4 #1 -Process fmempig (pid: 659, task: 000000007b712fd0, ksp: 000000007bed3670) -Krnl PSW : 0704d00180000000 0000000000124c2a (pmdp_clear_flush_young+0x5e/0x80) - R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3 - 00000000003cc000 0000000000000004 0000000000000000 0000000079800000 - 0000000000040000 0000000000000000 000000007bed3918 000000007cf40000 - 0000000000000001 000003fff7f00000 000003d281a94000 000000007bed383c - 000000007bed3918 00000000005ecbf8 00000000002314a6 000000007bed36e0 - Krnl Code:>0000000000124c2a: b9810025 ogr %r2,%r5 - 0000000000124c2e: 41343000 la %r3,0(%r4,%r3) - 0000000000124c32: a716fffa brct %r1,124c26 - 0000000000124c36: b9010022 lngr %r2,%r2 - 0000000000124c3a: e3d0f0800004 lg %r13,128(%r15) - 0000000000124c40: eb22003f000c srlg %r2,%r2,63 -[ 2150.713198] Call Trace: -[ 2150.713223] ([<00000000002312c4>] page_referenced_one+0x6c/0x27c) -[ 2150.713749] [<0000000000233812>] page_referenced+0x32a/0x410 -[...] - -Signed-off-by: Martin Schwidefsky -CC: Alex Graf -Signed-off-by: Christian Borntraeger -Signed-off-by: Marcelo Tosatti -Signed-off-by: Greg Kroah-Hartman - ---- - arch/s390/kvm/kvm-s390.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/s390/kvm/kvm-s390.c -+++ b/arch/s390/kvm/kvm-s390.c -@@ -997,7 +997,7 @@ static int __init kvm_s390_init(void) - } - memcpy(facilities, S390_lowcore.stfle_fac_list, 16); - facilities[0] &= 0xff00fff3f47c0000ULL; -- facilities[1] &= 0x201c000000000000ULL; -+ facilities[1] &= 0x001c000000000000ULL; - return 0; - } - -From ce6a04ac1b759beafc88dbc443ae5da867579eeb Mon Sep 17 00:00:00 2001 -From: Christian Borntraeger -Date: Thu, 15 Nov 2012 09:35:16 +0100 -Subject: s390/kvm: Fix address space mixup - -From: Christian Borntraeger - -commit ce6a04ac1b759beafc88dbc443ae5da867579eeb upstream. - -I was chasing down a bug of random validity intercepts on s390. -(guest prefix page not mapped in the host virtual aspace). Turns out -that the problem was a wrong address space control element. The -cause was quite complex: - -During paging activity a DAT protection during SIE caused a program -interrupt. Normally, the sie retry loop tries to catch all -interrupts during and shortly before sie to rerun the setup. The -problem is now that protection causes a suppressing program interrupt, -causing the PSW to point to the instruction AFTER SIE in case of DAT -protection. This confused the logic of the retry loop to not trigger, -instead we jumped directly back to SIE after return from -the program interrupt. (the protection fault handler itself did -a rewind of the psw). This usually works quite well, but: - -If now the protection fault handler has to wait, another program -might be scheduled in. Later on the sie process will be schedules -in again. In that case the content of CR1 (primary address space) -will be wrong because switch_to will put the user space ASCE into CR1 -and not the guest ASCE. - -In addition the program parameter is also wrong for every protection -fault of a guest, since we dont issue the SPP instruction. - -So lets also check for PSW == instruction after SIE in the program -check handler. Instead of expensively checking all program -interruption codes that might be suppressing we assume that a program -interrupt pointing after SIE was always a program interrupt in SIE. -(Otherwise we have a kernel bug anyway). - -We also have to compensate the rewinding, since the C-level handlers -will do that. Therefore we need to add a nop with the same length -as SIE before the sie_loop. - -Signed-off-by: Christian Borntraeger -Signed-off-by: Martin Schwidefsky -CC: Heiko Carstens -Signed-off-by: Greg Kroah-Hartman - ---- - arch/s390/kernel/entry64.S | 25 ++++++++++++++++++++----- - 1 file changed, 20 insertions(+), 5 deletions(-) - ---- a/arch/s390/kernel/entry64.S -+++ b/arch/s390/kernel/entry64.S -@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_ - #endif - .endm - -- .macro HANDLE_SIE_INTERCEPT scratch -+ .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck - #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) - tmhh %r8,0x0001 # interrupting from user ? - jnz .+42 - lgr \scratch,%r9 - slg \scratch,BASED(.Lsie_loop) - clg \scratch,BASED(.Lsie_length) -+ .if \pgmcheck -+ # Some program interrupts are suppressing (e.g. protection). -+ # We must also check the instruction after SIE in that case. -+ # do_protection_exception will rewind to rewind_pad -+ jh .+22 -+ .else - jhe .+22 -+ .endif - lg %r9,BASED(.Lsie_loop) - SPP BASED(.Lhost_id) # set host id - #endif -@@ -391,7 +398,7 @@ ENTRY(pgm_check_handler) - lg %r12,__LC_THREAD_INFO - larl %r13,system_call - lmg %r8,%r9,__LC_PGM_OLD_PSW -- HANDLE_SIE_INTERCEPT %r14 -+ HANDLE_SIE_INTERCEPT %r14,1 - tmhh %r8,0x0001 # test problem state bit - jnz 1f # -> fault in user space - tmhh %r8,0x4000 # PER bit set in old PSW ? -@@ -467,7 +474,7 @@ ENTRY(io_int_handler) - lg %r12,__LC_THREAD_INFO - larl %r13,system_call - lmg %r8,%r9,__LC_IO_OLD_PSW -- HANDLE_SIE_INTERCEPT %r14 -+ HANDLE_SIE_INTERCEPT %r14,0 - SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT - tmhh %r8,0x0001 # interrupting from user? - jz io_skip -@@ -613,7 +620,7 @@ ENTRY(ext_int_handler) - lg %r12,__LC_THREAD_INFO - larl %r13,system_call - lmg %r8,%r9,__LC_EXT_OLD_PSW -- HANDLE_SIE_INTERCEPT %r14 -+ HANDLE_SIE_INTERCEPT %r14,0 - SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT - tmhh %r8,0x0001 # interrupting from user ? - jz ext_skip -@@ -661,7 +668,7 @@ ENTRY(mcck_int_handler) - lg %r12,__LC_THREAD_INFO - larl %r13,system_call - lmg %r8,%r9,__LC_MCK_OLD_PSW -- HANDLE_SIE_INTERCEPT %r14 -+ HANDLE_SIE_INTERCEPT %r14,0 - tm __LC_MCCK_CODE,0x80 # system damage? - jo mcck_panic # yes -> rest of mcck code invalid - lghi %r14,__LC_CPU_TIMER_SAVE_AREA -@@ -960,6 +967,13 @@ ENTRY(sie64a) - stg %r3,__SF_EMPTY+8(%r15) # save guest register save area - xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 - lmg %r0,%r13,0(%r3) # load guest gprs 0-13 -+# some program checks are suppressing. C code (e.g. do_protection_exception) -+# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other -+# instructions in the sie_loop should not cause program interrupts. So -+# lets use a nop (47 00 00 00) as a landing pad. -+# See also HANDLE_SIE_INTERCEPT -+rewind_pad: -+ nop 0 - sie_loop: - lg %r14,__LC_THREAD_INFO # pointer thread_info struct - tm __TI_flags+7(%r14),_TIF_EXIT_SIE -@@ -999,6 +1013,7 @@ sie_fault: - .Lhost_id: - .quad 0 - -+ EX_TABLE(rewind_pad,sie_fault) - EX_TABLE(sie_loop,sie_fault) - #endif - -From 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 Mon Sep 17 00:00:00 2001 -From: Anton Blanchard -Date: Sun, 11 Nov 2012 19:01:05 +0000 -Subject: powerpc: Fix CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n build - -From: Anton Blanchard - -commit 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 upstream. - -If we build a kernel with CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n, -the kernel fails when we run at a non zero offset. It turns out -we were incorrectly wrapping some of the relocatable kernel code -with CONFIG_CRASH_DUMP. - -Signed-off-by: Anton Blanchard -Signed-off-by: Benjamin Herrenschmidt -Signed-off-by: Greg Kroah-Hartman - ---- - arch/powerpc/kernel/head_64.S | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/powerpc/kernel/head_64.S -+++ b/arch/powerpc/kernel/head_64.S -@@ -422,7 +422,7 @@ _STATIC(__after_prom_start) - tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ - #endif - --#ifdef CONFIG_CRASH_DUMP -+#ifdef CONFIG_RELOCATABLE - /* - * Check if the kernel has to be running as relocatable kernel based on the - * variable __run_at_load, if it is set the kernel is treated as relocatable -From ce73ec6db47af84d1466402781ae0872a9e7873c Mon Sep 17 00:00:00 2001 -From: Shan Hai -Date: Thu, 8 Nov 2012 15:57:49 +0000 -Subject: powerpc/vdso: Remove redundant locking in update_vsyscall_tz() - -From: Shan Hai - -commit ce73ec6db47af84d1466402781ae0872a9e7873c upstream. - -The locking in update_vsyscall_tz() is not only unnecessary because the vdso -code copies the data unproteced in __kernel_gettimeofday() but also -introduces a hard to reproduce race condition between update_vsyscall() -and update_vsyscall_tz(), which causes user space process to loop -forever in vdso code. - -The following patch removes the locking from update_vsyscall_tz(). - -Locking is not only unnecessary because the vdso code copies the data -unprotected in __kernel_gettimeofday() but also erroneous because updating -the tb_update_count is not atomic and introduces a hard to reproduce race -condition between update_vsyscall() and update_vsyscall_tz(), which further -causes user space process to loop forever in vdso code. - -The below scenario describes the race condition, -x==0 Boot CPU other CPU - proc_P: x==0 - timer interrupt - update_vsyscall -x==1 x++;sync settimeofday - update_vsyscall_tz -x==2 x++;sync -x==3 sync;x++ - sync;x++ - proc_P: x==3 (loops until x becomes even) - -Because the ++ operator would be implemented as three instructions and not -atomic on powerpc. - -A similar change was made for x86 in commit 6c260d58634 -("x86: vdso: Remove bogus locking in update_vsyscall_tz") - -Signed-off-by: Shan Hai -Signed-off-by: Benjamin Herrenschmidt -Signed-off-by: Greg Kroah-Hartman - ---- - arch/powerpc/kernel/time.c | 5 ----- - 1 file changed, 5 deletions(-) - ---- a/arch/powerpc/kernel/time.c -+++ b/arch/powerpc/kernel/time.c -@@ -774,13 +774,8 @@ void update_vsyscall_old(struct timespec - - void update_vsyscall_tz(void) - { -- /* Make userspace gettimeofday spin until we're done. */ -- ++vdso_data->tb_update_count; -- smp_mb(); - vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; - vdso_data->tz_dsttime = sys_tz.tz_dsttime; -- smp_mb(); -- ++vdso_data->tb_update_count; - } - - static void __init clocksource_init(void) -From e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 20 Dec 2012 03:44:28 +0000 -Subject: powerpc: Add missing NULL terminator to avoid boot panic on PPC40x - -From: Gabor Juhos - -commit e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b upstream. - -The missing NULL terminator can cause a panic on -PPC405 boards during boot: - - Linux/PowerPC load: console=ttyS0,115200 root=/dev/mtdblock1 rootfstype=squashfs,jffs2 noinitrd init=/etc/preinit - Finalizing device tree... flat tree at 0x6a5160 - bootconsole [udbg0] enabled - Page fault in user mode with in_atomic() = 1 mm = (null) - NIP = c0275f50 MSR = fffffffe - Oops: Weird page fault, sig: 11 [#1] - PowerPC 40x Platform - Modules linked in: - NIP: c0275f50 LR: c0275f60 CTR: c0280000 - REGS: c0275eb0 TRAP: 636f7265 Not tainted (3.7.1) - MSR: fffffffe CR: c06a6190 XER: 00000001 - TASK = c02662a8[0] 'swapper' THREAD: c0274000 - GPR00: c0275ec0 c000c658 c027c4bf 00000000 c0275ee0 c000a0ec c020a1a8 c020a1f0 - GPR08: c020f631 c020f404 c025f078 c025f080 c0275f10 - Call Trace: - ---[ end trace 31fd0ba7d8756001 ]--- - - Kernel panic - not syncing: Attempted to kill the idle task! - -The panic happens since commit 9597abe00c1bab2aedce6b49866bf6d1e81c9eed -(sections: fix section conflicts in arch/powerpc), however the root -cause of this is that the NULL terminator were not added in commit -a4f740cf33f7f6c164bbde3c0cdbcc77b0c4997c (of/flattree: Add of_flat_dt_match() -helper function). - -Signed-off-by: Gabor Juhos -Cc: Grant Likely -Signed-off-by: Benjamin Herrenschmidt -Signed-off-by: Greg Kroah-Hartman - ---- - arch/powerpc/platforms/40x/ppc40x_simple.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/powerpc/platforms/40x/ppc40x_simple.c -+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c -@@ -57,7 +57,8 @@ static const char * const board[] __init - "amcc,makalu", - "apm,klondike", - "est,hotfoot", -- "plathome,obs600" -+ "plathome,obs600", -+ NULL - }; - - static int __init ppc40x_probe(void) -From e400e72f250d2567e89c9bafb47ab91e8d9a15a2 Mon Sep 17 00:00:00 2001 -From: Scott Wood -Date: Wed, 22 Aug 2012 15:04:23 +0000 -Subject: KVM: PPC: e500: fix allocation size error on g2h_tlb1_map - -From: Scott Wood - -commit e400e72f250d2567e89c9bafb47ab91e8d9a15a2 upstream. - -We were only allocating half the bytes we need, which was made more -obvious by a recent fix to the memset in clear_tlb1_bitmap(). - -Signed-off-by: Scott Wood -Signed-off-by: Alexander Graf -Signed-off-by: Greg Kroah-Hartman - ---- - arch/powerpc/kvm/e500_tlb.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/powerpc/kvm/e500_tlb.c -+++ b/arch/powerpc/kvm/e500_tlb.c -@@ -1332,7 +1332,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_v - if (!vcpu_e500->gtlb_priv[1]) - goto err; - -- vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) * -+ vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) * - vcpu_e500->gtlb_params[1].entries, - GFP_KERNEL); - if (!vcpu_e500->g2h_tlb1_map) -From 5419369ed6bd4cf711fdda5e52a5999b940413f5 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Thu, 29 Nov 2012 14:07:59 -0700 -Subject: KVM: Fix user memslot overlap check - -From: Alex Williamson - -commit 5419369ed6bd4cf711fdda5e52a5999b940413f5 upstream. - -Prior to memory slot sorting this loop compared all of the user memory -slots for overlap with new entries. With memory slot sorting, we're -just checking some number of entries in the array that may or may not -be user slots. Instead, walk all the slots with kvm_for_each_memslot, -which has the added benefit of terminating early when we hit the first -empty slot, and skip comparison to private slots. - -Signed-off-by: Alex Williamson -Signed-off-by: Marcelo Tosatti -Signed-off-by: Greg Kroah-Hartman - ---- - virt/kvm/kvm_main.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -709,8 +709,7 @@ int __kvm_set_memory_region(struct kvm * - int r; - gfn_t base_gfn; - unsigned long npages; -- unsigned long i; -- struct kvm_memory_slot *memslot; -+ struct kvm_memory_slot *memslot, *slot; - struct kvm_memory_slot old, new; - struct kvm_memslots *slots, *old_memslots; - -@@ -761,13 +760,11 @@ int __kvm_set_memory_region(struct kvm * - - /* Check for overlaps */ - r = -EEXIST; -- for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { -- struct kvm_memory_slot *s = &kvm->memslots->memslots[i]; -- -- if (s == memslot || !s->npages) -+ kvm_for_each_memslot(slot, kvm->memslots) { -+ if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot) - continue; -- if (!((base_gfn + npages <= s->base_gfn) || -- (base_gfn >= s->base_gfn + s->npages))) -+ if (!((base_gfn + npages <= slot->base_gfn) || -+ (base_gfn >= slot->base_gfn + slot->npages))) - goto out_free; - } - -From d99e79ec5574fc556c988f613ed6175f6de66f4a Mon Sep 17 00:00:00 2001 -From: Sebastian Ott -Date: Fri, 30 Nov 2012 16:48:59 +0100 -Subject: s390/cio: fix pgid reserved check - -From: Sebastian Ott - -commit d99e79ec5574fc556c988f613ed6175f6de66f4a upstream. - -The check to whom a device is reserved is done by checking the path -state of the affected channel paths. If it turns out that one path is -flagged as reserved by someone else the whole device is marked as such. - -However the meaning of the RESVD_ELSE bit is that the addressed device -is reserved to a different pathgroup (and not reserved to a different -LPAR). If we do this test on a path which is currently not a member of -the pathgroup we could erroneously mark the device as reserved to -someone else. - -To fix this collect the reserved state for all potential members of the -pathgroup and only mark the device as reserved if all of those potential -members have the RESVD_ELSE bit set. - -Acked-by: Peter Oberparleiter -Signed-off-by: Sebastian Ott -Signed-off-by: Martin Schwidefsky -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/s390/cio/device_pgid.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/s390/cio/device_pgid.c -+++ b/drivers/s390/cio/device_pgid.c -@@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, str - * Determine pathgroup state from PGID data. - */ - static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, -- int *mismatch, int *reserved, u8 *reset) -+ int *mismatch, u8 *reserved, u8 *reset) - { - struct pgid *pgid = &cdev->private->pgid[0]; - struct pgid *first = NULL; -@@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_devi - if ((cdev->private->pgid_valid_mask & lpm) == 0) - continue; - if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE) -- *reserved = 1; -+ *reserved |= lpm; - if (pgid_is_reset(pgid)) { - *reset |= lpm; - continue; -@@ -316,14 +316,14 @@ static void snid_done(struct ccw_device - struct subchannel *sch = to_subchannel(cdev->dev.parent); - struct pgid *pgid; - int mismatch = 0; -- int reserved = 0; -+ u8 reserved = 0; - u8 reset = 0; - u8 donepm; - - if (rc) - goto out; - pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset); -- if (reserved) -+ if (reserved == cdev->private->pgid_valid_mask) - rc = -EUSERS; - else if (mismatch) - rc = -EOPNOTSUPP; -@@ -336,7 +336,7 @@ static void snid_done(struct ccw_device - } - out: - CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x " -- "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid, -+ "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid, - id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm, - cdev->private->pgid_todo_mask, mismatch, reserved, reset); - switch (rc) { -From 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 Mon Sep 17 00:00:00 2001 -From: Huacai Chen -Date: Mon, 13 Aug 2012 20:52:24 +0800 -Subject: MIPS: Fix poweroff failure when HOTPLUG_CPU configured. - -From: Huacai Chen - -commit 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 upstream. - -When poweroff machine, kernel_power_off() call disable_nonboot_cpus(). -And if we have HOTPLUG_CPU configured, disable_nonboot_cpus() is not an -empty function but attempt to actually disable the nonboot cpus. Since -system state is SYSTEM_POWER_OFF, play_dead() won't be called and thus -disable_nonboot_cpus() hangs. Therefore, we make this patch to avoid -poweroff failure. - -Signed-off-by: Huacai Chen -Signed-off-by: Hongliang Tao -Signed-off-by: Hua Yan -Cc: Yong Zhang -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/4211/ -Signed-off-by: Ralf Baechle -Signed-off-by: Greg Kroah-Hartman - ---- - arch/mips/kernel/process.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/arch/mips/kernel/process.c -+++ b/arch/mips/kernel/process.c -@@ -72,9 +72,7 @@ void __noreturn cpu_idle(void) - } - } - #ifdef CONFIG_HOTPLUG_CPU -- if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && -- (system_state == SYSTEM_RUNNING || -- system_state == SYSTEM_BOOTING)) -+ if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map)) - play_dead(); - #endif - rcu_idle_exit(); -From 7964c06d66c76507d8b6b662bffea770c29ef0ce Mon Sep 17 00:00:00 2001 -From: Jason Liu -Date: Fri, 11 Jan 2013 14:31:47 -0800 -Subject: mm: compaction: fix echo 1 > compact_memory return error issue - -From: Jason Liu - -commit 7964c06d66c76507d8b6b662bffea770c29ef0ce upstream. - -when run the folloing command under shell, it will return error - - sh/$ echo 1 > /proc/sys/vm/compact_memory - sh/$ sh: write error: Bad address - -After strace, I found the following log: - - ... - write(1, "1\n", 2) = 3 - write(1, "", 4294967295) = -1 EFAULT (Bad address) - write(2, "echo: write error: Bad address\n", 31echo: write error: Bad address - ) = 31 - -This tells system return 3(COMPACT_COMPLETE) after write data to -compact_memory. - -The fix is to make the system just return 0 instead 3(COMPACT_COMPLETE) -from sysctl_compaction_handler after compaction_nodes finished. - -Signed-off-by: Jason Liu -Suggested-by: David Rientjes -Acked-by: Mel Gorman -Cc: Rik van Riel -Cc: Minchan Kim -Cc: KAMEZAWA Hiroyuki -Acked-by: David Rientjes -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - mm/compaction.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/mm/compaction.c -+++ b/mm/compaction.c -@@ -1174,7 +1174,7 @@ static int compact_node(int nid) - } - - /* Compact all nodes in the system */ --static int compact_nodes(void) -+static void compact_nodes(void) - { - int nid; - -@@ -1183,8 +1183,6 @@ static int compact_nodes(void) - - for_each_online_node(nid) - compact_node(nid); -- -- return COMPACT_COMPLETE; - } - - /* The written value is actually unused, all memory is compacted */ -@@ -1195,7 +1193,7 @@ int sysctl_compaction_handler(struct ctl - void __user *buffer, size_t *length, loff_t *ppos) - { - if (write) -- return compact_nodes(); -+ compact_nodes(); - - return 0; - } -From c060f943d0929f3e429c5d9522290584f6281d6e Mon Sep 17 00:00:00 2001 -From: Laura Abbott -Date: Fri, 11 Jan 2013 14:31:51 -0800 -Subject: mm: use aligned zone start for pfn_to_bitidx calculation - -From: Laura Abbott - -commit c060f943d0929f3e429c5d9522290584f6281d6e upstream. - -The current calculation in pfn_to_bitidx assumes that (pfn - -zone->zone_start_pfn) >> pageblock_order will return the same bit for -all pfn in a pageblock. If zone_start_pfn is not aligned to -pageblock_nr_pages, this may not always be correct. - -Consider the following with pageblock order = 10, zone start 2MB: - - pfn | pfn - zone start | (pfn - zone start) >> page block order - ---------------------------------------------------------------- - 0x26000 | 0x25e00 | 0x97 - 0x26100 | 0x25f00 | 0x97 - 0x26200 | 0x26000 | 0x98 - 0x26300 | 0x26100 | 0x98 - -This means that calling {get,set}_pageblock_migratetype on a single page -will not set the migratetype for the full block. Fix this by rounding -down zone_start_pfn when doing the bitidx calculation. - -For our use case, the effects of this bug were mostly tied to the fact -that CMA allocations would either take a long time or fail to happen. -Depending on the driver using CMA, this could result in anything from -visual glitches to application failures. - -Signed-off-by: Laura Abbott -Acked-by: Mel Gorman -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - mm/page_alloc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -5506,7 +5506,7 @@ static inline int pfn_to_bitidx(struct z - pfn &= (PAGES_PER_SECTION-1); - return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; - #else -- pfn = pfn - zone->zone_start_pfn; -+ pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); - return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; - #endif /* CONFIG_SPARSEMEM */ - } -From 10d73e655cef6e86ea8589dca3df4e495e4900b0 Mon Sep 17 00:00:00 2001 -From: Max Filippov -Date: Fri, 11 Jan 2013 14:31:52 -0800 -Subject: mm: bootmem: fix free_all_bootmem_core() with odd bitmap alignment - -From: Max Filippov - -commit 10d73e655cef6e86ea8589dca3df4e495e4900b0 upstream. - -Currently free_all_bootmem_core ignores that node_min_pfn may be not -multiple of BITS_PER_LONG. Eg commit 6dccdcbe2c3e ("mm: bootmem: fix -checking the bitmap when finally freeing bootmem") shifts vec by lower -bits of start instead of lower bits of idx. Also - - if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) - -assumes that vec bit 0 corresponds to start pfn, which is only true when -node_min_pfn is a multiple of BITS_PER_LONG. Also loop in the else -clause can double-free pages (e.g. with node_min_pfn == start == 1, -map[0] == ~0 on 32-bit machine page 32 will be double-freed). - -This bug causes the following message during xtensa kernel boot: - - bootmem::free_all_bootmem_core nid=0 start=1 end=8000 - BUG: Bad page state in process swapper pfn:00001 - page:d04bd020 count:0 mapcount:-127 mapping: (null) index:0x2 - page flags: 0x0() - Call Trace: - bad_page+0x8c/0x9c - free_pages_prepare+0x5e/0x88 - free_hot_cold_page+0xc/0xa0 - __free_pages+0x24/0x38 - __free_pages_bootmem+0x54/0x56 - free_all_bootmem_core$part$11+0xeb/0x138 - free_all_bootmem+0x46/0x58 - mem_init+0x25/0xa4 - start_kernel+0x11e/0x25c - should_never_return+0x0/0x3be7 - -The fix is the following: - - always align vec so that its bit 0 corresponds to start - - provide BITS_PER_LONG bits in vec, if those bits are available in the - map - - don't free pages past next start position in the else clause. - -Signed-off-by: Max Filippov -Cc: Gavin Shan -Cc: Johannes Weiner -Cc: Tejun Heo -Cc: Yinghai Lu -Cc: Joonsoo Kim -Cc: Prasad Koya -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - mm/bootmem.c | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - ---- a/mm/bootmem.c -+++ b/mm/bootmem.c -@@ -185,10 +185,23 @@ static unsigned long __init free_all_boo - - while (start < end) { - unsigned long *map, idx, vec; -+ unsigned shift; - - map = bdata->node_bootmem_map; - idx = start - bdata->node_min_pfn; -+ shift = idx & (BITS_PER_LONG - 1); -+ /* -+ * vec holds at most BITS_PER_LONG map bits, -+ * bit 0 corresponds to start. -+ */ - vec = ~map[idx / BITS_PER_LONG]; -+ -+ if (shift) { -+ vec >>= shift; -+ if (end - start >= BITS_PER_LONG) -+ vec |= ~map[idx / BITS_PER_LONG + 1] << -+ (BITS_PER_LONG - shift); -+ } - /* - * If we have a properly aligned and fully unreserved - * BITS_PER_LONG block of pages in front of us, free -@@ -201,19 +214,18 @@ static unsigned long __init free_all_boo - count += BITS_PER_LONG; - start += BITS_PER_LONG; - } else { -- unsigned long off = 0; -+ unsigned long cur = start; - -- vec >>= start & (BITS_PER_LONG - 1); -- while (vec) { -+ start = ALIGN(start + 1, BITS_PER_LONG); -+ while (vec && cur != start) { - if (vec & 1) { -- page = pfn_to_page(start + off); -+ page = pfn_to_page(cur); - __free_pages_bootmem(page, 0); - count++; - } - vec >>= 1; -- off++; -+ ++cur; - } -- start = ALIGN(start + 1, BITS_PER_LONG); - } - } - -From 1680260226a8fd2aab590319da83ad8e610da9bd Mon Sep 17 00:00:00 2001 -From: Rajkumar Manoharan -Date: Thu, 25 Oct 2012 17:11:31 +0530 -Subject: ath9k_hw: Enable hw PLL power save for AR9462 - -From: Rajkumar Manoharan - -commit 1680260226a8fd2aab590319da83ad8e610da9bd upstream. - -This reduced the power consumption to half in full and network sleep. - -Signed-off-by: Rajkumar Manoharan -Cc: Paul Stewart -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c -@@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(str - - /* Awake -> Sleep Setting */ - INIT_INI_ARRAY(&ah->iniPcieSerdes, -- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); -+ ar9462_pciephy_clkreq_disable_L1_2p0); - /* Sleep -> Awake Setting */ - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, -- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); -+ ar9462_pciephy_clkreq_disable_L1_2p0); - - /* Fast clock modal settings */ - INIT_INI_ARRAY(&ah->iniModesFastClock, -From 9c170e068636deb3e3f96114034bb711675f0faa Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 6 Dec 2012 18:40:11 +0100 -Subject: Revert "ath9k_hw: Update AR9003 high_power tx gain table" - -From: Felix Fietkau - -commit 9c170e068636deb3e3f96114034bb711675f0faa upstream. - -This reverts commit f74b9d365ddd33a375802b064f96a5d0e99af7c0. - -Turns out reverting commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd -"ath9k_hw: Updated AR9003 tx gain table for 5GHz" was not enough to -bring the tx power back to normal levels on devices like the -Buffalo WZR-HP-G450H, this one needs to be reverted as well. - -This revert improves tx power by ~10 db on that device - -Signed-off-by: Felix Fietkau -Cc: rmanohar@qca.qualcomm.com -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 172 +++++++++---------- - 1 file changed, 86 insertions(+), 86 deletions(-) - ---- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h -+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h -@@ -534,98 +534,98 @@ static const u32 ar9300_2p2_baseband_cor - - static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, -- {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, -- {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, -+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, -+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, -+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, -- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, -- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, -- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, -- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, -- {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, -- {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, -- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, -- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, -- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, -- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, -- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, -- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, -- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, -- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, -- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, -- {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, -- {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, -- {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, -- {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, -- {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, -- {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, -- {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, -- {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, -- {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, -- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, -- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, -- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, -- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, -- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, -- {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, -- {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, -- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, -- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, -- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, -- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, -- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, -- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, -- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, -- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, -- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, -- {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, -- {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, -- {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, -- {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, -- {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, -- {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, -- {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, -- {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, -- {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -- {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, -+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, -- {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, -- {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, -- {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, -- {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, -- {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, -- {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -- {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -- {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -- {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -- {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -- {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, -- {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, -- {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, -+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, -+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, -+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, -+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, -+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, -+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, -+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, -+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, -+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, -+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -- {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, -- {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, -- {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, -+ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, -+ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, -+ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, -From b3cd8021379306c0be6932e4d3b4b01efc681769 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Sun, 9 Dec 2012 23:57:09 +0100 -Subject: ath9k: ar9003: fix OTP register offsets for AR9340 - -From: Gabor Juhos - -commit b3cd8021379306c0be6932e4d3b4b01efc681769 upstream. - -Trying to access the OTP memory on the AR9340 -causes a data bus error like this: - - Data bus error, epc == 86e84164, ra == 86e84164 - Oops[#1]: - Cpu 0 - $ 0 : 00000000 00000061 deadc0de 00000000 - $ 4 : b8115f18 00015f18 00000007 00000004 - $ 8 : 00000001 7c7c3c7c 7c7c7c7c 7c7c7c7c - $12 : 7c7c3c7c 001f0041 00000000 7c7c7c3c - $16 : 86ee0000 00015f18 00000000 00000007 - $20 : 00000004 00000064 00000004 86d71c44 - $24 : 00000000 86e6ca00 - $28 : 86d70000 86d71b20 86ece0c0 86e84164 - Hi : 00000000 - Lo : 00000064 - epc : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] - Tainted: G O - ra : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] - Status: 1100d403 KERNEL EXL IE - Cause : 4080801c - PrId : 0001974c (MIPS 74Kc) - Modules linked in: ath9k(O+) ath9k_common(O) ath9k_hw(O) ath(O) ar934x_nfc - mac80211(O) usbcore usb_common scsi_mod nls_base nand nand_ecc nand_ids - crc_ccitt cfg80211(O) compat(O) arc4 aes_generic crypto_blkcipher cryptomgr - aead crypto_hash crypto_algapi ledtrig_timer ledtrig_default_on leds_gpio - Process insmod (pid: 459, threadinfo=86d70000, task=87942140, tls=779ac440) - Stack : 802fb500 000200da 804db150 804e0000 87816130 86ee0000 00010000 86d71b88 - 86d71bc0 00000004 00000003 86e9fcd0 80305300 0002c0d0 86e74c50 800b4c20 - 000003e8 00000001 00000000 86ee0000 000003ff 86e9fd64 80305300 80123938 - fffffffc 00000004 000058bc 00000000 86ea0000 86ee0000 000001ff 878d6000 - 99999999 86e9fdc0 86ee0fcc 86e9e664 0000c0d0 86ee0000 0000700000007000 - ... - Call Trace: - [<86e84164>] ath9k_hw_wait+0x58/0xb0 [ath9k_hw] - [<86e9fcd0>] ath9k_hw_setup_statusring+0x16b8/0x1c7c [ath9k_hw] - - Code: 0000a812 0040f809 00000000 <00531024> 1054000b 24020001 0c05b5dc 2404000a 26520001 - -The cause of the error is that the OTP register -offsets are different on the AR9340 than the -actually used values. - -Signed-off-by: Gabor Juhos -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h -+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h -@@ -68,13 +68,13 @@ - #define AR9300_BASE_ADDR 0x3ff - #define AR9300_BASE_ADDR_512 0x1ff - --#define AR9300_OTP_BASE 0x14000 --#define AR9300_OTP_STATUS 0x15f18 -+#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) -+#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) - #define AR9300_OTP_STATUS_TYPE 0x7 - #define AR9300_OTP_STATUS_VALID 0x4 - #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 - #define AR9300_OTP_STATUS_SM_BUSY 0x1 --#define AR9300_OTP_READ_DATA 0x15f1c -+#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) - - enum targetPowerHTRates { - HT_TARGET_RATE_0_8_16, -From b7c0c238898d200e80487516e2b67aba2a522cc0 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Mon, 10 Dec 2012 14:03:17 +0100 -Subject: ath9k_hw: Fix signal strength / channel noise reporting - -From: Felix Fietkau - -commit b7c0c238898d200e80487516e2b67aba2a522cc0 upstream. - -While AR_PHY_CCA_NOM_VAL_* does contain the expected internal noise floor -for a chip measured in clean air, it refers to the lowest expected reading. - -Depending on the frequency, this measurement can vary by about 6db, thus -causing a higher reported channel noise and signal strength. - -Factor in the 6db offset when converting internal noisefloor to channel noise. - -This patch makes the reported values more accurate for all chips without -affecting NF calibration behavior. - -Signed-off-by: Felix Fietkau -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath9k/calib.c | 1 + - drivers/net/wireless/ath/ath9k/calib.h | 3 +++ - 2 files changed, 4 insertions(+) - ---- a/drivers/net/wireless/ath/ath9k/calib.c -+++ b/drivers/net/wireless/ath/ath9k/calib.c -@@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw - - if (chan && chan->noisefloor) { - s8 delta = chan->noisefloor - -+ ATH9K_NF_CAL_NOISE_THRESH - - ath9k_hw_get_default_nf(ah, chan); - if (delta > 0) - noise += delta; ---- a/drivers/net/wireless/ath/ath9k/calib.h -+++ b/drivers/net/wireless/ath/ath9k/calib.h -@@ -21,6 +21,9 @@ - - #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 - -+/* Internal noise floor can vary by about 6db depending on the frequency */ -+#define ATH9K_NF_CAL_NOISE_THRESH 6 -+ - #define NUM_NF_READINGS 6 - #define ATH9K_NF_CAL_HIST_MAX 5 - -From a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 Mon Sep 17 00:00:00 2001 -From: Sujith Manoharan -Date: Wed, 26 Dec 2012 12:27:39 +0530 -Subject: ath9k_hw: Fix RX gain initvals for AR9485 - -From: Sujith Manoharan - -commit a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 upstream. - -Populate iniModesRxGain with the correct initvals -array for AR9485 v1.1 - -Signed-off-by: Sujith Manoharan -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/ath9k/ar9003_hw.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c -@@ -540,7 +540,7 @@ static void ar9003_rx_gain_table_mode0(s - ar9340Common_rx_gain_table_1p0); - else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485Common_wo_xlna_rx_gain_1_1); -+ ar9485_common_rx_gain_1_1); - else if (AR_SREV_9550(ah)) { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar955x_1p0_common_rx_gain_table); -From 5b632fe85ec82e5c43740b52e74c66df50a37db3 Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Mon, 3 Dec 2012 12:56:33 +0100 -Subject: mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL - -From: Stanislaw Gruszka - -commit 5b632fe85ec82e5c43740b52e74c66df50a37db3 upstream. - -Commit f0425beda4d404a6e751439b562100b902ba9c98 "mac80211: retry sending -failed BAR frames later instead of tearing down aggr" caused regression -on rt2x00 hardware (connection hangs). This regression was fixed by -commit be03d4a45c09ee5100d3aaaedd087f19bc20d01 "rt2x00: Don't let -mac80211 send a BAR when an AMPDU subframe fails". But the latter -commit caused yet another problem reported in -https://bugzilla.kernel.org/show_bug.cgi?id=42828#c22 - -After long discussion in this thread: -http://mid.gmane.org/20121018075615.GA18212@redhat.com -and testing various alternative solutions, which failed on one or other -setup, we have no other good fix for the issues like just revert both -mentioned earlier commits. - -To do not affect other hardware which benefit from commit -f0425beda4d404a6e751439b562100b902ba9c98, instead of reverting it, -introduce flag that when used will restore mac80211 behaviour before -the commit. - -Signed-off-by: Stanislaw Gruszka -[replaced link with mid.gmane.org that has message-id] -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - include/net/mac80211.h | 5 +++++ - net/mac80211/status.c | 6 +++++- - 2 files changed, 10 insertions(+), 1 deletion(-) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1253,6 +1253,10 @@ struct ieee80211_tx_control { - * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any - * P2P Interface. This will be honoured even if more than one interface - * is supported. -+ * -+ * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session -+ * should be tear down once BAR frame will not be acked. -+ * - */ - enum ieee80211_hw_flags { - IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, -@@ -1281,6 +1285,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, - IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, - IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, -+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26, - }; - - /** ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -432,7 +432,11 @@ void ieee80211_tx_status(struct ieee8021 - IEEE80211_BAR_CTRL_TID_INFO_MASK) >> - IEEE80211_BAR_CTRL_TID_INFO_SHIFT; - -- ieee80211_set_bar_pending(sta, tid, ssn); -+ if (local->hw.flags & -+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL) -+ ieee80211_stop_tx_ba_session(&sta->sta, tid); -+ else -+ ieee80211_set_bar_pending(sta, tid, ssn); - } - } - -From 6c653f66772c39c5e25db715bbd4730596fccd9e Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Sat, 22 Dec 2012 04:35:24 +0100 -Subject: carl9170: fix -EINVAL bailout during init with !CONFIG_MAC80211_MESH - -From: Christian Lamparter - -commit 6c653f66772c39c5e25db715bbd4730596fccd9e upstream. - -Sean reported that as of 3.7, his AR9170 device no longer works -because the driver fails during initialization. He noted this -is due to: -"In carl9170/fw.c, ar->hw->wiphy is tagged with -NL80211_IFTYPE_MESH_POINT support if the firmware has Content -after Beacon Queuing. This is both in interface_modes and the -only iface_combinations entry. - -If CONFIG_MAC80211_MESH is not set, ieee80211_register_hw -removes NL80211_IFTYPE_MESH_POINT from interface_modes, but -not iface_combinations. - -wiphy_register then checks to see if every interface type in -every interface combination is in interface_modes. -NL80211_IFTYPE_MESH_POINT was removed, so you get a WARN_ON -warning and it returns -EINVAL, giving up." - -Unfortunately, the iface_combination (types) feature bitmap -in ieee80211_iface_limit is part of a const member in the -ieee80211_iface_combination struct. Hence, the MESH_POINT -feature flag can't be masked by wiphy_register in the -same way as interface_modes in ieee80211_register_hw. - -Reported-by: Sean Patrick Santos -Signed-off-by: Christian Lamparter -Tested-by: Sean Patrick Santos -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/ath/carl9170/fw.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/carl9170/fw.c -+++ b/drivers/net/wireless/ath/carl9170/fw.c -@@ -341,8 +341,12 @@ static int carl9170_fw(struct ar9170 *ar - if (SUPP(CARL9170FW_WLANTX_CAB)) { - if_comb_types |= - BIT(NL80211_IFTYPE_AP) | -- BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_P2P_GO); -+ -+#ifdef CONFIG_MAC80211_MESH -+ if_comb_types |= -+ BIT(NL80211_IFTYPE_MESH_POINT); -+#endif /* CONFIG_MAC80211_MESH */ - } - } - -From 9d2373420900a39f5212a3b289331aa3535b1000 Mon Sep 17 00:00:00 2001 -From: Stephan Gatzka -Date: Wed, 28 Nov 2012 20:04:32 +0100 -Subject: firewire: net: Fix handling of fragmented multicast/broadcast packets. - -From: Stephan Gatzka - -commit 9d2373420900a39f5212a3b289331aa3535b1000 upstream. - -This patch fixes both the transmit and receive portion of sending -fragmented mutlicast and broadcast packets. - -The transmit section was broken because the offset for INTFRAG and -LASTFRAG packets were just miscalculated by IEEE1394_GASP_HDR_SIZE (which -was reserved with skb_push() in fwnet_send_packet). - -The receive section was broken because in fwnet_incoming_packet is a call -to fwnet_peer_find_by_node_id(). Called with generation == -1 it will -not find a peer and the partial datagrams are associated to a peer. - -[Stefan R: The fix to use context->card->generation is not perfect. -It relies on the IR tasklet which processes packets from the prior bus -generation to run before the self-ID-complete worklet which sets the -current card generation. Alas, there is no simple way of a race-free -implementation. Let's do it this way for now.] - -Signed-off-by: Stephan Gatzka -Signed-off-by: Stefan Richter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/firewire/net.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - ---- a/drivers/firewire/net.c -+++ b/drivers/firewire/net.c -@@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(stru - if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { - buf_ptr += 2; - length -= IEEE1394_GASP_HDR_SIZE; -- fwnet_incoming_packet(dev, buf_ptr, length, -- source_node_id, -1, true); -+ fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, -+ context->card->generation, true); - } - - packet.payload_length = dev->rcv_buffer_size; -@@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(s - break; - } - -- skb_pull(skb, ptask->max_payload); -+ if (ptask->dest_node == IEEE1394_ALL_NODES) { -+ skb_pull(skb, -+ ptask->max_payload + IEEE1394_GASP_HDR_SIZE); -+ } else { -+ skb_pull(skb, ptask->max_payload); -+ } - if (ptask->outstanding_pkts > 1) { - fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, - dg_size, fg_off, datagram_label); -@@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwne - smp_rmb(); - node_id = dev->card->node_id; - -- p = skb_push(ptask->skb, 8); -+ p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); - put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); - put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 - | RFC2734_SW_VERSION, &p[4]); -From 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Wed, 19 Dec 2012 20:51:31 +0100 -Subject: watchdog: Fix disable/enable regression - -From: Bjørn Mork - -commit 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 upstream. - -Commit 8d4516904b39 ("watchdog: Fix CPU hotplug regression") causes an -oops or hard lockup when doing - - echo 0 > /proc/sys/kernel/nmi_watchdog - echo 1 > /proc/sys/kernel/nmi_watchdog - -and the kernel is booted with nmi_watchdog=1 (default) - -Running laptop-mode-tools and disconnecting/connecting AC power will -cause this to trigger, making it a common failure scenario on laptops. - -Instead of bailing out of watchdog_disable() when !watchdog_enabled we -can initialize the hrtimer regardless of watchdog_enabled status. This -makes it safe to call watchdog_disable() in the nmi_watchdog=0 case, -without the negative effect on the enabled => disabled => enabled case. - -All these tests pass with this patch: -- nmi_watchdog=1 - echo 0 > /proc/sys/kernel/nmi_watchdog - echo 1 > /proc/sys/kernel/nmi_watchdog - -- nmi_watchdog=0 - echo 0 > /sys/devices/system/cpu/cpu1/online - -- nmi_watchdog=0 - echo mem > /sys/power/state - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51661 - -Signed-off-by: Bjørn Mork -Cc: Norbert Warmuth -Cc: Joseph Salisbury -Cc: Thomas Gleixner -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/watchdog.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - ---- a/kernel/watchdog.c -+++ b/kernel/watchdog.c -@@ -343,6 +343,10 @@ static void watchdog_enable(unsigned int - { - struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); - -+ /* kick off the timer for the hardlockup detector */ -+ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -+ hrtimer->function = watchdog_timer_fn; -+ - if (!watchdog_enabled) { - kthread_park(current); - return; -@@ -351,10 +355,6 @@ static void watchdog_enable(unsigned int - /* Enable the perf event */ - watchdog_nmi_enable(cpu); - -- /* kick off the timer for the hardlockup detector */ -- hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -- hrtimer->function = watchdog_timer_fn; -- - /* done here because hrtimer_start can only pin to smp_processor_id() */ - hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()), - HRTIMER_MODE_REL_PINNED); -@@ -368,9 +368,6 @@ static void watchdog_disable(unsigned in - { - struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); - -- if (!watchdog_enabled) -- return; -- - watchdog_set_prio(SCHED_NORMAL, 0); - hrtimer_cancel(hrtimer); - /* disable the perf event */ -From 72222be39afbd39c16eb180646b0ac44bb1ba460 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 28 Nov 2012 13:46:56 +0000 -Subject: ASoC: wm8994: Use the same DCS codes for all WM1811 variants - -From: Mark Brown - -commit 72222be39afbd39c16eb180646b0ac44bb1ba460 upstream. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm8994.c | 16 ++-------------- - 1 file changed, 2 insertions(+), 14 deletions(-) - ---- a/sound/soc/codecs/wm8994.c -+++ b/sound/soc/codecs/wm8994.c -@@ -3839,20 +3839,8 @@ static int wm8994_codec_probe(struct snd - wm8994->hubs.no_cache_dac_hp_direct = true; - wm8994->fll_byp = true; - -- switch (control->cust_id) { -- case 0: -- case 2: -- wm8994->hubs.dcs_codes_l = -9; -- wm8994->hubs.dcs_codes_r = -7; -- break; -- case 1: -- case 3: -- wm8994->hubs.dcs_codes_l = -8; -- wm8994->hubs.dcs_codes_r = -7; -- break; -- default: -- break; -- } -+ wm8994->hubs.dcs_codes_l = -9; -+ wm8994->hubs.dcs_codes_r = -7; - - snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, - WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); -From a3adb1432d7a3ad86bb17a1638e44414537e4118 Mon Sep 17 00:00:00 2001 -From: Lars-Peter Clausen -Date: Fri, 7 Dec 2012 18:30:51 +0100 -Subject: ASoC: sigmadsp: Fix endianness conversion issue - -From: Lars-Peter Clausen - -commit a3adb1432d7a3ad86bb17a1638e44414537e4118 upstream. - -The 'addr' field of the sigma_action struct is stored as big endian in the -firmware file. - -Signed-off-by: Lars-Peter Clausen -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/sigmadsp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/sound/soc/codecs/sigmadsp.c -+++ b/sound/soc/codecs/sigmadsp.c -@@ -225,7 +225,7 @@ EXPORT_SYMBOL(process_sigma_firmware); - static int sigma_action_write_regmap(void *control_data, - const struct sigma_action *sa, size_t len) - { -- return regmap_raw_write(control_data, le16_to_cpu(sa->addr), -+ return regmap_raw_write(control_data, be16_to_cpu(sa->addr), - sa->payload, len - 2); - } - -From f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa Mon Sep 17 00:00:00 2001 -From: Sangbeom Kim -Date: Sat, 24 Nov 2012 11:13:28 +0900 -Subject: regulator: s2mps11: Fix ramp delay value shift operation - -From: Sangbeom Kim - -commit f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa upstream. - -This patch fix the abnormal ramp delay setting. -The shift operation was wrong. - -Signed-off-by: Sangbeom Kim -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/regulator/s2mps11.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/regulator/s2mps11.c -+++ b/drivers/regulator/s2mps11.c -@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe( - - if (ramp_enable) { - if (s2mps11->buck2_ramp) -- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; -+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6; - if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) -- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; -+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4; - sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); - } - - ramp_reg &= 0x00; -- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6; -- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; -- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; -+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6; -+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4; -+ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2; - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); - sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); - -From beecadea1b8d67f591b13f7099559f32f3fd601d Mon Sep 17 00:00:00 2001 -From: Xi Wang -Date: Fri, 16 Nov 2012 14:40:03 -0500 -Subject: SCSI: mvsas: fix undefined bit shift - -From: Xi Wang - -commit beecadea1b8d67f591b13f7099559f32f3fd601d upstream. - -The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't work -with n >= 32, such as in mvs_94xx_assign_reg_set(): - - if (i >= 32) { - mvi->sata_reg_set |= bit(i); - ... - } - -The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior. -The result varies depending on the architecture. - -This patch changes bit(n) to do a 64-bit shift. It also simplifies -mv_ffc64() using __ffs64(), since invoking ffz() with ~0 is undefined. - -Signed-off-by: Xi Wang -Acked-by: Xiangliang Yu -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/mvsas/mv_94xx.h | 14 ++------------ - drivers/scsi/mvsas/mv_sas.h | 2 +- - 2 files changed, 3 insertions(+), 13 deletions(-) - ---- a/drivers/scsi/mvsas/mv_94xx.h -+++ b/drivers/scsi/mvsas/mv_94xx.h -@@ -258,21 +258,11 @@ enum sas_sata_phy_regs { - #define SPI_ADDR_VLD_94XX (1U << 1) - #define SPI_CTRL_SpiStart_94XX (1U << 0) - --#define mv_ffc(x) ffz(x) -- - static inline int - mv_ffc64(u64 v) - { -- int i; -- i = mv_ffc((u32)v); -- if (i >= 0) -- return i; -- i = mv_ffc((u32)(v>>32)); -- -- if (i != 0) -- return 32 + i; -- -- return -1; -+ u64 x = ~v; -+ return x ? __ffs64(x) : -1; - } - - #define r_reg_set_enable(i) \ ---- a/drivers/scsi/mvsas/mv_sas.h -+++ b/drivers/scsi/mvsas/mv_sas.h -@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_ - #define DEV_IS_EXPANDER(type) \ - ((type == EDGE_DEV) || (type == FANOUT_DEV)) - --#define bit(n) ((u32)1 << n) -+#define bit(n) ((u64)1 << n) - - #define for_each_phy(__lseq_mask, __mc, __lseq) \ - for ((__mc) = (__lseq_mask), (__lseq) = 0; \ -From 072f19b4bea31cdd482d79f805413f2f9ac9e233 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 15 Nov 2012 15:51:46 -0500 -Subject: SCSI: prevent stack buffer overflow in host_reset - -From: Sasha Levin - -commit 072f19b4bea31cdd482d79f805413f2f9ac9e233 upstream. - -store_host_reset() has tried to re-invent the wheel to compare sysfs strings. -Unfortunately it did so poorly and never bothered to check the input from -userspace before overwriting stack with it, so something simple as: - -echo "WoopsieWoopsie" > -/sys/devices/pseudo_0/adapter0/host0/scsi_host/host0/host_reset - -would result in: - -[ 316.310101] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81f5bac7 -[ 316.310101] -[ 316.320051] Pid: 6655, comm: sh Tainted: G W 3.7.0-rc5-next-20121114-sasha-00016-g5c9d68d-dirty #129 -[ 316.320051] Call Trace: -[ 316.340058] pps pps0: PPS event at 1352918752.620355751 -[ 316.340062] pps pps0: capture assert seq #303 -[ 316.320051] [] panic+0xcd/0x1f4 -[ 316.320051] [] ? store_host_reset+0xd7/0x100 -[ 316.320051] [] __stack_chk_fail+0x16/0x20 -[ 316.320051] [] store_host_reset+0xd7/0x100 -[ 316.320051] [] dev_attr_store+0x13/0x30 -[ 316.320051] [] sysfs_write_file+0x101/0x170 -[ 316.320051] [] vfs_write+0xb8/0x180 -[ 316.320051] [] sys_write+0x50/0xa0 -[ 316.320051] [] tracesys+0xe1/0xe6 - -Fix this by uninventing whatever was going on there and just use sysfs_streq. - -Bug introduced by 29443691 ("[SCSI] scsi: Added support for adapter and -firmware reset"). - -[jejb: added necessary const to prevent compile warnings] -Signed-off-by: Sasha Levin -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/scsi_sysfs.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - ---- a/drivers/scsi/scsi_sysfs.c -+++ b/drivers/scsi/scsi_sysfs.c -@@ -247,11 +247,11 @@ show_shost_active_mode(struct device *de - - static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); - --static int check_reset_type(char *str) -+static int check_reset_type(const char *str) - { -- if (strncmp(str, "adapter", 10) == 0) -+ if (sysfs_streq(str, "adapter")) - return SCSI_ADAPTER_RESET; -- else if (strncmp(str, "firmware", 10) == 0) -+ else if (sysfs_streq(str, "firmware")) - return SCSI_FIRMWARE_RESET; - else - return 0; -@@ -264,12 +264,9 @@ store_host_reset(struct device *dev, str - struct Scsi_Host *shost = class_to_shost(dev); - struct scsi_host_template *sht = shost->hostt; - int ret = -EINVAL; -- char str[10]; - int type; - -- sscanf(buf, "%s", str); -- type = check_reset_type(str); -- -+ type = check_reset_type(buf); - if (!type) - goto exit_store_host_reset; - -From 63ea923a97cb0d78efcbbd229950e101588f0ddb Mon Sep 17 00:00:00 2001 -From: Armen Baloyan -Date: Wed, 21 Nov 2012 02:39:53 -0500 -Subject: SCSI: qla2xxx: Properly set result field of bsg_job reply structure for success and failure. - -From: Armen Baloyan - -commit 63ea923a97cb0d78efcbbd229950e101588f0ddb upstream. - -FC transport on receiving bsg_job submission failure, calls bsg_job->job_done() -and sets the bsg_job->reply->result the returned value. In contrast, when the -success code (0) is returned fc transport doesn't call bsg_job->job_done() and -doesn't populate bsg_job->reply->result. - -Signed-off-by: Steve Hodgson -Signed-off-by: Armen Baloyan -Signed-off-by: Saurav Kashyap -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_bsg.c | 65 +++++++++++++++-------------------------- - 1 file changed, 24 insertions(+), 41 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_bsg.c -+++ b/drivers/scsi/qla2xxx/qla_bsg.c -@@ -219,7 +219,8 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_ - break; - } - exit_fcp_prio_cfg: -- bsg_job->job_done(bsg_job); -+ if (!ret) -+ bsg_job->job_done(bsg_job); - return ret; - } - -@@ -741,7 +742,6 @@ qla2x00_process_loopback(struct fc_bsg_j - if (qla81xx_get_port_config(vha, config)) { - ql_log(ql_log_warn, vha, 0x701f, - "Get port config failed.\n"); -- bsg_job->reply->result = (DID_ERROR << 16); - rval = -EPERM; - goto done_free_dma_req; - } -@@ -761,7 +761,6 @@ qla2x00_process_loopback(struct fc_bsg_j - new_config, elreq.options); - - if (rval) { -- bsg_job->reply->result = (DID_ERROR << 16); - rval = -EPERM; - goto done_free_dma_req; - } -@@ -795,7 +794,6 @@ qla2x00_process_loopback(struct fc_bsg_j - "MPI reset failed.\n"); - } - -- bsg_job->reply->result = (DID_ERROR << 16); - rval = -EIO; - goto done_free_dma_req; - } -@@ -812,33 +810,25 @@ qla2x00_process_loopback(struct fc_bsg_j - ql_log(ql_log_warn, vha, 0x702c, - "Vendor request %s failed.\n", type); - -- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + -- sizeof(struct fc_bsg_reply); -- -- memcpy(fw_sts_ptr, response, sizeof(response)); -- fw_sts_ptr += sizeof(response); -- *fw_sts_ptr = command_sent; - rval = 0; - bsg_job->reply->result = (DID_ERROR << 16); -+ bsg_job->reply->reply_payload_rcv_len = 0; - } else { - ql_dbg(ql_dbg_user, vha, 0x702d, - "Vendor request %s completed.\n", type); -- -- bsg_job->reply_len = sizeof(struct fc_bsg_reply) + -- sizeof(response) + sizeof(uint8_t); -- bsg_job->reply->reply_payload_rcv_len = -- bsg_job->reply_payload.payload_len; -- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + -- sizeof(struct fc_bsg_reply); -- memcpy(fw_sts_ptr, response, sizeof(response)); -- fw_sts_ptr += sizeof(response); -- *fw_sts_ptr = command_sent; -- bsg_job->reply->result = DID_OK; -+ bsg_job->reply->result = (DID_OK << 16); - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, rsp_data, - rsp_data_len); - } -- bsg_job->job_done(bsg_job); -+ -+ bsg_job->reply_len = sizeof(struct fc_bsg_reply) + -+ sizeof(response) + sizeof(uint8_t); -+ fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + -+ sizeof(struct fc_bsg_reply); -+ memcpy(fw_sts_ptr, response, sizeof(response)); -+ fw_sts_ptr += sizeof(response); -+ *fw_sts_ptr = command_sent; - - dma_free_coherent(&ha->pdev->dev, rsp_data_len, - rsp_data, rsp_data_dma); -@@ -853,6 +843,8 @@ done_unmap_req_sg: - dma_unmap_sg(&ha->pdev->dev, - bsg_job->request_payload.sg_list, - bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); -+ if (!rval) -+ bsg_job->job_done(bsg_job); - return rval; - } - -@@ -877,16 +869,15 @@ qla84xx_reset(struct fc_bsg_job *bsg_job - if (rval) { - ql_log(ql_log_warn, vha, 0x7030, - "Vendor request 84xx reset failed.\n"); -- rval = 0; -- bsg_job->reply->result = (DID_ERROR << 16); -+ rval = (DID_ERROR << 16); - - } else { - ql_dbg(ql_dbg_user, vha, 0x7031, - "Vendor request 84xx reset completed.\n"); - bsg_job->reply->result = DID_OK; -+ bsg_job->job_done(bsg_job); - } - -- bsg_job->job_done(bsg_job); - return rval; - } - -@@ -976,8 +967,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ - ql_log(ql_log_warn, vha, 0x7037, - "Vendor request 84xx updatefw failed.\n"); - -- rval = 0; -- bsg_job->reply->result = (DID_ERROR << 16); -+ rval = (DID_ERROR << 16); - } else { - ql_dbg(ql_dbg_user, vha, 0x7038, - "Vendor request 84xx updatefw completed.\n"); -@@ -986,7 +976,6 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ - bsg_job->reply->result = DID_OK; - } - -- bsg_job->job_done(bsg_job); - dma_pool_free(ha->s_dma_pool, mn, mn_dma); - - done_free_fw_buf: -@@ -996,6 +985,8 @@ done_unmap_sg: - dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, - bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); - -+ if (!rval) -+ bsg_job->job_done(bsg_job); - return rval; - } - -@@ -1163,8 +1154,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ - ql_log(ql_log_warn, vha, 0x7043, - "Vendor request 84xx mgmt failed.\n"); - -- rval = 0; -- bsg_job->reply->result = (DID_ERROR << 16); -+ rval = (DID_ERROR << 16); - - } else { - ql_dbg(ql_dbg_user, vha, 0x7044, -@@ -1184,8 +1174,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ - } - } - -- bsg_job->job_done(bsg_job); -- - done_unmap_sg: - if (mgmt_b) - dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma); -@@ -1200,6 +1188,8 @@ done_unmap_sg: - exit_mgmt: - dma_pool_free(ha->s_dma_pool, mn, mn_dma); - -+ if (!rval) -+ bsg_job->job_done(bsg_job); - return rval; - } - -@@ -1276,9 +1266,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job - fcport->port_name[3], fcport->port_name[4], - fcport->port_name[5], fcport->port_name[6], - fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]); -- rval = 0; -- bsg_job->reply->result = (DID_ERROR << 16); -- -+ rval = (DID_ERROR << 16); - } else { - if (!port_param->mode) { - bsg_job->reply_len = sizeof(struct fc_bsg_reply) + -@@ -1292,9 +1280,9 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job - } - - bsg_job->reply->result = DID_OK; -+ bsg_job->job_done(bsg_job); - } - -- bsg_job->job_done(bsg_job); - return rval; - } - -@@ -1887,8 +1875,6 @@ qla2x00_process_vendor_specific(struct f - return qla24xx_process_bidir_cmd(bsg_job); - - default: -- bsg_job->reply->result = (DID_ERROR << 16); -- bsg_job->job_done(bsg_job); - return -ENOSYS; - } - } -@@ -1919,8 +1905,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b - ql_dbg(ql_dbg_user, vha, 0x709f, - "BSG: ISP abort active/needed -- cmd=%d.\n", - bsg_job->request->msgcode); -- bsg_job->reply->result = (DID_ERROR << 16); -- bsg_job->job_done(bsg_job); - return -EBUSY; - } - -@@ -1943,7 +1927,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b - case FC_BSG_RPT_CT: - default: - ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n"); -- bsg_job->reply->result = ret; - break; - } - return ret; -From a394aac88506159e047630fc90dc2242568382d8 Mon Sep 17 00:00:00 2001 -From: David Jeffery -Date: Wed, 21 Nov 2012 02:39:54 -0500 -Subject: SCSI: qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically. - -From: David Jeffery - -commit a394aac88506159e047630fc90dc2242568382d8 upstream. - -When the qla2xxx driver loses access to multiple, remote ports, there is a race -condition which can occur which will keep the request stuck on a scsi request -queue indefinitely. - -This bad state occurred do to a race condition with how the FCPORT_UPDATE_NEEDED -bit is set in qla2x00_schedule_rport_del(), and how it is cleared in -qla2x00_do_dpc(). The problem port has its drport pointer set, but it has never -been processed by the driver to inform the fc transport that the port has been -lost. qla2x00_schedule_rport_del() sets drport, and then sets the -FCPORT_UPDATE_NEEDED bit. In qla2x00_do_dpc(), the port lists are walked and -any drport pointer is handled and the fc transport informed of the port loss, -then the FCPORT_UPDATE_NEEDED bit is cleared. This leaves a race where the -dpc thread is processing one port removal, another port removal is marked -with a call to qla2x00_schedule_rport_del(), and the dpc thread clears the -bit for both removals, even though only the first removal was actually -handled. Until another event occurs to set FCPORT_UPDATE_NEEDED, the later -port removal is never finished and qla2xxx stays in a bad state which causes -requests to become stuck on request queues. - -This patch updates the driver to test and clear FCPORT_UPDATE_NEEDED -atomically. This ensures the port state changes are processed and not lost. - -Signed-off-by: David Jeffery -Signed-off-by: Chad Dupuis -Signed-off-by: Saurav Kashyap -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_os.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -4505,9 +4505,9 @@ qla2x00_do_dpc(void *data) - "ISP abort end.\n"); - } - -- if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { -+ if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, -+ &base_vha->dpc_flags)) { - qla2x00_update_fcports(base_vha); -- clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); - } - - if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) { -From 220d36b4c2d96446e88d561714829ec5801b4fc7 Mon Sep 17 00:00:00 2001 -From: Giridhar Malavali -Date: Wed, 21 Nov 2012 02:39:55 -0500 -Subject: SCSI: qla2xxx: Change in setting UNLOADING flag and FC vports logout sequence while unloading qla2xxx driver. - -From: Giridhar Malavali - -commit 220d36b4c2d96446e88d561714829ec5801b4fc7 upstream. - -Signed-off-by: Giridhar Malavali -Signed-off-by: Saurav Kashyap -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_attr.c | 3 +-- - drivers/scsi/qla2xxx/qla_os.c | 3 +-- - 2 files changed, 2 insertions(+), 4 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_attr.c -+++ b/drivers/scsi/qla2xxx/qla_attr.c -@@ -1615,8 +1615,7 @@ qla2x00_terminate_rport_io(struct fc_rpo - * At this point all fcport's software-states are cleared. Perform any - * final cleanup of firmware resources (PCBs and XCBs). - */ -- if (fcport->loop_id != FC_NO_LOOP_ID && -- !test_bit(UNLOADING, &fcport->vha->dpc_flags)) { -+ if (fcport->loop_id != FC_NO_LOOP_ID) { - if (IS_FWI2_CAPABLE(fcport->vha->hw)) - fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, - fcport->loop_id, fcport->d_id.b.domain, ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -2755,6 +2755,7 @@ qla2x00_remove_one(struct pci_dev *pdev) - - ha->flags.host_shutting_down = 1; - -+ set_bit(UNLOADING, &base_vha->dpc_flags); - mutex_lock(&ha->vport_lock); - while (ha->cur_vport_count) { - struct Scsi_Host *scsi_host; -@@ -2784,8 +2785,6 @@ qla2x00_remove_one(struct pci_dev *pdev) - "Error while clearing DRV-Presence.\n"); - } - -- set_bit(UNLOADING, &base_vha->dpc_flags); -- - qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); - - qla2x00_dfs_remove(base_vha); -From 9bceab4e08c5e329e9def7fe1cab41c467236517 Mon Sep 17 00:00:00 2001 -From: Steve Hodgson -Date: Wed, 21 Nov 2012 02:39:56 -0500 -Subject: SCSI: qla2xxx: Free rsp_data even on error in qla2x00_process_loopback() - -From: Steve Hodgson - -commit 9bceab4e08c5e329e9def7fe1cab41c467236517 upstream. - -Signed-off-by: Steve Hodgson -Signed-off-by: Armen Baloyan -Signed-off-by: Saurav Kashyap -Signed-off-by: James Bottomley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_bsg.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_bsg.c -+++ b/drivers/scsi/qla2xxx/qla_bsg.c -@@ -743,7 +743,7 @@ qla2x00_process_loopback(struct fc_bsg_j - ql_log(ql_log_warn, vha, 0x701f, - "Get port config failed.\n"); - rval = -EPERM; -- goto done_free_dma_req; -+ goto done_free_dma_rsp; - } - - ql_dbg(ql_dbg_user, vha, 0x70c0, -@@ -762,7 +762,7 @@ qla2x00_process_loopback(struct fc_bsg_j - - if (rval) { - rval = -EPERM; -- goto done_free_dma_req; -+ goto done_free_dma_rsp; - } - - type = "FC_BSG_HST_VENDOR_LOOPBACK"; -@@ -795,7 +795,7 @@ qla2x00_process_loopback(struct fc_bsg_j - } - - rval = -EIO; -- goto done_free_dma_req; -+ goto done_free_dma_rsp; - } - } else { - type = "FC_BSG_HST_VENDOR_LOOPBACK"; -@@ -830,6 +830,7 @@ qla2x00_process_loopback(struct fc_bsg_j - fw_sts_ptr += sizeof(response); - *fw_sts_ptr = command_sent; - -+done_free_dma_rsp: - dma_free_coherent(&ha->pdev->dev, rsp_data_len, - rsp_data, rsp_data_dma); - done_free_dma_req: -From 64c13330a38935120501b19c97a3e6095747c7a1 Mon Sep 17 00:00:00 2001 -From: Steve Hodgson -Date: Mon, 5 Nov 2012 18:02:41 -0800 -Subject: iscsi-target: Fix bug in handling of ExpStatSN ACK during u32 wrap-around - -From: Steve Hodgson - -commit 64c13330a38935120501b19c97a3e6095747c7a1 upstream. - -This patch fixes a bug in the hanlding of initiator provided ExpStatSN and -individual iscsi_cmd->stat_sn comparision during iscsi_conn->stat_sn -wrap-around within iscsit_ack_from_expstatsn() code. - -This bug would manifest itself as iscsi_cmd descriptors not being Acked -by a lower ExpStatSn, causing them to be leaked until an iSCSI connection -or session reinstatement event occurs to release all commands. - -Also fix up two other uses of incorrect CmdSN SNA comparison to use wrapper -usage from include/scsi/iscsi_proto.h. - -Signed-off-by: Steve Hodgson -Signed-off-by: Roland Dreier -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/iscsi/iscsi_target.c | 2 +- - drivers/target/iscsi/iscsi_target_erl2.c | 2 +- - drivers/target/iscsi/iscsi_target_tmr.c | 4 ++-- - 3 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(st - list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { - spin_lock(&cmd->istate_lock); - if ((cmd->i_state == ISTATE_SENT_STATUS) && -- (cmd->stat_sn < exp_statsn)) { -+ iscsi_sna_lt(cmd->stat_sn, exp_statsn)) { - cmd->i_state = ISTATE_REMOVE; - spin_unlock(&cmd->istate_lock); - iscsit_add_cmd_to_immediate_queue(cmd, conn, ---- a/drivers/target/iscsi/iscsi_target_erl2.c -+++ b/drivers/target/iscsi/iscsi_target_erl2.c -@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance( - * made generic here. - */ - if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && -- (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { -+ iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { - list_del(&cmd->i_conn_node); - spin_unlock_bh(&conn->cmd_lock); - iscsit_free_cmd(cmd); ---- a/drivers/target/iscsi/iscsi_target_tmr.c -+++ b/drivers/target/iscsi/iscsi_target_tmr.c -@@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task( - if (!ref_cmd) { - pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" - " %hu.\n", hdr->rtt, conn->cid); -- return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn && -- be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ? -+ return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && -+ iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? - ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; - } - if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { -From 1c5c12c666fda27c7c494b34934a0a0631a48130 Mon Sep 17 00:00:00 2001 -From: Roland Dreier -Date: Mon, 5 Nov 2012 18:02:42 -0800 -Subject: iscsi-target: Always send a response before terminating iSCSI connection - -From: Roland Dreier - -commit 1c5c12c666fda27c7c494b34934a0a0631a48130 upstream. - -There are some cases, for example when the initiator sends an -out-of-bounds ErrorRecoveryLevel value, where the iSCSI target -terminates the connection without sending back any error. Audit the -login path and add appropriate iscsit_tx_login_rsp() calls to make -sure this doesn't happen. - -Signed-off-by: Roland Dreier -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/iscsi/iscsi_target_login.c | 8 ++++---- - drivers/target/iscsi/iscsi_target_nego.c | 10 ++++++++-- - 2 files changed, 12 insertions(+), 6 deletions(-) - ---- a/drivers/target/iscsi/iscsi_target_login.c -+++ b/drivers/target/iscsi/iscsi_target_login.c -@@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatemen - - initiatorname_param = iscsi_find_param_from_key( - INITIATORNAME, conn->param_list); -- if (!initiatorname_param) -- return -1; -- - sessiontype_param = iscsi_find_param_from_key( - SESSIONTYPE, conn->param_list); -- if (!sessiontype_param) -+ if (!initiatorname_param || !sessiontype_param) { -+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, -+ ISCSI_LOGIN_STATUS_MISSING_FIELDS); - return -1; -+ } - - sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; - ---- a/drivers/target/iscsi/iscsi_target_nego.c -+++ b/drivers/target/iscsi/iscsi_target_nego.c -@@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(s - login->req_buf, - payload_length, - conn); -- if (ret < 0) -+ if (ret < 0) { -+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, -+ ISCSI_LOGIN_STATUS_INIT_ERR); - return -1; -+ } - - if (login->first_request) - if (iscsi_target_check_first_request(conn, login) < 0) -@@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(s - login->rsp_buf, - &login->rsp_length, - conn->param_list); -- if (ret < 0) -+ if (ret < 0) { -+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, -+ ISCSI_LOGIN_STATUS_INIT_ERR); - return -1; -+ } - - if (!login->auth_complete && - ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { -From 3c989d7603872bf878840f7ce3ea49b73bea4c6c Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Fri, 23 Nov 2012 12:07:39 +0800 -Subject: iscsit: use GFP_ATOMIC under spin lock - -From: Wei Yongjun - -commit 3c989d7603872bf878840f7ce3ea49b73bea4c6c upstream. - -The function iscsit_build_conn_drop_async_message() is called -from iscsit_close_connection() with spin lock 'sess->conn_lock' -held, so we should use GFP_ATOMIC instead of GFP_KERNEL. - -Signed-off-by: Wei Yongjun -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/iscsi/iscsi_target.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -2360,7 +2360,7 @@ static void iscsit_build_conn_drop_async - if (!conn_p) - return; - -- cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); -+ cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); - if (!cmd) { - iscsit_dec_conn_usage_count(conn_p); - return; -From 06e97b489006f28e23bb028febfa1c01c266d676 Mon Sep 17 00:00:00 2001 -From: Steve Hodgson -Date: Fri, 16 Nov 2012 08:06:17 -0800 -Subject: qla2xxx: Look up LUN for abort requests - -From: Steve Hodgson - -commit 06e97b489006f28e23bb028febfa1c01c266d676 upstream. - -Search through the list of pending commands on the session list to find -the command the initiator is actually aborting, so that we can pass the -correct LUN to the core TMR handling code. - -(nab: Allow abort requests to work to LUN=0 with mainline target code) - -Signed-off-by: Steve Hodgson -Signed-off-by: Roland Dreier -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_target.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - ---- a/drivers/scsi/qla2xxx/qla_target.c -+++ b/drivers/scsi/qla2xxx/qla_target.c -@@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct - struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) - { - struct qla_hw_data *ha = vha->hw; -+ struct se_session *se_sess = sess->se_sess; - struct qla_tgt_mgmt_cmd *mcmd; -+ struct se_cmd *se_cmd; -+ u32 lun = 0; - int rc; -+ bool found_lun = false; -+ -+ spin_lock(&se_sess->sess_cmd_lock); -+ list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { -+ struct qla_tgt_cmd *cmd = -+ container_of(se_cmd, struct qla_tgt_cmd, se_cmd); -+ if (cmd->tag == abts->exchange_addr_to_abort) { -+ lun = cmd->unpacked_lun; -+ found_lun = true; -+ break; -+ } -+ } -+ spin_unlock(&se_sess->sess_cmd_lock); -+ -+ if (!found_lun) -+ return -ENOENT; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, - "qla_target(%d): task abort (tag=%d)\n", -@@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct - mcmd->sess = sess; - memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); - -- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, -+ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK, - abts->exchange_addr_to_abort); - if (rc != 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, -From 3100d49d3cd236443faae9d81137c81b22d36003 Mon Sep 17 00:00:00 2001 -From: Mikael Pettersson -Date: Sun, 16 Sep 2012 20:53:43 +0200 -Subject: sata_promise: fix hardreset lockdep error - -From: Mikael Pettersson - -commit 3100d49d3cd236443faae9d81137c81b22d36003 upstream. - -sata_promise's pdc_hard_reset_port() needs to serialize because it -flips a port-specific bit in controller register that's shared by -all ports. The code takes the ata host lock for this, but that's -broken because an interrupt may arrive on our irq during the hard -reset sequence, and that too will take the ata host lock. With -lockdep enabled a big nasty warning is seen. - -Fixed by adding private state to the ata host structure, containing -a second lock used only for serializing the hard reset sequences. -This eliminated the lockdep warnings both on my test rig and on -the original reporter's machine. - -Signed-off-by: Mikael Pettersson -Tested-by: Adko Branil -Signed-off-by: Jeff Garzik -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/ata/sata_promise.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - ---- a/drivers/ata/sata_promise.c -+++ b/drivers/ata/sata_promise.c -@@ -147,6 +147,10 @@ struct pdc_port_priv { - dma_addr_t pkt_dma; - }; - -+struct pdc_host_priv { -+ spinlock_t hard_reset_lock; -+}; -+ - static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); - static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); - static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct a - void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; - void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; - unsigned int ata_no = pdc_ata_port_to_ata_no(ap); -+ struct pdc_host_priv *hpriv = ap->host->private_data; - u8 tmp; - -- spin_lock(&ap->host->lock); -+ spin_lock(&hpriv->hard_reset_lock); - - tmp = readb(pcictl_b1_mmio); - tmp &= ~(0x10 << ata_no); -@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct a - writeb(tmp, pcictl_b1_mmio); - readb(pcictl_b1_mmio); /* flush */ - -- spin_unlock(&ap->host->lock); -+ spin_unlock(&hpriv->hard_reset_lock); - } - - static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, -@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_d - const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; - const struct ata_port_info *ppi[PDC_MAX_PORTS]; - struct ata_host *host; -+ struct pdc_host_priv *hpriv; - void __iomem *host_mmio; - int n_ports, i, rc; - int is_sataii_tx4; -@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_d - dev_err(&pdev->dev, "failed to allocate host\n"); - return -ENOMEM; - } -+ hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); -+ if (!hpriv) -+ return -ENOMEM; -+ spin_lock_init(&hpriv->hard_reset_lock); -+ host->private_data = hpriv; - host->iomap = pcim_iomap_table(pdev); - - is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); -From dcbeec264d73b7228ffdfe767eab69b2353099b1 Mon Sep 17 00:00:00 2001 -From: Mattia Dongili -Date: Fri, 21 Dec 2012 07:21:09 +0900 -Subject: sony-laptop: fix SNC buffer calls when SN06 returns Integers - -From: Mattia Dongili - -commit dcbeec264d73b7228ffdfe767eab69b2353099b1 upstream. - -SN06 in some cases returns an Integer instead of a buffer. While the -code handling the return value was trying to cope with the difference, -the memcpy call was not making any difference between the two types of -acpi_object union. This regression was introduced in 3.5. -While there also rework the return value logic to improve readability. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48671 -Cc: Fabrizio Narni -Cc: -Signed-off-by: Mattia Dongili -Signed-off-by: Matthew Garrett -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/platform/x86/sony-laptop.c | 15 ++++++++------- - 1 file changed, 8 insertions(+), 7 deletions(-) - ---- a/drivers/platform/x86/sony-laptop.c -+++ b/drivers/platform/x86/sony-laptop.c -@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle - static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, - void *buffer, size_t buflen) - { -+ int ret = 0; - size_t len = len; - union acpi_object *object = __call_snc_method(handle, name, value); - - if (!object) - return -EINVAL; - -- if (object->type == ACPI_TYPE_BUFFER) -+ if (object->type == ACPI_TYPE_BUFFER) { - len = MIN(buflen, object->buffer.length); -+ memcpy(buffer, object->buffer.pointer, len); - -- else if (object->type == ACPI_TYPE_INTEGER) -+ } else if (object->type == ACPI_TYPE_INTEGER) { - len = MIN(buflen, sizeof(object->integer.value)); -+ memcpy(buffer, &object->integer.value, len); - -- else { -+ } else { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_BUFFER, object->type); -- kfree(object); -- return -EINVAL; -+ ret = -EINVAL; - } - -- memcpy(buffer, object->buffer.pointer, len); - kfree(object); -- return 0; -+ return ret; - } - - struct sony_nc_handles { -From ceb7decb366591e9b67d70832e07f5d240572a3d Mon Sep 17 00:00:00 2001 -From: Jack Morgenstein -Date: Tue, 27 Nov 2012 16:24:29 +0000 -Subject: IB/mlx4: Fix spinlock order to avoid lockdep warnings - -From: Jack Morgenstein - -commit ceb7decb366591e9b67d70832e07f5d240572a3d upstream. - -lockdep warns about taking a hard-irq-unsafe lock (sriov->id_map_lock) -inside a hard-irq-safe lock (sriov->going_down_lock). - -Since id_map_lock is never taken in the interrupt context, we can -simply reverse the order of taking the two spinlocks, thus avoiding -the warning and the depencency. - -Signed-off-by: Jack Morgenstein -Signed-off-by: Or Gerlitz -Signed-off-by: Roland Dreier -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/infiniband/hw/mlx4/cm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/infiniband/hw/mlx4/cm.c -+++ b/drivers/infiniband/hw/mlx4/cm.c -@@ -268,15 +268,15 @@ static void schedule_delayed(struct ib_d - struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov; - unsigned long flags; - -- spin_lock_irqsave(&sriov->going_down_lock, flags); - spin_lock(&sriov->id_map_lock); -+ spin_lock_irqsave(&sriov->going_down_lock, flags); - /*make sure that there is no schedule inside the scheduled work.*/ - if (!sriov->is_going_down) { - id->scheduled_delete = 1; - schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT); - } -- spin_unlock(&sriov->id_map_lock); - spin_unlock_irqrestore(&sriov->going_down_lock, flags); -+ spin_unlock(&sriov->id_map_lock); - } - - int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id, -From 311f813a2daefcba03f706a692fe0c67888d7622 Mon Sep 17 00:00:00 2001 -From: Jack Morgenstein -Date: Tue, 27 Nov 2012 16:24:30 +0000 -Subject: mlx4_core: Fix potential deadlock in mlx4_eq_int() - -From: Jack Morgenstein - -commit 311f813a2daefcba03f706a692fe0c67888d7622 upstream. - -The slave_state_lock spinlock is used in both interrupt context and -process context, hence irq locking must be used. Found by lockdep. - -Signed-off-by: Jack Morgenstein -Signed-off-by: Or Gerlitz -Signed-off-by: Roland Dreier -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 +++++---- - drivers/net/ethernet/mellanox/mlx4/eq.c | 10 ++++++---- - 2 files changed, 11 insertions(+), 8 deletions(-) - ---- a/drivers/net/ethernet/mellanox/mlx4/cmd.c -+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c -@@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct ml - u32 reply; - u8 is_going_down = 0; - int i; -+ unsigned long flags; - - slave_state[slave].comm_toggle ^= 1; - reply = (u32) slave_state[slave].comm_toggle << 31; -@@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct ml - mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); - goto reset_slave; - } -- spin_lock(&priv->mfunc.master.slave_state_lock); -+ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); - if (!slave_state[slave].is_slave_going_down) - slave_state[slave].last_cmd = cmd; - else - is_going_down = 1; -- spin_unlock(&priv->mfunc.master.slave_state_lock); -+ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); - if (is_going_down) { - mlx4_warn(dev, "Slave is going down aborting command(%d)" - " executing from slave:%d\n", -@@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct ml - reset_slave: - /* cleanup any slave resources */ - mlx4_delete_all_resources_for_slave(dev, slave); -- spin_lock(&priv->mfunc.master.slave_state_lock); -+ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); - if (!slave_state[slave].is_slave_going_down) - slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; -- spin_unlock(&priv->mfunc.master.slave_state_lock); -+ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); - /*with slave in the middle of flr, no need to clean resources again.*/ - inform_slave_state: - memset(&slave_state[slave].event_eq, 0, ---- a/drivers/net/ethernet/mellanox/mlx4/eq.c -+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c -@@ -401,6 +401,7 @@ void mlx4_master_handle_slave_flr(struct - struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; - int i; - int err; -+ unsigned long flags; - - mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); - -@@ -412,10 +413,10 @@ void mlx4_master_handle_slave_flr(struct - - mlx4_delete_all_resources_for_slave(dev, i); - /*return the slave to running mode*/ -- spin_lock(&priv->mfunc.master.slave_state_lock); -+ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); - slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; - slave_state[i].is_slave_going_down = 0; -- spin_unlock(&priv->mfunc.master.slave_state_lock); -+ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); - /*notify the FW:*/ - err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); -@@ -440,6 +441,7 @@ static int mlx4_eq_int(struct mlx4_dev * - u8 update_slave_state; - int i; - enum slave_port_gen_event gen_event; -+ unsigned long flags; - - while ((eqe = next_eqe_sw(eq))) { - /* -@@ -647,13 +649,13 @@ static int mlx4_eq_int(struct mlx4_dev * - } else - update_slave_state = 1; - -- spin_lock(&priv->mfunc.master.slave_state_lock); -+ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); - if (update_slave_state) { - priv->mfunc.master.slave_state[flr_slave].active = false; - priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; - priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; - } -- spin_unlock(&priv->mfunc.master.slave_state_lock); -+ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); - queue_work(priv->mfunc.master.comm_wq, - &priv->mfunc.master.slave_flr_event_work); - break; -From b042e47491ba5f487601b5141a3f1d8582304170 Mon Sep 17 00:00:00 2001 -From: Maxime Bizon -Date: Mon, 22 Oct 2012 11:19:28 +0200 -Subject: pstore/ram: Fix undefined usage of rounddown_pow_of_two(0) - -From: Maxime Bizon - -commit b042e47491ba5f487601b5141a3f1d8582304170 upstream. - -record_size / console_size / ftrace_size can be 0 (this is how you disable -the feature), but rounddown_pow_of_two(0) is undefined. As suggested by -Kees Cook, use !is_power_of_2() as a condition to call -rounddown_pow_of_two and avoid its undefined behavior on the value 0. This -issue has been present since commit 1894a253 (ramoops: Move to -fs/pstore/ram.c). - -Signed-off-by: Maxime Bizon -Signed-off-by: Florian Fainelli -Acked-by: Kees Cook -Signed-off-by: Anton Vorontsov -Signed-off-by: Greg Kroah-Hartman - ---- - fs/pstore/ram.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - ---- a/fs/pstore/ram.c -+++ b/fs/pstore/ram.c -@@ -374,10 +374,14 @@ static int __devinit ramoops_probe(struc - goto fail_out; - } - -- pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); -- pdata->record_size = rounddown_pow_of_two(pdata->record_size); -- pdata->console_size = rounddown_pow_of_two(pdata->console_size); -- pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); -+ if (!is_power_of_2(pdata->mem_size)) -+ pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); -+ if (!is_power_of_2(pdata->record_size)) -+ pdata->record_size = rounddown_pow_of_two(pdata->record_size); -+ if (!is_power_of_2(pdata->console_size)) -+ pdata->console_size = rounddown_pow_of_two(pdata->console_size); -+ if (!is_power_of_2(pdata->ftrace_size)) -+ pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); - - cxt->dump_read_cnt = 0; - cxt->size = pdata->mem_size; -From 5416912af75de9cba5d1c75b99a7888b0bbbd2fb Mon Sep 17 00:00:00 2001 -From: Aaron Lu -Date: Mon, 3 Dec 2012 11:35:02 +0800 -Subject: libata: set dma_mode to 0xff in reset - -From: Aaron Lu - -commit 5416912af75de9cba5d1c75b99a7888b0bbbd2fb upstream. - -ata_device->dma_mode's initial value is zero, which is not a valid dma -mode, but ata_dma_enabled will return true for this value. This patch -sets dma_mode to 0xff in reset function, so that ata_dma_enabled will -not return true for this case, or it will cause problem for pata_acpi. - -The corrsponding bugzilla page is at: -https://bugzilla.kernel.org/show_bug.cgi?id=49151 - -Reported-by: Phillip Wood -Signed-off-by: Aaron Lu -Tested-by: Szymon Janc -Tested-by: Dutra Julio -Acked-by: Alan Cox -Signed-off-by: Jeff Garzik -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/ata/libata-core.c | 1 + - drivers/ata/libata-eh.c | 1 + - 2 files changed, 2 insertions(+) - ---- a/drivers/ata/libata-core.c -+++ b/drivers/ata/libata-core.c -@@ -2560,6 +2560,7 @@ int ata_bus_probe(struct ata_port *ap) - * bus as we may be talking too fast. - */ - dev->pio_mode = XFER_PIO_0; -+ dev->dma_mode = 0xff; - - /* If the controller has a pio mode setup function - * then use it to set the chipset to rights. Don't ---- a/drivers/ata/libata-eh.c -+++ b/drivers/ata/libata-eh.c -@@ -2657,6 +2657,7 @@ int ata_eh_reset(struct ata_link *link, - * bus as we may be talking too fast. - */ - dev->pio_mode = XFER_PIO_0; -+ dev->dma_mode = 0xff; - - /* If the controller has a pio mode setup function - * then use it to set the chipset to rights. Don't -From 26cd4d65deba587f3cf2329b6869ce02bcbe68ec Mon Sep 17 00:00:00 2001 -From: Xiaotian Feng -Date: Thu, 13 Dec 2012 16:12:18 +0800 -Subject: libata: fix Null pointer dereference on disk error - -From: Xiaotian Feng - -commit 26cd4d65deba587f3cf2329b6869ce02bcbe68ec upstream. - -Following oops were observed when disk error happened: - -[ 4272.896937] sd 0:0:0:0: [sda] Unhandled error code -[ 4272.896939] sd 0:0:0:0: [sda] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK -[ 4272.896942] sd 0:0:0:0: [sda] CDB: Read(10): 28 00 00 5a de a7 00 00 08 00 -[ 4272.896951] end_request: I/O error, dev sda, sector 5955239 -[ 4291.574947] BUG: unable to handle kernel NULL pointer dereference at (null) -[ 4291.658305] IP: [] ahci_activity_show+0x1/0x40 -[ 4291.730090] PGD 76dbbc067 PUD 6c4fba067 PMD 0 -[ 4291.783408] Oops: 0000 [#1] SMP -[ 4291.822100] last sysfs file: /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sw_activity -[ 4291.934235] CPU 9 -[ 4291.958301] Pid: 27942, comm: hwinfo ...... - -ata_scsi_find_dev could return NULL, so ata_scsi_activity_{show,store} should check if atadev is NULL. - -Signed-off-by: Xiaotian Feng -Cc: James Bottomley -Signed-off-by: Jeff Garzik -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/ata/libata-scsi.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/ata/libata-scsi.c -+++ b/drivers/ata/libata-scsi.c -@@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *de - struct ata_port *ap = ata_shost_to_port(sdev->host); - struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); - -- if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) -+ if (atadev && ap->ops->sw_activity_show && -+ (ap->flags & ATA_FLAG_SW_ACTIVITY)) - return ap->ops->sw_activity_show(atadev, buf); - return -EINVAL; - } -@@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *d - enum sw_activity val; - int rc; - -- if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { -+ if (atadev && ap->ops->sw_activity_store && -+ (ap->flags & ATA_FLAG_SW_ACTIVITY)) { - val = simple_strtoul(buf, NULL, 0); - switch (val) { - case OFF: case BLINK_ON: case BLINK_OFF: -From 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf Mon Sep 17 00:00:00 2001 -From: Sebastian Andrzej Siewior -Date: Wed, 5 Dec 2012 12:08:29 +0100 -Subject: target/file: Fix 32-bit highmem breakage for SGL -> iovec mapping - -From: Sebastian Andrzej Siewior - -commit 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf upstream. - -This patch changes vectored file I/O to use kmap + kunmap when mapping -incoming SGL memory -> struct iovec in order to properly support 32-bit -highmem configurations. This is because an extra bounce buffer may be -required when processing scatterlist pages allocated with GFP_KERNEL. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/target_core_file.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/target/target_core_file.c -+++ b/drivers/target/target_core_file.c -@@ -260,7 +260,7 @@ static int fd_do_readv(struct se_cmd *cm - - for_each_sg(sgl, sg, sgl_nents, i) { - iov[i].iov_len = sg->length; -- iov[i].iov_base = sg_virt(sg); -+ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; - } - - old_fs = get_fs(); -@@ -268,6 +268,8 @@ static int fd_do_readv(struct se_cmd *cm - ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); - set_fs(old_fs); - -+ for_each_sg(sgl, sg, sgl_nents, i) -+ kunmap(sg_page(sg)); - kfree(iov); - /* - * Return zeros and GOOD status even if the READ did not return -@@ -313,7 +315,7 @@ static int fd_do_writev(struct se_cmd *c - - for_each_sg(sgl, sg, sgl_nents, i) { - iov[i].iov_len = sg->length; -- iov[i].iov_base = sg_virt(sg); -+ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; - } - - old_fs = get_fs(); -@@ -321,6 +323,9 @@ static int fd_do_writev(struct se_cmd *c - ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); - set_fs(old_fs); - -+ for_each_sg(sgl, sg, sgl_nents, i) -+ kunmap(sg_page(sg)); -+ - kfree(iov); - - if (ret < 0 || ret != cmd->data_length) { -From 9f4ad44b264f8bb61ffdd607148215566568430d Mon Sep 17 00:00:00 2001 -From: Yi Zou -Date: Mon, 10 Dec 2012 17:04:00 -0800 -Subject: target/tcm_fc: fix the lockdep warning due to inconsistent lock state - -From: Yi Zou - -commit 9f4ad44b264f8bb61ffdd607148215566568430d upstream. - -The lockdep warning below is in theory correct but it will be in really weird -rare situation that ends up that deadlock since the tcm fc session is hashed -based the rport id. Nonetheless, the complaining below is about rcu callback -that does the transport_deregister_session() is happening in softirq, where -transport_register_session() that happens earlier is not. This triggers the -lockdep warning below. So, just fix this to make lockdep happy by disabling -the soft irq before calling transport_register_session() in ft_prli. - -BTW, this was found in FCoE VN2VN over two VMs, couple of create and destroy -would get this triggered. - -v1: was enforcing register to be in softirq context which was not righ. See, -http://www.spinics.net/lists/target-devel/msg03614.html - -v2: following comments from Roland&Nick (thanks), it seems we don't have to -do transport_deregister_session() in rcu callback, so move it into ft_sess_free() -but still do kfree() of the corresponding ft_sess struct in rcu callback to -make sure the ft_sess is not freed till the rcu callback. - -... -[ 1328.370592] scsi2 : FCoE Driver -[ 1328.383429] fcoe: No FDMI support. -[ 1328.384509] host2: libfc: Link up on port (000000) -[ 1328.934229] host2: Assigned Port ID 00a292 -[ 1357.232132] host2: rport 00a393: Remove port -[ 1357.232568] host2: rport 00a393: Port sending LOGO from Ready state -[ 1357.233692] host2: rport 00a393: Delete port -[ 1357.234472] host2: rport 00a393: work event 3 -[ 1357.234969] host2: rport 00a393: callback ev 3 -[ 1357.235979] host2: rport 00a393: Received a LOGO response closed -[ 1357.236706] host2: rport 00a393: work delete -[ 1357.237481] -[ 1357.237631] ================================= -[ 1357.238064] [ INFO: inconsistent lock state ] -[ 1357.238450] 3.7.0-rc7-yikvm+ #3 Tainted: G O -[ 1357.238450] --------------------------------- -[ 1357.238450] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. -[ 1357.238450] ksoftirqd/0/3 [HC0[0]:SC1[1]:HE0:SE0] takes: -[ 1357.238450] (&(&se_tpg->session_lock)->rlock){+.?...}, at: [] transport_deregister_session+0x41/0x148 [target_core_mod] -[ 1357.238450] {SOFTIRQ-ON-W} state was registered at: -[ 1357.238450] [] mark_held_locks+0x6d/0x95 -[ 1357.238450] [] trace_hardirqs_on_caller+0x12d/0x197 -[ 1357.238450] [] trace_hardirqs_on+0xd/0xf -[ 1357.238450] [] _raw_spin_unlock_irq+0x2d/0x45 -[ 1357.238450] [] __transport_register_session+0xb8/0x122 [target_core_mod] -[ 1357.238450] [] transport_register_session+0x44/0x5a [target_core_mod] -[ 1357.238450] [] ft_prli+0x1e3/0x275 [tcm_fc] -[ 1357.238450] [] fc_rport_recv_req+0x95e/0xdc5 [libfc] -[ 1357.238450] [] fc_lport_recv_els_req+0xc4/0xd5 [libfc] -[ 1357.238450] [] fc_lport_recv_req+0x12f/0x18f [libfc] -[ 1357.238450] [] fc_exch_recv+0x8ba/0x981 [libfc] -[ 1357.238450] [] fcoe_percpu_receive_thread+0x47a/0x4e2 [fcoe] -[ 1357.238450] [] kthread+0xb1/0xb9 -[ 1357.238450] [] ret_from_fork+0x7c/0xb0 -[ 1357.238450] irq event stamp: 275411 -[ 1357.238450] hardirqs last enabled at (275410): [] rcu_process_callbacks+0x229/0x42a -[ 1357.238450] hardirqs last disabled at (275411): [] _raw_spin_lock_irqsave+0x22/0x8e -[ 1357.238450] softirqs last enabled at (275394): [] __do_softirq+0x246/0x26f -[ 1357.238450] softirqs last disabled at (275399): [] run_ksoftirqd+0x29/0x62 -[ 1357.238450] -[ 1357.238450] other info that might help us debug this: -[ 1357.238450] Possible unsafe locking scenario: -[ 1357.238450] -[ 1357.238450] CPU0 -[ 1357.238450] ---- -[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); -[ 1357.238450] -[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); -[ 1357.238450] -[ 1357.238450] *** DEADLOCK *** -[ 1357.238450] -[ 1357.238450] no locks held by ksoftirqd/0/3. -[ 1357.238450] -[ 1357.238450] stack backtrace: -[ 1357.238450] Pid: 3, comm: ksoftirqd/0 Tainted: G O 3.7.0-rc7-yikvm+ #3 -[ 1357.238450] Call Trace: -[ 1357.238450] [] print_usage_bug+0x1f5/0x206 -[ 1357.238450] [] ? save_stack_trace+0x2c/0x49 -[ 1357.238450] [] ? print_irq_inversion_bug.part.14+0x1ae/0x1ae -[ 1357.238450] [] mark_lock+0x106/0x258 -[ 1357.238450] [] __lock_acquire+0x2e7/0xe53 -[ 1357.238450] [] ? pvclock_clocksource_read+0x48/0xb4 -[ 1357.238450] [] ? rcu_process_gp_end+0xc0/0xc9 -[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] -[ 1357.238450] [] lock_acquire+0x119/0x143 -[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] -[ 1357.238450] [] _raw_spin_lock_irqsave+0x54/0x8e -[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] -[ 1357.238450] [] transport_deregister_session+0x41/0x148 [target_core_mod] -[ 1357.238450] [] ? rcu_process_callbacks+0x229/0x42a -[ 1357.238450] [] ft_sess_rcu_free+0x17/0x24 [tcm_fc] -[ 1357.238450] [] ? ft_sess_free+0x1b/0x1b [tcm_fc] -[ 1357.238450] [] rcu_process_callbacks+0x260/0x42a -[ 1357.238450] [] __do_softirq+0x13a/0x26f -[ 1357.238450] [] ? __schedule+0x65f/0x68e -[ 1357.238450] [] run_ksoftirqd+0x29/0x62 -[ 1357.238450] [] smpboot_thread_fn+0x1a5/0x1aa -[ 1357.238450] [] ? smpboot_unregister_percpu_thread+0x47/0x47 -[ 1357.238450] [] kthread+0xb1/0xb9 -[ 1357.238450] [] ? wait_for_common+0xbb/0x10a -[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 -[ 1357.238450] [] ret_from_fork+0x7c/0xb0 -[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 -[ 1417.440099] rport-2:0-0: blocked FC remote port time out: removing rport - -Signed-off-by: Yi Zou -Cc: Open-FCoE -Cc: Nicholas A. Bellinger -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/tcm_fc/tfc_sess.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/target/tcm_fc/tfc_sess.c -+++ b/drivers/target/tcm_fc/tfc_sess.c -@@ -430,7 +430,6 @@ static void ft_sess_rcu_free(struct rcu_ - { - struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); - -- transport_deregister_session(sess->se_sess); - kfree(sess); - } - -@@ -438,6 +437,7 @@ static void ft_sess_free(struct kref *kr - { - struct ft_sess *sess = container_of(kref, struct ft_sess, kref); - -+ transport_deregister_session(sess->se_sess); - call_rcu(&sess->rcu, ft_sess_rcu_free); - } - -From e1fe2060d7e8f58a69374135e32e90f0bb79a7fd Mon Sep 17 00:00:00 2001 -From: Chris Boot -Date: Tue, 11 Dec 2012 21:58:48 +0000 -Subject: sbp-target: fix error path in sbp_make_tpg() - -From: Chris Boot - -commit e1fe2060d7e8f58a69374135e32e90f0bb79a7fd upstream. - -If the TPG memory is allocated successfully, but we fail further along -in the function, a dangling pointer to freed memory is left in the TPort -structure. This is mostly harmless, but does prevent re-trying the -operation without first removing the TPort altogether. - -Reported-by: Chen Gang -Signed-off-by: Chris Boot -Cc: Andy Grover -Cc: Nicholas A. Bellinger -Signed-off-by: Nicholas Bellinger -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/target/sbp/sbp_target.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - ---- a/drivers/target/sbp/sbp_target.c -+++ b/drivers/target/sbp/sbp_target.c -@@ -2207,20 +2207,23 @@ static struct se_portal_group *sbp_make_ - tport->mgt_agt = sbp_management_agent_register(tport); - if (IS_ERR(tport->mgt_agt)) { - ret = PTR_ERR(tport->mgt_agt); -- kfree(tpg); -- return ERR_PTR(ret); -+ goto out_free_tpg; - } - - ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, - &tpg->se_tpg, (void *)tpg, - TRANSPORT_TPG_TYPE_NORMAL); -- if (ret < 0) { -- sbp_management_agent_unregister(tport->mgt_agt); -- kfree(tpg); -- return ERR_PTR(ret); -- } -+ if (ret < 0) -+ goto out_unreg_mgt_agt; - - return &tpg->se_tpg; -+ -+out_unreg_mgt_agt: -+ sbp_management_agent_unregister(tport->mgt_agt); -+out_free_tpg: -+ tport->tpg = NULL; -+ kfree(tpg); -+ return ERR_PTR(ret); - } - - static void sbp_drop_tpg(struct se_portal_group *se_tpg) -From fee546ce8cfd9dea1f53175f627e17ef5ff05df4 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 23 Nov 2012 12:05:33 +0900 -Subject: mfd: wm8994: Add support for WM1811 rev E - -From: Mark Brown - -commit fee546ce8cfd9dea1f53175f627e17ef5ff05df4 upstream. - -This is supported identically to the previous revisions. - -Signed-off-by: Mark Brown -Signed-off-by: Samuel Ortiz -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/mfd/wm8994-core.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/mfd/wm8994-core.c -+++ b/drivers/mfd/wm8994-core.c -@@ -557,6 +557,7 @@ static __devinit int wm8994_device_init( - case 1: - case 2: - case 3: -+ case 4: - regmap_patch = wm1811_reva_patch; - patch_regs = ARRAY_SIZE(wm1811_reva_patch); - break; -From b9fbb62eb61452d728c39b2e5020739c575aac53 Mon Sep 17 00:00:00 2001 -From: Charles Keepax -Date: Fri, 9 Nov 2012 16:15:28 +0000 -Subject: mfd: Only unregister platform devices allocated by the mfd core - -From: Charles Keepax - -commit b9fbb62eb61452d728c39b2e5020739c575aac53 upstream. - -mfd_remove_devices would iterate over all devices sharing a parent with -an mfd device regardless of whether they were allocated by the mfd core -or not. This especially caused problems when the device structure was -not contained within a platform_device, because to_platform_device is -used on each device pointer. - -This patch defines a device_type for mfd devices and checks this is -present from mfd_remove_devices_fn before processing the device. - -Signed-off-by: Charles Keepax -Tested-by: Peter Tyser -Reviewed-by: Mark Brown -Signed-off-by: Samuel Ortiz -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/mfd/mfd-core.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - ---- a/drivers/mfd/mfd-core.c -+++ b/drivers/mfd/mfd-core.c -@@ -21,6 +21,10 @@ - #include - #include - -+static struct device_type mfd_dev_type = { -+ .name = "mfd_device", -+}; -+ - int mfd_cell_enable(struct platform_device *pdev) - { - const struct mfd_cell *cell = mfd_get_cell(pdev); -@@ -91,6 +95,7 @@ static int mfd_add_device(struct device - goto fail_device; - - pdev->dev.parent = parent; -+ pdev->dev.type = &mfd_dev_type; - - if (parent->of_node && cell->of_compatible) { - for_each_child_of_node(parent->of_node, np) { -@@ -204,10 +209,16 @@ EXPORT_SYMBOL(mfd_add_devices); - - static int mfd_remove_devices_fn(struct device *dev, void *c) - { -- struct platform_device *pdev = to_platform_device(dev); -- const struct mfd_cell *cell = mfd_get_cell(pdev); -+ struct platform_device *pdev; -+ const struct mfd_cell *cell; - atomic_t **usage_count = c; - -+ if (dev->type != &mfd_dev_type) -+ return 0; -+ -+ pdev = to_platform_device(dev); -+ cell = mfd_get_cell(pdev); -+ - /* find the base address of usage_count pointers (for freeing) */ - if (!*usage_count || (cell->usage_count < *usage_count)) - *usage_count = cell->usage_count; -From 90a38d999739f35f4fc925c875e6ee518546b66c Mon Sep 17 00:00:00 2001 -From: Geert Uytterhoeven -Date: Mon, 15 Oct 2012 22:44:45 +0200 -Subject: mfd: Remove Unicode Byte Order Marks from da9055 - -From: Geert Uytterhoeven - -commit 90a38d999739f35f4fc925c875e6ee518546b66c upstream. - -Older gcc (< 4.4) doesn't like files starting with Unicode BOMs: - -include/linux/mfd/da9055/core.h:1: error: stray ‘\357’ in program -include/linux/mfd/da9055/core.h:1: error: stray ‘\273’ in program -include/linux/mfd/da9055/core.h:1: error: stray ‘\277’ in program -include/linux/mfd/da9055/pdata.h:1: error: stray ‘\357’ in program -include/linux/mfd/da9055/pdata.h:1: error: stray ‘\273’ in program -include/linux/mfd/da9055/pdata.h:1: error: stray ‘\277’ in program -include/linux/mfd/da9055/reg.h:1: error: stray ‘\357’ in program -include/linux/mfd/da9055/reg.h:1: error: stray ‘\273’ in program -include/linux/mfd/da9055/reg.h:1: error: stray ‘\277’ in program - -Remove the BOMs, the rest of the files is plain ASCII anyway. - -Output of "file" before: - -include/linux/mfd/da9055/core.h: UTF-8 Unicode (with BOM) C program text -include/linux/mfd/da9055/pdata.h: UTF-8 Unicode (with BOM) C program text -include/linux/mfd/da9055/reg.h: UTF-8 Unicode (with BOM) C program text - -Output of "file" after: - -include/linux/mfd/da9055/core.h: ASCII C program text -include/linux/mfd/da9055/pdata.h: ASCII C program text -include/linux/mfd/da9055/reg.h: ASCII C program text - -Signed-off-by: Geert Uytterhoeven -Signed-off-by: Samuel Ortiz -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/mfd/da9055/core.h | 2 +- - include/linux/mfd/da9055/pdata.h | 2 +- - include/linux/mfd/da9055/reg.h | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/include/linux/mfd/da9055/core.h -+++ b/include/linux/mfd/da9055/core.h -@@ -1,4 +1,4 @@ --/* -+/* - * da9055 declarations for DA9055 PMICs. - * - * Copyright(c) 2012 Dialog Semiconductor Ltd. ---- a/include/linux/mfd/da9055/pdata.h -+++ b/include/linux/mfd/da9055/pdata.h -@@ -1,4 +1,4 @@ --/* Copyright (C) 2012 Dialog Semiconductor Ltd. -+/* Copyright (C) 2012 Dialog Semiconductor Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by ---- a/include/linux/mfd/da9055/reg.h -+++ b/include/linux/mfd/da9055/reg.h -@@ -1,4 +1,4 @@ --/* -+/* - * DA9055 declarations for DA9055 PMICs. - * - * Copyright(c) 2012 Dialog Semiconductor Ltd. -From 24ec19b0ae83a385ad9c55520716da671274b96c Mon Sep 17 00:00:00 2001 -From: Eugene Shatokhin -Date: Thu, 8 Nov 2012 15:11:11 -0500 -Subject: ext4: fix memory leak in ext4_xattr_set_acl()'s error path - -From: Eugene Shatokhin - -commit 24ec19b0ae83a385ad9c55520716da671274b96c upstream. - -In ext4_xattr_set_acl(), if ext4_journal_start() returns an error, -posix_acl_release() will not be called for 'acl' which may result in a -memory leak. - -This patch fixes that. - -Reviewed-by: Lukas Czerner -Signed-off-by: Eugene Shatokhin -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/acl.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/fs/ext4/acl.c -+++ b/fs/ext4/acl.c -@@ -423,8 +423,10 @@ ext4_xattr_set_acl(struct dentry *dentry - - retry: - handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); -- if (IS_ERR(handle)) -- return PTR_ERR(handle); -+ if (IS_ERR(handle)) { -+ error = PTR_ERR(handle); -+ goto release_and_out; -+ } - error = ext4_set_acl(handle, inode, type, acl); - ext4_journal_stop(handle); - if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) -From aeb1e5d69a5be592e86a926be73efb38c55af404 Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Thu, 29 Nov 2012 21:21:22 -0500 -Subject: ext4: fix possible use after free with metadata csum - -From: Theodore Ts'o - -commit aeb1e5d69a5be592e86a926be73efb38c55af404 upstream. - -Commit fa77dcfafeaa introduces block bitmap checksum calculation into -ext4_new_inode() in the case that block group was uninitialized. -However we brelse() the bitmap buffer before we attempt to checksum it -so we have no guarantee that the buffer is still there. - -Fix this by releasing the buffer after the possible checksum -computation. - -Signed-off-by: Lukas Czerner -Signed-off-by: "Theodore Ts'o" -Acked-by: Darrick J. Wong -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/ialloc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/ext4/ialloc.c -+++ b/fs/ext4/ialloc.c -@@ -762,7 +762,6 @@ got: - - BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); - err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh); -- brelse(block_bitmap_bh); - - /* recheck and clear flag under lock if we still need to */ - ext4_lock_group(sb, group); -@@ -775,6 +774,7 @@ got: - ext4_group_desc_csum_set(sb, group, gdp); - } - ext4_unlock_group(sb, group); -+ brelse(block_bitmap_bh); - - if (err) - goto fail; -From d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee Mon Sep 17 00:00:00 2001 -From: Nathan Williams -Date: Thu, 22 Nov 2012 10:42:52 +1100 -Subject: mtd cs553x_nand: Initialise ecc.strength before nand_scan() - -From: Nathan Williams - -commit d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee upstream. - -Loading cs553x_nand with Hynix H27U1G8F2BTR NAND flash causes this bug: - -kernel BUG at drivers/mtd/nand/nand_base.c:3345! -invalid opcode: 0000 [#1] -Modules linked in: cs553x_nand(+) vfat fat usb_storage ehci_hcd usbcore usb_comr -Pid: 436, comm: modprobe Not tainted 3.6.7 #1 -EIP: 0060:[] EFLAGS: 00010296 CPU: 0 -EIP is at nand_scan_tail+0x64c/0x69c -EAX: 00000034 EBX: cea6ed98 ECX: 00000000 EDX: 00000000 -ESI: cea6ec00 EDI: cea6ec00 EBP: 20000000 ESP: cdd17e48 - DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 -CR0: 8005003b CR2: 0804e119 CR3: 0d850000 CR4: 00000090 -DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 -DR6: ffff0ff0 DR7: 00000400 -Process modprobe (pid: 436, ti=cdd16000 task=cdd1c320 task.ti=cdd16000) -Stack: - c12e962c c118f7ef 00000003 cea6ed98 d014b25c 20000000 fffff007 00000001 - 00000000 cdd53b00 d014b000 c1001021 cdd53b00 d01493c0 cdd53b00 cdd53b00 - d01493c0 c1047f83 d014b4a0 00000000 cdd17f9c ce4be454 cdd17f48 cdd1c320 -Call Trace: - [] ? nand_scan+0x1b/0x4d - [] ? init_module+0x25c/0x2de [cs553x_nand] - [] ? 0xd014afff - [] ? do_one_initcall+0x21/0x111 - [] ? sys_init_module+0xe4/0x1261 - [] ? task_work_run+0x36/0x43 - [] ? syscall_call+0x7/0xb -Code: fa ff ff c7 86 d8 00 00 00 01 00 00 00 e9 5f fc ff ff 68 f8 26 2e c1 e8 a7 -EIP: [] nand_scan_tail+0x64c/0x69c SS:ESP 0068:cdd17e48 - -Initialising ecc.strength before the call to nand_scan() fixes this. - -Signed-off-by: Nathan Williams -Acked-by: Brian Norris -Acked-by: Mike Dunn -Signed-off-by: Artem Bityutskiy -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/mtd/nand/cs553x_nand.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/mtd/nand/cs553x_nand.c -+++ b/drivers/mtd/nand/cs553x_nand.c -@@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs - this->ecc.hwctl = cs_enable_hwecc; - this->ecc.calculate = cs_calculate_ecc; - this->ecc.correct = nand_correct_data; -+ this->ecc.strength = 1; - - /* Enable the following for a flash based bad block table */ - this->bbt_options = NAND_BBT_USE_FLASH; -@@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs - goto out_ior; - } - -- this->ecc.strength = 1; -- - new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); - - cs553x_mtd[cs] = new_mtd; -From 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 Mon Sep 17 00:00:00 2001 -From: Wolfram Sang -Date: Wed, 5 Dec 2012 21:46:02 +0100 -Subject: mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems - -From: Wolfram Sang - -commit 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 upstream. - -It could happen (1 out of 100 times) that NAND did not start up -correctly after warm rebooting, so the kernel could not find the UBI or -DMA timed out due to a stalled BCH. When resetting BCH together with -GPMI, the issue could not be observed anymore (after 10000+ reboots). We -probably need the consistent state already before sending any command to -NAND, even when no ECC is needed. I chose to keep the extra reset for -BCH when changing the flash layout to be on the safe side. - -Signed-off-by: Wolfram Sang -Acked-by: Huang Shijie -Signed-off-by: Artem Bityutskiy -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c -+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c -@@ -166,6 +166,15 @@ int gpmi_init(struct gpmi_nand_data *thi - if (ret) - goto err_out; - -+ /* -+ * Reset BCH here, too. We got failures otherwise :( -+ * See later BCH reset for explanation of MX23 handling -+ */ -+ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); -+ if (ret) -+ goto err_out; -+ -+ - /* Choose NAND mode. */ - writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); - -From bd1ee804af8bdf2fd5131234330615f8aecbd9ed Mon Sep 17 00:00:00 2001 -From: Pawel Moll -Date: Mon, 29 Oct 2012 11:23:02 +0000 -Subject: kbuild: Do not remove vmlinux when cleaning external module - -From: Pawel Moll - -commit bd1ee804af8bdf2fd5131234330615f8aecbd9ed upstream. - -Since commit 1f2bfbd00e466ff3489b2ca5cc75b1cccd14c123 "kbuild: -link of vmlinux moved to a script" make clean with M= -argument (so cleaning external module) removes vmlinux, -System.map and couple of other files from the *main* kernel -build directory! This not what was happening before and almost -certainly not what one would expect. - -This patch moves makes the clean target of the script called -only when !KBUILD_EXTMOD. - -Signed-off-by: Pawel Moll -Signed-off-by: Michal Marek -Signed-off-by: Greg Kroah-Hartman - ---- - Makefile | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/Makefile -+++ b/Makefile -@@ -1021,11 +1021,14 @@ clean: rm-dirs := $(CLEAN_DIRS) - clean: rm-files := $(CLEAN_FILES) - clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples) - --PHONY += $(clean-dirs) clean archclean -+PHONY += $(clean-dirs) clean archclean vmlinuxclean - $(clean-dirs): - $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) - --clean: archclean -+vmlinuxclean: -+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean -+ -+clean: archclean vmlinuxclean - - # mrproper - Delete all generated files, including .config - # -@@ -1252,7 +1255,6 @@ scripts: ; - endif # KBUILD_EXTMOD - - clean: $(clean-dirs) -- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean - $(call cmd,rmdirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ -From ca2e16faa7378878c1522a7c1b6c38211de3331d Mon Sep 17 00:00:00 2001 -From: Tomi Valkeinen -Date: Thu, 22 Nov 2012 10:39:56 +0200 -Subject: OMAP: board-files: fix i2c_bus for tfp410 - -From: Tomi Valkeinen - -commit ca2e16faa7378878c1522a7c1b6c38211de3331d upstream. - -The i2c handling in tfp410 driver, which handles converting parallel RGB -to DVI, was changed in 958f2717b84e88bf833d996997fda8f73276f2af -(OMAPDSS: TFP410: pdata rewrite). The patch changed what value the -driver considers as invalid/undefined. Before the patch, 0 was the -invalid value, but as 0 is a valid bus number, the patch changed this to --1. - -However, the fact was missed that many board files do not define the bus -number at all, thus it's left to 0. This causes the driver to fail to -get the i2c bus, exiting from the driver's probe with an error, meaning -that the DVI output does not work for those boards. - -This patch fixes the issue by changing the i2c_bus number field in the -driver's platform data from u16 to int, and setting the bus number to -1 -in the board files for the boards that did not define the bus. The -exception is devkit8000, for which the bus is set to 1, which is the -correct bus for that board. - -The bug exists in v3.5+ kernels. - -Signed-off-by: Tomi Valkeinen -Reported-by: Thomas Weber -Cc: Thomas Weber -Signed-off-by: Tony Lindgren -Signed-off-by: Greg Kroah-Hartman - ---- - arch/arm/mach-omap2/board-3430sdp.c | 1 + - arch/arm/mach-omap2/board-am3517evm.c | 1 + - arch/arm/mach-omap2/board-cm-t35.c | 1 + - arch/arm/mach-omap2/board-devkit8000.c | 1 + - arch/arm/mach-omap2/board-omap3evm.c | 1 + - arch/arm/mach-omap2/board-omap3stalker.c | 1 + - include/video/omap-panel-tfp410.h | 2 +- - 7 files changed, 7 insertions(+), 1 deletion(-) - ---- a/arch/arm/mach-omap2/board-3430sdp.c -+++ b/arch/arm/mach-omap2/board-3430sdp.c -@@ -157,6 +157,7 @@ static struct omap_dss_device sdp3430_lc - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = -1, -+ .i2c_bus_num = -1, - }; - - static struct omap_dss_device sdp3430_dvi_device = { ---- a/arch/arm/mach-omap2/board-am3517evm.c -+++ b/arch/arm/mach-omap2/board-am3517evm.c -@@ -208,6 +208,7 @@ static struct omap_dss_device am3517_evm - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = -1, -+ .i2c_bus_num = -1, - }; - - static struct omap_dss_device am3517_evm_dvi_device = { ---- a/arch/arm/mach-omap2/board-cm-t35.c -+++ b/arch/arm/mach-omap2/board-cm-t35.c -@@ -243,6 +243,7 @@ static struct omap_dss_device cm_t35_lcd - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = CM_T35_DVI_EN_GPIO, -+ .i2c_bus_num = -1, - }; - - static struct omap_dss_device cm_t35_dvi_device = { ---- a/arch/arm/mach-omap2/board-devkit8000.c -+++ b/arch/arm/mach-omap2/board-devkit8000.c -@@ -139,6 +139,7 @@ static struct omap_dss_device devkit8000 - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = -1, -+ .i2c_bus_num = 1, - }; - - static struct omap_dss_device devkit8000_dvi_device = { ---- a/arch/arm/mach-omap2/board-omap3evm.c -+++ b/arch/arm/mach-omap2/board-omap3evm.c -@@ -236,6 +236,7 @@ static struct omap_dss_device omap3_evm_ - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = OMAP3EVM_DVI_PANEL_EN_GPIO, -+ .i2c_bus_num = -1, - }; - - static struct omap_dss_device omap3_evm_dvi_device = { ---- a/arch/arm/mach-omap2/board-omap3stalker.c -+++ b/arch/arm/mach-omap2/board-omap3stalker.c -@@ -119,6 +119,7 @@ static struct omap_dss_device omap3_stal - - static struct tfp410_platform_data dvi_panel = { - .power_down_gpio = DSS_ENABLE_GPIO, -+ .i2c_bus_num = -1, - }; - - static struct omap_dss_device omap3_stalker_dvi_device = { ---- a/include/video/omap-panel-tfp410.h -+++ b/include/video/omap-panel-tfp410.h -@@ -28,7 +28,7 @@ struct omap_dss_device; - * @power_down_gpio: gpio number for PD pin (or -1 if not available) - */ - struct tfp410_platform_data { -- u16 i2c_bus_num; -+ int i2c_bus_num; - int power_down_gpio; - }; - -From 642fe4d00db56d65060ce2fd4c105884414acb16 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Thu, 8 Nov 2012 10:01:26 -0500 -Subject: SUNRPC: Fix validity issues with rpc_pipefs sb->s_fs_info - -From: Trond Myklebust - -commit 642fe4d00db56d65060ce2fd4c105884414acb16 upstream. - -rpc_kill_sb() must defer calling put_net() until after the notifier -has been called, since most (all?) of the notifier callbacks assume -that sb->s_fs_info points to a valid net namespace. It also must not -call put_net() if the call to rpc_fill_super was unsuccessful. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48421 - -Signed-off-by: Trond Myklebust -Cc: Stanislav Kinsbursky -Signed-off-by: Greg Kroah-Hartman - ---- - net/sunrpc/rpc_pipe.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - ---- a/net/sunrpc/rpc_pipe.c -+++ b/net/sunrpc/rpc_pipe.c -@@ -1152,14 +1152,19 @@ static void rpc_kill_sb(struct super_blo - struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); - - mutex_lock(&sn->pipefs_sb_lock); -+ if (sn->pipefs_sb != sb) { -+ mutex_unlock(&sn->pipefs_sb_lock); -+ goto out; -+ } - sn->pipefs_sb = NULL; - mutex_unlock(&sn->pipefs_sb_lock); -- put_net(net); - dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", - net, NET_NAME(net)); - blocking_notifier_call_chain(&rpc_pipefs_notifier_list, - RPC_PIPEFS_UMOUNT, - sb); -+ put_net(net); -+out: - kill_litter_super(sb); - } - -From cd6c5968582a273561464fe6b1e8cc8214be02df Mon Sep 17 00:00:00 2001 -From: Stanislav Kinsbursky -Date: Mon, 17 Dec 2012 20:18:52 +0300 -Subject: SUNRPC: continue run over clients list on PipeFS event instead of break - -From: Stanislav Kinsbursky - -commit cd6c5968582a273561464fe6b1e8cc8214be02df upstream. - -There are SUNRPC clients, which program doesn't have pipe_dir_name. These -clients can be skipped on PipeFS events, because nothing have to be created or -destroyed. But instead of breaking in case of such a client was found, search -for suitable client over clients list have to be continued. Otherwise some -clients could not be covered by PipeFS event handler. - -Signed-off-by: Stanislav Kinsbursky -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - net/sunrpc/clnt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/sunrpc/clnt.c -+++ b/net/sunrpc/clnt.c -@@ -234,7 +234,7 @@ static struct rpc_clnt *rpc_get_client_f - spin_lock(&sn->rpc_client_lock); - list_for_each_entry(clnt, &sn->all_clients, cl_clients) { - if (clnt->cl_program->pipe_dir_name == NULL) -- break; -+ continue; - if (rpc_clnt_skip_event(clnt, event)) - continue; - if (atomic_inc_not_zero(&clnt->cl_count) == 0) -From 621eb19ce1ec216e03ad354cb0c4061736b2a436 Mon Sep 17 00:00:00 2001 -From: "J. Bruce Fields" -Date: Wed, 14 Nov 2012 10:48:05 -0500 -Subject: svcrpc: Revert "sunrpc/cache.h: replace simple_strtoul" - -From: "J. Bruce Fields" - -commit 621eb19ce1ec216e03ad354cb0c4061736b2a436 upstream. - -Commit bbf43dc888833ac0539e437dbaeb28bfd4fbab9f "sunrpc/cache.h: replace -simple_strtoul" introduced new range-checking which could cause get_int -to fail on unsigned integers too large to be represented as an int. - -We could parse them as unsigned instead--but it turns out svcgssd is -actually passing down "-1" in some cases. Which is perhaps stupid, but -there's nothing we can do about it now. - -So just revert back to the previous "sloppy" behavior that accepts -either representation. - -Reported-by: Sven Geggus -Signed-off-by: J. Bruce Fields -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/sunrpc/cache.h | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/include/linux/sunrpc/cache.h -+++ b/include/linux/sunrpc/cache.h -@@ -217,6 +217,8 @@ extern int qword_get(char **bpp, char *d - static inline int get_int(char **bpp, int *anint) - { - char buf[50]; -+ char *ep; -+ int rv; - int len = qword_get(bpp, buf, sizeof(buf)); - - if (len < 0) -@@ -224,9 +226,11 @@ static inline int get_int(char **bpp, in - if (len == 0) - return -ENOENT; - -- if (kstrtoint(buf, 0, anint)) -+ rv = simple_strtol(buf, &ep, 0); -+ if (*ep) - return -EINVAL; - -+ *anint = rv; - return 0; - } - -From c6567ed1402c55e19b012e66a8398baec2a726f3 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Fri, 4 Jan 2013 12:23:21 -0500 -Subject: SUNRPC: Ensure that we free the rpc_task after cleanups are done - -From: Trond Myklebust - -commit c6567ed1402c55e19b012e66a8398baec2a726f3 upstream. - -This patch ensures that we free the rpc_task after the cleanup callbacks -are done in order to avoid a deadlock problem that can be triggered if -the callback needs to wait for another workqueue item to complete. - -Signed-off-by: Trond Myklebust -Cc: Weston Andros Adamson -Cc: Tejun Heo -Cc: Bruce Fields -Signed-off-by: Greg Kroah-Hartman - ---- - net/sunrpc/sched.c | 27 +++++++++++++++++++++++---- - 1 file changed, 23 insertions(+), 4 deletions(-) - ---- a/net/sunrpc/sched.c -+++ b/net/sunrpc/sched.c -@@ -919,16 +919,35 @@ struct rpc_task *rpc_new_task(const stru - return task; - } - -+/* -+ * rpc_free_task - release rpc task and perform cleanups -+ * -+ * Note that we free up the rpc_task _after_ rpc_release_calldata() -+ * in order to work around a workqueue dependency issue. -+ * -+ * Tejun Heo states: -+ * "Workqueue currently considers two work items to be the same if they're -+ * on the same address and won't execute them concurrently - ie. it -+ * makes a work item which is queued again while being executed wait -+ * for the previous execution to complete. -+ * -+ * If a work function frees the work item, and then waits for an event -+ * which should be performed by another work item and *that* work item -+ * recycles the freed work item, it can create a false dependency loop. -+ * There really is no reliable way to detect this short of verifying -+ * every memory free." -+ * -+ */ - static void rpc_free_task(struct rpc_task *task) - { -- const struct rpc_call_ops *tk_ops = task->tk_ops; -- void *calldata = task->tk_calldata; -+ unsigned short tk_flags = task->tk_flags; - -- if (task->tk_flags & RPC_TASK_DYNAMIC) { -+ rpc_release_calldata(task->tk_ops, task->tk_calldata); -+ -+ if (tk_flags & RPC_TASK_DYNAMIC) { - dprintk("RPC: %5u freeing task\n", task->tk_pid); - mempool_free(task, rpc_task_mempool); - } -- rpc_release_calldata(tk_ops, calldata); - } - - static void rpc_async_release(struct work_struct *work) -From 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Mon, 7 Jan 2013 14:30:46 -0500 -Subject: SUNRPC: Ensure we release the socket write lock if the rpc_task exits early - -From: Trond Myklebust - -commit 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 upstream. - -If the rpc_task exits while holding the socket write lock before it has -allocated an rpc slot, then the usual mechanism for releasing the write -lock in xprt_release() is defeated. - -The problem occurs if the call to xprt_lock_write() initially fails, so -that the rpc_task is put on the xprt->sending wait queue. If the task -exits after being assigned the lock by __xprt_lock_write_func, but -before it has retried the call to xprt_lock_and_alloc_slot(), then -it calls xprt_release() while holding the write lock, but will -immediately exit due to the test for task->tk_rqstp != NULL. - -Reported-by: Chris Perl -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - net/sunrpc/sched.c | 3 +-- - net/sunrpc/xprt.c | 12 ++++++++++-- - 2 files changed, 11 insertions(+), 4 deletions(-) - ---- a/net/sunrpc/sched.c -+++ b/net/sunrpc/sched.c -@@ -957,8 +957,7 @@ static void rpc_async_release(struct wor - - static void rpc_release_resources_task(struct rpc_task *task) - { -- if (task->tk_rqstp) -- xprt_release(task); -+ xprt_release(task); - if (task->tk_msg.rpc_cred) { - put_rpccred(task->tk_msg.rpc_cred); - task->tk_msg.rpc_cred = NULL; ---- a/net/sunrpc/xprt.c -+++ b/net/sunrpc/xprt.c -@@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc - void xprt_release(struct rpc_task *task) - { - struct rpc_xprt *xprt; -- struct rpc_rqst *req; -+ struct rpc_rqst *req = task->tk_rqstp; - -- if (!(req = task->tk_rqstp)) -+ if (req == NULL) { -+ if (task->tk_client) { -+ rcu_read_lock(); -+ xprt = rcu_dereference(task->tk_client->cl_xprt); -+ if (xprt->snd_task == task) -+ xprt_release_write(xprt, task); -+ rcu_read_unlock(); -+ } - return; -+ } - - xprt = req->rq_xprt; - if (task->tk_ops->rpc_count_stats != NULL) -From 2cbba75a56ea78e6876b4e2547a882f10b3fe72b Mon Sep 17 00:00:00 2001 -From: Alexey Khoroshilov -Date: Mon, 5 Nov 2012 22:40:14 +0400 -Subject: jffs2: hold erase_completion_lock on exit - -From: Alexey Khoroshilov - -commit 2cbba75a56ea78e6876b4e2547a882f10b3fe72b upstream. - -Users of jffs2_do_reserve_space() expect they still held -erase_completion_lock after call to it. But there is a path -where jffs2_do_reserve_space() leaves erase_completion_lock unlocked. -The patch fixes it. - -Found by Linux Driver Verification project (linuxtesting.org). - -Signed-off-by: Alexey Khoroshilov -Signed-off-by: Artem Bityutskiy -Signed-off-by: Greg Kroah-Hartman - ---- - fs/jffs2/nodemgmt.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/fs/jffs2/nodemgmt.c -+++ b/fs/jffs2/nodemgmt.c -@@ -417,14 +417,16 @@ static int jffs2_do_reserve_space(struct - spin_unlock(&c->erase_completion_lock); - - ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); -- if (ret) -- return ret; -+ - /* Just lock it again and continue. Nothing much can change because - we hold c->alloc_sem anyway. In fact, it's not entirely clear why - we hold c->erase_completion_lock in the majority of this function... - but that's a question for another (more caffeine-rich) day. */ - spin_lock(&c->erase_completion_lock); - -+ if (ret) -+ return ret; -+ - waste = jeb->free_size; - jffs2_link_node_ref(c, jeb, - (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, -From 999a7c5776a0ed2133645fa7e008bec05bda9254 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 14 Dec 2012 13:10:50 +0000 -Subject: i2400m: add Intel 6150 device IDs - -From: Dan Williams - -commit 999a7c5776a0ed2133645fa7e008bec05bda9254 upstream. - -Add device IDs for WiMAX function of Intel 6150 cards. - -Signed-off-by: Dan Williams -Signed-off-by: David S. Miller -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wimax/i2400m/i2400m-usb.h | 3 +++ - drivers/net/wimax/i2400m/usb.c | 6 ++++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/net/wimax/i2400m/i2400m-usb.h -+++ b/drivers/net/wimax/i2400m/i2400m-usb.h -@@ -152,6 +152,9 @@ enum { - /* Device IDs */ - USB_DEVICE_ID_I6050 = 0x0186, - USB_DEVICE_ID_I6050_2 = 0x0188, -+ USB_DEVICE_ID_I6150 = 0x07d6, -+ USB_DEVICE_ID_I6150_2 = 0x07d7, -+ USB_DEVICE_ID_I6150_3 = 0x07d9, - USB_DEVICE_ID_I6250 = 0x0187, - }; - ---- a/drivers/net/wimax/i2400m/usb.c -+++ b/drivers/net/wimax/i2400m/usb.c -@@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface * - switch (id->idProduct) { - case USB_DEVICE_ID_I6050: - case USB_DEVICE_ID_I6050_2: -+ case USB_DEVICE_ID_I6150: -+ case USB_DEVICE_ID_I6150_2: -+ case USB_DEVICE_ID_I6150_3: - case USB_DEVICE_ID_I6250: - i2400mu->i6050 = 1; - break; -@@ -759,6 +762,9 @@ static - struct usb_device_id i2400mu_id_table[] = { - { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, - { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, -+ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, -+ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, -+ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, - { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, - { USB_DEVICE(0x8086, 0x0181) }, - { USB_DEVICE(0x8086, 0x1403) }, -From 6491d4d02893d9787ba67279595990217177b351 Mon Sep 17 00:00:00 2001 -From: "Woodhouse, David" -Date: Wed, 19 Dec 2012 13:25:35 +0000 -Subject: intel-iommu: Free old page tables before creating superpage - -From: "Woodhouse, David" - -commit 6491d4d02893d9787ba67279595990217177b351 upstream. - -The dma_pte_free_pagetable() function will only free a page table page -if it is asked to free the *entire* 2MiB range that it covers. So if a -page table page was used for one or more small mappings, it's likely to -end up still present in the page tables... but with no valid PTEs. - -This was fine when we'd only be repopulating it with 4KiB PTEs anyway -but the same virtual address range can end up being reused for a -*large-page* mapping. And in that case were were trying to insert the -large page into the second-level page table, and getting a complaint -from the sanity check in __domain_mapping() because there was already a -corresponding entry. This was *relatively* harmless; it led to a memory -leak of the old page table page, but no other ill-effects. - -Fix it by calling dma_pte_clear_range (hopefully redundant) and -dma_pte_free_pagetable() before setting up the new large page. - -Signed-off-by: David Woodhouse -Tested-by: Ravi Murty -Tested-by: Sudeep Dutt -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/iommu/intel-iommu.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c -@@ -1827,10 +1827,17 @@ static int __domain_mapping(struct dmar_ - if (!pte) - return -ENOMEM; - /* It is large page*/ -- if (largepage_lvl > 1) -+ if (largepage_lvl > 1) { - pteval |= DMA_PTE_LARGE_PAGE; -- else -+ /* Ensure that old small page tables are removed to make room -+ for superpage, if they exist. */ -+ dma_pte_clear_range(domain, iov_pfn, -+ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); -+ dma_pte_free_pagetable(domain, iov_pfn, -+ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); -+ } else { - pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; -+ } - - } - /* We don't need lock here, nobody else -From ae133a1129790ec288b429b5f08ab4701633844a Mon Sep 17 00:00:00 2001 -From: Christian König -Date: Tue, 18 Sep 2012 15:30:44 -0400 -Subject: drm/radeon: stop page faults from hanging the system (v2) - -From: Christian König - -commit ae133a1129790ec288b429b5f08ab4701633844a upstream. - -Redirect invalid memory accesses to the default page -instead of locking up the memory controller. Also -enable the invalid memory access interrupts and -start spamming system log with it. - -v2 (agd5f): fix up against 2 level PT changes - -Signed-off-by: Christian König -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen.c | 10 ++++++++++ - drivers/gpu/drm/radeon/evergreend.h | 3 +++ - drivers/gpu/drm/radeon/ni.c | 16 +++++++++++++--- - drivers/gpu/drm/radeon/nid.h | 11 +++++++++++ - drivers/gpu/drm/radeon/si.c | 25 +++++++++++++++++++++++-- - drivers/gpu/drm/radeon/sid.h | 14 ++++++++++++++ - 6 files changed, 74 insertions(+), 5 deletions(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -3093,6 +3093,16 @@ restart_ih: - break; - } - break; -+ case 146: -+ case 147: -+ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); -+ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", -+ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); -+ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", -+ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); -+ /* reset addr and status */ -+ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); -+ break; - case 176: /* CP_INT in ring buffer */ - case 177: /* CP_INT in IB1 */ - case 178: /* CP_INT in IB2 */ ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -651,6 +651,7 @@ - #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) - #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) - #define VM_CONTEXT1_CNTL 0x1414 -+#define VM_CONTEXT1_CNTL2 0x1434 - #define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C - #define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C - #define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C -@@ -672,6 +673,8 @@ - #define CACHE_UPDATE_MODE(x) ((x) << 6) - #define VM_L2_STATUS 0x140C - #define L2_BUSY (1 << 0) -+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC -+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC - - #define WAIT_UNTIL 0x8040 - ---- a/drivers/gpu/drm/radeon/ni.c -+++ b/drivers/gpu/drm/radeon/ni.c -@@ -784,10 +784,20 @@ static int cayman_pcie_gart_enable(struc - /* enable context1-7 */ - WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, - (u32)(rdev->dummy_page.addr >> 12)); -- WREG32(VM_CONTEXT1_CNTL2, 0); -- WREG32(VM_CONTEXT1_CNTL, 0); -+ WREG32(VM_CONTEXT1_CNTL2, 4); - WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | -- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); -+ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | -+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | -+ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | -+ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | -+ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ READ_PROTECTION_FAULT_ENABLE_DEFAULT | -+ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); - - cayman_pcie_gart_tlb_flush(rdev); - DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", ---- a/drivers/gpu/drm/radeon/nid.h -+++ b/drivers/gpu/drm/radeon/nid.h -@@ -80,7 +80,18 @@ - #define VM_CONTEXT0_CNTL 0x1410 - #define ENABLE_CONTEXT (1 << 0) - #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) -+#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) - #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) -+#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) -+#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) -+#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) -+#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) -+#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) -+#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) -+#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) -+#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) -+#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) -+#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) - #define VM_CONTEXT1_CNTL 0x1414 - #define VM_CONTEXT0_CNTL2 0x1430 - #define VM_CONTEXT1_CNTL2 0x1434 ---- a/drivers/gpu/drm/radeon/si.c -+++ b/drivers/gpu/drm/radeon/si.c -@@ -2426,9 +2426,20 @@ static int si_pcie_gart_enable(struct ra - /* enable context1-15 */ - WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, - (u32)(rdev->dummy_page.addr >> 12)); -- WREG32(VM_CONTEXT1_CNTL2, 0); -+ WREG32(VM_CONTEXT1_CNTL2, 4); - WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | -- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); -+ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | -+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | -+ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | -+ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | -+ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ READ_PROTECTION_FAULT_ENABLE_DEFAULT | -+ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | -+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); - - si_pcie_gart_tlb_flush(rdev); - DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", -@@ -3684,6 +3695,16 @@ restart_ih: - break; - } - break; -+ case 146: -+ case 147: -+ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); -+ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", -+ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); -+ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", -+ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); -+ /* reset addr and status */ -+ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); -+ break; - case 176: /* RINGID0 CP_INT */ - radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); - break; ---- a/drivers/gpu/drm/radeon/sid.h -+++ b/drivers/gpu/drm/radeon/sid.h -@@ -91,7 +91,18 @@ - #define VM_CONTEXT0_CNTL 0x1410 - #define ENABLE_CONTEXT (1 << 0) - #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) -+#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) - #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) -+#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) -+#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) -+#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) -+#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) -+#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) -+#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) -+#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) -+#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) -+#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) -+#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) - #define VM_CONTEXT1_CNTL 0x1414 - #define VM_CONTEXT0_CNTL2 0x1430 - #define VM_CONTEXT1_CNTL2 0x1434 -@@ -104,6 +115,9 @@ - #define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x1450 - #define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x1454 - -+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC -+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC -+ - #define VM_INVALIDATE_REQUEST 0x1478 - #define VM_INVALIDATE_RESPONSE 0x147c - -From a02dc74b317d78298cb0587b9b1f6f741fd5c139 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Tue, 13 Nov 2012 18:03:41 -0500 -Subject: drm/radeon/dce32+: use fractional fb dividers for high clocks - -From: Alex Deucher - -commit a02dc74b317d78298cb0587b9b1f6f741fd5c139 upstream. - -Fixes flickering with some high res montiors. - -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/atombios_crtc.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -561,6 +561,8 @@ static u32 atombios_adjust_pll(struct dr - /* use frac fb div on APUs */ - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; -+ if (ASIC_IS_DCE32(rdev) && mode->clock > 165000) -+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; - } else { - radeon_crtc->pll_flags |= RADEON_PLL_LEGACY; - -From 93927f9c1db5f55085457e820f0631064c7bfa34 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Tue, 4 Dec 2012 16:50:28 -0500 -Subject: drm/radeon: fix eDP clk and lane setup for scaled modes - -From: Alex Deucher - -commit 93927f9c1db5f55085457e820f0631064c7bfa34 upstream. - -Need to use the adjusted mode since we are sending native -timing and using the scaler for non-native modes. - -Signed-off-by: Alex Deucher -Reviewed-by: Jerome Glisse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/radeon/atombios_encoders.c -+++ b/drivers/gpu/drm/radeon/atombios_encoders.c -@@ -340,7 +340,7 @@ static bool radeon_atom_mode_fixup(struc - ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || - (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); -- radeon_dp_set_link_config(connector, mode); -+ radeon_dp_set_link_config(connector, adjusted_mode); - } - - return true; -From bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Tue, 11 Dec 2012 11:56:52 -0500 -Subject: drm/radeon: fix amd afusion gpu setup aka sumo v2 - -From: Jerome Glisse - -commit bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a upstream. - -Set the proper number of tile pipe that should be a multiple of -pipe depending on the number of se engine. - -Fix: -https://bugs.freedesktop.org/show_bug.cgi?id=56405 -https://bugs.freedesktop.org/show_bug.cgi?id=56720 - -v2: Don't change sumo2 - -Signed-off-by: Jerome Glisse -Reviewed-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen.c | 8 ++++---- - drivers/gpu/drm/radeon/evergreend.h | 2 ++ - 2 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1821,7 +1821,7 @@ static void evergreen_gpu_init(struct ra - case CHIP_SUMO: - rdev->config.evergreen.num_ses = 1; - rdev->config.evergreen.max_pipes = 4; -- rdev->config.evergreen.max_tile_pipes = 2; -+ rdev->config.evergreen.max_tile_pipes = 4; - if (rdev->pdev->device == 0x9648) - rdev->config.evergreen.max_simds = 3; - else if ((rdev->pdev->device == 0x9647) || -@@ -1844,7 +1844,7 @@ static void evergreen_gpu_init(struct ra - rdev->config.evergreen.sc_prim_fifo_size = 0x40; - rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; - rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; -- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; -+ gb_addr_config = SUMO_GB_ADDR_CONFIG_GOLDEN; - break; - case CHIP_SUMO2: - rdev->config.evergreen.num_ses = 1; -@@ -1866,7 +1866,7 @@ static void evergreen_gpu_init(struct ra - rdev->config.evergreen.sc_prim_fifo_size = 0x40; - rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; - rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; -- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; -+ gb_addr_config = SUMO2_GB_ADDR_CONFIG_GOLDEN; - break; - case CHIP_BARTS: - rdev->config.evergreen.num_ses = 2; -@@ -1914,7 +1914,7 @@ static void evergreen_gpu_init(struct ra - break; - case CHIP_CAICOS: - rdev->config.evergreen.num_ses = 1; -- rdev->config.evergreen.max_pipes = 4; -+ rdev->config.evergreen.max_pipes = 2; - rdev->config.evergreen.max_tile_pipes = 2; - rdev->config.evergreen.max_simds = 2; - rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -45,6 +45,8 @@ - #define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 - #define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 - #define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 -+#define SUMO_GB_ADDR_CONFIG_GOLDEN 0x02010002 -+#define SUMO2_GB_ADDR_CONFIG_GOLDEN 0x02010002 - - /* Registers */ - -From d3493574e267c203836bfdcb9c58d8af46fc0da1 Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Fri, 14 Dec 2012 16:20:46 -0500 -Subject: drm/radeon: restore modeset late in GPU reset path - -From: Jerome Glisse - -commit d3493574e267c203836bfdcb9c58d8af46fc0da1 upstream. - -Modeset path seems to conflict sometimes with the memory management -leading to kernel deadlock. This move modesetting reset after GPU -acceleration reset. - -Signed-off-by: Jerome Glisse -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon_device.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -1337,7 +1337,6 @@ retry: - } - - radeon_restore_bios_scratch_regs(rdev); -- drm_helper_resume_force_mode(rdev->ddev); - - if (!r) { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { -@@ -1362,6 +1361,8 @@ retry: - } - } - -+ drm_helper_resume_force_mode(rdev->ddev); -+ - ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - if (r) { - /* bad news, how to tell it to userspace ? */ -From 76903b96adbfbb38b049765add21e02e44c387a5 Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Mon, 17 Dec 2012 10:29:06 -0500 -Subject: drm/radeon: don't leave fence blocked process on failed GPU reset - -From: Jerome Glisse - -commit 76903b96adbfbb38b049765add21e02e44c387a5 upstream. - -Force all fence to signal if GPU reset failed so no process get stuck -on waiting fence. - -Signed-off-by: Jerome Glisse -Reviewed-by: Christian König -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon.h | 1 + - drivers/gpu/drm/radeon/radeon_device.c | 1 + - drivers/gpu/drm/radeon/radeon_fence.c | 19 +++++++++++++++++++ - 3 files changed, 21 insertions(+) - ---- a/drivers/gpu/drm/radeon/radeon.h -+++ b/drivers/gpu/drm/radeon/radeon.h -@@ -220,6 +220,7 @@ struct radeon_fence { - int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); - int radeon_fence_driver_init(struct radeon_device *rdev); - void radeon_fence_driver_fini(struct radeon_device *rdev); -+void radeon_fence_driver_force_completion(struct radeon_device *rdev); - int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); - void radeon_fence_process(struct radeon_device *rdev, int ring); - bool radeon_fence_signaled(struct radeon_fence *fence); ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -1356,6 +1356,7 @@ retry: - } - } - } else { -+ radeon_fence_driver_force_completion(rdev); - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - kfree(ring_data[i]); - } ---- a/drivers/gpu/drm/radeon/radeon_fence.c -+++ b/drivers/gpu/drm/radeon/radeon_fence.c -@@ -868,6 +868,25 @@ void radeon_fence_driver_fini(struct rad - mutex_unlock(&rdev->ring_lock); - } - -+/** -+ * radeon_fence_driver_force_completion - force all fence waiter to complete -+ * -+ * @rdev: radeon device pointer -+ * -+ * In case of GPU reset failure make sure no process keep waiting on fence -+ * that will never complete. -+ */ -+void radeon_fence_driver_force_completion(struct radeon_device *rdev) -+{ -+ int ring; -+ -+ for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { -+ if (!rdev->fence_drv[ring].initialized) -+ continue; -+ radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); -+ } -+} -+ - - /* - * Fence debugfs -From 5f8f635edd8ad5a6416bff4c5ff486500357f473 Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Mon, 17 Dec 2012 11:04:32 -0500 -Subject: drm/radeon: avoid deadlock in pm path when waiting for fence - -From: Jerome Glisse - -commit 5f8f635edd8ad5a6416bff4c5ff486500357f473 upstream. - -radeon_fence_wait_empty_locked should not trigger GPU reset as no -place where it's call from would benefit from such thing and it -actually lead to a kernel deadlock in case the reset is triggered -from pm codepath. Instead force ring completion in place where it -makes sense or return early in others. - -Signed-off-by: Jerome Glisse -Reviewed-by: Christian König -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon.h | 2 +- - drivers/gpu/drm/radeon/radeon_device.c | 13 +++++++++++-- - drivers/gpu/drm/radeon/radeon_fence.c | 30 ++++++++++++++---------------- - drivers/gpu/drm/radeon/radeon_pm.c | 15 ++++++++++++--- - 4 files changed, 38 insertions(+), 22 deletions(-) - ---- a/drivers/gpu/drm/radeon/radeon.h -+++ b/drivers/gpu/drm/radeon/radeon.h -@@ -226,7 +226,7 @@ void radeon_fence_process(struct radeon_ - bool radeon_fence_signaled(struct radeon_fence *fence); - int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); - int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); --void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); -+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); - int radeon_fence_wait_any(struct radeon_device *rdev, - struct radeon_fence **fences, - bool intr); ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -1163,6 +1163,7 @@ int radeon_suspend_kms(struct drm_device - struct drm_crtc *crtc; - struct drm_connector *connector; - int i, r; -+ bool force_completion = false; - - if (dev == NULL || dev->dev_private == NULL) { - return -ENODEV; -@@ -1205,8 +1206,16 @@ int radeon_suspend_kms(struct drm_device - - mutex_lock(&rdev->ring_lock); - /* wait for gpu to finish processing current batch */ -- for (i = 0; i < RADEON_NUM_RINGS; i++) -- radeon_fence_wait_empty_locked(rdev, i); -+ for (i = 0; i < RADEON_NUM_RINGS; i++) { -+ r = radeon_fence_wait_empty_locked(rdev, i); -+ if (r) { -+ /* delay GPU reset to resume */ -+ force_completion = true; -+ } -+ } -+ if (force_completion) { -+ radeon_fence_driver_force_completion(rdev); -+ } - mutex_unlock(&rdev->ring_lock); - - radeon_save_bios_scratch_regs(rdev); ---- a/drivers/gpu/drm/radeon/radeon_fence.c -+++ b/drivers/gpu/drm/radeon/radeon_fence.c -@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct - * Returns 0 if the fences have passed, error for all other cases. - * Caller must hold ring lock. - */ --void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) -+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) - { - uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; -+ int r; - -- while(1) { -- int r; -- r = radeon_fence_wait_seq(rdev, seq, ring, false, false); -+ r = radeon_fence_wait_seq(rdev, seq, ring, false, false); -+ if (r) { - if (r == -EDEADLK) { -- mutex_unlock(&rdev->ring_lock); -- r = radeon_gpu_reset(rdev); -- mutex_lock(&rdev->ring_lock); -- if (!r) -- continue; -- } -- if (r) { -- dev_err(rdev->dev, "error waiting for ring to become" -- " idle (%d)\n", r); -+ return -EDEADLK; - } -- return; -+ dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", -+ ring, r); - } -+ return 0; - } - - /** -@@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct rade - */ - void radeon_fence_driver_fini(struct radeon_device *rdev) - { -- int ring; -+ int ring, r; - - mutex_lock(&rdev->ring_lock); - for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { - if (!rdev->fence_drv[ring].initialized) - continue; -- radeon_fence_wait_empty_locked(rdev, ring); -+ r = radeon_fence_wait_empty_locked(rdev, ring); -+ if (r) { -+ /* no need to trigger GPU reset as we are unloading */ -+ radeon_fence_driver_force_completion(rdev); -+ } - wake_up_all(&rdev->fence_queue); - radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); - rdev->fence_drv[ring].initialized = false; ---- a/drivers/gpu/drm/radeon/radeon_pm.c -+++ b/drivers/gpu/drm/radeon/radeon_pm.c -@@ -234,7 +234,7 @@ static void radeon_set_power_state(struc - - static void radeon_pm_set_clocks(struct radeon_device *rdev) - { -- int i; -+ int i, r; - - /* no need to take locks, etc. if nothing's going to change */ - if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && -@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct - /* wait for the rings to drain */ - for (i = 0; i < RADEON_NUM_RINGS; i++) { - struct radeon_ring *ring = &rdev->ring[i]; -- if (ring->ready) -- radeon_fence_wait_empty_locked(rdev, i); -+ if (!ring->ready) { -+ continue; -+ } -+ r = radeon_fence_wait_empty_locked(rdev, i); -+ if (r) { -+ /* needs a GPU reset dont reset here */ -+ mutex_unlock(&rdev->ring_lock); -+ up_write(&rdev->pm.mclk_lock); -+ mutex_unlock(&rdev->ddev->struct_mutex); -+ return; -+ } - } - - radeon_unmap_vram_bos(rdev); -From 668bbc81baf0f34df832d8aca5c7d5e19a493c68 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Thu, 20 Dec 2012 21:19:32 -0500 -Subject: drm/radeon: add WAIT_UNTIL to evergreen VM safe reg list - -From: Alex Deucher - -commit 668bbc81baf0f34df832d8aca5c7d5e19a493c68 upstream. - -It's used in a recent mesa commit: -http://cgit.freedesktop.org/mesa/mesa/commit/?id=24b1206ab2dcd506aaac3ef656aebc8bc20cd27a -and there may be some other cases in the future where it's required. - -Signed-off-by: Alex Deucher -Reviewed-by: Jerome Glisse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen_cs.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/gpu/drm/radeon/evergreen_cs.c -+++ b/drivers/gpu/drm/radeon/evergreen_cs.c -@@ -2724,6 +2724,7 @@ static bool evergreen_vm_reg_valid(u32 r - - /* check config regs */ - switch (reg) { -+ case WAIT_UNTIL: - case GRBM_GFX_INDEX: - case CP_STRMOUT_CNTL: - case CP_COHER_CNTL: -From cafa59b9011a7790be4ddd5979419259844a165d Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Thu, 20 Dec 2012 16:35:47 -0500 -Subject: drm/radeon: add connector table for Mac G4 Silver - -From: Alex Deucher - -commit cafa59b9011a7790be4ddd5979419259844a165d upstream. - -Apple cards do not provide data tables in the vbios -so we have to hard code the connector parameters -in the driver. - -Reported-by: Albrecht Dreß -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon_combios.c | 51 ++++++++++++++++++++++++++++++++ - drivers/gpu/drm/radeon/radeon_mode.h | 3 + - 2 files changed, 53 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/radeon/radeon_combios.c -+++ b/drivers/gpu/drm/radeon/radeon_combios.c -@@ -1548,6 +1548,9 @@ bool radeon_get_legacy_connector_info_fr - of_machine_is_compatible("PowerBook6,7")) { - /* ibook */ - rdev->mode_info.connector_table = CT_IBOOK; -+ } else if (of_machine_is_compatible("PowerMac3,5")) { -+ /* PowerMac G4 Silver radeon 7500 */ -+ rdev->mode_info.connector_table = CT_MAC_G4_SILVER; - } else if (of_machine_is_compatible("PowerMac4,4")) { - /* emac */ - rdev->mode_info.connector_table = CT_EMAC; -@@ -2210,6 +2213,54 @@ bool radeon_get_legacy_connector_info_fr - DRM_MODE_CONNECTOR_SVIDEO, - &ddc_i2c, - CONNECTOR_OBJECT_ID_SVIDEO, -+ &hpd); -+ break; -+ case CT_MAC_G4_SILVER: -+ DRM_INFO("Connector Table: %d (mac g4 silver)\n", -+ rdev->mode_info.connector_table); -+ /* DVI-I - tv dac, int tmds */ -+ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); -+ hpd.hpd = RADEON_HPD_1; /* ??? */ -+ radeon_add_legacy_encoder(dev, -+ radeon_get_encoder_enum(dev, -+ ATOM_DEVICE_DFP1_SUPPORT, -+ 0), -+ ATOM_DEVICE_DFP1_SUPPORT); -+ radeon_add_legacy_encoder(dev, -+ radeon_get_encoder_enum(dev, -+ ATOM_DEVICE_CRT2_SUPPORT, -+ 2), -+ ATOM_DEVICE_CRT2_SUPPORT); -+ radeon_add_legacy_connector(dev, 0, -+ ATOM_DEVICE_DFP1_SUPPORT | -+ ATOM_DEVICE_CRT2_SUPPORT, -+ DRM_MODE_CONNECTOR_DVII, &ddc_i2c, -+ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, -+ &hpd); -+ /* VGA - primary dac */ -+ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); -+ hpd.hpd = RADEON_HPD_NONE; -+ radeon_add_legacy_encoder(dev, -+ radeon_get_encoder_enum(dev, -+ ATOM_DEVICE_CRT1_SUPPORT, -+ 1), -+ ATOM_DEVICE_CRT1_SUPPORT); -+ radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, -+ DRM_MODE_CONNECTOR_VGA, &ddc_i2c, -+ CONNECTOR_OBJECT_ID_VGA, -+ &hpd); -+ /* TV - TV DAC */ -+ ddc_i2c.valid = false; -+ hpd.hpd = RADEON_HPD_NONE; -+ radeon_add_legacy_encoder(dev, -+ radeon_get_encoder_enum(dev, -+ ATOM_DEVICE_TV1_SUPPORT, -+ 2), -+ ATOM_DEVICE_TV1_SUPPORT); -+ radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, -+ DRM_MODE_CONNECTOR_SVIDEO, -+ &ddc_i2c, -+ CONNECTOR_OBJECT_ID_SVIDEO, - &hpd); - break; - default: ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -209,7 +209,8 @@ enum radeon_connector_table { - CT_RN50_POWER, - CT_MAC_X800, - CT_MAC_G5_9600, -- CT_SAM440EP -+ CT_SAM440EP, -+ CT_MAC_G4_SILVER - }; - - enum radeon_dvo_chip { -From 0a9069d34918659bc8a89e21e69e60b2b83291a3 Mon Sep 17 00:00:00 2001 -From: Niels Ole Salscheider -Date: Thu, 3 Jan 2013 19:09:28 +0100 -Subject: drm/radeon: Properly handle DDC probe for DP bridges - -From: Niels Ole Salscheider - -commit 0a9069d34918659bc8a89e21e69e60b2b83291a3 upstream. - -DDC information can be accessed using AUX CH - -Fixes failure to probe monitors on some systems with -DP bridge chips. - -agd5f: minor fixes - -Signed-off-by: Niels Ole Salscheider -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon_connectors.c | 10 ++++++---- - drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++---- - drivers/gpu/drm/radeon/radeon_i2c.c | 10 ++++++++-- - drivers/gpu/drm/radeon/radeon_mode.h | 2 +- - 4 files changed, 24 insertions(+), 11 deletions(-) - ---- a/drivers/gpu/drm/radeon/radeon_connectors.c -+++ b/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -741,7 +741,7 @@ radeon_vga_detect(struct drm_connector * - ret = connector_status_disconnected; - - if (radeon_connector->ddc_bus) -- dret = radeon_ddc_probe(radeon_connector); -+ dret = radeon_ddc_probe(radeon_connector, false); - if (dret) { - radeon_connector->detected_by_load = false; - if (radeon_connector->edid) { -@@ -947,7 +947,7 @@ radeon_dvi_detect(struct drm_connector * - return connector->status; - - if (radeon_connector->ddc_bus) -- dret = radeon_ddc_probe(radeon_connector); -+ dret = radeon_ddc_probe(radeon_connector, false); - if (dret) { - radeon_connector->detected_by_load = false; - if (radeon_connector->edid) { -@@ -1401,7 +1401,8 @@ radeon_dp_detect(struct drm_connector *c - if (encoder) { - /* setup ddc on the bridge */ - radeon_atom_ext_encoder_setup_ddc(encoder); -- if (radeon_ddc_probe(radeon_connector)) /* try DDC */ -+ /* bridge chips are always aux */ -+ if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ - ret = connector_status_connected; - else if (radeon_connector->dac_load_detect) { /* try load detection */ - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -@@ -1419,7 +1420,8 @@ radeon_dp_detect(struct drm_connector *c - if (radeon_dp_getdpcd(radeon_connector)) - ret = connector_status_connected; - } else { -- if (radeon_ddc_probe(radeon_connector)) -+ /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ -+ if (radeon_ddc_probe(radeon_connector, false)) - ret = connector_status_connected; - } - } ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -695,10 +695,15 @@ int radeon_ddc_get_modes(struct radeon_c - if (radeon_connector->router.ddc_valid) - radeon_router_select_ddc_port(radeon_connector); - -- if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || -- (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || -- (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != -- ENCODER_OBJECT_ID_NONE)) { -+ if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != -+ ENCODER_OBJECT_ID_NONE) { -+ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; -+ -+ if (dig->dp_i2c_bus) -+ radeon_connector->edid = drm_get_edid(&radeon_connector->base, -+ &dig->dp_i2c_bus->adapter); -+ } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || -+ (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - - if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || ---- a/drivers/gpu/drm/radeon/radeon_i2c.c -+++ b/drivers/gpu/drm/radeon/radeon_i2c.c -@@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struc - * radeon_ddc_probe - * - */ --bool radeon_ddc_probe(struct radeon_connector *radeon_connector) -+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) - { - u8 out = 0x0; - u8 buf[8]; -@@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_conn - if (radeon_connector->router.ddc_valid) - radeon_router_select_ddc_port(radeon_connector); - -- ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); -+ if (use_aux) { -+ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; -+ ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); -+ } else { -+ ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); -+ } -+ - if (ret != 2) - /* Couldn't find an accessible DDC on this connector */ - return false; ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -559,7 +559,7 @@ extern void radeon_i2c_put_byte(struct r - u8 val); - extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); - extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); --extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); -+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); - extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); - - extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); -From eda85d6ad490923152544fba0473798b6cc0edf6 Mon Sep 17 00:00:00 2001 -From: Aaro Koskinen -Date: Mon, 31 Dec 2012 03:34:59 +0200 -Subject: drm/nouveau: fix init with agpgart-uninorth - -From: Aaro Koskinen - -commit eda85d6ad490923152544fba0473798b6cc0edf6 upstream. - -Check that the AGP aperture can be mapped. This follows a similar change -done for Radeon (commit 365048ff, drm/radeon: AGP memory is only I/O if -the aperture can be mapped by the CPU.). - -The patch fixes the following error seen on G5 iMac: - - nouveau E[ DRM] failed to create kernel channel, -12 - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58806 -Reviewed-by: Michel Dänzer -Signed-off-by: Aaro Koskinen -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/nouveau/nouveau_bo.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -1279,7 +1279,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo - if (drm->agp.stat == ENABLED) { - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = drm->agp.base; -- mem->bus.is_iomem = true; -+ mem->bus.is_iomem = !dev->agp->cant_use_aperture; - } - #endif - break; -From 13888d78c664a1f61d7b09d282f5916993827a40 Mon Sep 17 00:00:00 2001 -From: Paulo Zanoni -Date: Tue, 20 Nov 2012 13:27:41 -0200 -Subject: drm/i915: make the panel fitter work on pipes B and C on IVB - -From: Paulo Zanoni - -commit 13888d78c664a1f61d7b09d282f5916993827a40 upstream. - -I actually found this problem on Haswell, but then discovered Ivy -Bridge also has it by reading the spec. - -I don't have the hardware to test this. - -Signed-off-by: Paulo Zanoni -Reviewed-by: Damien Lespiau -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_reg.h | 2 ++ - drivers/gpu/drm/i915/intel_display.c | 6 +++++- - 2 files changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/i915/i915_reg.h -+++ b/drivers/gpu/drm/i915/i915_reg.h -@@ -3315,6 +3315,8 @@ - #define _PFA_CTL_1 0x68080 - #define _PFB_CTL_1 0x68880 - #define PF_ENABLE (1<<31) -+#define PF_PIPE_SEL_MASK_IVB (3<<29) -+#define PF_PIPE_SEL_IVB(pipe) ((pipe)<<29) - #define PF_FILTER_MASK (3<<23) - #define PF_FILTER_PROGRAMMED (0<<23) - #define PF_FILTER_MED_3x3 (1<<23) ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -3225,7 +3225,11 @@ static void ironlake_crtc_enable(struct - * as some pre-programmed values are broken, - * e.g. x201. - */ -- I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); -+ if (IS_IVYBRIDGE(dev)) -+ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | -+ PF_PIPE_SEL_IVB(pipe)); -+ else -+ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); - I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); - I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); - } -From 8fb74b9fb2b182d54beee592350d9ea1f325917a Mon Sep 17 00:00:00 2001 -From: Mel Gorman -Date: Fri, 11 Jan 2013 14:32:16 -0800 -Subject: mm: compaction: partially revert capture of suitable high-order page - -From: Mel Gorman - -commit 8fb74b9fb2b182d54beee592350d9ea1f325917a upstream. - -Eric Wong reported on 3.7 and 3.8-rc2 that ppoll() got stuck when -waiting for POLLIN on a local TCP socket. It was easier to trigger if -there was disk IO and dirty pages at the same time and he bisected it to -commit 1fb3f8ca0e92 ("mm: compaction: capture a suitable high-order page -immediately when it is made available"). - -The intention of that patch was to improve high-order allocations under -memory pressure after changes made to reclaim in 3.6 drastically hurt -THP allocations but the approach was flawed. For Eric, the problem was -that page->pfmemalloc was not being cleared for captured pages leading -to a poor interaction with swap-over-NFS support causing the packets to -be dropped. However, I identified a few more problems with the patch -including the fact that it can increase contention on zone->lock in some -cases which could result in async direct compaction being aborted early. - -In retrospect the capture patch took the wrong approach. What it should -have done is mark the pageblock being migrated as MIGRATE_ISOLATE if it -was allocating for THP and avoided races that way. While the patch was -showing to improve allocation success rates at the time, the benefit is -marginal given the relative complexity and it should be revisited from -scratch in the context of the other reclaim-related changes that have -taken place since the patch was first written and tested. This patch -partially reverts commit 1fb3f8ca0e92 ("mm: compaction: capture a -suitable high-order page immediately when it is made available"). - -Reported-and-tested-by: Eric Wong -Tested-by: Eric Dumazet -Signed-off-by: Mel Gorman -Cc: David Miller -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/compaction.h | 4 - - include/linux/mm.h | 1 - mm/compaction.c | 92 ++++++--------------------------------------- - mm/internal.h | 1 - mm/page_alloc.c | 35 +++-------------- - 5 files changed, 23 insertions(+), 110 deletions(-) - ---- a/include/linux/compaction.h -+++ b/include/linux/compaction.h -@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct - extern int fragmentation_index(struct zone *zone, unsigned int order); - extern unsigned long try_to_compact_pages(struct zonelist *zonelist, - int order, gfp_t gfp_mask, nodemask_t *mask, -- bool sync, bool *contended, struct page **page); -+ bool sync, bool *contended); - extern int compact_pgdat(pg_data_t *pgdat, int order); - extern void reset_isolation_suitable(pg_data_t *pgdat); - extern unsigned long compaction_suitable(struct zone *zone, int order); -@@ -75,7 +75,7 @@ static inline bool compaction_restarting - #else - static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, - int order, gfp_t gfp_mask, nodemask_t *nodemask, -- bool sync, bool *contended, struct page **page) -+ bool sync, bool *contended) - { - return COMPACT_CONTINUE; - } ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pa - - void split_page(struct page *page, unsigned int order); - int split_free_page(struct page *page); --int capture_free_page(struct page *page, int alloc_order, int migratetype); - - /* - * Compound pages have a destructor function. Provide a ---- a/mm/compaction.c -+++ b/mm/compaction.c -@@ -214,60 +214,6 @@ static bool suitable_migration_target(st - return false; - } - --static void compact_capture_page(struct compact_control *cc) --{ -- unsigned long flags; -- int mtype, mtype_low, mtype_high; -- -- if (!cc->page || *cc->page) -- return; -- -- /* -- * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP -- * regardless of the migratetype of the freelist is is captured from. -- * This is fine because the order for a high-order MIGRATE_MOVABLE -- * allocation is typically at least a pageblock size and overall -- * fragmentation is not impaired. Other allocation types must -- * capture pages from their own migratelist because otherwise they -- * could pollute other pageblocks like MIGRATE_MOVABLE with -- * difficult to move pages and making fragmentation worse overall. -- */ -- if (cc->migratetype == MIGRATE_MOVABLE) { -- mtype_low = 0; -- mtype_high = MIGRATE_PCPTYPES; -- } else { -- mtype_low = cc->migratetype; -- mtype_high = cc->migratetype + 1; -- } -- -- /* Speculatively examine the free lists without zone lock */ -- for (mtype = mtype_low; mtype < mtype_high; mtype++) { -- int order; -- for (order = cc->order; order < MAX_ORDER; order++) { -- struct page *page; -- struct free_area *area; -- area = &(cc->zone->free_area[order]); -- if (list_empty(&area->free_list[mtype])) -- continue; -- -- /* Take the lock and attempt capture of the page */ -- if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc)) -- return; -- if (!list_empty(&area->free_list[mtype])) { -- page = list_entry(area->free_list[mtype].next, -- struct page, lru); -- if (capture_free_page(page, cc->order, mtype)) { -- spin_unlock_irqrestore(&cc->zone->lock, -- flags); -- *cc->page = page; -- return; -- } -- } -- spin_unlock_irqrestore(&cc->zone->lock, flags); -- } -- } --} -- - /* - * Isolate free pages onto a private freelist. Caller must hold zone->lock. - * If @strict is true, will abort returning 0 on any invalid PFNs or non-free -@@ -831,6 +777,7 @@ static isolate_migrate_t isolate_migrate - static int compact_finished(struct zone *zone, - struct compact_control *cc) - { -+ unsigned int order; - unsigned long watermark; - - if (fatal_signal_pending(current)) -@@ -865,22 +812,16 @@ static int compact_finished(struct zone - return COMPACT_CONTINUE; - - /* Direct compactor: Is a suitable page free? */ -- if (cc->page) { -- /* Was a suitable page captured? */ -- if (*cc->page) -+ for (order = cc->order; order < MAX_ORDER; order++) { -+ struct free_area *area = &zone->free_area[order]; -+ -+ /* Job done if page is free of the right migratetype */ -+ if (!list_empty(&area->free_list[cc->migratetype])) -+ return COMPACT_PARTIAL; -+ -+ /* Job done if allocation would set block type */ -+ if (cc->order >= pageblock_order && area->nr_free) - return COMPACT_PARTIAL; -- } else { -- unsigned int order; -- for (order = cc->order; order < MAX_ORDER; order++) { -- struct free_area *area = &zone->free_area[cc->order]; -- /* Job done if page is free of the right migratetype */ -- if (!list_empty(&area->free_list[cc->migratetype])) -- return COMPACT_PARTIAL; -- -- /* Job done if allocation would set block type */ -- if (cc->order >= pageblock_order && area->nr_free) -- return COMPACT_PARTIAL; -- } - } - - return COMPACT_CONTINUE; -@@ -1018,9 +959,6 @@ static int compact_zone(struct zone *zon - goto out; - } - } -- -- /* Capture a page now if it is a suitable size */ -- compact_capture_page(cc); - } - - out: -@@ -1033,8 +971,7 @@ out: - - static unsigned long compact_zone_order(struct zone *zone, - int order, gfp_t gfp_mask, -- bool sync, bool *contended, -- struct page **page) -+ bool sync, bool *contended) - { - unsigned long ret; - struct compact_control cc = { -@@ -1044,7 +981,6 @@ static unsigned long compact_zone_order( - .migratetype = allocflags_to_migratetype(gfp_mask), - .zone = zone, - .sync = sync, -- .page = page, - }; - INIT_LIST_HEAD(&cc.freepages); - INIT_LIST_HEAD(&cc.migratepages); -@@ -1074,7 +1010,7 @@ int sysctl_extfrag_threshold = 500; - */ - unsigned long try_to_compact_pages(struct zonelist *zonelist, - int order, gfp_t gfp_mask, nodemask_t *nodemask, -- bool sync, bool *contended, struct page **page) -+ bool sync, bool *contended) - { - enum zone_type high_zoneidx = gfp_zone(gfp_mask); - int may_enter_fs = gfp_mask & __GFP_FS; -@@ -1100,7 +1036,7 @@ unsigned long try_to_compact_pages(struc - int status; - - status = compact_zone_order(zone, order, gfp_mask, sync, -- contended, page); -+ contended); - rc = max(status, rc); - - /* If a normal allocation would succeed, stop compacting */ -@@ -1156,7 +1092,6 @@ int compact_pgdat(pg_data_t *pgdat, int - struct compact_control cc = { - .order = order, - .sync = false, -- .page = NULL, - }; - - return __compact_pgdat(pgdat, &cc); -@@ -1167,7 +1102,6 @@ static int compact_node(int nid) - struct compact_control cc = { - .order = -1, - .sync = true, -- .page = NULL, - }; - - return __compact_pgdat(NODE_DATA(nid), &cc); ---- a/mm/internal.h -+++ b/mm/internal.h -@@ -130,7 +130,6 @@ struct compact_control { - int migratetype; /* MOVABLE, RECLAIMABLE etc */ - struct zone *zone; - bool contended; /* True if a lock was contended */ -- struct page **page; /* Page captured of requested size */ - }; - - unsigned long ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -1376,14 +1376,8 @@ void split_page(struct page *page, unsig - set_page_refcounted(page + i); - } - --/* -- * Similar to the split_page family of functions except that the page -- * required at the given order and being isolated now to prevent races -- * with parallel allocators -- */ --int capture_free_page(struct page *page, int alloc_order, int migratetype) -+static int __isolate_free_page(struct page *page, unsigned int order) - { -- unsigned int order; - unsigned long watermark; - struct zone *zone; - int mt; -@@ -1391,7 +1385,6 @@ int capture_free_page(struct page *page, - BUG_ON(!PageBuddy(page)); - - zone = page_zone(page); -- order = page_order(page); - - /* Obey watermarks as if the page was being allocated */ - watermark = low_wmark_pages(zone) + (1 << order); -@@ -1405,13 +1398,9 @@ int capture_free_page(struct page *page, - - mt = get_pageblock_migratetype(page); - if (unlikely(mt != MIGRATE_ISOLATE)) -- __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); -- -- if (alloc_order != order) -- expand(zone, page, alloc_order, order, -- &zone->free_area[order], migratetype); -+ __mod_zone_freepage_state(zone, -(1UL << order), mt); - -- /* Set the pageblock if the captured page is at least a pageblock */ -+ /* Set the pageblock if the isolated page is at least a pageblock */ - if (order >= pageblock_order - 1) { - struct page *endpage = page + (1 << order) - 1; - for (; page < endpage; page += pageblock_nr_pages) { -@@ -1422,7 +1411,7 @@ int capture_free_page(struct page *page, - } - } - -- return 1UL << alloc_order; -+ return 1UL << order; - } - - /* -@@ -1440,10 +1429,9 @@ int split_free_page(struct page *page) - unsigned int order; - int nr_pages; - -- BUG_ON(!PageBuddy(page)); - order = page_order(page); - -- nr_pages = capture_free_page(page, order, 0); -+ nr_pages = __isolate_free_page(page, order); - if (!nr_pages) - return 0; - -@@ -2148,8 +2136,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m - bool *contended_compaction, bool *deferred_compaction, - unsigned long *did_some_progress) - { -- struct page *page = NULL; -- - if (!order) - return NULL; - -@@ -2161,16 +2147,12 @@ __alloc_pages_direct_compact(gfp_t gfp_m - current->flags |= PF_MEMALLOC; - *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, - nodemask, sync_migration, -- contended_compaction, &page); -+ contended_compaction); - current->flags &= ~PF_MEMALLOC; - -- /* If compaction captured a page, prep and use it */ -- if (page) { -- prep_new_page(page, order, gfp_mask); -- goto got_page; -- } -- - if (*did_some_progress != COMPACT_SKIPPED) { -+ struct page *page; -+ - /* Page migration frees to the PCP lists but we want merging */ - drain_pages(get_cpu()); - put_cpu(); -@@ -2180,7 +2162,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m - alloc_flags & ~ALLOC_NO_WATERMARKS, - preferred_zone, migratetype); - if (page) { --got_page: - preferred_zone->compact_blockskip_flush = false; - preferred_zone->compact_considered = 0; - preferred_zone->compact_defer_shift = 0; -From e7d841ca03b7ab668620045cd7b428eda9f41601 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Mon, 3 Dec 2012 11:36:30 +0000 -Subject: drm/i915: Close race between processing unpin task and queueing the flip - -From: Chris Wilson - -commit e7d841ca03b7ab668620045cd7b428eda9f41601 upstream. - -Before queuing the flip but crucially after attaching the unpin-work to -the crtc, we continue to setup the unpin-work. However, should the -hardware fire early, we see the connected unpin-work and queue the task. -The task then promptly runs and unpins the fb before we finish taking -the required references or even pinning it... Havoc. - -To close the race, we use the flip-pending atomic to indicate when the -flip is finally setup and enqueued. So during the flip-done processing, -we can check more accurately whether the flip was expected. - -v2: Add the appropriate mb() to ensure that the writes to the page-flip -worker are complete prior to marking it active and emitting the MI_FLIP. -On the read side, the mb should be enforced by the spinlocks. - -Signed-off-by: Chris Wilson -[danvet: Review the barriers a bit, we need a write barrier both -before and after updating ->pending. Similarly we need a read barrier -in the interrupt handler both before and after reading ->pending. With -well-ordered irqs only one barrier in each place should be required, -but since this patch explicitly sets out to combat spurious interrupts -with is staged activation of the unpin work we need to go full-bore on -the barriers, too. Discussed with Chris Wilson on irc and changes -acked by him.] -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- - drivers/gpu/drm/i915/i915_irq.c | 4 ++- - drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++++++++++++++------- - drivers/gpu/drm/i915/intel_drv.h | 5 +++- - 4 files changed, 41 insertions(+), 11 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_debugfs.c -+++ b/drivers/gpu/drm/i915/i915_debugfs.c -@@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct - seq_printf(m, "No flip due on pipe %c (plane %c)\n", - pipe, plane); - } else { -- if (!work->pending) { -+ if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { - seq_printf(m, "Flip queued on pipe %c (plane %c)\n", - pipe, plane); - } else { -@@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct - seq_printf(m, "Stall check enabled, "); - else - seq_printf(m, "Stall check waiting for page flip ioctl, "); -- seq_printf(m, "%d prepares\n", work->pending); -+ seq_printf(m, "%d prepares\n", atomic_read(&work->pending)); - - if (work->old_fb_obj) { - struct drm_i915_gem_object *obj = work->old_fb_obj; ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -1464,7 +1464,9 @@ static void i915_pageflip_stall_check(st - spin_lock_irqsave(&dev->event_lock, flags); - work = intel_crtc->unpin_work; - -- if (work == NULL || work->pending || !work->enable_stall_check) { -+ if (work == NULL || -+ atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE || -+ !work->enable_stall_check) { - /* Either the pending flip IRQ arrived, or we're too early. Don't check */ - spin_unlock_irqrestore(&dev->event_lock, flags); - return; ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -6215,11 +6215,18 @@ static void do_intel_finish_page_flip(st - - spin_lock_irqsave(&dev->event_lock, flags); - work = intel_crtc->unpin_work; -- if (work == NULL || !work->pending) { -+ -+ /* Ensure we don't miss a work->pending update ... */ -+ smp_rmb(); -+ -+ if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { - spin_unlock_irqrestore(&dev->event_lock, flags); - return; - } - -+ /* and that the unpin work is consistent wrt ->pending. */ -+ smp_rmb(); -+ - intel_crtc->unpin_work = NULL; - - if (work->event) { -@@ -6272,16 +6279,25 @@ void intel_prepare_page_flip(struct drm_ - to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); - unsigned long flags; - -+ /* NB: An MMIO update of the plane base pointer will also -+ * generate a page-flip completion irq, i.e. every modeset -+ * is also accompanied by a spurious intel_prepare_page_flip(). -+ */ - spin_lock_irqsave(&dev->event_lock, flags); -- if (intel_crtc->unpin_work) { -- if ((++intel_crtc->unpin_work->pending) > 1) -- DRM_ERROR("Prepared flip multiple times\n"); -- } else { -- DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); -- } -+ if (intel_crtc->unpin_work) -+ atomic_inc_not_zero(&intel_crtc->unpin_work->pending); - spin_unlock_irqrestore(&dev->event_lock, flags); - } - -+inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) -+{ -+ /* Ensure that the work item is consistent when activating it ... */ -+ smp_wmb(); -+ atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING); -+ /* and that it is marked active as soon as the irq could fire. */ -+ smp_wmb(); -+} -+ - static int intel_gen2_queue_flip(struct drm_device *dev, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, -@@ -6315,6 +6331,8 @@ static int intel_gen2_queue_flip(struct - intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); - intel_ring_emit(ring, 0); /* aux display base address, unused */ -+ -+ intel_mark_page_flip_active(intel_crtc); - intel_ring_advance(ring); - return 0; - -@@ -6355,6 +6373,7 @@ static int intel_gen3_queue_flip(struct - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); - intel_ring_emit(ring, MI_NOOP); - -+ intel_mark_page_flip_active(intel_crtc); - intel_ring_advance(ring); - return 0; - -@@ -6401,6 +6420,8 @@ static int intel_gen4_queue_flip(struct - pf = 0; - pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - intel_ring_emit(ring, pf | pipesrc); -+ -+ intel_mark_page_flip_active(intel_crtc); - intel_ring_advance(ring); - return 0; - -@@ -6443,6 +6464,8 @@ static int intel_gen6_queue_flip(struct - pf = 0; - pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - intel_ring_emit(ring, pf | pipesrc); -+ -+ intel_mark_page_flip_active(intel_crtc); - intel_ring_advance(ring); - return 0; - -@@ -6497,6 +6520,8 @@ static int intel_gen7_queue_flip(struct - intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); - intel_ring_emit(ring, (MI_NOOP)); -+ -+ intel_mark_page_flip_active(intel_crtc); - intel_ring_advance(ring); - return 0; - ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -384,7 +384,10 @@ struct intel_unpin_work { - struct drm_i915_gem_object *old_fb_obj; - struct drm_i915_gem_object *pending_flip_obj; - struct drm_pending_vblank_event *event; -- int pending; -+ atomic_t pending; -+#define INTEL_FLIP_INACTIVE 0 -+#define INTEL_FLIP_PENDING 1 -+#define INTEL_FLIP_COMPLETE 2 - bool enable_stall_check; - }; - -From b4a98e57fc27854b5938fc8b08b68e5e68b91e1f Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Thu, 1 Nov 2012 09:26:26 +0000 -Subject: drm/i915: Flush outstanding unpin tasks before pageflipping - -From: Chris Wilson - -commit b4a98e57fc27854b5938fc8b08b68e5e68b91e1f upstream. - -If we accumulate unpin tasks because we are pageflipping faster than the -system can schedule its workers, we can effectively create a -pin-leak. The solution taken here is to limit the number of unpin tasks -we have per-crtc and to flush those outstanding tasks if we accumulate -too many. This should prevent any jitter in the normal case, and also -prevent the hang if we should run too fast. - -Note: It is important that we switch from the system workqueue to our -own dev_priv->wq since all work items on that queue are guaranteed to -only need the dev->struct_mutex and not any modeset resources. For -otherwise if we have a work item ahead in the queue which needs the -modeset lock (like the output detect work used by both polling or -hpd), this work and so the unpin work will never execute since the -pageflip code already holds that lock. Unfortunately there's no -lockdep support for this scenario in the workqueue code. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46991 -Reported-and-tested-by: Tvrtko Ursulin -Signed-off-by: Chris Wilson -[danvet: Added note about workqueu deadlock.] -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56337 -Signed-off-by: Daniel Vetter -Tested-by: Daniel Gnoutcheff -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++------ - drivers/gpu/drm/i915/intel_drv.h | 4 +++- - 2 files changed, 19 insertions(+), 7 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -6187,14 +6187,19 @@ static void intel_unpin_work_fn(struct w - { - struct intel_unpin_work *work = - container_of(__work, struct intel_unpin_work, work); -+ struct drm_device *dev = work->crtc->dev; - -- mutex_lock(&work->dev->struct_mutex); -+ mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(work->old_fb_obj); - drm_gem_object_unreference(&work->pending_flip_obj->base); - drm_gem_object_unreference(&work->old_fb_obj->base); - -- intel_update_fbc(work->dev); -- mutex_unlock(&work->dev->struct_mutex); -+ intel_update_fbc(dev); -+ mutex_unlock(&dev->struct_mutex); -+ -+ BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0); -+ atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count); -+ - kfree(work); - } - -@@ -6249,9 +6254,9 @@ static void do_intel_finish_page_flip(st - - atomic_clear_mask(1 << intel_crtc->plane, - &obj->pending_flip.counter); -- - wake_up(&dev_priv->pending_flip_queue); -- schedule_work(&work->work); -+ -+ queue_work(dev_priv->wq, &work->work); - - trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); - } -@@ -6570,7 +6575,7 @@ static int intel_crtc_page_flip(struct d - return -ENOMEM; - - work->event = event; -- work->dev = crtc->dev; -+ work->crtc = crtc; - intel_fb = to_intel_framebuffer(crtc->fb); - work->old_fb_obj = intel_fb->obj; - INIT_WORK(&work->work, intel_unpin_work_fn); -@@ -6595,6 +6600,9 @@ static int intel_crtc_page_flip(struct d - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; - -+ if (atomic_read(&intel_crtc->unpin_work_count) >= 2) -+ flush_workqueue(dev_priv->wq); -+ - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto cleanup; -@@ -6613,6 +6621,7 @@ static int intel_crtc_page_flip(struct d - * the flip occurs and the object is no longer visible. - */ - atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); -+ atomic_inc(&intel_crtc->unpin_work_count); - - ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); - if (ret) -@@ -6627,6 +6636,7 @@ static int intel_crtc_page_flip(struct d - return 0; - - cleanup_pending: -+ atomic_dec(&intel_crtc->unpin_work_count); - atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); - drm_gem_object_unreference(&work->old_fb_obj->base); - drm_gem_object_unreference(&obj->base); ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -198,6 +198,8 @@ struct intel_crtc { - struct intel_unpin_work *unpin_work; - int fdi_lanes; - -+ atomic_t unpin_work_count; -+ - /* Display surface base address adjustement for pageflips. Note that on - * gen4+ this only adjusts up to a tile, offsets within a tile are - * handled in the hw itself (with the TILEOFF register). */ -@@ -380,7 +382,7 @@ intel_get_crtc_for_plane(struct drm_devi - - struct intel_unpin_work { - struct work_struct work; -- struct drm_device *dev; -+ struct drm_crtc *crtc; - struct drm_i915_gem_object *old_fb_obj; - struct drm_i915_gem_object *pending_flip_obj; - struct drm_pending_vblank_event *event; -From b0a2658acb5bf9ca86b4aab011b7106de3af0add Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Tue, 18 Dec 2012 09:37:54 +0100 -Subject: drm/i915: don't disable disconnected outputs - -From: Daniel Vetter - -commit b0a2658acb5bf9ca86b4aab011b7106de3af0add upstream. - -This piece of neat lore has been ported painstakingly and bug-for-bug -compatible from the old crtc helper code. - -Imo it's utter nonsense. - -If you disconnected a cable and before you reconnect it, userspace (or -the kernel) does an set_crtc call, this will result in that connector -getting disabled. Which will result in a nice black screen when -plugging in the cable again. - -There's absolutely no reason the kernel does such policy enforcements -- if userspace tries to set up a mode on something disconnected we -might fail loudly (since the dp link training fails), but silently -adjusting the output configuration behind userspace's back is a recipe -for disaster. Specifically I think that this could explain some of our -MI_WAIT hangs around suspend, where userspace issues a scanline wait -on a disable pipe. This mechanisims here could explain how that pipe -got disabled without userspace noticing. - -Note that this fixes a NULL deref at BIOS takeover when the firmware -sets up a disconnected output in a clone configuration with a -connected output on the 2nd pipe: When doing the full modeset we don't -have a mode for the 2nd pipe and OOPS. On the first pipe this doesn't -matter, since at boot-up the fbdev helpers will set up the choosen -configuration on that on first. Since this is now the umptenth bug -around handling this imo brain-dead semantics correctly, I think it's -time to kill it and see whether there's any userspace out there which -relies on this. - -It also nicely demonstrates that we have a tiny window where DP -hotplug can still kill the driver. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58396 -Tested-by: Peter Ujfalusi -Reviewed-by: Rodrigo Vivi -Reviewed-by: Jesse Barnes -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_display.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -7298,10 +7298,6 @@ intel_modeset_stage_output_state(struct - DRM_DEBUG_KMS("encoder changed, full mode switch\n"); - config->mode_changed = true; - } -- -- /* Disable all disconnected encoders. */ -- if (connector->base.status == connector_status_disconnected) -- connector->new_encoder = NULL; - } - /* connector->new_encoder is now updated for all connectors. */ - -From 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Thu, 20 Dec 2012 10:51:09 +1000 -Subject: drm/i915: fix flags in dma buf exporting - -From: Dave Airlie - -commit 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 upstream. - -As pointed out by Seung-Woo Kim this should have been -passing flags like nouveau/radeon have. - -Signed-off-by: Dave Airlie -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c -+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c -@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(st - { - struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); - -- return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600); -+ return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags); - } - - static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) -From be8a42ae60addd8b6092535c11b42d099d6470ec Mon Sep 17 00:00:00 2001 -From: Seung-Woo Kim -Date: Thu, 27 Sep 2012 15:30:06 +0900 -Subject: drm/prime: drop reference on imported dma-buf come from gem - -From: Seung-Woo Kim - -commit be8a42ae60addd8b6092535c11b42d099d6470ec upstream. - -Increasing ref counts of both dma-buf and gem for imported dma-buf come from gem -makes memory leak. release function of dma-buf cannot be called because f_count -of dma-buf increased by importing gem and gem ref count cannot be decrease -because of exported dma-buf. - -So I add dma_buf_put() for imported gem come from its own gem into each drivers -having prime_import and prime_export capabilities. With this, only gem ref -count is increased if importing gem exported from gem of same driver. - -Signed-off-by: Seung-Woo Kim -Signed-off-by: Kyungmin.park -Cc: Inki Dae -Cc: Daniel Vetter -Cc: Rob Clark -Cc: Alex Deucher -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 5 +++++ - drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 +++++ - drivers/gpu/drm/nouveau/nouveau_prime.c | 1 + - drivers/gpu/drm/radeon/radeon_prime.c | 1 + - drivers/staging/omapdrm/omap_gem_dmabuf.c | 5 +++++ - 5 files changed, 17 insertions(+) - ---- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c -+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c -@@ -210,7 +210,12 @@ struct drm_gem_object *exynos_dmabuf_pri - - /* is it from our device? */ - if (obj->dev == drm_dev) { -+ /* -+ * Importing dmabuf exported from out own gem increases -+ * refcount on gem itself instead of f_count of dmabuf. -+ */ - drm_gem_object_reference(obj); -+ dma_buf_put(dma_buf); - return obj; - } - } ---- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c -+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c -@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_im - obj = dma_buf->priv; - /* is it from our device? */ - if (obj->base.dev == dev) { -+ /* -+ * Importing dmabuf exported from out own gem increases -+ * refcount on gem itself instead of f_count of dmabuf. -+ */ - drm_gem_object_reference(&obj->base); -+ dma_buf_put(dma_buf); - return &obj->base; - } - } ---- a/drivers/gpu/drm/nouveau/nouveau_prime.c -+++ b/drivers/gpu/drm/nouveau/nouveau_prime.c -@@ -197,6 +197,7 @@ struct drm_gem_object *nouveau_gem_prime - if (nvbo->gem) { - if (nvbo->gem->dev == dev) { - drm_gem_object_reference(nvbo->gem); -+ dma_buf_put(dma_buf); - return nvbo->gem; - } - } ---- a/drivers/gpu/drm/radeon/radeon_prime.c -+++ b/drivers/gpu/drm/radeon/radeon_prime.c -@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_ - bo = dma_buf->priv; - if (bo->gem_base.dev == dev) { - drm_gem_object_reference(&bo->gem_base); -+ dma_buf_put(dma_buf); - return &bo->gem_base; - } - } ---- a/drivers/staging/omapdrm/omap_gem_dmabuf.c -+++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c -@@ -207,7 +207,12 @@ struct drm_gem_object * omap_gem_prime_i - obj = buffer->priv; - /* is it from our device? */ - if (obj->dev == dev) { -+ /* -+ * Importing dmabuf exported from out own gem increases -+ * refcount on gem itself instead of f_count of dmabuf. -+ */ - drm_gem_object_reference(obj); -+ dma_buf_put(buffer); - return obj; - } - } -From 901593f2bf221659a605bdc1dcb11376ea934163 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Wed, 19 Dec 2012 16:51:06 +0000 -Subject: drm: Only evict the blocks required to create the requested hole - -From: Chris Wilson - -commit 901593f2bf221659a605bdc1dcb11376ea934163 upstream. - -Avoid clobbering adjacent blocks if they happen to expire earlier and -amalgamate together to form the requested hole. - -In passing this fixes a regression from -commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c -Author: Daniel Vetter -Date: Fri Feb 18 17:59:12 2011 +0100 - - drm: mm: track free areas implicitly - -which swaps the end address for size (with a potential overflow) and -effectively causes the eviction code to clobber almost all earlier -buffers above the evictee. - -v2: Check the original hole not the adjusted as the coloring may confuse -us when later searching for the overlapping nodes. Also make sure that -we do apply the range restriction and color adjustment in the same -order for both scanning, searching and insertion. - -v3: Send the version that was actually tested. - -Note that this seems to be ducttape of decent quality ot paper over -some of our unbind related gpu hangs reported since 3.7. It is not -fully effective though, and certainly doesn't fix the underlying bug. - -Signed-off-by: Chris Wilson -Cc: Daniel Vetter -[danvet: Added note plus bugzilla link and tested-by.] -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 -Tested-by: Norbert Preining -Acked-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/drm_mm.c | 45 +++++++++++++++++---------------------------- - include/drm/drm_mm.h | 2 +- - 2 files changed, 18 insertions(+), 29 deletions(-) - ---- a/drivers/gpu/drm/drm_mm.c -+++ b/drivers/gpu/drm/drm_mm.c -@@ -213,11 +213,13 @@ static void drm_mm_insert_helper_range(s - - BUG_ON(!hole_node->hole_follows || node->allocated); - -- if (mm->color_adjust) -- mm->color_adjust(hole_node, color, &adj_start, &adj_end); -- - if (adj_start < start) - adj_start = start; -+ if (adj_end > end) -+ adj_end = end; -+ -+ if (mm->color_adjust) -+ mm->color_adjust(hole_node, color, &adj_start, &adj_end); - - if (alignment) { - unsigned tmp = adj_start % alignment; -@@ -489,7 +491,7 @@ void drm_mm_init_scan(struct drm_mm *mm, - mm->scan_size = size; - mm->scanned_blocks = 0; - mm->scan_hit_start = 0; -- mm->scan_hit_size = 0; -+ mm->scan_hit_end = 0; - mm->scan_check_range = 0; - mm->prev_scanned_node = NULL; - } -@@ -516,7 +518,7 @@ void drm_mm_init_scan_with_range(struct - mm->scan_size = size; - mm->scanned_blocks = 0; - mm->scan_hit_start = 0; -- mm->scan_hit_size = 0; -+ mm->scan_hit_end = 0; - mm->scan_start = start; - mm->scan_end = end; - mm->scan_check_range = 1; -@@ -535,8 +537,7 @@ int drm_mm_scan_add_block(struct drm_mm_ - struct drm_mm *mm = node->mm; - struct drm_mm_node *prev_node; - unsigned long hole_start, hole_end; -- unsigned long adj_start; -- unsigned long adj_end; -+ unsigned long adj_start, adj_end; - - mm->scanned_blocks++; - -@@ -553,14 +554,8 @@ int drm_mm_scan_add_block(struct drm_mm_ - node->node_list.next = &mm->prev_scanned_node->node_list; - mm->prev_scanned_node = node; - -- hole_start = drm_mm_hole_node_start(prev_node); -- hole_end = drm_mm_hole_node_end(prev_node); -- -- adj_start = hole_start; -- adj_end = hole_end; -- -- if (mm->color_adjust) -- mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); -+ adj_start = hole_start = drm_mm_hole_node_start(prev_node); -+ adj_end = hole_end = drm_mm_hole_node_end(prev_node); - - if (mm->scan_check_range) { - if (adj_start < mm->scan_start) -@@ -569,11 +564,14 @@ int drm_mm_scan_add_block(struct drm_mm_ - adj_end = mm->scan_end; - } - -+ if (mm->color_adjust) -+ mm->color_adjust(prev_node, mm->scan_color, -+ &adj_start, &adj_end); -+ - if (check_free_hole(adj_start, adj_end, - mm->scan_size, mm->scan_alignment)) { - mm->scan_hit_start = hole_start; -- mm->scan_hit_size = hole_end; -- -+ mm->scan_hit_end = hole_end; - return 1; - } - -@@ -609,19 +607,10 @@ int drm_mm_scan_remove_block(struct drm_ - node_list); - - prev_node->hole_follows = node->scanned_preceeds_hole; -- INIT_LIST_HEAD(&node->node_list); - list_add(&node->node_list, &prev_node->node_list); - -- /* Only need to check for containement because start&size for the -- * complete resulting free block (not just the desired part) is -- * stored. */ -- if (node->start >= mm->scan_hit_start && -- node->start + node->size -- <= mm->scan_hit_start + mm->scan_hit_size) { -- return 1; -- } -- -- return 0; -+ return (drm_mm_hole_node_end(node) > mm->scan_hit_start && -+ node->start < mm->scan_hit_end); - } - EXPORT_SYMBOL(drm_mm_scan_remove_block); - ---- a/include/drm/drm_mm.h -+++ b/include/drm/drm_mm.h -@@ -70,7 +70,7 @@ struct drm_mm { - unsigned long scan_color; - unsigned long scan_size; - unsigned long scan_hit_start; -- unsigned scan_hit_size; -+ unsigned long scan_hit_end; - unsigned scanned_blocks; - unsigned long scan_start; - unsigned long scan_end; -From 93be8788e648817d62fda33e2998eb6ca6ebf3a3 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Wed, 2 Jan 2013 10:31:22 +0000 -Subject: drm/i915; Only increment the user-pin-count after successfully pinning the bo - -From: Chris Wilson - -commit 93be8788e648817d62fda33e2998eb6ca6ebf3a3 upstream. - -As along the error path we do not correct the user pin-count for the -failure, we may end up with userspace believing that it has a pinned -object at offset 0 (when interrupted by a signal for example). - -Signed-off-by: Chris Wilson -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_gem.c -+++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -3511,14 +3511,15 @@ i915_gem_pin_ioctl(struct drm_device *de - goto out; - } - -- obj->user_pin_count++; -- obj->pin_filp = file; -- if (obj->user_pin_count == 1) { -+ if (obj->user_pin_count == 0) { - ret = i915_gem_object_pin(obj, args->alignment, true, false); - if (ret) - goto out; - } - -+ obj->user_pin_count++; -+ obj->pin_filp = file; -+ - /* XXX - flush the CPU caches for pinned objects - * as the X server doesn't manage domains yet - */ -From 93927ca52a55c23e0a6a305e7e9082e8411ac9fa Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Thu, 10 Jan 2013 18:03:00 +0100 -Subject: drm/i915: Revert shrinker changes from "Track unbound pages" - -From: Daniel Vetter - -commit 93927ca52a55c23e0a6a305e7e9082e8411ac9fa upstream. - -This partially reverts - -commit 6c085a728cf000ac1865d66f8c9b52935558b328 -Author: Chris Wilson -Date: Mon Aug 20 11:40:46 2012 +0200 - - drm/i915: Track unbound pages - -Closer inspection of that patch revealed a bunch of unrelated changes -in the shrinker: -- The shrinker count is now in pages instead of objects. -- For counting the shrinkable objects the old code only looked at the - inactive list, the new code looks at all bounds objects (including - pinned ones). That is obviously in addition to the new unbound list. -- The shrinker cound is no longer scaled with - sysctl_vfs_cache_pressure. Note though that with the default tuning - value of vfs_cache_pressue = 100 this doesn't affect the shrinker - behaviour. -- When actually shrinking objects, the old code first dropped - purgeable objects, then normal (inactive) objects. Only then did it, - in a last-ditch effort idle the gpu and evict everything. The new - code omits the intermediate step of evicting normal inactive - objects. - -Safe for the first change, which seems benign, and the shrinker count -scaling, which is a bit a different story, the endresult of all these -changes is that the shrinker is _much_ more likely to fall back to the -last-ditch resort of idling the gpu and evicting everything. The old -code could only do that if something else evicted lots of objects -meanwhile (since without any other changes the nr_to_scan will be -smaller than the object count). - -Reverting the vfs_cache_pressure behaviour itself is a bit bogus: Only -dentry/inode object caches should scale their shrinker counts with -vfs_cache_pressure. Originally I've had that change reverted, too. But -Chris Wilson insisted that it's too bogus and shouldn't again see the -light of day. - -Hence revert all these other changes and restore the old shrinker -behaviour, with the minor adjustment that we now first scan the -unbound list, then the inactive list for each object category -(purgeable or normal). - -A similar patch has been tested by a few people affected by the gen4/5 -hangs which started to appear in 3.7, which some people bisected to -the "drm/i915: Track unbound pages" commit. But just disabling the -unbound logic alone didn't change things at all. - -Note that this patch doesn't fix the referenced bugs, it only hides -the underlying bug(s) well enough to restore pre-3.7 behaviour. The -key to achieve that is to massively reduce the likelyhood of going -into a full gpu stall and evicting everything. - -v2: Reword commit message a bit, taking Chris Wilson's comment into -account. - -v3: On Chris Wilson's insistency, do not reinstate the rather bogus -vfs_cache_pressure change. - -Tested-by: Greg KH -Tested-by: Dave Kleikamp -References: https://bugs.freedesktop.org/show_bug.cgi?id=55984 -References: https://bugs.freedesktop.org/show_bug.cgi?id=57122 -References: https://bugs.freedesktop.org/show_bug.cgi?id=56916 -References: https://bugs.freedesktop.org/show_bug.cgi?id=57136 -Cc: Chris Wilson -Acked-by: Chris Wilson -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_gem.c -+++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -1718,7 +1718,8 @@ i915_gem_object_put_pages(struct drm_i91 - } - - static long --i915_gem_purge(struct drm_i915_private *dev_priv, long target) -+__i915_gem_shrink(struct drm_i915_private *dev_priv, long target, -+ bool purgeable_only) - { - struct drm_i915_gem_object *obj, *next; - long count = 0; -@@ -1726,7 +1727,7 @@ i915_gem_purge(struct drm_i915_private * - list_for_each_entry_safe(obj, next, - &dev_priv->mm.unbound_list, - gtt_list) { -- if (i915_gem_object_is_purgeable(obj) && -+ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && - i915_gem_object_put_pages(obj) == 0) { - count += obj->base.size >> PAGE_SHIFT; - if (count >= target) -@@ -1737,7 +1738,7 @@ i915_gem_purge(struct drm_i915_private * - list_for_each_entry_safe(obj, next, - &dev_priv->mm.inactive_list, - mm_list) { -- if (i915_gem_object_is_purgeable(obj) && -+ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && - i915_gem_object_unbind(obj) == 0 && - i915_gem_object_put_pages(obj) == 0) { - count += obj->base.size >> PAGE_SHIFT; -@@ -1749,6 +1750,12 @@ i915_gem_purge(struct drm_i915_private * - return count; - } - -+static long -+i915_gem_purge(struct drm_i915_private *dev_priv, long target) -+{ -+ return __i915_gem_shrink(dev_priv, target, true); -+} -+ - static void - i915_gem_shrink_all(struct drm_i915_private *dev_priv) - { -@@ -4426,6 +4433,9 @@ i915_gem_inactive_shrink(struct shrinker - if (nr_to_scan) { - nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); - if (nr_to_scan > 0) -+ nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, -+ false); -+ if (nr_to_scan > 0) - i915_gem_shrink_all(dev_priv); - } - -@@ -4433,7 +4443,7 @@ i915_gem_inactive_shrink(struct shrinker - list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) - if (obj->pages_pin_count == 0) - cnt += obj->base.size >> PAGE_SHIFT; -- list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) -+ list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) - if (obj->pin_count == 0 && obj->pages_pin_count == 0) - cnt += obj->base.size >> PAGE_SHIFT; - -From 7d9c199a55200c9b9fcad08e150470d02fb385be Mon Sep 17 00:00:00 2001 -From: Tatyana Nikolova -Date: Thu, 6 Dec 2012 20:05:02 +0000 -Subject: RDMA/nes: Fix for crash when registering zero length MR for CQ - -From: Tatyana Nikolova - -commit 7d9c199a55200c9b9fcad08e150470d02fb385be upstream. - -Signed-off-by: Tatyana Nikolova -Signed-off-by: Roland Dreier -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/infiniband/hw/nes/nes_verbs.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/infiniband/hw/nes/nes_verbs.c -+++ b/drivers/infiniband/hw/nes/nes_verbs.c -@@ -2559,6 +2559,11 @@ static struct ib_mr *nes_reg_user_mr(str - return ibmr; - case IWNES_MEMREG_TYPE_QP: - case IWNES_MEMREG_TYPE_CQ: -+ if (!region->length) { -+ nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); -+ ib_umem_release(region); -+ return ERR_PTR(-EINVAL); -+ } - nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); - if (!nespbl) { - nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); -From 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 Mon Sep 17 00:00:00 2001 -From: Tatyana Nikolova -Date: Thu, 6 Dec 2012 19:58:27 +0000 -Subject: RDMA/nes: Fix for terminate timer crash - -From: Tatyana Nikolova - -commit 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 upstream. - -The terminate timer needs to be initialized just once. - -Signed-off-by: Tatyana Nikolova -Signed-off-by: Roland Dreier -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/infiniband/hw/nes/nes.h | 1 + - drivers/infiniband/hw/nes/nes_hw.c | 9 ++------- - drivers/infiniband/hw/nes/nes_verbs.c | 4 +++- - 3 files changed, 6 insertions(+), 8 deletions(-) - ---- a/drivers/infiniband/hw/nes/nes.h -+++ b/drivers/infiniband/hw/nes/nes.h -@@ -532,6 +532,7 @@ void nes_iwarp_ce_handler(struct nes_dev - int nes_destroy_cqp(struct nes_device *); - int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); - void nes_recheck_link_status(struct work_struct *work); -+void nes_terminate_timeout(unsigned long context); - - /* nes_nic.c */ - struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); ---- a/drivers/infiniband/hw/nes/nes_hw.c -+++ b/drivers/infiniband/hw/nes/nes_hw.c -@@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struc - static void process_critical_error(struct nes_device *nesdev); - static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); - static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); --static void nes_terminate_timeout(unsigned long context); - static void nes_terminate_start_timer(struct nes_qp *nesqp); - - #ifdef CONFIG_INFINIBAND_NES_DEBUG -@@ -3520,7 +3519,7 @@ static void nes_terminate_received(struc - } - - /* Timeout routine in case terminate fails to complete */ --static void nes_terminate_timeout(unsigned long context) -+void nes_terminate_timeout(unsigned long context) - { - struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; - -@@ -3530,11 +3529,7 @@ static void nes_terminate_timeout(unsign - /* Set a timer in case hw cannot complete the terminate sequence */ - static void nes_terminate_start_timer(struct nes_qp *nesqp) - { -- init_timer(&nesqp->terminate_timer); -- nesqp->terminate_timer.function = nes_terminate_timeout; -- nesqp->terminate_timer.expires = jiffies + HZ; -- nesqp->terminate_timer.data = (unsigned long)nesqp; -- add_timer(&nesqp->terminate_timer); -+ mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); - } - - /** ---- a/drivers/infiniband/hw/nes/nes_verbs.c -+++ b/drivers/infiniband/hw/nes/nes_verbs.c -@@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struc - } - - nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); -+ init_timer(&nesqp->terminate_timer); -+ nesqp->terminate_timer.function = nes_terminate_timeout; -+ nesqp->terminate_timer.data = (unsigned long)nesqp; - - /* update the QP table */ - nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; -@@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struc - return &nesqp->ibqp; - } - -- - /** - * nes_clean_cq - */ -From c1a94672a830e01d58c7c7e8de530c3f136d6ff2 Mon Sep 17 00:00:00 2001 -From: Mike Snitzer -Date: Fri, 21 Dec 2012 20:23:30 +0000 -Subject: dm: disable WRITE SAME - -From: Mike Snitzer - -commit c1a94672a830e01d58c7c7e8de530c3f136d6ff2 upstream. - -WRITE SAME bios are not yet handled correctly by device-mapper so -disable their use on device-mapper devices by setting -max_write_same_sectors to zero. - -As an example, a ciphertext device is incompatible because the data -gets changed according to the location at which it written and so the -dm crypt target cannot support it. - -Signed-off-by: Mike Snitzer -Cc: Milan Broz -Signed-off-by: Alasdair G Kergon -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/md/dm-table.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/md/dm-table.c -+++ b/drivers/md/dm-table.c -@@ -1445,6 +1445,8 @@ void dm_table_set_restrictions(struct dm - else - queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); - -+ q->limits.max_write_same_sectors = 0; -+ - dm_table_set_integrity(t); - - /* -From 550929faf89e2e2cdb3e9945ea87d383989274cf Mon Sep 17 00:00:00 2001 -From: Mikulas Patocka -Date: Fri, 21 Dec 2012 20:23:30 +0000 -Subject: dm persistent data: rename node to btree_node - -From: Mikulas Patocka - -commit 550929faf89e2e2cdb3e9945ea87d383989274cf upstream. - -This patch fixes a compilation failure on sparc32 by renaming struct node. - -struct node is already defined in include/linux/node.h. On sparc32, it -happens to be included through other dependencies and persistent-data -doesn't compile because of conflicting declarations. - -Signed-off-by: Mikulas Patocka -Signed-off-by: Alasdair G Kergon -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/md/persistent-data/dm-btree-internal.h | 16 ++++---- - drivers/md/persistent-data/dm-btree-remove.c | 50 ++++++++++++------------- - drivers/md/persistent-data/dm-btree-spine.c | 6 +-- - drivers/md/persistent-data/dm-btree.c | 22 +++++------ - 4 files changed, 47 insertions(+), 47 deletions(-) - ---- a/drivers/md/persistent-data/dm-btree-internal.h -+++ b/drivers/md/persistent-data/dm-btree-internal.h -@@ -36,13 +36,13 @@ struct node_header { - __le32 padding; - } __packed; - --struct node { -+struct btree_node { - struct node_header header; - __le64 keys[0]; - } __packed; - - --void inc_children(struct dm_transaction_manager *tm, struct node *n, -+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, - struct dm_btree_value_type *vt); - - int new_block(struct dm_btree_info *info, struct dm_block **result); -@@ -64,7 +64,7 @@ struct ro_spine { - void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); - int exit_ro_spine(struct ro_spine *s); - int ro_step(struct ro_spine *s, dm_block_t new_child); --struct node *ro_node(struct ro_spine *s); -+struct btree_node *ro_node(struct ro_spine *s); - - struct shadow_spine { - struct dm_btree_info *info; -@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); - /* - * Some inlines. - */ --static inline __le64 *key_ptr(struct node *n, uint32_t index) -+static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) - { - return n->keys + index; - } - --static inline void *value_base(struct node *n) -+static inline void *value_base(struct btree_node *n) - { - return &n->keys[le32_to_cpu(n->header.max_entries)]; - } - --static inline void *value_ptr(struct node *n, uint32_t index) -+static inline void *value_ptr(struct btree_node *n, uint32_t index) - { - uint32_t value_size = le32_to_cpu(n->header.value_size); - return value_base(n) + (value_size * index); -@@ -117,7 +117,7 @@ static inline void *value_ptr(struct nod - /* - * Assumes the values are suitably-aligned and converts to core format. - */ --static inline uint64_t value64(struct node *n, uint32_t index) -+static inline uint64_t value64(struct btree_node *n, uint32_t index) - { - __le64 *values_le = value_base(n); - -@@ -127,7 +127,7 @@ static inline uint64_t value64(struct no - /* - * Searching for a key within a single node. - */ --int lower_bound(struct node *n, uint64_t key); -+int lower_bound(struct btree_node *n, uint64_t key); - - extern struct dm_block_validator btree_node_validator; - ---- a/drivers/md/persistent-data/dm-btree-remove.c -+++ b/drivers/md/persistent-data/dm-btree-remove.c -@@ -53,7 +53,7 @@ - /* - * Some little utilities for moving node data around. - */ --static void node_shift(struct node *n, int shift) -+static void node_shift(struct btree_node *n, int shift) - { - uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); - uint32_t value_size = le32_to_cpu(n->header.value_size); -@@ -79,7 +79,7 @@ static void node_shift(struct node *n, i - } - } - --static void node_copy(struct node *left, struct node *right, int shift) -+static void node_copy(struct btree_node *left, struct btree_node *right, int shift) - { - uint32_t nr_left = le32_to_cpu(left->header.nr_entries); - uint32_t value_size = le32_to_cpu(left->header.value_size); -@@ -108,7 +108,7 @@ static void node_copy(struct node *left, - /* - * Delete a specific entry from a leaf node. - */ --static void delete_at(struct node *n, unsigned index) -+static void delete_at(struct btree_node *n, unsigned index) - { - unsigned nr_entries = le32_to_cpu(n->header.nr_entries); - unsigned nr_to_copy = nr_entries - (index + 1); -@@ -128,7 +128,7 @@ static void delete_at(struct node *n, un - n->header.nr_entries = cpu_to_le32(nr_entries - 1); - } - --static unsigned merge_threshold(struct node *n) -+static unsigned merge_threshold(struct btree_node *n) - { - return le32_to_cpu(n->header.max_entries) / 3; - } -@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct n - struct child { - unsigned index; - struct dm_block *block; -- struct node *n; -+ struct btree_node *n; - }; - - static struct dm_btree_value_type le64_type = { -@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_t - .equal = NULL - }; - --static int init_child(struct dm_btree_info *info, struct node *parent, -+static int init_child(struct dm_btree_info *info, struct btree_node *parent, - unsigned index, struct child *result) - { - int r, inc; -@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_in - return dm_tm_unlock(info->tm, c->block); - } - --static void shift(struct node *left, struct node *right, int count) -+static void shift(struct btree_node *left, struct btree_node *right, int count) - { - uint32_t nr_left = le32_to_cpu(left->header.nr_entries); - uint32_t nr_right = le32_to_cpu(right->header.nr_entries); -@@ -203,11 +203,11 @@ static void shift(struct node *left, str - right->header.nr_entries = cpu_to_le32(nr_right + count); - } - --static void __rebalance2(struct dm_btree_info *info, struct node *parent, -+static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, - struct child *l, struct child *r) - { -- struct node *left = l->n; -- struct node *right = r->n; -+ struct btree_node *left = l->n; -+ struct btree_node *right = r->n; - uint32_t nr_left = le32_to_cpu(left->header.nr_entries); - uint32_t nr_right = le32_to_cpu(right->header.nr_entries); - unsigned threshold = 2 * merge_threshold(left) + 1; -@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spin - unsigned left_index) - { - int r; -- struct node *parent; -+ struct btree_node *parent; - struct child left, right; - - parent = dm_block_data(shadow_current(s)); -@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spin - * in right, then rebalance2. This wastes some cpu, but I want something - * simple atm. - */ --static void delete_center_node(struct dm_btree_info *info, struct node *parent, -+static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, - struct child *l, struct child *c, struct child *r, -- struct node *left, struct node *center, struct node *right, -+ struct btree_node *left, struct btree_node *center, struct btree_node *right, - uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) - { - uint32_t max_entries = le32_to_cpu(left->header.max_entries); -@@ -301,9 +301,9 @@ static void delete_center_node(struct dm - /* - * Redistributes entries among 3 sibling nodes. - */ --static void redistribute3(struct dm_btree_info *info, struct node *parent, -+static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, - struct child *l, struct child *c, struct child *r, -- struct node *left, struct node *center, struct node *right, -+ struct btree_node *left, struct btree_node *center, struct btree_node *right, - uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) - { - int s; -@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btre - *key_ptr(parent, r->index) = right->keys[0]; - } - --static void __rebalance3(struct dm_btree_info *info, struct node *parent, -+static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, - struct child *l, struct child *c, struct child *r) - { -- struct node *left = l->n; -- struct node *center = c->n; -- struct node *right = r->n; -+ struct btree_node *left = l->n; -+ struct btree_node *center = c->n; -+ struct btree_node *right = r->n; - - uint32_t nr_left = le32_to_cpu(left->header.nr_entries); - uint32_t nr_center = le32_to_cpu(center->header.nr_entries); -@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spin - unsigned left_index) - { - int r; -- struct node *parent = dm_block_data(shadow_current(s)); -+ struct btree_node *parent = dm_block_data(shadow_current(s)); - struct child left, center, right; - - /* -@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_tran - { - int r; - struct dm_block *block; -- struct node *n; -+ struct btree_node *n; - - r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); - if (r) -@@ -438,7 +438,7 @@ static int rebalance_children(struct sha - { - int i, r, has_left_sibling, has_right_sibling; - uint32_t child_entries; -- struct node *n; -+ struct btree_node *n; - - n = dm_block_data(shadow_current(s)); - -@@ -483,7 +483,7 @@ static int rebalance_children(struct sha - return r; - } - --static int do_leaf(struct node *n, uint64_t key, unsigned *index) -+static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) - { - int i = lower_bound(n, key); - -@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spin - uint64_t key, unsigned *index) - { - int i = *index, r; -- struct node *n; -+ struct btree_node *n; - - for (;;) { - r = shadow_step(s, root, vt); -@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info - unsigned level, last_level = info->levels - 1; - int index = 0, r = 0; - struct shadow_spine spine; -- struct node *n; -+ struct btree_node *n; - - init_shadow_spine(&spine, info); - for (level = 0; level < info->levels; level++) { ---- a/drivers/md/persistent-data/dm-btree-spine.c -+++ b/drivers/md/persistent-data/dm-btree-spine.c -@@ -23,7 +23,7 @@ static void node_prepare_for_write(struc - struct dm_block *b, - size_t block_size) - { -- struct node *n = dm_block_data(b); -+ struct btree_node *n = dm_block_data(b); - struct node_header *h = &n->header; - - h->blocknr = cpu_to_le64(dm_block_location(b)); -@@ -38,7 +38,7 @@ static int node_check(struct dm_block_va - struct dm_block *b, - size_t block_size) - { -- struct node *n = dm_block_data(b); -+ struct btree_node *n = dm_block_data(b); - struct node_header *h = &n->header; - size_t value_size; - __le32 csum_disk; -@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block - return r; - } - --struct node *ro_node(struct ro_spine *s) -+struct btree_node *ro_node(struct ro_spine *s) - { - struct dm_block *block; - ---- a/drivers/md/persistent-data/dm-btree.c -+++ b/drivers/md/persistent-data/dm-btree.c -@@ -38,7 +38,7 @@ static void array_insert(void *base, siz - /*----------------------------------------------------------------*/ - - /* makes the assumption that no two keys are the same. */ --static int bsearch(struct node *n, uint64_t key, int want_hi) -+static int bsearch(struct btree_node *n, uint64_t key, int want_hi) - { - int lo = -1, hi = le32_to_cpu(n->header.nr_entries); - -@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint6 - return want_hi ? hi : lo; - } - --int lower_bound(struct node *n, uint64_t key) -+int lower_bound(struct btree_node *n, uint64_t key) - { - return bsearch(n, key, 0); - } - --void inc_children(struct dm_transaction_manager *tm, struct node *n, -+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, - struct dm_btree_value_type *vt) - { - unsigned i; -@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_ - vt->inc(vt->context, value_ptr(n, i)); - } - --static int insert_at(size_t value_size, struct node *node, unsigned index, -+static int insert_at(size_t value_size, struct btree_node *node, unsigned index, - uint64_t key, void *value) - __dm_written_to_disk(value) - { -@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info - { - int r; - struct dm_block *b; -- struct node *n; -+ struct btree_node *n; - size_t block_size; - uint32_t max_entries; - -@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); - #define MAX_SPINE_DEPTH 64 - struct frame { - struct dm_block *b; -- struct node *n; -+ struct btree_node *n; - unsigned level; - unsigned nr_children; - unsigned current_child; -@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); - /*----------------------------------------------------------------*/ - - static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, -- int (*search_fn)(struct node *, uint64_t), -+ int (*search_fn)(struct btree_node *, uint64_t), - uint64_t *result_key, void *v, size_t value_size) - { - int i, r; -@@ -406,7 +406,7 @@ static int btree_split_sibling(struct sh - size_t size; - unsigned nr_left, nr_right; - struct dm_block *left, *right, *parent; -- struct node *ln, *rn, *pn; -+ struct btree_node *ln, *rn, *pn; - __le64 location; - - left = shadow_current(s); -@@ -491,7 +491,7 @@ static int btree_split_beneath(struct sh - size_t size; - unsigned nr_left, nr_right; - struct dm_block *left, *right, *new_parent; -- struct node *pn, *ln, *rn; -+ struct btree_node *pn, *ln, *rn; - __le64 val; - - new_parent = shadow_current(s); -@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shado - uint64_t key, unsigned *index) - { - int r, i = *index, top = 1; -- struct node *node; -+ struct btree_node *node; - - for (;;) { - r = shadow_step(s, root, vt); -@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info * - unsigned level, index = -1, last_level = info->levels - 1; - dm_block_t block = root; - struct shadow_spine spine; -- struct node *n; -+ struct btree_node *n; - struct dm_btree_value_type le64_type; - - le64_type.context = NULL; -From e910d7ebecd1aac43125944a8641b6cb1a0dfabe Mon Sep 17 00:00:00 2001 -From: Alasdair G Kergon -Date: Fri, 21 Dec 2012 20:23:30 +0000 -Subject: dm ioctl: prevent unsafe change to dm_ioctl data_size - -From: Alasdair G Kergon - -commit e910d7ebecd1aac43125944a8641b6cb1a0dfabe upstream. - -Abort dm ioctl processing if userspace changes the data_size parameter -after we validated it but before we finished copying the data buffer -from userspace. - -The dm ioctl parameters are processed in the following sequence: - 1. ctl_ioctl() calls copy_params(); - 2. copy_params() makes a first copy of the fixed-sized portion of the - userspace parameters into the local variable "tmp"; - 3. copy_params() then validates tmp.data_size and allocates a new - structure big enough to hold the complete data and copies the whole - userspace buffer there; - 4. ctl_ioctl() reads userspace data the second time and copies the whole - buffer into the pointer "param"; - 5. ctl_ioctl() reads param->data_size without any validation and stores it - in the variable "input_param_size"; - 6. "input_param_size" is further used as the authoritative size of the - kernel buffer. - -The problem is that userspace code could change the contents of user -memory between steps 2 and 4. In particular, the data_size parameter -can be changed to an invalid value after the kernel has validated it. -This lets userspace force the kernel to access invalid kernel memory. - -The fix is to ensure that the size has not changed at step 4. - -This patch shouldn't have a security impact because CAP_SYS_ADMIN is -required to run this code, but it should be fixed anyway. - -Reported-by: Mikulas Patocka -Signed-off-by: Alasdair G Kergon -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/md/dm-ioctl.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/md/dm-ioctl.c -+++ b/drivers/md/dm-ioctl.c -@@ -1566,6 +1566,14 @@ static int copy_params(struct dm_ioctl _ - if (copy_from_user(dmi, user, tmp.data_size)) - goto bad; - -+ /* -+ * Abort if something changed the ioctl data while it was being copied. -+ */ -+ if (dmi->data_size != tmp.data_size) { -+ DMERR("rejecting ioctl: data size modified while processing parameters"); -+ goto bad; -+ } -+ - /* Wipe the user buffer so we do not return it to userspace */ - if (secure_data && clear_user(user, tmp.data_size)) - goto bad; -From b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d Mon Sep 17 00:00:00 2001 -From: Joe Thornber -Date: Fri, 21 Dec 2012 20:23:31 +0000 -Subject: dm thin: replace dm_cell_release_singleton with cell_defer_except - -From: Joe Thornber - -commit b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d upstream. - -Change existing users of the function dm_cell_release_singleton to share -cell_defer_except instead, and then remove the now-unused function. - -Everywhere that calls dm_cell_release_singleton, the bio in question -is the holder of the cell. - -If there are no non-holder entries in the cell then cell_defer_except -behaves exactly like dm_cell_release_singleton. Conversely, if there -*are* non-holder entries then dm_cell_release_singleton must not be used -because those entries would need to be deferred. - -Consequently, it is safe to replace use of dm_cell_release_singleton -with cell_defer_except. - -This patch is a pre-requisite for "dm thin: fix race between -simultaneous io and discards to same block". - -Signed-off-by: Joe Thornber -Signed-off-by: Mike Snitzer -Signed-off-by: Alasdair G Kergon -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/md/dm-bio-prison.c | 25 ------------------------- - drivers/md/dm-bio-prison.h | 1 - - drivers/md/dm-thin.c | 25 ++++++++++++------------- - 3 files changed, 12 insertions(+), 39 deletions(-) - ---- a/drivers/md/dm-bio-prison.c -+++ b/drivers/md/dm-bio-prison.c -@@ -208,31 +208,6 @@ void dm_cell_release(struct dm_bio_priso - EXPORT_SYMBOL_GPL(dm_cell_release); - - /* -- * There are a couple of places where we put a bio into a cell briefly -- * before taking it out again. In these situations we know that no other -- * bio may be in the cell. This function releases the cell, and also does -- * a sanity check. -- */ --static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) --{ -- BUG_ON(cell->holder != bio); -- BUG_ON(!bio_list_empty(&cell->bios)); -- -- __cell_release(cell, NULL); --} -- --void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) --{ -- unsigned long flags; -- struct dm_bio_prison *prison = cell->prison; -- -- spin_lock_irqsave(&prison->lock, flags); -- __cell_release_singleton(cell, bio); -- spin_unlock_irqrestore(&prison->lock, flags); --} --EXPORT_SYMBOL_GPL(dm_cell_release_singleton); -- --/* - * Sometimes we don't want the holder, just the additional bios. - */ - static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) ---- a/drivers/md/dm-bio-prison.h -+++ b/drivers/md/dm-bio-prison.h -@@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison * - struct bio *inmate, struct dm_bio_prison_cell **ref); - - void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); --void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed - void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); - void dm_cell_error(struct dm_bio_prison_cell *cell); - ---- a/drivers/md/dm-thin.c -+++ b/drivers/md/dm-thin.c -@@ -513,8 +513,7 @@ static void cell_defer(struct thin_c *tc - } - - /* -- * Same as cell_defer above, except it omits one particular detainee, -- * a write bio that covers the block and has already been processed. -+ * Same as cell_defer except it omits the original holder of the cell. - */ - static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) - { -@@ -936,7 +935,7 @@ static void process_discard(struct thin_ - */ - build_data_key(tc->td, lookup_result.block, &key2); - if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - break; - } - -@@ -967,8 +966,8 @@ static void process_discard(struct thin_ - * a block boundary. So we submit the discard of a - * partial block appropriately. - */ -- dm_cell_release_singleton(cell, bio); -- dm_cell_release_singleton(cell2, bio); -+ cell_defer_except(tc, cell); -+ cell_defer_except(tc, cell2); - if ((!lookup_result.shared) && pool->pf.discard_passdown) - remap_and_issue(tc, bio, lookup_result.block); - else -@@ -980,13 +979,13 @@ static void process_discard(struct thin_ - /* - * It isn't provisioned, just forget it. - */ -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - bio_endio(bio, 0); - break; - - default: - DMERR("discard: find block unexpectedly returned %d", r); -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - bio_io_error(bio); - break; - } -@@ -1041,7 +1040,7 @@ static void process_shared_bio(struct th - - h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); - -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - remap_and_issue(tc, bio, lookup_result->block); - } - } -@@ -1056,7 +1055,7 @@ static void provision_block(struct thin_ - * Remap empty bios (flushes) immediately, without provisioning. - */ - if (!bio->bi_size) { -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - remap_and_issue(tc, bio, 0); - return; - } -@@ -1066,7 +1065,7 @@ static void provision_block(struct thin_ - */ - if (bio_data_dir(bio) == READ) { - zero_fill_bio(bio); -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - bio_endio(bio, 0); - return; - } -@@ -1120,7 +1119,7 @@ static void process_bio(struct thin_c *t - * TODO: this will probably have to change when discard goes - * back in. - */ -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - - if (lookup_result.shared) - process_shared_bio(tc, bio, block, &lookup_result); -@@ -1130,7 +1129,7 @@ static void process_bio(struct thin_c *t - - case -ENODATA: - if (bio_data_dir(bio) == READ && tc->origin_dev) { -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - remap_to_origin_and_issue(tc, bio); - } else - provision_block(tc, bio, block, cell); -@@ -1138,7 +1137,7 @@ static void process_bio(struct thin_c *t - - default: - DMERR("dm_thin_find_block() failed, error = %d", r); -- dm_cell_release_singleton(cell, bio); -+ cell_defer_except(tc, cell); - bio_io_error(bio); - break; - } -From ab1dd9963137a1e122004d5378a581bf16ae9bc8 Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 7 Oct 2012 08:27:00 +0100 -Subject: staging: vt6656: [BUG] out of bound array reference in RFbSetPower. - -From: Malcolm Priestley - -commit ab1dd9963137a1e122004d5378a581bf16ae9bc8 upstream. - -Calling RFbSetPower with uCH zero value will cause out of bound array reference. - -This causes 64 bit kernels to oops on boot. - -Note: Driver does not function on 64 bit kernels and should be -blacklisted on them. - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/rf.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/staging/vt6656/rf.c -+++ b/drivers/staging/vt6656/rf.c -@@ -769,6 +769,9 @@ BYTE byPwr = pDevice->byCCKPwr; - return TRUE; - } - -+ if (uCH == 0) -+ return -EINVAL; -+ - switch (uRATE) { - case RATE_1M: - case RATE_2M: -From a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 11 Nov 2012 15:32:05 +0000 -Subject: staging: vt6656: 64 bit fixes: use u32 for QWORD definition. - -From: Malcolm Priestley - -commit a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 upstream. - -Size of long issues replace with u32. - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/ttype.h | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/staging/vt6656/ttype.h -+++ b/drivers/staging/vt6656/ttype.h -@@ -29,6 +29,8 @@ - #ifndef __TTYPE_H__ - #define __TTYPE_H__ - -+#include -+ - /******* Common definitions and typedefs ***********************************/ - - typedef int BOOL; -@@ -51,8 +53,8 @@ typedef unsigned long DWORD; - // which is NOT really a floating point number. - typedef union tagUQuadWord { - struct { -- DWORD dwLowDword; -- DWORD dwHighDword; -+ u32 dwLowDword; -+ u32 dwHighDword; - } u; - double DoNotUseThisField; - } UQuadWord; -From 7730492855a2f9c828599bcd8d62760f96d319e4 Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 11 Nov 2012 15:41:25 +0000 -Subject: staging: vt6656: 64 bit fixes : correct all type sizes - -From: Malcolm Priestley - -commit 7730492855a2f9c828599bcd8d62760f96d319e4 upstream. - -After this patch all BYTE/WORD/DWORD types can be replaced with the appropriate u sizes. - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/ttype.h | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/staging/vt6656/ttype.h -+++ b/drivers/staging/vt6656/ttype.h -@@ -44,9 +44,9 @@ typedef int BOOL; - - /****** Simple typedefs ***************************************************/ - --typedef unsigned char BYTE; // 8-bit --typedef unsigned short WORD; // 16-bit --typedef unsigned long DWORD; // 32-bit -+typedef u8 BYTE; -+typedef u16 WORD; -+typedef u32 DWORD; - - // QWORD is for those situation that we want - // an 8-byte-aligned 8 byte long structure -@@ -62,8 +62,8 @@ typedef UQuadWord QWORD; - - /****** Common pointer types ***********************************************/ - --typedef unsigned long ULONG_PTR; // 32-bit --typedef unsigned long DWORD_PTR; // 32-bit -+typedef u32 ULONG_PTR; -+typedef u32 DWORD_PTR; - - // boolean pointer - -From b4dc03af5513774277c9c36b12a25cd3f25f4404 Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 11 Nov 2012 15:45:52 +0000 -Subject: staging: vt6656: 64 bit fixes: fix long warning messages. - -From: Malcolm Priestley - -commit b4dc03af5513774277c9c36b12a25cd3f25f4404 upstream. - -Fixes long warning messages from patch -[PATCH 08/14] staging: vt6656: 64 bit fixes : correct all type sizes - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/dpc.c | 4 +-- - drivers/staging/vt6656/key.c | 47 +++++++++++++++++++++++++++++------------- - drivers/staging/vt6656/mac.c | 6 +++-- - drivers/staging/vt6656/rxtx.c | 18 ++++++++++------ - 4 files changed, 51 insertions(+), 24 deletions(-) - ---- a/drivers/staging/vt6656/dpc.c -+++ b/drivers/staging/vt6656/dpc.c -@@ -1238,7 +1238,7 @@ static BOOL s_bHandleRxEncryption ( - - PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc - *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); - if (byDecMode == KEY_CTL_TKIP) { - *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); - } else { -@@ -1349,7 +1349,7 @@ static BOOL s_bHostWepRxEncryption ( - - PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc - *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); - - if (byDecMode == KEY_CTL_TKIP) { - *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); ---- a/drivers/staging/vt6656/key.c -+++ b/drivers/staging/vt6656/key.c -@@ -235,7 +235,8 @@ BOOL KeybSetKey( - PSKeyItem pKey; - unsigned int uKeyIdx; - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO -+ "Enter KeybSetKey: %X\n", dwKeyIndex); - - j = (MAX_KEY_TABLE-1); - for (i=0;i<(MAX_KEY_TABLE-1);i++) { -@@ -261,7 +262,9 @@ BOOL KeybSetKey( - if ((dwKeyIndex & TRANSMIT_KEY) != 0) { - // Group transmit key - pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO -+ "Group transmit key(R)[%X]: %d\n", -+ pTable->KeyTable[i].dwGTKeyIndex, i); - } - pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed - pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); -@@ -302,9 +305,12 @@ BOOL KeybSetKey( - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", -+ pKey->dwTSC47_16); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", -+ pKey->wTSC15_0); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", -+ pKey->dwKeyIndex); - - return (TRUE); - } -@@ -326,7 +332,9 @@ BOOL KeybSetKey( - if ((dwKeyIndex & TRANSMIT_KEY) != 0) { - // Group transmit key - pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO -+ "Group transmit key(N)[%X]: %d\n", -+ pTable->KeyTable[j].dwGTKeyIndex, j); - } - pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed - pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); -@@ -367,9 +375,11 @@ BOOL KeybSetKey( - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", -+ pKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", -+ pKey->dwKeyIndex); - - return (TRUE); - } -@@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", -+ pTable->KeyTable[i].dwGTKeyIndex); - - return (TRUE); - } -@@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey( - if ((dwKeyIndex & TRANSMIT_KEY) != 0) { - // Group transmit key - pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO -+ "Group transmit key(R)[%X]: %d\n", -+ pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, -+ MAX_KEY_TABLE-1); - - } - pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed -@@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey( - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", -+ pKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", -+ pKey->dwKeyIndex); - - return (TRUE); - } -@@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey( - PSKeyItem pKey; - unsigned int uKeyIdx; - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", -+ dwKeyIndex); - - - if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key -@@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey( - if ((dwKeyIndex & TRANSMIT_KEY) != 0) { - // Group transmit key - pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO -+ "Group transmit key(R)[%X]: %d\n", -+ pTable->KeyTable[i].dwGTKeyIndex, i); - - } - pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed ---- a/drivers/staging/vt6656/mac.c -+++ b/drivers/staging/vt6656/mac.c -@@ -260,7 +260,8 @@ BYTE pbyData[24]; - dwData1 <<= 16; - dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ -+ " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); - - //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); - //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); -@@ -277,7 +278,8 @@ BYTE pbyData[24]; - dwData2 <<= 8; - dwData2 |= *(pbyAddr+0); - -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", -+ wOffset, dwData2); - - //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); - //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); ---- a/drivers/staging/vt6656/rxtx.c -+++ b/drivers/staging/vt6656/rxtx.c -@@ -375,7 +375,8 @@ s_vFillTxKey ( - *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV - // Append IV&ExtIV after Mac Header - *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", -+ *pdwExtIV); - - } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { - pTransmitKey->wTSC15_0++; -@@ -1751,7 +1752,8 @@ s_bPacketToWirelessUsb( - MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); - dwMIC_Priority = 0; - MIC_vAppend((PBYTE)&dwMIC_Priority, 4); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", -+ dwMICKey0, dwMICKey1); - - /////////////////////////////////////////////////////////////////// - -@@ -2633,7 +2635,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct - MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); - dwMIC_Priority = 0; - MIC_vAppend((PBYTE)&dwMIC_Priority, 4); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ -+ " %X, %X\n", dwMICKey0, dwMICKey1); - - uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; - -@@ -2653,7 +2656,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", -+ *pdwMIC_L, *pdwMIC_R); - - } - -@@ -3027,7 +3031,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); - } - else { -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", -+ pTransmitKey->dwKeyIndex); - bNeedEncryption = TRUE; - } - } -@@ -3041,7 +3046,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un - if (pDevice->bEnableHostWEP) { - if ((uNodeIndex != 0) && - (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { -- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); -+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", -+ pTransmitKey->dwKeyIndex); - bNeedEncryption = TRUE; - } - } -From c0d05b305b00c698b0a8c1b3d46c9380bce9db45 Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 11 Nov 2012 15:49:59 +0000 -Subject: staging: vt6656: 64bit fixes: key.c/h change unsigned long to u32 - -From: Malcolm Priestley - -commit c0d05b305b00c698b0a8c1b3d46c9380bce9db45 upstream. - -Fixes long issues. - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/key.c | 6 +++--- - drivers/staging/vt6656/key.h | 8 ++++---- - 2 files changed, 7 insertions(+), 7 deletions(-) - ---- a/drivers/staging/vt6656/key.c -+++ b/drivers/staging/vt6656/key.c -@@ -223,7 +223,7 @@ BOOL KeybSetKey( - PSKeyManagement pTable, - PBYTE pbyBSSID, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode -@@ -675,7 +675,7 @@ BOOL KeybSetDefaultKey( - void *pDeviceHandler, - PSKeyManagement pTable, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode -@@ -791,7 +791,7 @@ BOOL KeybSetAllGroupKey( - void *pDeviceHandler, - PSKeyManagement pTable, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode ---- a/drivers/staging/vt6656/key.h -+++ b/drivers/staging/vt6656/key.h -@@ -58,7 +58,7 @@ - typedef struct tagSKeyItem - { - BOOL bKeyValid; -- unsigned long uKeyLength; -+ u32 uKeyLength; - BYTE abyKey[MAX_KEY_LEN]; - QWORD KeyRSC; - DWORD dwTSC47_16; -@@ -107,7 +107,7 @@ BOOL KeybSetKey( - PSKeyManagement pTable, - PBYTE pbyBSSID, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode -@@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey( - void *pDeviceHandler, - PSKeyManagement pTable, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode -@@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey( - void *pDeviceHandler, - PSKeyManagement pTable, - DWORD dwKeyIndex, -- unsigned long uKeyLength, -+ u32 uKeyLength, - PQWORD pKeyRSC, - PBYTE pbyKey, - BYTE byKeyDecMode -From 70e227790d4ee4590023d8041a3485f8053593fc Mon Sep 17 00:00:00 2001 -From: Malcolm Priestley -Date: Sun, 11 Nov 2012 16:07:57 +0000 -Subject: staging: vt6656: 64bit fixes: vCommandTimerWait change calculation of timer. - -From: Malcolm Priestley - -commit 70e227790d4ee4590023d8041a3485f8053593fc upstream. - -The timer appears to run too fast/race on 64 bit systems. - -Using msecs_to_jiffies seems to cause a deadlock on 64 bit. - -A calculation of (MSecond * HZ) / 1000 appears to run satisfactory. - -Change BSSIDInfoCount to u32. - -After this patch the driver can be successfully connect on little endian 64/32 bit systems. - -Signed-off-by: Malcolm Priestley -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/vt6656/wcmd.c | 20 +++++++++++--------- - drivers/staging/vt6656/wpa2.h | 4 ++-- - 2 files changed, 13 insertions(+), 11 deletions(-) - ---- a/drivers/staging/vt6656/wcmd.c -+++ b/drivers/staging/vt6656/wcmd.c -@@ -316,17 +316,19 @@ s_MgrMakeProbeRequest( - return pTxPacket; - } - --void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond) -+void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond) - { -- PSDevice pDevice = (PSDevice)hDeviceContext; -+ PSDevice pDevice = (PSDevice)hDeviceContext; - -- init_timer(&pDevice->sTimerCommand); -- pDevice->sTimerCommand.data = (unsigned long)pDevice; -- pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; -- // RUN_AT :1 msec ~= (HZ/1024) -- pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); -- add_timer(&pDevice->sTimerCommand); -- return; -+ init_timer(&pDevice->sTimerCommand); -+ -+ pDevice->sTimerCommand.data = (unsigned long)pDevice; -+ pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; -+ pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); -+ -+ add_timer(&pDevice->sTimerCommand); -+ -+ return; - } - - void vRunCommand(void *hDeviceContext) ---- a/drivers/staging/vt6656/wpa2.h -+++ b/drivers/staging/vt6656/wpa2.h -@@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo { - } PMKIDInfo, *PPMKIDInfo; - - typedef struct tagSPMKIDCache { -- unsigned long BSSIDInfoCount; -- PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; -+ u32 BSSIDInfoCount; -+ PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; - } SPMKIDCache, *PSPMKIDCache; - - -From 0602934f302e016e2ea5dc6951681bfac77455ef Mon Sep 17 00:00:00 2001 -From: Chris Verges -Date: Fri, 21 Dec 2012 01:58:34 -0800 -Subject: hwmon: (lm73} Detect and report i2c bus errors - -From: Chris Verges - -commit 0602934f302e016e2ea5dc6951681bfac77455ef upstream. - -If an LM73 device does not exist on an I2C bus, attempts to communicate -with the device result in an error code returned from the i2c read/write -functions. The current lm73 driver casts that return value from a s32 -type to a s16 type, then converts it to a temperature in celsius. -Because negative temperatures are valid, it is difficult to distinguish -between an error code printed to the response buffer and a negative -temperature recorded by the sensor. - -The solution is to evaluate the return value from the i2c functions -before performing any temperature calculations. If the i2c function did -not succeed, the error code should be passed back through the virtual -file system layer instead of being printed into the response buffer. - -Before: - - $ cat /sys/class/hwmon/hwmon0/device/temp1_input - -46 - -After: - - $ cat /sys/class/hwmon/hwmon0/device/temp1_input - cat: read error: No such device or address - -Signed-off-by: Chris Verges -Signed-off-by: Guenter Roeck -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hwmon/lm73.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - ---- a/drivers/hwmon/lm73.c -+++ b/drivers/hwmon/lm73.c -@@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *d - struct i2c_client *client = to_i2c_client(dev); - long temp; - short value; -+ s32 err; - - int status = kstrtol(buf, 10, &temp); - if (status < 0) -@@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *d - /* Write value */ - value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), - (LM73_TEMP_MAX*4)) << 5; -- i2c_smbus_write_word_swapped(client, attr->index, value); -- return count; -+ err = i2c_smbus_write_word_swapped(client, attr->index, value); -+ return (err < 0) ? err : count; - } - - static ssize_t show_temp(struct device *dev, struct device_attribute *da, -@@ -66,11 +67,16 @@ static ssize_t show_temp(struct device * - { - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); -+ int temp; -+ -+ s32 err = i2c_smbus_read_word_swapped(client, attr->index); -+ if (err < 0) -+ return err; -+ - /* use integer division instead of equivalent right shift to - guarantee arithmetic shift and preserve the sign */ -- int temp = ((s16) (i2c_smbus_read_word_swapped(client, -- attr->index))*250) / 32; -- return sprintf(buf, "%d\n", temp); -+ temp = (((s16) err) * 250) / 32; -+ return scnprintf(buf, PAGE_SIZE, "%d\n", temp); - } - - -From 7b9205bd775afc4439ed86d617f9042ee9e76a71 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Fri, 11 Jan 2013 14:32:05 -0800 -Subject: audit: create explicit AUDIT_SECCOMP event type - -From: Kees Cook - -commit 7b9205bd775afc4439ed86d617f9042ee9e76a71 upstream. - -The seccomp path was using AUDIT_ANOM_ABEND from when seccomp mode 1 -could only kill a process. While we still want to make sure an audit -record is forced on a kill, this should use a separate record type since -seccomp mode 2 introduces other behaviors. - -In the case of "handled" behaviors (process wasn't killed), only emit a -record if the process is under inspection. This change also fixes -userspace examination of seccomp audit events, since it was considered -malformed due to missing fields of the AUDIT_ANOM_ABEND event type. - -Signed-off-by: Kees Cook -Cc: Al Viro -Cc: Eric Paris -Cc: Jeff Layton -Cc: "Eric W. Biederman" -Cc: Julien Tinnes -Acked-by: Will Drewry -Acked-by: Steve Grubb -Cc: Andrea Arcangeli -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/audit.h | 3 ++- - include/uapi/linux/audit.h | 1 + - kernel/auditsc.c | 14 +++++++++++--- - 3 files changed, 14 insertions(+), 4 deletions(-) - ---- a/include/linux/audit.h -+++ b/include/linux/audit.h -@@ -157,7 +157,8 @@ void audit_core_dumps(long signr); - - static inline void audit_seccomp(unsigned long syscall, long signr, int code) - { -- if (unlikely(!audit_dummy_context())) -+ /* Force a record to be reported if a signal was delivered. */ -+ if (signr || unlikely(!audit_dummy_context())) - __audit_seccomp(syscall, signr, code); - } - ---- a/include/uapi/linux/audit.h -+++ b/include/uapi/linux/audit.h -@@ -106,6 +106,7 @@ - #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ - #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ - #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ -+#define AUDIT_SECCOMP 1326 /* Secure Computing event */ - - #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ - #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ ---- a/kernel/auditsc.c -+++ b/kernel/auditsc.c -@@ -2735,7 +2735,7 @@ void __audit_mmap_fd(int fd, int flags) - context->type = AUDIT_MMAP; - } - --static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) -+static void audit_log_task(struct audit_buffer *ab) - { - kuid_t auid, uid; - kgid_t gid; -@@ -2753,6 +2753,11 @@ static void audit_log_abend(struct audit - audit_log_task_context(ab); - audit_log_format(ab, " pid=%d comm=", current->pid); - audit_log_untrustedstring(ab, current->comm); -+} -+ -+static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) -+{ -+ audit_log_task(ab); - audit_log_format(ab, " reason="); - audit_log_string(ab, reason); - audit_log_format(ab, " sig=%ld", signr); -@@ -2783,8 +2788,11 @@ void __audit_seccomp(unsigned long sysca - { - struct audit_buffer *ab; - -- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); -- audit_log_abend(ab, "seccomp", signr); -+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); -+ if (unlikely(!ab)) -+ return; -+ audit_log_task(ab); -+ audit_log_format(ab, " sig=%ld", signr); - audit_log_format(ab, " syscall=%ld", syscall); - audit_log_format(ab, " compat=%d", is_compat_task()); - audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); -From d9a58a782e396a0f04e8445b7ba3763c8a48c7fe Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Mon, 7 Jan 2013 05:32:06 +0000 -Subject: xen/netfront: improve truesize tracking - -From: Ian Campbell - -commit d9a58a782e396a0f04e8445b7ba3763c8a48c7fe upstream. - -Using RX_COPY_THRESHOLD is incorrect if the SKB is actually smaller -than that. We have already accounted for this in -NETFRONT_SKB_CB(skb)->pull_to so use that instead. - -Fixes WARN_ON from skb_try_coalesce. - -Signed-off-by: Ian Campbell -Cc: Sander Eikelenboom -Cc: Konrad Rzeszutek Wilk -Cc: annie li -Cc: xen-devel@lists.xen.org -Cc: netdev@vger.kernel.org -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/xen-netfront.c | 27 ++++----------------------- - 1 file changed, 4 insertions(+), 23 deletions(-) - ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -1015,29 +1015,10 @@ err: - i = xennet_fill_frags(np, skb, &tmpq); - - /* -- * Truesize approximates the size of true data plus -- * any supervisor overheads. Adding hypervisor -- * overheads has been shown to significantly reduce -- * achievable bandwidth with the default receive -- * buffer size. It is therefore not wise to account -- * for it here. -- * -- * After alloc_skb(RX_COPY_THRESHOLD), truesize is set -- * to RX_COPY_THRESHOLD + the supervisor -- * overheads. Here, we add the size of the data pulled -- * in xennet_fill_frags(). -- * -- * We also adjust for any unused space in the main -- * data area by subtracting (RX_COPY_THRESHOLD - -- * len). This is especially important with drivers -- * which split incoming packets into header and data, -- * using only 66 bytes of the main data area (see the -- * e1000 driver for example.) On such systems, -- * without this last adjustement, our achievable -- * receive throughout using the standard receive -- * buffer size was cut by 25%(!!!). -- */ -- skb->truesize += skb->data_len - RX_COPY_THRESHOLD; -+ * Truesize is the actual allocation size, even if the -+ * allocation is only partially used. -+ */ -+ skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags; - skb->len += skb->data_len; - - if (rx->flags & XEN_NETRXF_csum_blank) -From 92638e2facc5330475c7d558acec77721c3214e4 Mon Sep 17 00:00:00 2001 -From: Sivaram Nair -Date: Tue, 18 Dec 2012 13:52:54 +0100 -Subject: cpuidle / coupled: fix ready counter decrement - -From: Sivaram Nair - -commit 92638e2facc5330475c7d558acec77721c3214e4 upstream. - -The ready_waiting_counts atomic variable is compared against the wrong -online cpu count. The latter is computed incorrectly using logical-OR -instead of bit-OR. This patch fixes that. - -Signed-off-by: Sivaram Nair -Acked-by: Santosh Shilimkar -Acked-by: Colin Cross -Signed-off-by: Rafael J. Wysocki -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/cpuidle/coupled.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/cpuidle/coupled.c -+++ b/drivers/cpuidle/coupled.c -@@ -209,7 +209,7 @@ inline int cpuidle_coupled_set_not_ready - int all; - int ret; - -- all = coupled->online_count || (coupled->online_count << WAITING_BITS); -+ all = coupled->online_count | (coupled->online_count << WAITING_BITS); - ret = atomic_add_unless(&coupled->ready_waiting_counts, - -MAX_WAITING_CPUS, all); - -From 619c5a9ad54e6bbdafd16d1cdc6c049403710540 Mon Sep 17 00:00:00 2001 -From: Hante Meuleman -Date: Wed, 2 Jan 2013 15:12:39 +0100 -Subject: brcmfmac: fix parsing rsn ie for ap mode. - -From: Hante Meuleman - -commit 619c5a9ad54e6bbdafd16d1cdc6c049403710540 upstream. - -RSN IEs got incorrectly parsed and therefore ap mode using WPA2 -security was not working. - -Reviewed-by: Arend Van Spriel -Reviewed-by: Pieter-Paul Giesberts -Signed-off-by: Hante Meuleman -Signed-off-by: Arend van Spriel -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -@@ -3730,10 +3730,11 @@ brcmf_configure_wpaie(struct net_device - - len = wpa_ie->len + TLV_HDR_LEN; - data = (u8 *)wpa_ie; -- offset = 0; -+ offset = TLV_HDR_LEN; - if (!is_rsn_ie) - offset += VS_IE_FIXED_HDR_LEN; -- offset += WPA_IE_VERSION_LEN; -+ else -+ offset += WPA_IE_VERSION_LEN; - - /* check for multicast cipher suite */ - if (offset + WPA_IE_MIN_OUI_LEN > len) { -From 6c1ecba8d84841277d68140ef485335d5be28485 Mon Sep 17 00:00:00 2001 -From: Lothar Waßmann -Date: Thu, 22 Nov 2012 13:49:14 +0100 -Subject: video: mxsfb: fix crash when unblanking the display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Lothar Waßmann - -commit 6c1ecba8d84841277d68140ef485335d5be28485 upstream. - -The VDCTRL4 register does not provide the MXS SET/CLR/TOGGLE feature. -The write in mxsfb_disable_controller() sets the data_cnt for the LCD -DMA to 0 which obviously means the max. count for the LCD DMA and -leads to overwriting arbitrary memory when the display is unblanked. - -Signed-off-by: Lothar Waßmann -Acked-by: Juergen Beisert -Tested-by: Lauri Hintsala -Signed-off-by: Shawn Guo -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/video/mxsfb.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/video/mxsfb.c -+++ b/drivers/video/mxsfb.c -@@ -369,7 +369,8 @@ static void mxsfb_disable_controller(str - loop--; - } - -- writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR); -+ reg = readl(host->base + LCDC_VDCTRL4); -+ writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); - - clk_disable_unprepare(host->clk); - -From e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Wed, 5 Dec 2012 16:08:33 -0600 -Subject: samsung-laptop: Add quirk for broken acpi_video backlight on N250P - -From: Seth Forshee - -commit e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 upstream. - -BugLink: http://bugs.launchpad.net/bugs/1086921 -Signed-off-by: Seth Forshee -Signed-off-by: Matthew Garrett -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/platform/x86/samsung-laptop.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -1523,6 +1523,16 @@ static struct dmi_system_id __initdata s - }, - .driver_data = &samsung_broken_acpi_video, - }, -+ { -+ .callback = samsung_dmi_matched, -+ .ident = "N250P", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), -+ DMI_MATCH(DMI_BOARD_NAME, "N250P"), -+ }, -+ .driver_data = &samsung_broken_acpi_video, -+ }, - { }, - }; - MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); -From 9f6d8f6ab26b42620a914d67f29822f9bba90233 Mon Sep 17 00:00:00 2001 -From: "Rafael J. Wysocki" -Date: Sat, 22 Dec 2012 23:59:01 +0100 -Subject: PM: Move disabling/enabling runtime PM to late suspend/early resume - -From: "Rafael J. Wysocki" - -commit 9f6d8f6ab26b42620a914d67f29822f9bba90233 upstream. - -Currently, the PM core disables runtime PM for all devices right -after executing subsystem/driver .suspend() callbacks for them -and re-enables it right before executing subsystem/driver .resume() -callbacks for them. This may lead to problems when there are -two devices such that the .suspend() callback executed for one of -them depends on runtime PM working for the other. In that case, -if runtime PM has already been disabled for the second device, -the first one's .suspend() won't work correctly (and analogously -for resume). - -To make those issues go away, make the PM core disable runtime PM -for devices right before executing subsystem/driver .suspend_late() -callbacks for them and enable runtime PM for them right after -executing subsystem/driver .resume_early() callbacks for them. This -way the potential conflitcs between .suspend_late()/.resume_early() -and their runtime PM counterparts are still prevented from happening, -but the subtle ordering issues related to disabling/enabling runtime -PM for devices during system suspend/resume are much easier to avoid. - -Reported-and-tested-by: Jan-Matthias Braun -Signed-off-by: Rafael J. Wysocki -Reviewed-by: Ulf Hansson -Reviewed-by: Kevin Hilman -Signed-off-by: Greg Kroah-Hartman - ---- - Documentation/power/runtime_pm.txt | 9 +++++---- - drivers/base/power/main.c | 9 ++++----- - 2 files changed, 9 insertions(+), 9 deletions(-) - ---- a/Documentation/power/runtime_pm.txt -+++ b/Documentation/power/runtime_pm.txt -@@ -642,12 +642,13 @@ out the following operations: - * During system suspend it calls pm_runtime_get_noresume() and - pm_runtime_barrier() for every device right before executing the - subsystem-level .suspend() callback for it. In addition to that it calls -- pm_runtime_disable() for every device right after executing the -- subsystem-level .suspend() callback for it. -+ __pm_runtime_disable() with 'false' as the second argument for every device -+ right before executing the subsystem-level .suspend_late() callback for it. - - * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync() -- for every device right before and right after executing the subsystem-level -- .resume() callback for it, respectively. -+ for every device right after executing the subsystem-level .resume_early() -+ callback and right after executing the subsystem-level .resume() callback -+ for it, respectively. - - 7. Generic subsystem callbacks - ---- a/drivers/base/power/main.c -+++ b/drivers/base/power/main.c -@@ -513,6 +513,8 @@ static int device_resume_early(struct de - - Out: - TRACE_RESUME(error); -+ -+ pm_runtime_enable(dev); - return error; - } - -@@ -589,8 +591,6 @@ static int device_resume(struct device * - if (!dev->power.is_suspended) - goto Unlock; - -- pm_runtime_enable(dev); -- - if (dev->pm_domain) { - info = "power domain "; - callback = pm_op(&dev->pm_domain->ops, state); -@@ -930,6 +930,8 @@ static int device_suspend_late(struct de - pm_callback_t callback = NULL; - char *info = NULL; - -+ __pm_runtime_disable(dev, false); -+ - if (dev->power.syscore) - return 0; - -@@ -1133,11 +1135,8 @@ static int __device_suspend(struct devic - - Complete: - complete_all(&dev->power.completion); -- - if (error) - async_error = error; -- else if (dev->power.is_suspended) -- __pm_runtime_disable(dev, false); - - return error; - } -From c36575e663e302dbaa4d16b9c72d2c9a913a9aef Mon Sep 17 00:00:00 2001 -From: Forrest Liu -Date: Mon, 17 Dec 2012 09:55:39 -0500 -Subject: ext4: fix extent tree corruption caused by hole punch - -From: Forrest Liu - -commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream. - -When depth of extent tree is greater than 1, logical start value of -interior node is not correctly updated in ext4_ext_rm_idx. - -Signed-off-by: Forrest Liu -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Ashish Sangwan -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/extents.c | 22 ++++++++++++++++++---- - 1 file changed, 18 insertions(+), 4 deletions(-) - ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -2190,13 +2190,14 @@ errout: - * removes index from the index block. - */ - static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, -- struct ext4_ext_path *path) -+ struct ext4_ext_path *path, int depth) - { - int err; - ext4_fsblk_t leaf; - - /* free index block */ -- path--; -+ depth--; -+ path = path + depth; - leaf = ext4_idx_pblock(path->p_idx); - if (unlikely(path->p_hdr->eh_entries == 0)) { - EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); -@@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *han - - ext4_free_blocks(handle, inode, NULL, leaf, 1, - EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); -+ -+ while (--depth >= 0) { -+ if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) -+ break; -+ path--; -+ err = ext4_ext_get_access(handle, inode, path); -+ if (err) -+ break; -+ path->p_idx->ei_block = (path+1)->p_idx->ei_block; -+ err = ext4_ext_dirty(handle, inode, path); -+ if (err) -+ break; -+ } - return err; - } - -@@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struc - /* if this leaf is free, then we should - * remove it from index block above */ - if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) -- err = ext4_ext_rm_idx(handle, inode, path + depth); -+ err = ext4_ext_rm_idx(handle, inode, path, depth); - - out: - return err; -@@ -2760,7 +2774,7 @@ again: - /* index is empty, remove it; - * handle must be already prepared by the - * truncatei_leaf() */ -- err = ext4_ext_rm_idx(handle, inode, path + i); -+ err = ext4_ext_rm_idx(handle, inode, path, i); - } - /* root level has p_bh == NULL, brelse() eats this */ - brelse(path[i].p_bh); -From 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Thu, 20 Dec 2012 00:07:18 -0500 -Subject: ext4: check dioread_nolock on remount - -From: Jan Kara - -commit 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 upstream. - -Currently we allow enabling dioread_nolock mount option on remount for -filesystems where blocksize < PAGE_CACHE_SIZE. This isn't really -supported so fix the bug by moving the check for blocksize != -PAGE_CACHE_SIZE into parse_options(). Change the original PAGE_SIZE to -PAGE_CACHE_SIZE along the way because that's what we are really -interested in. - -Signed-off-by: Jan Kara -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Eric Sandeen -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -1650,9 +1650,7 @@ static int parse_options(char *options, - unsigned int *journal_ioprio, - int is_remount) - { --#ifdef CONFIG_QUOTA - struct ext4_sb_info *sbi = EXT4_SB(sb); --#endif - char *p; - substring_t args[MAX_OPT_ARGS]; - int token; -@@ -1701,6 +1699,16 @@ static int parse_options(char *options, - } - } - #endif -+ if (test_opt(sb, DIOREAD_NOLOCK)) { -+ int blocksize = -+ BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); -+ -+ if (blocksize < PAGE_CACHE_SIZE) { -+ ext4_msg(sb, KERN_ERR, "can't mount with " -+ "dioread_nolock if block size != PAGE_SIZE"); -+ return 0; -+ } -+ } - return 1; - } - -@@ -3446,15 +3454,6 @@ static int ext4_fill_super(struct super_ - clear_opt(sb, DELALLOC); - } - -- blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); -- if (test_opt(sb, DIOREAD_NOLOCK)) { -- if (blocksize < PAGE_SIZE) { -- ext4_msg(sb, KERN_ERR, "can't mount with " -- "dioread_nolock if block size != PAGE_SIZE"); -- goto failed_mount; -- } -- } -- - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | - (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); - -@@ -3496,6 +3495,7 @@ static int ext4_fill_super(struct super_ - if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) - goto failed_mount; - -+ blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); - if (blocksize < EXT4_MIN_BLOCK_SIZE || - blocksize > EXT4_MAX_BLOCK_SIZE) { - ext4_msg(sb, KERN_ERR, -From d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Fri, 21 Dec 2012 00:15:51 -0500 -Subject: jbd2: fix assertion failure in jbd2_journal_flush() - -From: Jan Kara - -commit d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a upstream. - -The following race is possible between start_this_handle() and someone -calling jbd2_journal_flush(). - -Process A Process B -start_this_handle(). - if (journal->j_barrier_count) # false - if (!journal->j_running_transaction) { #true - read_unlock(&journal->j_state_lock); - jbd2_journal_lock_updates() - jbd2_journal_flush() - write_lock(&journal->j_state_lock); - if (journal->j_running_transaction) { - # false - ... wait for committing trans ... - write_unlock(&journal->j_state_lock); - ... - write_lock(&journal->j_state_lock); - if (!journal->j_running_transaction) { # true - jbd2_get_transaction(journal, new_transaction); - write_unlock(&journal->j_state_lock); - goto repeat; # eventually blocks on j_barrier_count > 0 - ... - J_ASSERT(!journal->j_running_transaction); - # fails - -We fix the race by rechecking j_barrier_count after reacquiring j_state_lock -in exclusive mode. - -Reported-by: yjwsignal@empal.com -Signed-off-by: Jan Kara -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/jbd2/transaction.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -209,7 +209,8 @@ repeat: - if (!new_transaction) - goto alloc_transaction; - write_lock(&journal->j_state_lock); -- if (!journal->j_running_transaction) { -+ if (!journal->j_running_transaction && -+ !journal->j_barrier_count) { - jbd2_get_transaction(journal, new_transaction); - new_transaction = NULL; - } -From d096ad0f79a782935d2e06ae8fb235e8c5397775 Mon Sep 17 00:00:00 2001 -From: Michael Tokarev -Date: Tue, 25 Dec 2012 14:08:16 -0500 -Subject: ext4: do not try to write superblock on ro remount w/o journal - -From: Michael Tokarev - -commit d096ad0f79a782935d2e06ae8fb235e8c5397775 upstream. - -When a journal-less ext4 filesystem is mounted on a read-only block -device (blockdev --setro will do), each remount (for other, unrelated, -flags, like suid=>nosuid etc) results in a series of scary messages -from kernel telling about I/O errors on the device. - -This is becauese of the following code ext4_remount(): - - if (sbi->s_journal == NULL) - ext4_commit_super(sb, 1); - -at the end of remount procedure, which forces writing (flushing) of -a superblock regardless whenever it is dirty or not, if the filesystem -is readonly or not, and whenever the device itself is readonly or not. - -We only need call ext4_commit_super when the file system had been -previously mounted read/write. - -Thanks to Eric Sandeen for help in diagnosing this issue. - -Signed-off-By: Michael Tokarev -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -4729,7 +4729,7 @@ static int ext4_remount(struct super_blo - } - - ext4_setup_system_zone(sb); -- if (sbi->s_journal == NULL) -+ if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) - ext4_commit_super(sb, 1); - - #ifdef CONFIG_QUOTA -From 721e3eba21e43532e438652dd8f1fcdfce3187e7 Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Thu, 27 Dec 2012 01:42:48 -0500 -Subject: ext4: lock i_mutex when truncating orphan inodes - -From: Theodore Ts'o - -commit 721e3eba21e43532e438652dd8f1fcdfce3187e7 upstream. - -Commit c278531d39 added a warning when ext4_flush_unwritten_io() is -called without i_mutex being taken. It had previously not been taken -during orphan cleanup since races weren't possible at that point in -the mount process, but as a result of this c278531d39, we will now see -a kernel WARN_ON in this case. Take the i_mutex in -ext4_orphan_cleanup() to suppress this warning. - -Reported-by: Alexander Beregalov -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Zheng Liu -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2225,7 +2225,9 @@ static void ext4_orphan_cleanup(struct s - __func__, inode->i_ino, inode->i_size); - jbd_debug(2, "truncating inode %lu to %lld bytes\n", - inode->i_ino, inode->i_size); -+ mutex_lock(&inode->i_mutex); - ext4_truncate(inode); -+ mutex_unlock(&inode->i_mutex); - nr_truncates++; - } else { - ext4_msg(sb, KERN_DEBUG, -From 0e9a9a1ad619e7e987815d20262d36a2f95717ca Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Thu, 27 Dec 2012 01:42:50 -0500 -Subject: ext4: avoid hang when mounting non-journal filesystems with orphan list - -From: Theodore Ts'o - -commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. - -When trying to mount a file system which does not contain a journal, -but which does have a orphan list containing an inode which needs to -be truncated, the mount call with hang forever in -ext4_orphan_cleanup() because ext4_orphan_del() will return -immediately without removing the inode from the orphan list, leading -to an uninterruptible loop in kernel code which will busy out one of -the CPU's on the system. - -This can be trivially reproduced by trying to mount the file system -found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs -source tree. If a malicious user were to put this on a USB stick, and -mount it on a Linux desktop which has automatic mounts enabled, this -could be considered a potential denial of service attack. (Not a big -deal in practice, but professional paranoids worry about such things, -and have even been known to allocate CVE numbers for such problems.) - -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Zheng Liu -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/namei.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/fs/ext4/namei.c -+++ b/fs/ext4/namei.c -@@ -2498,7 +2498,8 @@ int ext4_orphan_del(handle_t *handle, st - struct ext4_iloc iloc; - int err = 0; - -- if (!EXT4_SB(inode->i_sb)->s_journal) -+ if ((!EXT4_SB(inode->i_sb)->s_journal) && -+ !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) - return 0; - - mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); -From 0ecaef0644973e9006fdbc6974301047aaff9bc6 Mon Sep 17 00:00:00 2001 -From: Guo Chao -Date: Sun, 6 Jan 2013 23:38:47 -0500 -Subject: ext4: release buffer in failed path in dx_probe() - -From: Guo Chao - -commit 0ecaef0644973e9006fdbc6974301047aaff9bc6 upstream. - -If checksum fails, we should also release the buffer -read from previous iteration. - -Signed-off-by: Guo Chao -Signed-off-by: "Theodore Ts'o" -Reviewed-by: Darrick J. Wong - -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/namei.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/ext4/namei.c -+++ b/fs/ext4/namei.c -@@ -725,7 +725,7 @@ dx_probe(const struct qstr *d_name, stru - ext4_warning(dir->i_sb, "Node failed checksum"); - brelse(bh); - *err = ERR_BAD_DX_DIR; -- goto fail; -+ goto fail2; - } - set_buffer_verified(bh); - -From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 -From: Ed Cashin -Date: Mon, 17 Dec 2012 16:03:58 -0800 -Subject: aoe: remove vestigial request queue allocation - -From: Ed Cashin - -commit 0a41409c518083133e79015092585d68915865be upstream. - -Before the aoe driver was an I/O request handler, it was a -make_request-style block driver. Even so, there was a problem where -sysfs expected a request queue to exist, so one was provided in commit -7135a71b19be ("aoe: allocate unused request_queue for sysfs"). - -During the transition to the request-handler style, a patch was merged -that was based on a driver without the noop queue, and the noop queue -remained in place after the patch was merged, even though a new -functional queue was introduced by the patch, allocated through -blk_init_queue. - -The user impact is a memory leak proportional to the number of AoE -targets discovered. This patch removes the memory leak and cleans up -vestiges of the old do-nothing queue from the aoeblk_gdalloc function. - -Signed-off-by: Ed Cashin -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/block/aoe/aoeblk.c | 17 ++++------------- - 1 file changed, 4 insertions(+), 13 deletions(-) - ---- a/drivers/block/aoe/aoeblk.c -+++ b/drivers/block/aoe/aoeblk.c -@@ -231,18 +231,12 @@ aoeblk_gdalloc(void *vp) - if (q == NULL) { - pr_err("aoe: cannot allocate block queue for %ld.%d\n", - d->aoemajor, d->aoeminor); -- mempool_destroy(mp); -- goto err_disk; -+ goto err_mempool; - } - -- d->blkq = blk_alloc_queue(GFP_KERNEL); -- if (!d->blkq) -- goto err_mempool; -- d->blkq->backing_dev_info.name = "aoe"; -- if (bdi_init(&d->blkq->backing_dev_info)) -- goto err_blkq; - spin_lock_irqsave(&d->lock, flags); -- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); -+ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); -+ q->backing_dev_info.name = "aoe"; - q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; - d->bufpool = mp; - d->blkq = gd->queue = q; -@@ -265,11 +259,8 @@ aoeblk_gdalloc(void *vp) - aoedisk_add_sysfs(d); - return; - --err_blkq: -- blk_cleanup_queue(d->blkq); -- d->blkq = NULL; - err_mempool: -- mempool_destroy(d->bufpool); -+ mempool_destroy(mp); - err_disk: - put_disk(gd); - err: -From 2fb7d99d0de3fd8ae869f35ab682581d8455887a Mon Sep 17 00:00:00 2001 -From: Namjae Jeon -Date: Wed, 10 Oct 2012 00:08:56 +0900 -Subject: udf: fix memory leak while allocating blocks during write - -From: Namjae Jeon - -commit 2fb7d99d0de3fd8ae869f35ab682581d8455887a upstream. - -Need to brelse the buffer_head stored in cur_epos and next_epos. - -Signed-off-by: Namjae Jeon -Signed-off-by: Ashish Sangwan -Signed-off-by: Jan Kara -Signed-off-by: Shuah Khan -Signed-off-by: Greg Kroah-Hartman - ---- - fs/udf/inode.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/fs/udf/inode.c -+++ b/fs/udf/inode.c -@@ -765,6 +765,8 @@ static sector_t inode_getblk(struct inod - goal, err); - if (!newblocknum) { - brelse(prev_epos.bh); -+ brelse(cur_epos.bh); -+ brelse(next_epos.bh); - *err = -ENOSPC; - return 0; - } -@@ -795,6 +797,8 @@ static sector_t inode_getblk(struct inod - udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); - - brelse(prev_epos.bh); -+ brelse(cur_epos.bh); -+ brelse(next_epos.bh); - - newblock = udf_get_pblock(inode->i_sb, newblocknum, - iinfo->i_location.partitionReferenceNum, 0); -From fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 Mon Sep 17 00:00:00 2001 -From: Namjae Jeon -Date: Wed, 10 Oct 2012 00:09:12 +0900 -Subject: udf: don't increment lenExtents while writing to a hole - -From: Namjae Jeon - -commit fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 upstream. - -Incrementing lenExtents even while writing to a hole is bad -for performance as calls to udf_discard_prealloc and -udf_truncate_tail_extent would not return from start if -isize != lenExtents - -Signed-off-by: Namjae Jeon -Signed-off-by: Ashish Sangwan -Signed-off-by: Jan Kara -Signed-off-by: Shuah Khan -Signed-off-by: Greg Kroah-Hartman - ---- - fs/udf/inode.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/fs/udf/inode.c -+++ b/fs/udf/inode.c -@@ -601,6 +601,7 @@ static sector_t inode_getblk(struct inod - struct udf_inode_info *iinfo = UDF_I(inode); - int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; - int lastblock = 0; -+ bool isBeyondEOF; - - *err = 0; - *new = 0; -@@ -680,7 +681,7 @@ static sector_t inode_getblk(struct inod - /* Are we beyond EOF? */ - if (etype == -1) { - int ret; -- -+ isBeyondEOF = 1; - if (count) { - if (c) - laarr[0] = laarr[1]; -@@ -723,6 +724,7 @@ static sector_t inode_getblk(struct inod - endnum = c + 1; - lastblock = 1; - } else { -+ isBeyondEOF = 0; - endnum = startnum = ((count > 2) ? 2 : count); - - /* if the current extent is in position 0, -@@ -770,7 +772,8 @@ static sector_t inode_getblk(struct inod - *err = -ENOSPC; - return 0; - } -- iinfo->i_lenExtents += inode->i_sb->s_blocksize; -+ if (isBeyondEOF) -+ iinfo->i_lenExtents += inode->i_sb->s_blocksize; - } - - /* if the extent the requsted block is located in contains multiple -From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 -From: Zhang Rui -Date: Tue, 4 Dec 2012 23:23:16 +0100 -Subject: ACPI : do not use Lid and Sleep button for S5 wakeup - -From: Zhang Rui - -commit b7e383046c2c7c13ad928cd7407eafff758ddd4b upstream. - -When system enters power off, the _PSW of Lid device is enabled. -But this may cause the system to reboot instead of power off. - -A proper way to fix this is to always disable lid wakeup capability for S5. - -References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 -Signed-off-by: Zhang Rui -Signed-off-by: Rafael J. Wysocki -Cc: Joseph Salisbury -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/acpi/scan.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - ---- a/drivers/acpi/scan.c -+++ b/drivers/acpi/scan.c -@@ -859,8 +859,8 @@ acpi_bus_extract_wakeup_device_power_pac - static void acpi_bus_set_run_wake_flags(struct acpi_device *device) - { - struct acpi_device_id button_device_ids[] = { -- {"PNP0C0D", 0}, - {"PNP0C0C", 0}, -+ {"PNP0C0D", 0}, - {"PNP0C0E", 0}, - {"", 0}, - }; -@@ -872,6 +872,11 @@ static void acpi_bus_set_run_wake_flags( - /* Power button, Lid switch always enable wakeup */ - if (!acpi_match_device_ids(device, button_device_ids)) { - device->wakeup.flags.run_wake = 1; -+ if (!acpi_match_device_ids(device, &button_device_ids[1])) { -+ /* Do not use Lid/sleep button for S5 wakeup */ -+ if (device->wakeup.sleep_state == ACPI_STATE_S5) -+ device->wakeup.sleep_state = ACPI_STATE_S4; -+ } - device_set_wakeup_capable(&device->dev, true); - return; - } -From db04328c167ff8e7c57f4a3532214aeada3a82fd Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Tue, 11 Dec 2012 01:14:11 +0900 -Subject: regmap: debugfs: Avoid overflows for very small reads - -From: Mark Brown - -commit db04328c167ff8e7c57f4a3532214aeada3a82fd upstream. - -If count is less than the size of a register then we may hit integer -wraparound when trying to move backwards to check if we're still in -the buffer. Instead move the position forwards to check if it's still -in the buffer, we are unlikely to be able to allocate a buffer -sufficiently big to overflow here. - -Signed-off-by: Mark Brown -Cc: stable@vger.kernel.org - ---- - drivers/base/regmap/regmap-debugfs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/base/regmap/regmap-debugfs.c -+++ b/drivers/base/regmap/regmap-debugfs.c -@@ -90,7 +90,7 @@ static ssize_t regmap_map_read_file(stru - /* If we're in the region the user is trying to read */ - if (p >= *ppos) { - /* ...but not beyond it */ -- if (buf_pos >= count - 1 - tot_len) -+ if (buf_pos + 1 + tot_len >= count) - break; - - /* Format the register */ -From 128dd1759d96ad36c379240f8b9463e8acfd37a1 Mon Sep 17 00:00:00 2001 -From: Eric Wong -Date: Tue, 1 Jan 2013 21:20:27 +0000 -Subject: epoll: prevent missed events on EPOLL_CTL_MOD - -From: Eric Wong - -commit 128dd1759d96ad36c379240f8b9463e8acfd37a1 upstream. - -EPOLL_CTL_MOD sets the interest mask before calling f_op->poll() to -ensure events are not missed. Since the modifications to the interest -mask are not protected by the same lock as ep_poll_callback, we need to -ensure the change is visible to other CPUs calling ep_poll_callback. - -We also need to ensure f_op->poll() has an up-to-date view of past -events which occured before we modified the interest mask. So this -barrier also pairs with the barrier in wq_has_sleeper(). - -This should guarantee either ep_poll_callback or f_op->poll() (or both) -will notice the readiness of a recently-ready/modified item. - -This issue was encountered by Andreas Voellmy and Junchang(Jason) Wang in: -http://thread.gmane.org/gmane.linux.kernel/1408782/ - -Signed-off-by: Eric Wong -Cc: Hans Verkuil -Cc: Jiri Olsa -Cc: Jonathan Corbet -Cc: Al Viro -Cc: Davide Libenzi -Cc: Hans de Goede -Cc: Mauro Carvalho Chehab -Cc: David Miller -Cc: Eric Dumazet -Cc: Andrew Morton -Cc: Andreas Voellmy -Tested-by: "Junchang(Jason) Wang" -Cc: netdev@vger.kernel.org -Cc: linux-fsdevel@vger.kernel.org -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/eventpoll.c | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -1285,7 +1285,7 @@ static int ep_modify(struct eventpoll *e - * otherwise we might miss an event that happens between the - * f_op->poll() call and the new event set registering. - */ -- epi->event.events = event->events; -+ epi->event.events = event->events; /* need barrier below */ - pt._key = event->events; - epi->event.data = event->data; /* protected by mtx */ - if (epi->event.events & EPOLLWAKEUP) { -@@ -1296,6 +1296,26 @@ static int ep_modify(struct eventpoll *e - } - - /* -+ * The following barrier has two effects: -+ * -+ * 1) Flush epi changes above to other CPUs. This ensures -+ * we do not miss events from ep_poll_callback if an -+ * event occurs immediately after we call f_op->poll(). -+ * We need this because we did not take ep->lock while -+ * changing epi above (but ep_poll_callback does take -+ * ep->lock). -+ * -+ * 2) We also need to ensure we do not miss _past_ events -+ * when calling f_op->poll(). This barrier also -+ * pairs with the barrier in wq_has_sleeper (see -+ * comments for wq_has_sleeper). -+ * -+ * This barrier will now guarantee ep_poll_callback or f_op->poll -+ * (or both) will notice the readiness of an item. -+ */ -+ smp_mb(); -+ -+ /* - * Get current event bits. We can safely use the file* here because - * its usage count has been increased by the caller of this function. - */ -From 436136cec650d661eb662fcb508a99878606d050 Mon Sep 17 00:00:00 2001 -From: Marek Vasut -Date: Sat, 24 Nov 2012 06:15:57 +0100 -Subject: HID: add quirk for Freescale i.MX23 ROM recovery - -From: Marek Vasut - -commit 436136cec650d661eb662fcb508a99878606d050 upstream. - -The USB recovery mode present in i.MX23 ROM emulates USB HID. It needs this -quirk to behave properly. - -Even if the official branding of the chip is Freescale i.MX23, I named it -Sigmatel STMP3780 since that's what the chip really is and it even reports -itself as STMP3780. - -Signed-off-by: Marek Vasut -Signed-off-by: Jiri Kosina -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hid/hid-ids.h | 3 +++ - drivers/hid/usbhid/hid-quirks.c | 1 + - 2 files changed, 4 insertions(+) - ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -696,6 +696,9 @@ - #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f - #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 - -+#define USB_VENDOR_ID_SIGMATEL 0x066F -+#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 -+ - #define USB_VENDOR_ID_SKYCABLE 0x1223 - #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 - ---- a/drivers/hid/usbhid/hid-quirks.c -+++ b/drivers/hid/usbhid/hid-quirks.c -@@ -79,6 +79,7 @@ static const struct hid_blacklist { - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, -+ { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -From a8c02db029385fb4426e0396e108ab23cd08f384 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Tue, 18 Dec 2012 14:05:01 +0000 -Subject: ASoC: arizona: Correct FLL source definitions - -From: Mark Brown - -commit a8c02db029385fb4426e0396e108ab23cd08f384 upstream. - -The FLL source constants were numbered as a simple enumeration but were -being used in the code as direct values to be written to the registers. -Renumber the constants to reflect the usage. - -Reported-by: Ryo Tsutsui -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/arizona.h | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - ---- a/sound/soc/codecs/arizona.h -+++ b/sound/soc/codecs/arizona.h -@@ -32,15 +32,15 @@ - - #define ARIZONA_FLL_SRC_MCLK1 0 - #define ARIZONA_FLL_SRC_MCLK2 1 --#define ARIZONA_FLL_SRC_SLIMCLK 2 --#define ARIZONA_FLL_SRC_FLL1 3 --#define ARIZONA_FLL_SRC_FLL2 4 --#define ARIZONA_FLL_SRC_AIF1BCLK 5 --#define ARIZONA_FLL_SRC_AIF2BCLK 6 --#define ARIZONA_FLL_SRC_AIF3BCLK 7 --#define ARIZONA_FLL_SRC_AIF1LRCLK 8 --#define ARIZONA_FLL_SRC_AIF2LRCLK 9 --#define ARIZONA_FLL_SRC_AIF3LRCLK 10 -+#define ARIZONA_FLL_SRC_SLIMCLK 3 -+#define ARIZONA_FLL_SRC_FLL1 4 -+#define ARIZONA_FLL_SRC_FLL2 5 -+#define ARIZONA_FLL_SRC_AIF1BCLK 8 -+#define ARIZONA_FLL_SRC_AIF2BCLK 9 -+#define ARIZONA_FLL_SRC_AIF3BCLK 10 -+#define ARIZONA_FLL_SRC_AIF1LRCLK 12 -+#define ARIZONA_FLL_SRC_AIF2LRCLK 13 -+#define ARIZONA_FLL_SRC_AIF3LRCLK 14 - - #define ARIZONA_MIXER_VOL_MASK 0x00FE - #define ARIZONA_MIXER_VOL_SHIFT 1 -From 7110a287ff2b1f3780905d1686a1a4edccb95133 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Thu, 20 Dec 2012 23:29:42 +0800 -Subject: ASoC: arizona: Do proper shift for setting AIF rate - -From: Axel Lin - -commit 7110a287ff2b1f3780905d1686a1a4edccb95133 upstream. - -ARIZONA_AIF1_RATE_MASK is 0x7800 /* AIF1_RATE - [14:11] */ -Thus we need left shift ARIZONA_AIF1_RATE_SHIFT when setting aif1 rate. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/arizona.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/sound/soc/codecs/arizona.c -+++ b/sound/soc/codecs/arizona.c -@@ -677,7 +677,8 @@ static int arizona_hw_params(struct snd_ - snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, - ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); - snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, -- ARIZONA_AIF1_RATE_MASK, 8); -+ ARIZONA_AIF1_RATE_MASK, -+ 8 << ARIZONA_AIF1_RATE_SHIFT); - break; - default: - arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); -From d71753e22b24548911b377db28f80870cf50d07b Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 4 Jan 2013 10:48:02 +0000 -Subject: ASoC: arizona: Remove DSP B and left justified AIF modes - -From: Mark Brown - -commit d71753e22b24548911b377db28f80870cf50d07b upstream. - -These are not supported. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/arizona.c | 6 ------ - 1 file changed, 6 deletions(-) - ---- a/sound/soc/codecs/arizona.c -+++ b/sound/soc/codecs/arizona.c -@@ -409,15 +409,9 @@ static int arizona_set_fmt(struct snd_so - case SND_SOC_DAIFMT_DSP_A: - mode = 0; - break; -- case SND_SOC_DAIFMT_DSP_B: -- mode = 1; -- break; - case SND_SOC_DAIFMT_I2S: - mode = 2; - break; -- case SND_SOC_DAIFMT_LEFT_J: -- mode = 3; -- break; - default: - arizona_aif_err(dai, "Unsupported DAI format %d\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); -From 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 4 Jan 2013 21:18:12 +0000 -Subject: ASoC: wm2000: Fix sense of speech clarity enable - -From: Mark Brown - -commit 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa upstream. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm2000.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/sound/soc/codecs/wm2000.c -+++ b/sound/soc/codecs/wm2000.c -@@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_cl - - ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); - if (wm2000->speech_clarity) -- ret &= ~WM2000_SPEECH_CLARITY; -- else - ret |= WM2000_SPEECH_CLARITY; -+ else -+ ret &= ~WM2000_SPEECH_CLARITY; - wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); - - wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); -From 2a5f431592343b78896013b055582f94c12a5049 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Fri, 21 Dec 2012 16:28:37 +0800 -Subject: ASoC: wm2200: Fix setting dai format in wm2200_set_fmt - -From: Axel Lin - -commit 2a5f431592343b78896013b055582f94c12a5049 upstream. - -According to the defines in wm2200.h: -/* - * R1284 (0x504) - Audio IF 1_5 - */ - -We should not left shift 1 bit for fmt_val when setting dai format. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm2200.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/sound/soc/codecs/wm2200.c -+++ b/sound/soc/codecs/wm2200.c -@@ -1440,7 +1440,7 @@ static int wm2200_set_fmt(struct snd_soc - WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, - lrclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, -- WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); -+ WM2200_AIF1_FMT_MASK, fmt_val); - - return 0; - } -From 0cc411b934c4317b363d1af993549f391852b980 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 4 Jan 2013 10:48:10 +0000 -Subject: ASoC: wm2200: Remove DSP B and left justified AIF modes - -From: Mark Brown - -commit 0cc411b934c4317b363d1af993549f391852b980 upstream. - -These are not supported. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm2200.c | 6 ------ - 1 file changed, 6 deletions(-) - ---- a/sound/soc/codecs/wm2200.c -+++ b/sound/soc/codecs/wm2200.c -@@ -1380,15 +1380,9 @@ static int wm2200_set_fmt(struct snd_soc - case SND_SOC_DAIFMT_DSP_A: - fmt_val = 0; - break; -- case SND_SOC_DAIFMT_DSP_B: -- fmt_val = 1; -- break; - case SND_SOC_DAIFMT_I2S: - fmt_val = 2; - break; -- case SND_SOC_DAIFMT_LEFT_J: -- fmt_val = 3; -- break; - default: - dev_err(codec->dev, "Unsupported DAI format %d\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); -From ad1937cdd59c412097ec2bb8f38c12a5640f1f9a Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Thu, 20 Dec 2012 16:17:25 +0800 -Subject: ASoC: sta529: Fix update register bits in sta529_set_dai_fmt - -From: Axel Lin - -commit ad1937cdd59c412097ec2bb8f38c12a5640f1f9a upstream. - -Both the mask and mode settings are wrong in current code. - -According to the datasheet: - -S2PCFG0 (0x0A) -BIT[3:1] DATA_FORMAT - serial interface protocol format: - 000: left Justified - 001: I2S (default) - 010: right justified - 100: PCM no delay - 101: PCM delay - 111: DSP - -Thus fixes the defines for LEFT_J_DATA_FORMAT, I2S_DATA_FORMAT, and -RIGHT_J_DATA_FORMAT. -Also adds define for DATA_FORMAT_MSK. - -Signed-off-by: Axel Lin -Acked-by: Rajeev Kumar -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/sta529.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/sound/soc/codecs/sta529.c -+++ b/sound/soc/codecs/sta529.c -@@ -74,9 +74,10 @@ - SNDRV_PCM_FMTBIT_S32_LE) - #define S2PC_VALUE 0x98 - #define CLOCK_OUT 0x60 --#define LEFT_J_DATA_FORMAT 0x10 --#define I2S_DATA_FORMAT 0x12 --#define RIGHT_J_DATA_FORMAT 0x14 -+#define DATA_FORMAT_MSK 0x0E -+#define LEFT_J_DATA_FORMAT 0x00 -+#define I2S_DATA_FORMAT 0x02 -+#define RIGHT_J_DATA_FORMAT 0x04 - #define CODEC_MUTE_VAL 0x80 - - #define POWER_CNTLMSAK 0x40 -@@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd - return -EINVAL; - } - -- snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); -+ snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); - - return 0; - } -From 08b27848da620f206a8b6d80f26184485dd7aa40 Mon Sep 17 00:00:00 2001 -From: Patrick Lai -Date: Wed, 19 Dec 2012 19:36:02 -0800 -Subject: ASoC: pcm: allow backend hardware to be freed in pause state - -From: Patrick Lai - -commit 08b27848da620f206a8b6d80f26184485dd7aa40 upstream. - -When front-end PCM session is in paused state, back-end -PCM session will be put in paused state as well if given -front-end PCM session is the only client of given back-end. -Then, application closes front-end PCM session, DPCM -framework will not allow back-end enters HW_FREE state -so back-end will never get shutdown completely. - -Signed-off-by: Patrick Lai -Acked-by: Liam Girdwood -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/soc-pcm.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/sound/soc/soc-pcm.c -+++ b/sound/soc/soc-pcm.c -@@ -1240,6 +1240,7 @@ static int dpcm_be_dai_hw_free(struct sn - if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && -+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) - continue; - -From 5f960294e2031d12f10c8488c3446fecbf59628d Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 4 Jan 2013 21:06:08 +0000 -Subject: ASoC: wm5100: Remove DSP B and left justified formats - -From: Mark Brown - -commit 5f960294e2031d12f10c8488c3446fecbf59628d upstream. - -These are not supported - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm5100.c | 6 ------ - 1 file changed, 6 deletions(-) - ---- a/sound/soc/codecs/wm5100.c -+++ b/sound/soc/codecs/wm5100.c -@@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc - case SND_SOC_DAIFMT_DSP_A: - mask = 0; - break; -- case SND_SOC_DAIFMT_DSP_B: -- mask = 1; -- break; - case SND_SOC_DAIFMT_I2S: - mask = 2; - break; -- case SND_SOC_DAIFMT_LEFT_J: -- mask = 3; -- break; - default: - dev_err(codec->dev, "Unsupported DAI format %d\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); -From c930812fe5ebe725760422c9c351d1f6fde1502d Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 11 Jan 2013 12:08:56 +0100 -Subject: udldrmfb: Fix EDID not working with monitors with EDID - extension blocks - -From: Hans de Goede - -commit c930812fe5ebe725760422c9c351d1f6fde1502d upstream. - -udldrmfb only reads the main EDID block, and if that advertises extensions -the drm_edid code expects them to be present, and starts reading beyond the -buffer udldrmfb passes it. - -Although it may be possible to read more EDID info with the udl we simpy don't -know how, and even if trial and error gets it working on one device, that is -no guarantee it will work on other revisions. So this patch does a simple fix -in the form of patching the EDID info to report 0 extension blocks, this -fixes udldrmfb only doing 1024x768 on monitors with EDID extension blocks. - -Signed-off-by: Hans de Goede -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/udl/udl_connector.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/gpu/drm/udl/udl_connector.c -+++ b/drivers/gpu/drm/udl/udl_connector.c -@@ -57,6 +57,14 @@ static int udl_get_modes(struct drm_conn - - edid = (struct edid *)udl_get_edid(udl); - -+ /* -+ * We only read the main block, but if the monitor reports extension -+ * blocks then the drm edid code expects them to be present, so patch -+ * the extension count to 0. -+ */ -+ edid->checksum += edid->extensions; -+ edid->extensions = 0; -+ - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - kfree(edid); -From 242187b362555849e8c971dfbbfd55f8bd9fa717 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 11 Jan 2013 12:08:57 +0100 -Subject: udldrmfb: udl_get_edid: usb_control_msg buffer must not be on the stack - -From: Hans de Goede - -commit 242187b362555849e8c971dfbbfd55f8bd9fa717 upstream. - -The buffer passed to usb_control_msg may end up in scatter-gather list, and -may thus not be on the stack. Having it on the stack usually works on x86, but -not on other archs. - -Signed-off-by: Hans de Goede -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/udl/udl_connector.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/udl/udl_connector.c -+++ b/drivers/gpu/drm/udl/udl_connector.c -@@ -22,13 +22,17 @@ - static u8 *udl_get_edid(struct udl_device *udl) - { - u8 *block; -- char rbuf[3]; -+ char *rbuf; - int ret, i; - - block = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (block == NULL) - return NULL; - -+ rbuf = kmalloc(2, GFP_KERNEL); -+ if (rbuf == NULL) -+ goto error; -+ - for (i = 0; i < EDID_LENGTH; i++) { - ret = usb_control_msg(udl->ddev->usbdev, - usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), -@@ -42,10 +46,12 @@ static u8 *udl_get_edid(struct udl_devic - block[i] = rbuf[1]; - } - -+ kfree(rbuf); - return block; - - error: - kfree(block); -+ kfree(rbuf); - return NULL; - } - -From 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 11 Jan 2013 12:08:58 +0100 -Subject: udldrmfb: udl_get_edid: drop unneeded i-- - -From: Hans de Goede - -commit 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 upstream. - -This is a left-over from when udl_get_edid returned the amount of bytes -successfully read, which it no longer does. - -Signed-off-by: Hans de Goede -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/udl/udl_connector.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/gpu/drm/udl/udl_connector.c -+++ b/drivers/gpu/drm/udl/udl_connector.c -@@ -40,7 +40,6 @@ static u8 *udl_get_edid(struct udl_devic - HZ); - if (ret < 1) { - DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); -- i--; - goto error; - } - block[i] = rbuf[1]; -From 6d283dba3721cc43be014b50a1acc2f35860a65a Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Mon, 14 Jan 2013 13:17:50 -0800 -Subject: vfs: add missing virtual cache flush after editing partial pages - -From: Linus Torvalds - -commit 6d283dba3721cc43be014b50a1acc2f35860a65a upstream. - -Andrew Morton pointed this out a month ago, and then I completely forgot -about it. - -If we read a partial last page of a block device, we will zero out the -end of the page, but since that page can then be mapped into user space, -we should also make sure to flush the cache on architectures that have -virtual caches. We have the flush_dcache_page() function for this, so -use it. - -Now, in practice this really never matters, because nobody sane uses -virtual caches to begin with, and they largely exist on old broken RISC -arhitectures. - -And even if you did run on one of those obsolete CPU's, the whole "mmap -and access the last partial page of a block device" behavior probably -doesn't actually exist. The normal IO functions (read/write) will never -see the zeroed-out part of the page that migth not be coherent in the -cache, because they honor the size of the device. - -So I'm marking this for stable (3.7 only), but I'm not sure anybody will -ever care. - -Pointed-out-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/buffer.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/fs/buffer.c -+++ b/fs/buffer.c -@@ -2939,6 +2939,7 @@ static void guard_bh_eod(int rw, struct - void *kaddr = kmap_atomic(bh->b_page); - memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); - kunmap_atomic(kaddr); -+ flush_dcache_page(bh->b_page); - } - } - -From 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 Mon Sep 17 00:00:00 2001 -From: David Henningsson -Date: Wed, 19 Dec 2012 09:44:47 +0100 -Subject: Revert "ALSA: hda - Shut up pins at power-saving mode with Conexnat codecs" - -From: David Henningsson - -commit 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 upstream. - -This reverts commit 697c373e34613609cb5450f98b91fefb6e910588. - -The original patch was meant to remove clicking, but in fact caused even -more clicking instead. - -Thanks to c4pp4 for doing most of the work with this bug. - -BugLink: https://bugs.launchpad.net/bugs/886975 -Signed-off-by: David Henningsson -Signed-off-by: Takashi Iwai -Signed-off-by: Greg Kroah-Hartman - ---- - sound/pci/hda/patch_conexant.c | 16 ---------------- - 1 file changed, 16 deletions(-) - ---- a/sound/pci/hda/patch_conexant.c -+++ b/sound/pci/hda/patch_conexant.c -@@ -553,24 +553,12 @@ static int conexant_build_controls(struc - return 0; - } - --#ifdef CONFIG_PM --static int conexant_suspend(struct hda_codec *codec) --{ -- snd_hda_shutup_pins(codec); -- return 0; --} --#endif -- - static const struct hda_codec_ops conexant_patch_ops = { - .build_controls = conexant_build_controls, - .build_pcms = conexant_build_pcms, - .init = conexant_init, - .free = conexant_free, - .set_power_state = conexant_set_power, --#ifdef CONFIG_PM -- .suspend = conexant_suspend, --#endif -- .reboot_notify = snd_hda_shutup_pins, - }; - - #ifdef CONFIG_SND_HDA_INPUT_BEEP -@@ -4393,10 +4381,6 @@ static const struct hda_codec_ops cx_aut - .init = cx_auto_init, - .free = conexant_free, - .unsol_event = snd_hda_jack_unsol_event, --#ifdef CONFIG_PM -- .suspend = conexant_suspend, --#endif -- .reboot_notify = snd_hda_shutup_pins, - }; - - /* -From d7dab4dbbb2d1b0c903378d6bade2e4ae161804e Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Tue, 8 Jan 2013 13:51:30 +0100 -Subject: ALSA: hda - Disable runtime D3 for Intel CPT & co - -From: Takashi Iwai - -commit d7dab4dbbb2d1b0c903378d6bade2e4ae161804e upstream. - -We've got a few bug reports that the runtime D3 results in the dead -HD-audio controller. It seems that the problem is in a deeper level -than the sound driver itself, so as a temporal solution, disable the -feature for these controllers again. - -Reported-and-tested-by: Vincent Blut -Reported-and-tested-by: Maurizio Avogadro -Signed-off-by: Takashi Iwai -Signed-off-by: Greg Kroah-Hartman - ---- - sound/pci/hda/hda_intel.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - ---- a/sound/pci/hda/hda_intel.c -+++ b/sound/pci/hda/hda_intel.c -@@ -559,9 +559,12 @@ enum { - #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ - - /* quirks for Intel PCH */ --#define AZX_DCAPS_INTEL_PCH \ -+#define AZX_DCAPS_INTEL_PCH_NOPM \ - (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ -- AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) -+ AZX_DCAPS_COUNT_LPIB_DELAY) -+ -+#define AZX_DCAPS_INTEL_PCH \ -+ (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) - - /* quirks for ATI SB / AMD Hudson */ - #define AZX_DCAPS_PRESET_ATI_SB \ -@@ -3448,13 +3451,13 @@ static void __devexit azx_remove(struct - static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { - /* CPT */ - { PCI_DEVICE(0x8086, 0x1c20), -- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, -+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, - /* PBG */ - { PCI_DEVICE(0x8086, 0x1d20), -- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, -+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, - /* Panther Point */ - { PCI_DEVICE(0x8086, 0x1e20), -- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, -+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, - /* Lynx Point */ - { PCI_DEVICE(0x8086, 0x8c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, -From 41b645c8624df6ace020a8863ad1449d69140f7d Mon Sep 17 00:00:00 2001 -From: Mike Dunn -Date: Mon, 7 Jan 2013 13:55:12 -0800 -Subject: ALSA: pxa27x: fix ac97 cold reset - -From: Mike Dunn - -commit 41b645c8624df6ace020a8863ad1449d69140f7d upstream. - -Cold reset on the pxa27x currently fails and - - pxa2xx_ac97_try_cold_reset: cold reset timeout (GSR=0x44) - -appears in the kernel log. Through trial-and-error (the pxa270 developer's -manual is mostly incoherent on the topic of ac97 reset), I got cold reset to -complete by setting the WARM_RST bit in the GCR register (and later noticed that -pxa3xx does this for cold reset as well). Also, a timeout loop is needed to -wait for the reset to complete. - -Tested on a palm treo 680 machine. - -Signed-off-by: Mike Dunn -Acked-by: Igor Grinberg -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/arm/pxa2xx-ac97-lib.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/sound/arm/pxa2xx-ac97-lib.c -+++ b/sound/arm/pxa2xx-ac97-lib.c -@@ -148,6 +148,8 @@ static inline void pxa_ac97_warm_pxa27x( - - static inline void pxa_ac97_cold_pxa27x(void) - { -+ unsigned int timeout; -+ - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ - -@@ -157,8 +159,10 @@ static inline void pxa_ac97_cold_pxa27x( - clk_enable(ac97conf_clk); - udelay(5); - clk_disable(ac97conf_clk); -- GCR = GCR_COLD_RST; -- udelay(50); -+ GCR = GCR_COLD_RST | GCR_WARM_RST; -+ timeout = 100; /* wait for the codec-ready bit to be set */ -+ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) -+ mdelay(1); - } - #endif - -From 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd Mon Sep 17 00:00:00 2001 -From: Mike Dunn -Date: Mon, 7 Jan 2013 13:55:13 -0800 -Subject: ALSA: pxa27x: fix ac97 warm reset - -From: Mike Dunn - -commit 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd upstream. - -This patch fixes some code that implements a work-around to a hardware bug in -the ac97 controller on the pxa27x. A bug in the controller's warm reset -functionality requires that the mfp used by the controller as the AC97_nRESET -line be temporarily reconfigured as a generic output gpio (AF0) and manually -held high for the duration of the warm reset cycle. This is what was done in -the original code, but it was broken long ago by commit fb1bf8cd - ([ARM] pxa: introduce processor specific pxa27x_assert_ac97reset()) -which changed the mfp to a GPIO input instead of a high output. - -The fix requires the ac97 controller to obtain the gpio via gpio_request_one(), -with arguments that configure the gpio as an output initially driven high. - -Tested on a palm treo 680 machine. Reportedly, this broken code only prevents a -warm reset on hardware that lacks a pull-up on the line, which appears to be the -case for me. - -Signed-off-by: Mike Dunn -Signed-off-by: Igor Grinberg -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 +++ - arch/arm/mach-pxa/pxa27x.c | 4 ++-- - sound/arm/pxa2xx-ac97-lib.c | 18 +++++++++++++++++- - 3 files changed, 22 insertions(+), 3 deletions(-) - ---- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h -+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h -@@ -463,6 +463,9 @@ - GPIO76_LCD_PCLK, \ - GPIO77_LCD_BIAS - -+/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ -+#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) -+#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) - - extern int keypad_set_wake(unsigned int on); - #endif /* __ASM_ARCH_MFP_PXA27X_H */ ---- a/arch/arm/mach-pxa/pxa27x.c -+++ b/arch/arm/mach-pxa/pxa27x.c -@@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) - EXPORT_SYMBOL(pxa27x_clear_otgph); - - static unsigned long ac97_reset_config[] = { -- GPIO113_GPIO, -+ GPIO113_AC97_nRESET_GPIO_HIGH, - GPIO113_AC97_nRESET, -- GPIO95_GPIO, -+ GPIO95_AC97_nRESET_GPIO_HIGH, - GPIO95_AC97_nRESET, - }; - ---- a/sound/arm/pxa2xx-ac97-lib.c -+++ b/sound/arm/pxa2xx-ac97-lib.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -344,8 +345,21 @@ int __devinit pxa2xx_ac97_hw_probe(struc - } - - if (cpu_is_pxa27x()) { -- /* Use GPIO 113 as AC97 Reset on Bulverde */ -+ /* -+ * This gpio is needed for a work-around to a bug in the ac97 -+ * controller during warm reset. The direction and level is set -+ * here so that it is an output driven high when switching from -+ * AC97_nRESET alt function to generic gpio. -+ */ -+ ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, -+ "pxa27x ac97 reset"); -+ if (ret < 0) { -+ pr_err("%s: gpio_request_one() failed: %d\n", -+ __func__, ret); -+ goto err_conf; -+ } - pxa27x_assert_ac97reset(reset_gpio, 0); -+ - ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); - if (IS_ERR(ac97conf_clk)) { - ret = PTR_ERR(ac97conf_clk); -@@ -388,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); - - void pxa2xx_ac97_hw_remove(struct platform_device *dev) - { -+ if (cpu_is_pxa27x()) -+ gpio_free(reset_gpio); - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); - if (ac97conf_clk) { -From 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c Mon Sep 17 00:00:00 2001 -From: Ian Abbott -Date: Tue, 4 Dec 2012 15:59:55 +0000 -Subject: staging: comedi: prevent auto-unconfig of manually configured devices - -From: Ian Abbott - -commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c upstream. - -When a low-level comedi driver auto-configures a device, a `struct -comedi_dev_file_info` is allocated (as well as a `struct -comedi_device`) by `comedi_alloc_board_minor()`. A pointer to the -hardware `struct device` is stored as a cookie in the `struct -comedi_dev_file_info`. When the low-level comedi driver -auto-unconfigures the device, `comedi_auto_unconfig()` uses the cookie -to find the `struct comedi_dev_file_info` so it can detach the comedi -device from the driver, clean it up and free it. - -A problem arises if the user manually unconfigures and reconfigures the -comedi device using the `COMEDI_DEVCONFIG` ioctl so that is no longer -associated with the original hardware device. The problem is that the -cookie is not cleared, so that a call to `comedi_auto_unconfig()` from -the low-level driver will still find it, detach it, clean it up and free -it. - -Stop this problem occurring by always clearing the `hardware_device` -cookie in the `struct comedi_dev_file_info` whenever the -`COMEDI_DEVCONFIG` ioctl call is successful. - -Signed-off-by: Ian Abbott -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/comedi/comedi_fops.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/staging/comedi/comedi_fops.c -+++ b/drivers/staging/comedi/comedi_fops.c -@@ -1546,6 +1546,9 @@ static long comedi_unlocked_ioctl(struct - if (cmd == COMEDI_DEVCONFIG) { - rc = do_devconfig_ioctl(dev, - (struct comedi_devconfig __user *)arg); -+ if (rc == 0) -+ /* Evade comedi_auto_unconfig(). */ -+ dev_file_info->hardware_device = NULL; - goto done; - } - -From 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 Mon Sep 17 00:00:00 2001 -From: Éric Piel -Date: Wed, 19 Dec 2012 13:03:13 +0100 -Subject: staging: comedi: fix minimum AO period for NI 625x and NI 628x - -From: Éric Piel - -commit 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 upstream. - -The minimum period was set to 357 ns, while the divider for these boards is 50 -ns. This prevented to output at maximum speed as ni_ao_cmdtest() would return -357 but would not accept it. - -Not sure why it was set to 357 ns (this was done before the git history, -which starts 5 years ago). My guess is that it comes from reading the -specification stating a 2.8 MHz rate (~ 357 ns). The latest -specification states a 2.86 MHz rate (~ 350 ns), which makes a lot -more sense. - -Tested on a pci-6251. - -Signed-off-by: Éric Piel -Acked-By: Ian Abbott -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/comedi/drivers/ni_pcimio.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/staging/comedi/drivers/ni_pcimio.c -+++ b/drivers/staging/comedi/drivers/ni_pcimio.c -@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_628x_ao, - .reg_type = ni_reg_628x, - .ao_unipolar = 1, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_628x_ao, - .reg_type = ni_reg_628x, - .ao_unipolar = 1, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, -@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_b - .ao_range_table = &range_ni_M_628x_ao, - .reg_type = ni_reg_628x, - .ao_unipolar = 1, -- .ao_speed = 357, -+ .ao_speed = 350, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, -From 34ffb33e09132401872fe79e95c30824ce194d23 Mon Sep 17 00:00:00 2001 -From: Ian Abbott -Date: Thu, 3 Jan 2013 12:15:26 +0000 -Subject: staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC - -From: Ian Abbott - -commit 34ffb33e09132401872fe79e95c30824ce194d23 upstream. - -The 'ni_at_a2150' module links to `cfc_write_to_buffer` in the -'comedi_fc' module, so selecting 'COMEDI_NI_AT_A2150' in the kernel config -needs to also select 'COMEDI_FC'. - -Signed-off-by: Ian Abbott -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/comedi/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/staging/comedi/Kconfig -+++ b/drivers/staging/comedi/Kconfig -@@ -444,6 +444,7 @@ config COMEDI_ADQ12B - - config COMEDI_NI_AT_A2150 - tristate "NI AT-A2150 ISA card support" -+ select COMEDI_FC - depends on VIRT_TO_BUS - ---help--- - Enable support for National Instruments AT-A2150 cards -From c0729eeefdcd76db338f635162bf0739fd2c5f6f Mon Sep 17 00:00:00 2001 -From: Ian Abbott -Date: Fri, 4 Jan 2013 11:33:21 +0000 -Subject: staging: comedi: comedi_test: fix race when cancelling command - -From: Ian Abbott - -commit c0729eeefdcd76db338f635162bf0739fd2c5f6f upstream. - -Éric Piel reported a kernel oops in the "comedi_test" module. It was a -NULL pointer dereference within `waveform_ai_interrupt()` (actually a -timer function) that sometimes occurred when a running asynchronous -command is cancelled (either by the `COMEDI_CANCEL` ioctl or by closing -the device file). - -This seems to be a race between the caller of `waveform_ai_cancel()` -which on return from that function goes and tears down the running -command, and the timer function which uses the command. In particular, -`async->cmd.chanlist` gets freed (and the pointer set to NULL) by -`do_become_nonbusy()` in "comedi_fops.c" but a previously scheduled -`waveform_ai_interrupt()` timer function will dereference that pointer -regardless, leading to the oops. - -Fix it by replacing the `del_timer()` call in `waveform_ai_cancel()` -with `del_timer_sync()`. - -Signed-off-by: Ian Abbott -Reported-by: Éric Piel -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/comedi/drivers/comedi_test.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/staging/comedi/drivers/comedi_test.c -+++ b/drivers/staging/comedi/drivers/comedi_test.c -@@ -372,7 +372,7 @@ static int waveform_ai_cancel(struct com - struct waveform_private *devpriv = dev->private; - - devpriv->timer_running = 0; -- del_timer(&devpriv->timer); -+ del_timer_sync(&devpriv->timer); - return 0; - } - -From da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 Mon Sep 17 00:00:00 2001 -From: Larry Finger -Date: Sat, 29 Dec 2012 11:36:53 -0600 -Subject: staging: r8712u: Add new device ID - -From: Larry Finger - -commit da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 upstream. - -The ISY IWL 1000 USB WLAN stick with USB ID 050d:11f1 is a clone of -the Belkin F7D1101 V1 device. - -Reported-by: Thomas Hartmann -Signed-off-by: Larry Finger -Cc: Thomas Hartmann -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/rtl8712/usb_intf.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/staging/rtl8712/usb_intf.c -+++ b/drivers/staging/rtl8712/usb_intf.c -@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_ - {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ - /* Belkin */ - {USB_DEVICE(0x050D, 0x945A)}, -+ /* ISY IWL - Belkin clone */ -+ {USB_DEVICE(0x050D, 0x11F1)}, - /* Corega */ - {USB_DEVICE(0x07AA, 0x0047)}, - /* D-Link */ -From ae428655b826f2755a8101b27beda42a275ef8ad Mon Sep 17 00:00:00 2001 -From: Nickolai Zeldovich -Date: Sat, 5 Jan 2013 14:17:45 -0500 -Subject: staging: speakup: avoid out-of-range access in synth_init() - -From: Nickolai Zeldovich - -commit ae428655b826f2755a8101b27beda42a275ef8ad upstream. - -Check that array index is in-bounds before accessing the synths[] array. - -Signed-off-by: Nickolai Zeldovich -Cc: Samuel Thibault -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/speakup/synth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/staging/speakup/synth.c -+++ b/drivers/staging/speakup/synth.c -@@ -342,7 +342,7 @@ int synth_init(char *synth_name) - - mutex_lock(&spk_mutex); - /* First, check if we already have it loaded. */ -- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) -+ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) - if (strcmp(synths[i]->name, synth_name) == 0) - synth = synths[i]; - -From 6102c48bd421074a33e102f2ebda3724e8d275f9 Mon Sep 17 00:00:00 2001 -From: Samuel Thibault -Date: Mon, 7 Jan 2013 22:03:51 +0100 -Subject: staging: speakup: avoid out-of-range access in synth_add() - -From: Samuel Thibault - -commit 6102c48bd421074a33e102f2ebda3724e8d275f9 upstream. - -Check that array index is in-bounds before accessing the synths[] array. - -Signed-off-by: Samuel Thibault -Cc: Nickolai Zeldovich -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/speakup/synth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/staging/speakup/synth.c -+++ b/drivers/staging/speakup/synth.c -@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth - int i; - int status = 0; - mutex_lock(&spk_mutex); -- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) -+ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) - /* synth_remove() is responsible for rotating the array down */ - if (in_synth == synths[i]) { - mutex_unlock(&spk_mutex); -From 37b51fdddf64e7ba0971d070428655f8d6f36578 Mon Sep 17 00:00:00 2001 -From: Sergey Senozhatsky -Date: Tue, 30 Oct 2012 22:40:23 +0300 -Subject: staging: zram: factor-out zram_decompress_page() function - -From: Sergey Senozhatsky - -commit 37b51fdddf64e7ba0971d070428655f8d6f36578 upstream. - -zram_bvec_read() shared decompress functionality with zram_read_before_write() function. -Factor-out and make commonly used zram_decompress_page() function, which also simplified -error handling in zram_bvec_read(). - -Signed-off-by: Sergey Senozhatsky -Reviewed-by: Nitin Gupta -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/zram/zram_drv.c | 113 ++++++++++++++++------------------------ - 1 file changed, 48 insertions(+), 65 deletions(-) - ---- a/drivers/staging/zram/zram_drv.c -+++ b/drivers/staging/zram/zram_drv.c -@@ -183,62 +183,25 @@ static inline int is_partial_io(struct b - return bvec->bv_len != PAGE_SIZE; - } - --static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, -- u32 index, int offset, struct bio *bio) -+static int zram_decompress_page(struct zram *zram, char *mem, u32 index) - { -- int ret; -- size_t clen; -- struct page *page; -- unsigned char *user_mem, *cmem, *uncmem = NULL; -- -- page = bvec->bv_page; -- -- if (zram_test_flag(zram, index, ZRAM_ZERO)) { -- handle_zero_page(bvec); -- return 0; -- } -+ int ret = LZO_E_OK; -+ size_t clen = PAGE_SIZE; -+ unsigned char *cmem; -+ unsigned long handle = zram->table[index].handle; - -- /* Requested page is not present in compressed area */ -- if (unlikely(!zram->table[index].handle)) { -- pr_debug("Read before write: sector=%lu, size=%u", -- (ulong)(bio->bi_sector), bio->bi_size); -- handle_zero_page(bvec); -+ if (!handle || zram_test_flag(zram, index, ZRAM_ZERO)) { -+ memset(mem, 0, PAGE_SIZE); - return 0; - } - -- if (is_partial_io(bvec)) { -- /* Use a temporary buffer to decompress the page */ -- uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); -- if (!uncmem) { -- pr_info("Error allocating temp memory!\n"); -- return -ENOMEM; -- } -- } -- -- user_mem = kmap_atomic(page); -- if (!is_partial_io(bvec)) -- uncmem = user_mem; -- clen = PAGE_SIZE; -- -- cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, -- ZS_MM_RO); -- -- if (zram->table[index].size == PAGE_SIZE) { -- memcpy(uncmem, cmem, PAGE_SIZE); -- ret = LZO_E_OK; -- } else { -+ cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); -+ if (zram->table[index].size == PAGE_SIZE) -+ memcpy(mem, cmem, PAGE_SIZE); -+ else - ret = lzo1x_decompress_safe(cmem, zram->table[index].size, -- uncmem, &clen); -- } -- -- if (is_partial_io(bvec)) { -- memcpy(user_mem + bvec->bv_offset, uncmem + offset, -- bvec->bv_len); -- kfree(uncmem); -- } -- -- zs_unmap_object(zram->mem_pool, zram->table[index].handle); -- kunmap_atomic(user_mem); -+ mem, &clen); -+ zs_unmap_object(zram->mem_pool, handle); - - /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret != LZO_E_OK)) { -@@ -247,36 +210,56 @@ static int zram_bvec_read(struct zram *z - return ret; - } - -- flush_dcache_page(page); -- - return 0; - } - --static int zram_read_before_write(struct zram *zram, char *mem, u32 index) -+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, -+ u32 index, int offset, struct bio *bio) - { - int ret; -- size_t clen = PAGE_SIZE; -- unsigned char *cmem; -- unsigned long handle = zram->table[index].handle; -+ struct page *page; -+ unsigned char *user_mem, *uncmem = NULL; - -- if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) { -- memset(mem, 0, PAGE_SIZE); -+ page = bvec->bv_page; -+ -+ if (unlikely(!zram->table[index].handle) || -+ zram_test_flag(zram, index, ZRAM_ZERO)) { -+ handle_zero_page(bvec); - return 0; - } - -- cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); -- ret = lzo1x_decompress_safe(cmem, zram->table[index].size, -- mem, &clen); -- zs_unmap_object(zram->mem_pool, handle); -+ user_mem = kmap_atomic(page); -+ if (is_partial_io(bvec)) -+ /* Use a temporary buffer to decompress the page */ -+ uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ else -+ uncmem = user_mem; -+ -+ if (!uncmem) { -+ pr_info("Unable to allocate temp memory\n"); -+ ret = -ENOMEM; -+ goto out_cleanup; -+ } - -+ ret = zram_decompress_page(zram, uncmem, index); - /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret != LZO_E_OK)) { - pr_err("Decompression failed! err=%d, page=%u\n", ret, index); - zram_stat64_inc(zram, &zram->stats.failed_reads); -- return ret; -+ goto out_cleanup; - } - -- return 0; -+ if (is_partial_io(bvec)) -+ memcpy(user_mem + bvec->bv_offset, uncmem + offset, -+ bvec->bv_len); -+ -+ flush_dcache_page(page); -+ ret = 0; -+out_cleanup: -+ kunmap_atomic(user_mem); -+ if (is_partial_io(bvec)) -+ kfree(uncmem); -+ return ret; - } - - static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, -@@ -302,7 +285,7 @@ static int zram_bvec_write(struct zram * - ret = -ENOMEM; - goto out; - } -- ret = zram_read_before_write(zram, uncmem, index); -+ ret = zram_decompress_page(zram, uncmem, index); - if (ret) { - kfree(uncmem); - goto out; -From 397c60668aa5ae7130b5ad4e73870d7b8a787085 Mon Sep 17 00:00:00 2001 -From: Nitin Gupta -Date: Wed, 2 Jan 2013 08:53:41 -0800 -Subject: staging: zram: fix invalid memory references during disk write - -From: Nitin Gupta - -commit 397c60668aa5ae7130b5ad4e73870d7b8a787085 upstream. - -Fixes a bug introduced by commit c8f2f0db1 ("zram: Fix handling -of incompressible pages") which caused invalid memory references -during disk write. Invalid references could occur in two cases: - - Incoming data expands on compression: In this case, reference was -made to kunmap()'ed bio page. - - Partial (non PAGE_SIZE) write with incompressible data: In this -case, reference was made to a kfree()'ed buffer. - -Fixes bug 50081: -https://bugzilla.kernel.org/show_bug.cgi?id=50081 - -Signed-off-by: Nitin Gupta -Reported-by: Mihail Kasadjikov -Reported-by: Tomas M -Reviewed-by: Minchan Kim -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/staging/zram/zram_drv.c | 39 ++++++++++++++++++++++++--------------- - 1 file changed, 24 insertions(+), 15 deletions(-) - ---- a/drivers/staging/zram/zram_drv.c -+++ b/drivers/staging/zram/zram_drv.c -@@ -265,7 +265,7 @@ out_cleanup: - static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, - int offset) - { -- int ret; -+ int ret = 0; - size_t clen; - unsigned long handle; - struct page *page; -@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram * - goto out; - } - ret = zram_decompress_page(zram, uncmem, index); -- if (ret) { -- kfree(uncmem); -+ if (ret) - goto out; -- } - } - - /* -@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram * - - user_mem = kmap_atomic(page); - -- if (is_partial_io(bvec)) -+ if (is_partial_io(bvec)) { - memcpy(uncmem + offset, user_mem + bvec->bv_offset, - bvec->bv_len); -- else -+ kunmap_atomic(user_mem); -+ user_mem = NULL; -+ } else { - uncmem = user_mem; -+ } - - if (page_zero_filled(uncmem)) { -- kunmap_atomic(user_mem); -- if (is_partial_io(bvec)) -- kfree(uncmem); -+ if (!is_partial_io(bvec)) -+ kunmap_atomic(user_mem); - zram_stat_inc(&zram->stats.pages_zero); - zram_set_flag(zram, index, ZRAM_ZERO); - ret = 0; -@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram * - ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, - zram->compress_workmem); - -- kunmap_atomic(user_mem); -- if (is_partial_io(bvec)) -- kfree(uncmem); -+ if (!is_partial_io(bvec)) { -+ kunmap_atomic(user_mem); -+ user_mem = NULL; -+ uncmem = NULL; -+ } - - if (unlikely(ret != LZO_E_OK)) { - pr_err("Compression failed! err=%d\n", ret); -@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram * - - if (unlikely(clen > max_zpage_size)) { - zram_stat_inc(&zram->stats.bad_compress); -- src = uncmem; - clen = PAGE_SIZE; -+ src = NULL; -+ if (is_partial_io(bvec)) -+ src = uncmem; - } - - handle = zs_malloc(zram->mem_pool, clen); -@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram * - } - cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); - -+ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) -+ src = kmap_atomic(page); - memcpy(cmem, src, clen); -+ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) -+ kunmap_atomic(src); - - zs_unmap_object(zram->mem_pool, handle); - -@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram * - if (clen <= PAGE_SIZE / 2) - zram_stat_inc(&zram->stats.good_compress); - -- return 0; -- - out: -+ if (is_partial_io(bvec)) -+ kfree(uncmem); -+ - if (ret) - zram_stat64_inc(zram, &zram->stats.failed_writes); - return ret; -From 51861d4eebc2ddc25c77084343d060fa79f6e291 Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Tue, 8 Jan 2013 18:41:01 -0500 -Subject: radeon/kms: force rn50 chip to always report connected on analog output - -From: Jerome Glisse - -commit 51861d4eebc2ddc25c77084343d060fa79f6e291 upstream. - -Those rn50 chip are often connected to console remoting hw and load -detection often fails with those. Just don't try to load detect and -report connect. - -Signed-off-by: Jerome Glisse -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c -+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c -@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_ - enum drm_connector_status found = connector_status_disconnected; - bool color = true; - -+ /* just don't bother on RN50 those chip are often connected to remoting -+ * console hw and often we get failure to load detect those. So to make -+ * everyone happy report the encoder as always connected. -+ */ -+ if (ASIC_IS_RN50(rdev)) { -+ return connector_status_connected; -+ } -+ - /* save the regs we need */ - vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); - crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); -From 392d4cad7907f6cb4ffc85e135a01abfddc89027 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Thu, 27 Dec 2012 21:37:04 +0100 -Subject: iwlwifi: fix PCIe interrupt handle return value - -From: Johannes Berg - -commit 392d4cad7907f6cb4ffc85e135a01abfddc89027 upstream. - -By accident, commit eb6476441bc2fecf6232a87d0313a85f8e3da7f4 -("iwlwifi: protect use_ict with irq_lock") changed the return -value of the iwl_pcie_isr() function in case it handles an -interrupt -- it now returns IRQ_NONE instead of IRQ_HANDLED. - -Put back the correct return value. - -Reviewed-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/iwlwifi/pcie/rx.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/wireless/iwlwifi/pcie/rx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c -@@ -971,6 +971,7 @@ static irqreturn_t iwl_isr(int irq, void - else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); -+ return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ -From f590dcec944552f9a4a61155810f3abd17d6465d Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Mon, 31 Dec 2012 09:26:10 +0200 -Subject: iwlwifi: fix the reclaimed packet tracking upon flush queue - -From: Emmanuel Grumbach - -commit f590dcec944552f9a4a61155810f3abd17d6465d upstream. - -There's a bug in the currently released firmware version, -the sequence control in the Tx response isn't updated in -all cases. Take it from the packet as a workaround. - -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/iwlwifi/dvm/tx.c | 24 +++++++++++++++++------- - 1 file changed, 17 insertions(+), 7 deletions(-) - ---- a/drivers/net/wireless/iwlwifi/dvm/tx.c -+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c -@@ -1154,13 +1154,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv * - next_reclaimed = ssn; - } - -- if (tid != IWL_TID_NON_QOS) { -- priv->tid_data[sta_id][tid].next_reclaimed = -- next_reclaimed; -- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", -- next_reclaimed); -- } -- - iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); - - iwlagn_check_ratid_empty(priv, sta_id, tid); -@@ -1211,11 +1204,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv * - if (!is_agg) - iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); - -+ /* -+ * W/A for FW bug - the seq_ctl isn't updated when the -+ * queues are flushed. Fetch it from the packet itself -+ */ -+ if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { -+ next_reclaimed = le16_to_cpu(hdr->seq_ctrl); -+ next_reclaimed = -+ SEQ_TO_SN(next_reclaimed + 0x10); -+ } -+ - is_offchannel_skb = - (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); - freed++; - } - -+ if (tid != IWL_TID_NON_QOS) { -+ priv->tid_data[sta_id][tid].next_reclaimed = -+ next_reclaimed; -+ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", -+ next_reclaimed); -+ } -+ - WARN_ON(!is_agg && freed != 1); - - /* -From 34bcf71502413f8903ade93746f2d0f04b937a78 Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Tue, 11 Dec 2012 10:48:23 +0100 -Subject: mac80211: fix ibss scanning - -From: Stanislaw Gruszka - -commit 34bcf71502413f8903ade93746f2d0f04b937a78 upstream. - -Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this -can trigger Microcode errors on iwlwifi and iwlegacy drivers. - -Also rename ieee80211_request_internal_scan() function since it is only -used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). - -This patch should address: -https://bugzilla.redhat.com/show_bug.cgi?id=883414 -https://bugzilla.kernel.org/show_bug.cgi?id=49411 - -Reported-by: Jesse Kahtava -Reported-by: Mikko Rapeli -Signed-off-by: Stanislaw Gruszka -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - net/mac80211/ibss.c | 9 ++++----- - net/mac80211/ieee80211_i.h | 6 +++--- - net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- - 3 files changed, 31 insertions(+), 18 deletions(-) - ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(str - sdata_info(sdata, - "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, -+ NULL); - } - - static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) -@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(stru - IEEE80211_SCAN_INTERVAL)) { - sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, -- ifibss->fixed_channel ? ifibss->channel : NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, -+ ifibss->ssid_len, chan); - } else { - int interval = IEEE80211_SCAN_INTERVAL; - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struc - - /* scan/BSS handling */ - void ieee80211_scan_work(struct work_struct *work); --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan); -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan); - int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req); - void ieee80211_scan_cancel(struct ieee80211_local *local); ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80 - return res; - } - --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan) -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan) - { - struct ieee80211_local *local = sdata->local; - int ret = -EBUSY; -@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(stru - - /* fill internal scan request */ - if (!chan) { -- int i, nchan = 0; -+ int i, max_n; -+ int n_ch = 0; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!local->hw.wiphy->bands[band]) - continue; -- for (i = 0; -- i < local->hw.wiphy->bands[band]->n_channels; -- i++) { -- local->int_scan_req->channels[nchan] = -+ -+ max_n = local->hw.wiphy->bands[band]->n_channels; -+ for (i = 0; i < max_n; i++) { -+ struct ieee80211_channel *tmp_ch = - &local->hw.wiphy->bands[band]->channels[i]; -- nchan++; -+ -+ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED)) -+ continue; -+ -+ local->int_scan_req->channels[n_ch] = tmp_ch; -+ n_ch++; - } - } - -- local->int_scan_req->n_channels = nchan; -+ if (WARN_ON_ONCE(n_ch == 0)) -+ goto unlock; -+ -+ local->int_scan_req->n_channels = n_ch; - } else { -+ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED))) -+ goto unlock; -+ - local->int_scan_req->channels[0] = chan; - local->int_scan_req->n_channels = 1; - } -From 97f97b1f5fe0878b35c8e314f98591771696321b Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Thu, 13 Dec 2012 22:54:58 +0100 -Subject: mac80211: fix station destruction in AP/mesh modes - -From: Johannes Berg - -commit 97f97b1f5fe0878b35c8e314f98591771696321b upstream. - -Unfortunately, commit b22cfcfcae5b, intended to speed up roaming -by avoiding the synchronize_rcu() broke AP/mesh modes as it moved -some code into that work item that will still call into the driver -at a time where it's no longer expected to handle this: after the -AP or mesh has been stopped. - -To fix this problem remove the per-station work struct, maintain a -station cleanup list instead and flush this list when stations are -flushed. To keep this patch smaller for stable, do this when the -stations are flushed (sta_info_flush()). This unfortunately brings -back the original roaming delay; I'll fix that again in a separate -patch. - -Also, Ben reported that the original commit could sometimes (with -many interfaces) cause long delays when an interface is set down, -due to blocking on flush_workqueue(). Since we now maintain the -cleanup list, this particular change of the original patch can be -reverted. - -Reported-by: Ben Greear -Tested-by: Ben Greear -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - net/mac80211/ieee80211_i.h | 4 ++++ - net/mac80211/iface.c | 28 ++++++++++++++++------------ - net/mac80211/sta_info.c | 44 ++++++++++++++++++++++++++++++++++++++++---- - net/mac80211/sta_info.h | 3 ++- - 4 files changed, 62 insertions(+), 17 deletions(-) - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -730,6 +730,10 @@ struct ieee80211_sub_if_data { - u32 mntr_flags; - } u; - -+ spinlock_t cleanup_stations_lock; -+ struct list_head cleanup_stations; -+ struct work_struct cleanup_stations_wk; -+ - #ifdef CONFIG_MAC80211_DEBUGFS - struct { - struct dentry *dir; ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -793,20 +793,11 @@ static void ieee80211_do_stop(struct iee - flush_work(&sdata->work); - /* - * When we get here, the interface is marked down. -- * Call rcu_barrier() to wait both for the RX path -+ * Call synchronize_rcu() to wait for the RX path - * should it be using the interface and enqueuing -- * frames at this very time on another CPU, and -- * for the sta free call_rcu callbacks. -+ * frames at this very time on another CPU. - */ -- rcu_barrier(); -- -- /* -- * free_sta_rcu() enqueues a work for the actual -- * sta cleanup, so we need to flush it while -- * sdata is still valid. -- */ -- flush_workqueue(local->workqueue); -- -+ synchronize_rcu(); - skb_queue_purge(&sdata->skb_queue); - - /* -@@ -1432,6 +1423,15 @@ static void ieee80211_assign_perm_addr(s - mutex_unlock(&local->iflist_mtx); - } - -+static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) -+{ -+ struct ieee80211_sub_if_data *sdata; -+ -+ sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); -+ -+ ieee80211_cleanup_sdata_stas(sdata); -+} -+ - int ieee80211_if_add(struct ieee80211_local *local, const char *name, - struct wireless_dev **new_wdev, enum nl80211_iftype type, - struct vif_params *params) -@@ -1507,6 +1507,10 @@ int ieee80211_if_add(struct ieee80211_lo - - INIT_LIST_HEAD(&sdata->key_list); - -+ spin_lock_init(&sdata->cleanup_stations_lock); -+ INIT_LIST_HEAD(&sdata->cleanup_stations); -+ INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); -+ - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - struct ieee80211_supported_band *sband; - sband = local->hw.wiphy->bands[i]; ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee - return -ENOENT; - } - --static void free_sta_work(struct work_struct *wk) -+static void cleanup_single_sta(struct sta_info *sta) - { -- struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); - int ac, i; - struct tid_ampdu_tx *tid_tx; - struct ieee80211_sub_if_data *sdata = sta->sdata; -@@ -148,11 +147,35 @@ static void free_sta_work(struct work_st - sta_info_free(local, sta); - } - -+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) -+{ -+ struct sta_info *sta; -+ -+ spin_lock_bh(&sdata->cleanup_stations_lock); -+ while (!list_empty(&sdata->cleanup_stations)) { -+ sta = list_first_entry(&sdata->cleanup_stations, -+ struct sta_info, list); -+ list_del(&sta->list); -+ spin_unlock_bh(&sdata->cleanup_stations_lock); -+ -+ cleanup_single_sta(sta); -+ -+ spin_lock_bh(&sdata->cleanup_stations_lock); -+ } -+ -+ spin_unlock_bh(&sdata->cleanup_stations_lock); -+} -+ - static void free_sta_rcu(struct rcu_head *h) - { - struct sta_info *sta = container_of(h, struct sta_info, rcu_head); -+ struct ieee80211_sub_if_data *sdata = sta->sdata; - -- ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); -+ spin_lock(&sdata->cleanup_stations_lock); -+ list_add_tail(&sta->list, &sdata->cleanup_stations); -+ spin_unlock(&sdata->cleanup_stations_lock); -+ -+ ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); - } - - /* protected by RCU */ -@@ -305,7 +328,6 @@ struct sta_info *sta_info_alloc(struct i - - spin_lock_init(&sta->lock); - INIT_WORK(&sta->drv_unblock_wk, sta_unblock); -- INIT_WORK(&sta->free_sta_wk, free_sta_work); - INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); - mutex_init(&sta->ampdu_mlme.mtx); - -@@ -877,6 +899,20 @@ int sta_info_flush(struct ieee80211_loca - } - mutex_unlock(&local->sta_mtx); - -+ rcu_barrier(); -+ -+ if (sdata) { -+ ieee80211_cleanup_sdata_stas(sdata); -+ cancel_work_sync(&sdata->cleanup_stations_wk); -+ } else { -+ mutex_lock(&local->iflist_mtx); -+ list_for_each_entry(sdata, &local->interfaces, list) { -+ ieee80211_cleanup_sdata_stas(sdata); -+ cancel_work_sync(&sdata->cleanup_stations_wk); -+ } -+ mutex_unlock(&local->iflist_mtx); -+ } -+ - return ret; - } - ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -298,7 +298,6 @@ struct sta_info { - spinlock_t lock; - - struct work_struct drv_unblock_wk; -- struct work_struct free_sta_wk; - - u16 listen_interval; - -@@ -558,4 +557,6 @@ void ieee80211_sta_ps_deliver_wakeup(str - void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); - void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); - -+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); -+ - #endif /* STA_INFO_H */ -From a56f992cdabc63f56b4b142885deebebf936ff76 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Thu, 13 Dec 2012 23:08:52 +0100 -Subject: mac80211: use del_timer_sync for final sta cleanup timer deletion - -From: Johannes Berg - -commit a56f992cdabc63f56b4b142885deebebf936ff76 upstream. - -This is a very old bug, but there's nothing that prevents the -timer from running while the module is being removed when we -only do del_timer() instead of del_timer_sync(). - -The timer should normally not be running at this point, but -it's not clearly impossible (or we could just remove this.) - -Tested-by: Ben Greear -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - net/mac80211/sta_info.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -870,7 +870,7 @@ void sta_info_init(struct ieee80211_loca - - void sta_info_stop(struct ieee80211_local *local) - { -- del_timer(&local->sta_cleanup); -+ del_timer_sync(&local->sta_cleanup); - sta_info_flush(local, NULL); - } - -From 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 Mon Sep 17 00:00:00 2001 -From: Bing Zhao -Date: Wed, 2 Jan 2013 16:07:35 -0800 -Subject: mwifiex: check wait_event_interruptible return value - -From: Bing Zhao - -commit 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 upstream. - -wait_event_interruptible function returns -ERESTARTSYS if it's -interrupted by a signal. Driver should check the return value -and handle this case properly. - -In mwifiex_wait_queue_complete() routine, as we are now checking -wait_event_interruptible return value, the condition check is not -required. Also, we have removed mwifiex_cancel_pending_ioctl() -call to avoid a chance of sending second command to FW by other path -as soon as we clear current command node. FW can not handle two -commands simultaneously. - -Signed-off-by: Bing Zhao -Signed-off-by: Amitkumar Karwar -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/mwifiex/sta_ioctl.c | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - ---- a/drivers/net/wireless/mwifiex/sta_ioctl.c -+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c -@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifi - */ - int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) - { -- bool cancel_flag = false; - int status; - struct cmd_ctrl_node *cmd_queued; - -@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct m - atomic_inc(&adapter->cmd_pending); - - /* Wait for completion */ -- wait_event_interruptible(adapter->cmd_wait_q.wait, -- *(cmd_queued->condition)); -- if (!*(cmd_queued->condition)) -- cancel_flag = true; -- -- if (cancel_flag) { -- mwifiex_cancel_pending_ioctl(adapter); -- dev_dbg(adapter->dev, "cmd cancel\n"); -+ status = wait_event_interruptible(adapter->cmd_wait_q.wait, -+ *(cmd_queued->condition)); -+ if (status) { -+ dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); -+ return status; - } - - status = adapter->cmd_wait_q.status; -@@ -480,8 +476,11 @@ int mwifiex_enable_hs(struct mwifiex_ada - return false; - } - -- wait_event_interruptible(adapter->hs_activate_wait_q, -- adapter->hs_activate_wait_q_woken); -+ if (wait_event_interruptible(adapter->hs_activate_wait_q, -+ adapter->hs_activate_wait_q_woken)) { -+ dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); -+ return false; -+ } - - return true; - } -From 5e20a4b53094651d80f856ff55a916b999dbb57a Mon Sep 17 00:00:00 2001 -From: Larry Finger -Date: Thu, 20 Dec 2012 15:55:01 -0600 -Subject: b43: Fix firmware loading when driver is built into the kernel - -From: Larry Finger - -commit 5e20a4b53094651d80f856ff55a916b999dbb57a upstream. - -Recent versions of udev cause synchronous firmware loading from the -probe routine to fail because the request to user space would time -out. The original fix for b43 (commit 6b6fa58) moved the firmware -load from the probe routine to a work queue, but it still used synchronous -firmware loading. This method is OK when b43 is built as a module; -however, it fails when the driver is compiled into the kernel. - -This version changes the code to load the initial firmware file -using request_firmware_nowait(). A completion event is used to -hold the work queue until that file is available. This driver -reads several firmware files - the remainder can be read synchronously. -On some test systems, the async read fails; however, a following synch -read works, thus the async failure falls through to the sync try. - -Reported-and-Tested by: Felix Janda -Signed-off-by: Larry Finger -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/b43/b43.h | 5 +++ - drivers/net/wireless/b43/main.c | 54 ++++++++++++++++++++++++++++++---------- - drivers/net/wireless/b43/main.h | 5 +-- - 3 files changed, 48 insertions(+), 16 deletions(-) - ---- a/drivers/net/wireless/b43/b43.h -+++ b/drivers/net/wireless/b43/b43.h -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - - #include "debugfs.h" -@@ -722,6 +723,10 @@ enum b43_firmware_file_type { - struct b43_request_fw_context { - /* The device we are requesting the fw for. */ - struct b43_wldev *dev; -+ /* a completion event structure needed if this call is asynchronous */ -+ struct completion fw_load_complete; -+ /* a pointer to the firmware object */ -+ const struct firmware *blob; - /* The type of firmware to request. */ - enum b43_firmware_file_type req_type; - /* Error messages for each firmware type. */ ---- a/drivers/net/wireless/b43/main.c -+++ b/drivers/net/wireless/b43/main.c -@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct - b43warn(wl, text); - } - -+static void b43_fw_cb(const struct firmware *firmware, void *context) -+{ -+ struct b43_request_fw_context *ctx = context; -+ -+ ctx->blob = firmware; -+ complete(&ctx->fw_load_complete); -+} -+ - int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, -- struct b43_firmware_file *fw) -+ struct b43_firmware_file *fw, bool async) - { -- const struct firmware *blob; - struct b43_fw_header *hdr; - u32 size; - int err; -@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request - B43_WARN_ON(1); - return -ENOSYS; - } -- err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); -+ if (async) { -+ /* do this part asynchronously */ -+ init_completion(&ctx->fw_load_complete); -+ err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, -+ ctx->dev->dev->dev, GFP_KERNEL, -+ ctx, b43_fw_cb); -+ if (err < 0) { -+ pr_err("Unable to load firmware\n"); -+ return err; -+ } -+ /* stall here until fw ready */ -+ wait_for_completion(&ctx->fw_load_complete); -+ if (ctx->blob) -+ goto fw_ready; -+ /* On some ARM systems, the async request will fail, but the next sync -+ * request works. For this reason, we dall through here -+ */ -+ } -+ err = request_firmware(&ctx->blob, ctx->fwname, -+ ctx->dev->dev->dev); - if (err == -ENOENT) { - snprintf(ctx->errors[ctx->req_type], - sizeof(ctx->errors[ctx->req_type]), -- "Firmware file \"%s\" not found\n", ctx->fwname); -+ "Firmware file \"%s\" not found\n", -+ ctx->fwname); - return err; - } else if (err) { - snprintf(ctx->errors[ctx->req_type], -@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request - ctx->fwname, err); - return err; - } -- if (blob->size < sizeof(struct b43_fw_header)) -+fw_ready: -+ if (ctx->blob->size < sizeof(struct b43_fw_header)) - goto err_format; -- hdr = (struct b43_fw_header *)(blob->data); -+ hdr = (struct b43_fw_header *)(ctx->blob->data); - switch (hdr->type) { - case B43_FW_TYPE_UCODE: - case B43_FW_TYPE_PCM: - size = be32_to_cpu(hdr->size); -- if (size != blob->size - sizeof(struct b43_fw_header)) -+ if (size != ctx->blob->size - sizeof(struct b43_fw_header)) - goto err_format; - /* fallthrough */ - case B43_FW_TYPE_IV: -@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request - goto err_format; - } - -- fw->data = blob; -+ fw->data = ctx->blob; - fw->filename = name; - fw->type = ctx->req_type; - -@@ -2172,7 +2200,7 @@ err_format: - snprintf(ctx->errors[ctx->req_type], - sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" format error.\n", ctx->fwname); -- release_firmware(blob); -+ release_firmware(ctx->blob); - - return -EPROTO; - } -@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43 - goto err_no_ucode; - } - } -- err = b43_do_request_fw(ctx, filename, &fw->ucode); -+ err = b43_do_request_fw(ctx, filename, &fw->ucode, true); - if (err) - goto err_load; - -@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43 - else - goto err_no_pcm; - fw->pcm_request_failed = false; -- err = b43_do_request_fw(ctx, filename, &fw->pcm); -+ err = b43_do_request_fw(ctx, filename, &fw->pcm, false); - if (err == -ENOENT) { - /* We did not find a PCM file? Not fatal, but - * core rev <= 10 must do without hwcrypto then. */ -@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43 - default: - goto err_no_initvals; - } -- err = b43_do_request_fw(ctx, filename, &fw->initvals); -+ err = b43_do_request_fw(ctx, filename, &fw->initvals, false); - if (err) - goto err_load; - -@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43 - default: - goto err_no_initvals; - } -- err = b43_do_request_fw(ctx, filename, &fw->initvals_band); -+ err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); - if (err) - goto err_load; - ---- a/drivers/net/wireless/b43/main.h -+++ b/drivers/net/wireless/b43/main.h -@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wl - - - struct b43_request_fw_context; --int b43_do_request_fw(struct b43_request_fw_context *ctx, -- const char *name, -- struct b43_firmware_file *fw); -+int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, -+ struct b43_firmware_file *fw, bool async); - void b43_do_release_fw(struct b43_firmware_file *fw); - - #endif /* B43_MAIN_H_ */ -From ad86e58661b38b279b7519d4e49c7a19dc1654bb Mon Sep 17 00:00:00 2001 -From: Dzianis Kahanovich -Date: Mon, 3 Dec 2012 16:06:26 +0300 -Subject: USB: option: add Nexpring NP10T terminal id - -From: Dzianis Kahanovich - -commit ad86e58661b38b279b7519d4e49c7a19dc1654bb upstream. - -Hyundai Petatel Inc. Nexpring NP10T terminal (EV-DO rev.A USB modem) ID - -Signed-off-by: Denis Kaganovich -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -442,6 +442,10 @@ static void option_instat_callback(struc - #define CELLIENT_VENDOR_ID 0x2692 - #define CELLIENT_PRODUCT_MEN200 0x9005 - -+/* Hyundai Petatel Inc. products */ -+#define PETATEL_VENDOR_ID 0x1ff4 -+#define PETATEL_PRODUCT_NP10T 0x600e -+ - /* some devices interfaces need special handling due to a number of reasons */ - enum option_blacklist_reason { - OPTION_BLACKLIST_NONE = 0, -@@ -1296,6 +1300,7 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, - { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, -+ { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, - { } /* Terminating entry */ - }; - MODULE_DEVICE_TABLE(usb, option_ids); -From fab38246f318edcd0dcb8fd3852a47cf8938878a Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Wed, 19 Dec 2012 15:15:17 +0100 -Subject: USB: option: blacklist network interface on ZTE MF880 - -From: Bjørn Mork - -commit fab38246f318edcd0dcb8fd3852a47cf8938878a upstream. - -The driver description files gives these names to the vendor specific -functions on this modem: - - diag: VID_19D2&PID_0284&MI_00 - nmea: VID_19D2&PID_0284&MI_01 - at: VID_19D2&PID_0284&MI_02 - mdm: VID_19D2&PID_0284&MI_03 - net: VID_19D2&PID_0284&MI_04 - -Signed-off-by: Bjørn Mork -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -928,7 +928,8 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ - .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ -+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -From 94a85b633829b946eef53fc1825d526312fb856f Mon Sep 17 00:00:00 2001 -From: "Quentin.Li" -Date: Wed, 26 Dec 2012 16:58:22 +0800 -Subject: USB: option: Add new MEDIATEK PID support - -From: "Quentin.Li" - -commit 94a85b633829b946eef53fc1825d526312fb856f upstream. - -In option.c, add some new MEDIATEK PIDs support for MEDIATEK new products. This -is a MEDIATEK inc. release patch. - -Signed-off-by: Quentin.Li -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -430,9 +430,12 @@ static void option_instat_callback(struc - #define MEDIATEK_VENDOR_ID 0x0e8d - #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 - #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 -+#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 - #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 - #define MEDIATEK_PRODUCT_7208_1COM 0x7101 - #define MEDIATEK_PRODUCT_7208_2COM 0x7102 -+#define MEDIATEK_PRODUCT_7103_2COM 0x7103 -+#define MEDIATEK_PRODUCT_7106_2COM 0x7106 - #define MEDIATEK_PRODUCT_FP_1COM 0x0003 - #define MEDIATEK_PRODUCT_FP_2COM 0x0023 - #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 -@@ -1300,6 +1303,10 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, - { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, - { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, - { } /* Terminating entry */ -From 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Fri, 28 Dec 2012 17:29:52 +0100 -Subject: USB: option: add Telekom Speedstick LTE II - -From: Bjørn Mork - -commit 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf upstream. - -also known as Alcatel One Touch L100V LTE - -The driver description files gives these names to the vendor specific -functions on this modem: - - Application1: VID_1BBB&PID_011E&MI_00 - Application2: VID_1BBB&PID_011E&MI_01 - Modem: VID_1BBB&PID_011E&MI_03 - Ethernet: VID_1BBB&PID_011E&MI_04 - -Reported-by: Thomas Schäfer -Signed-off-by: Bjørn Mork -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -289,6 +289,7 @@ static void option_instat_callback(struc - #define ALCATEL_VENDOR_ID 0x1bbb - #define ALCATEL_PRODUCT_X060S_X200 0x0000 - #define ALCATEL_PRODUCT_X220_X500D 0x0017 -+#define ALCATEL_PRODUCT_L100V 0x011e - - #define PIRELLI_VENDOR_ID 0x1266 - #define PIRELLI_PRODUCT_C100_1 0x1002 -@@ -1199,6 +1200,8 @@ static const struct usb_device_id option - .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist - }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, -+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), -+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, - { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, - { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), -From 8cf65dc386f3634a43312f436cc7a935476a40c4 Mon Sep 17 00:00:00 2001 -From: Tomasz Mloduchowski -Date: Sun, 13 Jan 2013 23:32:53 +0100 -Subject: usb: ftdi_sio: Crucible Technologies COMET Caller ID - pid added - -From: Tomasz Mloduchowski - -commit 8cf65dc386f3634a43312f436cc7a935476a40c4 upstream. - -Simple fix to add support for Crucible Technologies COMET Caller ID -USB decoder - a device containing FTDI USB/Serial converter chip, -handling 1200bps CallerID messages decoded from the phone line - -adding correct USB PID is sufficient. - -Tested to apply cleanly and work flawlessly against 3.6.9, 3.7.0-rc8 -and 3.8.0-rc3 on both amd64 and x86 arches. - -Signed-off-by: Tomasz Mloduchowski -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/ftdi_sio.c | 2 ++ - drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -876,6 +876,8 @@ static struct usb_device_id id_table_com - { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, -+ /* Crucible Devices */ -+ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, - { }, /* Optional parameter entry */ - { } /* Terminating entry */ - }; ---- a/drivers/usb/serial/ftdi_sio_ids.h -+++ b/drivers/usb/serial/ftdi_sio_ids.h -@@ -1259,3 +1259,9 @@ - * ATI command output: Cinterion MC55i - */ - #define FTDI_CINTERION_MC55I_PID 0xA951 -+ -+/* -+ * Product: Comet Caller ID decoder -+ * Manufacturer: Crucible Technologies -+ */ -+#define FTDI_CT_COMET_PID 0x8e08 -From 036915a7a402753c05b8d0529f5fd08805ab46d0 Mon Sep 17 00:00:00 2001 -From: Denis N Ladin -Date: Wed, 26 Dec 2012 18:29:44 +0500 -Subject: USB: cdc-acm: Add support for "PSC Scanning, Magellan 800i" - -From: Denis N Ladin - -commit 036915a7a402753c05b8d0529f5fd08805ab46d0 upstream. - -Adding support "PSC Scanning, Magellan 800i" in cdc-acm - -Very simple, but very necessary. -Suitable for all versions of the kernel > 2.6 - -Signed-off-by: Denis N Ladin -Acked-by: Oliver Neukum -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/class/cdc-acm.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_id - { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ - .driver_info = NO_UNION_NORMAL, - }, -+ { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ -+ .driver_info = NO_UNION_NORMAL, -+ }, - { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ - .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ - }, -From 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 Mon Sep 17 00:00:00 2001 -From: Sebastian Andrzej Siewior -Date: Tue, 20 Nov 2012 13:23:15 +0100 -Subject: usb: gadget: dummy: fix enumeration with g_multi - -From: Sebastian Andrzej Siewior - -commit 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 upstream. - -If we do have endpoints named like "ep-a" then bEndpointAddress is -counted internally by the gadget framework. - -If we do have endpoints named like "ep-1" then bEndpointAddress is -assigned from the digit after "ep-". - -If we do have both, then it is likely that after we used up the -"generic" endpoints we will use the digits and thus assign one -bEndpointAddress to multiple endpoints. - -This theory can be proofed by using the completely enabled g_multi. -Without this patch, the mass storage won't enumerate and times out -because it shares endpoints with RNDIS. - -This patch also adds fills up the endpoints list so we have in total -endpoints 1 to 15 in + out available while some of them are restricted -to certain types like BULK or ISO. Without this change the nokia gadget -won't load because the system does not provide enough (BULK) endpoints -but it did before ep-a - ep-f were removed. - -Signed-off-by: Sebastian Andrzej Siewior -Acked-by: Alan Stern -Signed-off-by: Felipe Balbi -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/gadget/dummy_hcd.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/usb/gadget/dummy_hcd.c -+++ b/drivers/usb/gadget/dummy_hcd.c -@@ -126,10 +126,7 @@ static const char ep0name[] = "ep0"; - static const char *const ep_name[] = { - ep0name, /* everyone has ep0 */ - -- /* act like a net2280: high speed, six configurable endpoints */ -- "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", -- -- /* or like pxa250: fifteen fixed function endpoints */ -+ /* act like a pxa250: fifteen fixed function endpoints */ - "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", - "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", - "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", -@@ -137,6 +134,10 @@ static const char *const ep_name[] = { - - /* or like sa1100: two fixed function endpoints */ - "ep1out-bulk", "ep2in-bulk", -+ -+ /* and now some generic EPs so we have enough in multi config */ -+ "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", -+ "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", - }; - #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) - -From 2ac788f705e5118dd45204e7a5bc8d5bb6873835 Mon Sep 17 00:00:00 2001 -From: Sergei Shtylyov -Date: Wed, 14 Nov 2012 18:49:50 +0300 -Subject: usb: musb: core: print new line in the driver banner again - -From: Sergei Shtylyov - -commit 2ac788f705e5118dd45204e7a5bc8d5bb6873835 upstream. - -Commit 5c8a86e10a7c164f44537fabdc169fd8b4e7a440 (usb: musb: drop unneeded -musb_debug trickery) erroneously removed '\n' from the driver's banner. -Concatenate all the banner substrings while adding it back... - -Signed-off-by: Sergei Shtylyov -Signed-off-by: Felipe Balbi -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/musb/musb_core.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - ---- a/drivers/usb/musb/musb_core.c -+++ b/drivers/usb/musb/musb_core.c -@@ -2351,10 +2351,7 @@ static int __init musb_init(void) - if (usb_disabled()) - return 0; - -- pr_info("%s: version " MUSB_VERSION ", " -- "?dma?" -- ", " -- "otg (peripheral+host)", -+ pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", - musb_driver_name); - return platform_driver_register(&musb_driver); - } -From f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 Mon Sep 17 00:00:00 2001 -From: Marcin Slusarz -Date: Tue, 25 Dec 2012 18:13:22 +0100 -Subject: drm/nv17-50: restore fence buffer on resume - -From: Marcin Slusarz - -commit f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 upstream. - -Since commit 5e120f6e4b3f35b741c5445dfc755f50128c3c44 "drm/nouveau/fence: -convert to exec engine, and improve channel sync" nouveau fence sync -implementation for nv17-50 and nvc0+ started to rely on state of fence buffer -left by previous sync operation. But as pinned bo's (where fence state is -stored) are not saved+restored across suspend/resume, we need to do it -manually. - -nvc0+ was fixed by commit d6ba6d215a538a58f0f0026f0961b0b9125e8042 -"drm/nvc0/fence: restore pre-suspend fence buffer context on resume". - -Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=50121 - -Signed-off-by: Marcin Slusarz -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/nouveau_fence.h | 1 + - drivers/gpu/drm/nouveau/nv10_fence.c | 8 ++++++++ - drivers/gpu/drm/nouveau/nv50_fence.c | 1 + - 3 files changed, 10 insertions(+) - ---- a/drivers/gpu/drm/nouveau/nouveau_fence.h -+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h -@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_chan - void nv10_fence_context_del(struct nouveau_channel *); - void nv10_fence_destroy(struct nouveau_drm *); - int nv10_fence_create(struct nouveau_drm *); -+void nv17_fence_resume(struct nouveau_drm *drm); - - int nv50_fence_create(struct nouveau_drm *); - int nv84_fence_create(struct nouveau_drm *); ---- a/drivers/gpu/drm/nouveau/nv10_fence.c -+++ b/drivers/gpu/drm/nouveau/nv10_fence.c -@@ -160,6 +160,13 @@ nv10_fence_destroy(struct nouveau_drm *d - kfree(priv); - } - -+void nv17_fence_resume(struct nouveau_drm *drm) -+{ -+ struct nv10_fence_priv *priv = drm->fence; -+ -+ nouveau_bo_wr32(priv->bo, 0, priv->sequence); -+} -+ - int - nv10_fence_create(struct nouveau_drm *drm) - { -@@ -192,6 +199,7 @@ nv10_fence_create(struct nouveau_drm *dr - if (ret == 0) { - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); - priv->base.sync = nv17_fence_sync; -+ priv->base.resume = nv17_fence_resume; - } - } - ---- a/drivers/gpu/drm/nouveau/nv50_fence.c -+++ b/drivers/gpu/drm/nouveau/nv50_fence.c -@@ -119,6 +119,7 @@ nv50_fence_create(struct nouveau_drm *dr - if (ret == 0) { - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); - priv->base.sync = nv17_fence_sync; -+ priv->base.resume = nv17_fence_resume; - } - - if (ret) -From 92441b2263866c27ef48137be5aa6c8c692652fc Mon Sep 17 00:00:00 2001 -From: Marcin Slusarz -Date: Tue, 18 Dec 2012 20:30:47 +0100 -Subject: drm/nouveau: fix blank LVDS screen regression on pre-nv50 cards - -From: Marcin Slusarz - -commit 92441b2263866c27ef48137be5aa6c8c692652fc upstream. - -Commit 2a44e499 ("drm/nouveau/disp: introduce proper init/fini, separate -from create/destroy") started to call display init routines on pre-nv50 -hardware on module load. But LVDS init code sets driver state in a way -which prevents modesetting code from operating properly. - -nv04_display_init calls nv04_dfp_restore, which sets encoder->last_dpms to -NV_DPMS_CLEARED. - -drm_crtc_helper_set_mode - nv04_dfp_prepare - nv04_lvds_dpms(DRM_MODE_DPMS_OFF) - -nv04_lvds_dpms checks last_dpms mode (which is NV_DPMS_CLEARED) and wrongly -assumes it's a "powersaving mode", the new one (DRM_MODE_DPMS_OFF) is too, -so it skips calling some crucial lvds scripts. - -Reported-by: Chris Paulson-Ellis -Signed-off-by: Marcin Slusarz -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/nv04_dfp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/nouveau/nv04_dfp.c -+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c -@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(st - - static inline bool is_powersaving_dpms(int mode) - { -- return (mode != DRM_MODE_DPMS_ON); -+ return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; - } - - static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) -From 4c4101d29fb6c63f78791d02c437702b11e1d4f0 Mon Sep 17 00:00:00 2001 -From: Marcin Slusarz -Date: Sun, 2 Dec 2012 12:56:22 +0100 -Subject: drm/nouveau: add locking around instobj list operations - -From: Marcin Slusarz - -commit 4c4101d29fb6c63f78791d02c437702b11e1d4f0 upstream. - -Fixes memory corruptions, oopses, etc. when multiple gpuobjs are -simultaneously created or destroyed. - -Signed-off-by: Marcin Slusarz -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | 35 ++++++++++++++++----- - 1 file changed, 27 insertions(+), 8 deletions(-) - ---- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c -+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c -@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_o - if (ret) - return ret; - -+ mutex_lock(&imem->base.mutex); - list_add(&iobj->head, &imem->list); -+ mutex_unlock(&imem->base.mutex); - return 0; - } - - void - nouveau_instobj_destroy(struct nouveau_instobj *iobj) - { -- if (iobj->head.prev) -- list_del(&iobj->head); -+ struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); -+ -+ mutex_lock(&subdev->mutex); -+ list_del(&iobj->head); -+ mutex_unlock(&subdev->mutex); -+ - return nouveau_object_destroy(&iobj->base); - } - -@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_inst - if (ret) - return ret; - -+ mutex_lock(&imem->base.mutex); -+ - list_for_each_entry(iobj, &imem->list, head) { - if (iobj->suspend) { - for (i = 0; i < iobj->size; i += 4) -@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_inst - } - } - -+ mutex_unlock(&imem->base.mutex); -+ - return 0; - } - -@@ -104,17 +114,26 @@ int - nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) - { - struct nouveau_instobj *iobj; -- int i; -+ int i, ret = 0; - - if (suspend) { -+ mutex_lock(&imem->base.mutex); -+ - list_for_each_entry(iobj, &imem->list, head) { - iobj->suspend = vmalloc(iobj->size); -- if (iobj->suspend) { -- for (i = 0; i < iobj->size; i += 4) -- iobj->suspend[i / 4] = nv_ro32(iobj, i); -- } else -- return -ENOMEM; -+ if (!iobj->suspend) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ for (i = 0; i < iobj->size; i += 4) -+ iobj->suspend[i / 4] = nv_ro32(iobj, i); - } -+ -+ mutex_unlock(&imem->base.mutex); -+ -+ if (ret) -+ return ret; - } - - return nouveau_subdev_fini(&imem->base, suspend); -From d19528a9e4f220519c2cb3f56ef0c84ead3ee440 Mon Sep 17 00:00:00 2001 -From: Aleksi Torhamo -Date: Fri, 4 Jan 2013 18:39:13 +0200 -Subject: drm/nouveau/clock: fix support for more than 2 monitors on nve0 - -From: Aleksi Torhamo - -commit d19528a9e4f220519c2cb3f56ef0c84ead3ee440 upstream. - -Fixes regression introduced in commit 70790f4f -"drm/nouveau/clock: pull in the implementation from all over the place" - -When code was moved from nv50_crtc_set_clock to nvc0_clock_pll_set, -the PLLs it is used for got limited to only the first two VPLLs. - -nv50_crtc_set_clock was only called to change VPLLs, so it didn't -limit what it was used for in any way. Since nvc0_clock_pll_set is -used for all PLLs, it has to specify which PLLs the code is used for, -and only listed the first two VPLLs. - -Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=58735 - -This patch is a -stable candidate for 3.7. - -Signed-off-by: Aleksi Torhamo -Tested-by: Aleksi Torhamo -Tested-by: Sean Santos -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | 2 ++ - drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h -+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h -@@ -38,6 +38,8 @@ enum nvbios_pll_type { - PLL_UNK42 = 0x42, - PLL_VPLL0 = 0x80, - PLL_VPLL1 = 0x81, -+ PLL_VPLL2 = 0x82, -+ PLL_VPLL3 = 0x83, - PLL_MAX = 0xff - }; - ---- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c -+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c -@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock - switch (info.type) { - case PLL_VPLL0: - case PLL_VPLL1: -+ case PLL_VPLL2: -+ case PLL_VPLL3: - nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); - nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); - nv_wr32(priv, info.reg + 0x10, fN << 16); -From 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 Mon Sep 17 00:00:00 2001 -From: Aleksi Torhamo -Date: Wed, 9 Jan 2013 20:08:48 +0200 -Subject: drm/nvc0/fb: fix crash when different mutex is used to protect same list - -From: Aleksi Torhamo - -commit 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 upstream. - -Fixes regression introduced in commit 861d2107 -"drm/nouveau/fb: merge fb/vram and port to subdev interfaces" - -nv50_fb_vram_{new,del} functions were changed to use -nouveau_subdev->mutex instead of the old nouveau_mm->mutex. -nvc0_fb_vram_new still uses the nouveau_mm->mutex, but nvc0 doesn't -have its own fb_vram_del function, using nv50_fb_vram_del instead. -Because of this, on nvc0 a different mutex ends up being used to protect -additions and deletions to the same list. - -This patch is a -stable candidate for 3.7. - -Signed-off-by: Aleksi Torhamo -Reported-by: Roy Spliet -Tested-by: Roy Spliet -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c -+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c -@@ -86,14 +86,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, - mem->memtype = type; - mem->size = size; - -- mutex_lock(&mm->mutex); -+ mutex_lock(&pfb->base.mutex); - do { - if (back) - ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); - if (ret) { -- mutex_unlock(&mm->mutex); -+ mutex_unlock(&pfb->base.mutex); - pfb->ram.put(pfb, &mem); - return ret; - } -@@ -101,7 +101,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); -- mutex_unlock(&mm->mutex); -+ mutex_unlock(&pfb->base.mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; -From 1c7439c61fa6516419c32a9824976334ea969d47 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Wed, 14 Nov 2012 15:58:52 -0800 -Subject: USB: Handle auto-transition from hot to warm reset. - -From: Sarah Sharp - -commit 1c7439c61fa6516419c32a9824976334ea969d47 upstream. - -USB 3.0 hubs and roothubs will automatically transition a failed hot -reset to a warm (BH) reset. In that case, the warm reset change bit -will be set, and the link state change bit may also be set. Change -hub_port_finish_reset to unconditionally clear those change bits for USB -3.0 hubs. If these bits are not cleared, we may lose port change events -from the roothub. - -This commit should be backported to kernels as old as 3.2, that contain -the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine -warm reset logic". - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2541,16 +2541,16 @@ static void hub_port_finish_reset(struct - clear_port_feature(hub->hdev, - port1, USB_PORT_FEAT_C_RESET); - /* FIXME need disconnect() for NOTATTACHED device */ -- if (warm) { -+ if (hub_is_superspeed(hub->hdev)) { - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_BH_PORT_RESET); - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_PORT_LINK_STATE); -- } else { -+ } -+ if (!warm) - usb_set_device_state(udev, *status - ? USB_STATE_NOTATTACHED - : USB_STATE_DEFAULT); -- } - break; - } - } -From bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 Mon Sep 17 00:00:00 2001 -From: Andreas Fleig -Date: Wed, 5 Dec 2012 16:17:49 +0100 -Subject: USB: Add device quirk for Microsoft VX700 webcam - -From: Andreas Fleig - -commit bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 upstream. - -Add device quirk for Microsoft Lifecam VX700 v2.0 webcams. -Fixes squeaking noise of the microphone. - -Signed-off-by: Andreas Fleig -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/quirks.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -43,6 +43,9 @@ static const struct usb_device_id usb_qu - /* Creative SB Audigy 2 NX */ - { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, - -+ /* Microsoft LifeCam-VX700 v2.0 */ -+ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* Logitech Quickcam Fusion */ - { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, - -From 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Wed, 14 Nov 2012 16:10:49 -0800 -Subject: USB: Ignore xHCI Reset Device status. - -From: Sarah Sharp - -commit 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a upstream. - -When the USB core finishes reseting a USB device, the xHCI driver sends -a Reset Device command to the host. The xHC then updates its internal -representation of the USB device to the 'Default' device state. If the -device was already in the Default state, the xHC will complete the -command with an error status. - -If a device needs to be reset several times during enumeration, the -second reset will always fail because of the xHCI Reset Device command. -This can cause issues during enumeration. - -For example, usb_reset_and_verify_device calls into hub_port_init in a -loop. Say that on the first call into hub_port_init, the device is -successfully reset, but doesn't respond to several set address control -transfers. Then the port will be disabled, but the udev will remain in -tact. usb_reset_and_verify_device will call into hub_port_init again. - -On the second call into hub_port_init, the device will be reset, and the -xHCI driver will issue a Reset Device command. This command will fail -(because the device is already in the Default state), and -usb_reset_and_verify_device will fail. The port will be disabled, and -the device won't be able to enumerate. - -Fix this by ignoring the return value of the HCD reset_device callback. - -This commit should be backported to kernels as old as 3.2, that contain -the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine -warm reset logic". - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2526,14 +2526,11 @@ static void hub_port_finish_reset(struct - msleep(10 + 40); - update_devnum(udev, 0); - hcd = bus_to_hcd(udev->bus); -- if (hcd->driver->reset_device) { -- *status = hcd->driver->reset_device(hcd, udev); -- if (*status < 0) { -- dev_err(&udev->dev, "Cannot reset " -- "HCD device state\n"); -- break; -- } -- } -+ /* The xHC may think the device is already reset, -+ * so ignore the status. -+ */ -+ if (hcd->driver->reset_device) -+ hcd->driver->reset_device(hcd, udev); - } - /* FALL THROUGH */ - case -ENOTCONN: -From 41e7e056cdc662f704fa9262e5c6e213b4ab45dd Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Wed, 14 Nov 2012 16:42:32 -0800 -Subject: USB: Allow USB 3.0 ports to be disabled. - -From: Sarah Sharp - -commit 41e7e056cdc662f704fa9262e5c6e213b4ab45dd upstream. - -If hot and warm reset fails, or a port remains in the Compliance Mode, -the USB core needs to be able to disable a USB 3.0 port. Unlike USB 2.0 -ports, once the port is placed into the Disabled link state, it will not -report any new device connects. To get device connect notifications, we -need to put the link into the Disabled state, and then the RxDetect -state. - -The xHCI driver needs to atomically clear all change bits on USB 3.0 -port disable, so that we get Port Status Change Events for future port -changes. We could technically do this in the USB core instead of in the -xHCI roothub code, since the port state machine can't advance out of the -disabled state until we set the link state to RxDetect. However, -external USB 3.0 hubs don't need this code. They are level-triggered, -not edge-triggered like xHCI, so they will continue to send interrupt -events when any change bit is set. Therefore it doesn't make sense to -put this code in the USB core. - -This patch is part of a series to fix several reports of infinite loops -on device enumeration failure. This includes John, when he boots with -a USB 3.0 device (Roseweil eusb3 enclosure) attached to his NEC 0.96 -host controller. The fix requires warm reset support, so it does not -make sense to backport this patch to stable kernels without warm reset -support. - -This patch should be backported to kernels as old as 3.2, contain the -commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm -reset logic" - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Reported-by: John Covici -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 63 ++++++++++++++++++++++++++++++++++++++++++-- - drivers/usb/host/xhci-hub.c | 31 ++++++++++++++++++++- - 2 files changed, 90 insertions(+), 4 deletions(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -876,6 +876,60 @@ static int hub_hub_status(struct usb_hub - return ret; - } - -+static int hub_set_port_link_state(struct usb_hub *hub, int port1, -+ unsigned int link_status) -+{ -+ return set_port_feature(hub->hdev, -+ port1 | (link_status << 3), -+ USB_PORT_FEAT_LINK_STATE); -+} -+ -+/* -+ * If USB 3.0 ports are placed into the Disabled state, they will no longer -+ * detect any device connects or disconnects. This is generally not what the -+ * USB core wants, since it expects a disabled port to produce a port status -+ * change event when a new device connects. -+ * -+ * Instead, set the link state to Disabled, wait for the link to settle into -+ * that state, clear any change bits, and then put the port into the RxDetect -+ * state. -+ */ -+static int hub_usb3_port_disable(struct usb_hub *hub, int port1) -+{ -+ int ret; -+ int total_time; -+ u16 portchange, portstatus; -+ -+ if (!hub_is_superspeed(hub->hdev)) -+ return -EINVAL; -+ -+ ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); -+ if (ret) { -+ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", -+ port1, ret); -+ return ret; -+ } -+ -+ /* Wait for the link to enter the disabled state. */ -+ for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { -+ ret = hub_port_status(hub, port1, &portstatus, &portchange); -+ if (ret < 0) -+ return ret; -+ -+ if ((portstatus & USB_PORT_STAT_LINK_STATE) == -+ USB_SS_PORT_LS_SS_DISABLED) -+ break; -+ if (total_time >= HUB_DEBOUNCE_TIMEOUT) -+ break; -+ msleep(HUB_DEBOUNCE_STEP); -+ } -+ if (total_time >= HUB_DEBOUNCE_TIMEOUT) -+ dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", -+ port1, total_time); -+ -+ return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); -+} -+ - static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) - { - struct usb_device *hdev = hub->hdev; -@@ -884,8 +938,13 @@ static int hub_port_disable(struct usb_h - if (hub->ports[port1 - 1]->child && set_state) - usb_set_device_state(hub->ports[port1 - 1]->child, - USB_STATE_NOTATTACHED); -- if (!hub->error && !hub_is_superspeed(hub->hdev)) -- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); -+ if (!hub->error) { -+ if (hub_is_superspeed(hub->hdev)) -+ ret = hub_usb3_port_disable(hub, port1); -+ else -+ ret = clear_port_feature(hdev, port1, -+ USB_PORT_FEAT_ENABLE); -+ } - if (ret) - dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", - port1, ret); ---- a/drivers/usb/host/xhci-hub.c -+++ b/drivers/usb/host/xhci-hub.c -@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd - break; - case USB_PORT_FEAT_LINK_STATE: - temp = xhci_readl(xhci, port_array[wIndex]); -+ -+ /* Disable port */ -+ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { -+ xhci_dbg(xhci, "Disable port %d\n", wIndex); -+ temp = xhci_port_state_to_neutral(temp); -+ /* -+ * Clear all change bits, so that we get a new -+ * connection event. -+ */ -+ temp |= PORT_CSC | PORT_PEC | PORT_WRC | -+ PORT_OCC | PORT_RC | PORT_PLC | -+ PORT_CEC; -+ xhci_writel(xhci, temp | PORT_PE, -+ port_array[wIndex]); -+ temp = xhci_readl(xhci, port_array[wIndex]); -+ break; -+ } -+ -+ /* Put link in RxDetect (enable port) */ -+ if (link_state == USB_SS_PORT_LS_RX_DETECT) { -+ xhci_dbg(xhci, "Enable port %d\n", wIndex); -+ xhci_set_link_state(xhci, port_array, wIndex, -+ link_state); -+ temp = xhci_readl(xhci, port_array[wIndex]); -+ break; -+ } -+ - /* Software should not attempt to set -- * port link state above '5' (Rx.Detect) and the port -+ * port link state above '3' (U3) and the port - * must be enabled. - */ - if ((temp & PORT_PE) == 0 || -- (link_state > USB_SS_PORT_LS_RX_DETECT)) { -+ (link_state > USB_SS_PORT_LS_U3)) { - xhci_warn(xhci, "Cannot set link state.\n"); - goto error; - } -From 77c7f072c87fa951e9a74805febf26466f31170c Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Wed, 14 Nov 2012 17:16:52 -0800 -Subject: USB: Increase reset timeout. - -From: Sarah Sharp - -commit 77c7f072c87fa951e9a74805febf26466f31170c upstream. - -John's NEC 0.96 xHCI host controller needs a longer timeout for a warm -reset to complete. The logs show it takes 650ms to complete the warm -reset, so extend the hub reset timeout to 800ms to be on the safe side. - -This commit should be backported to kernels as old as 3.2, that contain -the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine -warm reset logic". - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Reported-by: John Covici -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2460,7 +2460,7 @@ static unsigned hub_is_wusb(struct usb_h - #define HUB_SHORT_RESET_TIME 10 - #define HUB_BH_RESET_TIME 50 - #define HUB_LONG_RESET_TIME 200 --#define HUB_RESET_TIMEOUT 500 -+#define HUB_RESET_TIMEOUT 800 - - static int hub_port_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, unsigned int delay, bool warm); -From 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Thu, 15 Nov 2012 14:58:04 -0800 -Subject: USB: Ignore port state until reset completes. - -From: Sarah Sharp - -commit 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 upstream. - -The port reset code bails out early if the current connect status is -cleared (device disconnected). If we're issuing a hot reset, it may -also look at the link state before the reset is finished. - -Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the -Error state or Resetting state, the port connection bit retains the -value from the previous state. Therefore we can't trust it until the -reset finishes. Also, the xHCI spec section 4.19.1.2.5 says software -shall ignore the link state while the port is resetting, as it can be in -an unknown state. - -The port state during reset is also unknown for USB 2.0 hubs. The hub -sends a reset signal by driving the bus into an SE0 state. This -overwhelms the "connect" signal from the device, so the port can't tell -whether anything is connected or not. - -Fix the port reset code to ignore the port link state and current -connect bit until the reset finishes, and USB_PORT_STAT_RESET is -cleared. - -Remove the check for USB_PORT_STAT_C_BH_RESET in the warm reset case, -because it's redundant. When the warm reset finishes, the port reset -bit will be cleared at the same time USB_PORT_STAT_C_BH_RESET is set. -Remove the now-redundant check for a cleared USB_PORT_STAT_RESET bit -in the code to deal with the finished reset. - -This patch should be backported to all stable kernels. - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2495,6 +2495,10 @@ static int hub_port_wait_reset(struct us - if (ret < 0) - return ret; - -+ /* The port state is unknown until the reset completes. */ -+ if ((portstatus & USB_PORT_STAT_RESET)) -+ goto delay; -+ - /* - * Some buggy devices require a warm reset to be issued even - * when the port appears not to be connected. -@@ -2540,11 +2544,7 @@ static int hub_port_wait_reset(struct us - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; - -- /* if we`ve finished resetting, then break out of -- * the loop -- */ -- if (!(portstatus & USB_PORT_STAT_RESET) && -- (portstatus & USB_PORT_STAT_ENABLE)) { -+ if ((portstatus & USB_PORT_STAT_ENABLE)) { - if (hub_is_wusb(hub)) - udev->speed = USB_SPEED_WIRELESS; - else if (hub_is_superspeed(hub->hdev)) -@@ -2558,10 +2558,10 @@ static int hub_port_wait_reset(struct us - return 0; - } - } else { -- if (portchange & USB_PORT_STAT_C_BH_RESET) -- return 0; -+ return 0; - } - -+delay: - /* switch to the long delay after two short delay failures */ - if (delay_time >= 2 * HUB_SHORT_RESET_TIME) - delay = HUB_LONG_RESET_TIME; -From 65bdac5effd15d6af619b3b7218627ef4d84ed6a Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Wed, 14 Nov 2012 17:58:04 -0800 -Subject: USB: Handle warm reset failure on empty port. - -From: Sarah Sharp - -commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a upstream. - -An empty port can transition to either Inactive or Compliance Mode if a -newly connected USB 3.0 device fails to link train. In that case, we -issue a warm reset. Some devices, such as John's Roseweil eusb3 -enclosure, slip back into Compliance Mode after the warm reset. - -The current warm reset code does not check for device connect status on -warm reset completion, and it incorrectly reports the warm reset -succeeded. This causes the USB core to attempt to send a Set Address -control transfer to a port in Compliance Mode, which will always fail. - -Make hub_port_wait_reset check the current connect status and link state -after the warm reset completes. Return a failure status if the device -is disconnected or the link state is Compliance Mode or SS.Inactive. - -Make hub_events disable the port if warm reset fails. This will disable -the port, and then bring it back into the RxDetect state. Make the USB -core ignore the connect change until the device reconnects. - -Note that this patch does NOT handle connected devices slipping into the -Inactive state very well. This is a concern, because devices can go -into the Inactive state on U1/U2 exit failure. However, the fix for -that case is too large for stable, so it will be submitted in a separate -patch. - -This patch should be backported to kernels as old as 3.2, contain the -commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm -reset logic" - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Reported-by: John Covici -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2558,6 +2558,11 @@ static int hub_port_wait_reset(struct us - return 0; - } - } else { -+ if (!(portstatus & USB_PORT_STAT_CONNECTION) || -+ hub_port_warm_reset_required(hub, -+ portstatus)) -+ return -ENOTCONN; -+ - return 0; - } - -@@ -4628,9 +4633,14 @@ static void hub_events(void) - * SS.Inactive state. - */ - if (hub_port_warm_reset_required(hub, portstatus)) { -+ int status; -+ - dev_dbg(hub_dev, "warm reset port %d\n", i); -- hub_port_reset(hub, i, NULL, -+ status = hub_port_reset(hub, i, NULL, - HUB_BH_RESET_TIME, true); -+ if (status < 0) -+ hub_port_disable(hub, i, 1); -+ connect_change = 0; - } - - if (connect_change) -From c52804a472649b2e5005342308739434cbd51119 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Tue, 27 Nov 2012 12:30:23 -0800 -Subject: xhci: Avoid "dead ports", add roothub port polling. - -From: Sarah Sharp - -commit c52804a472649b2e5005342308739434cbd51119 upstream. - -The USB core hub thread (khubd) is designed with external USB hubs in -mind. It expects that if a port status change bit is set, the hub will -continue to send a notification through the hub status data transfer. -Basically, it expects hub notifications to be level-triggered. - -The xHCI host controller is designed to be edge-triggered on the logical -'OR' of all the port status change bits. When all port status change -bits are clear, and a new change bit is set, the xHC will generate a -Port Status Change Event. If another change bit is set in the same port -status register before the first bit is cleared, it will not send -another event. - -This means that the hub code may lose port status changes because of -race conditions between clearing change bits. The user sees this as a -"dead port" that doesn't react to device connects. - -The fix is to turn on port polling whenever a new change bit is set. -Once the USB core issues a hub status request that shows that no change -bits are set in any USB ports, turn off port polling. - -We can't allow the USB core to poll the roothub for port events during -host suspend because if the PCI host is in D3cold, the port registers -will be all f's. Instead, stop the port polling timer, and -unconditionally restart it when the host resumes. If there are no port -change bits set after the resume, the first call to hub_status_data will -disable polling. - -This patch should be backported to stable kernels with the first xHCI -support, 2.6.31 and newer, that include the commit -0f2a79300a1471cf92ab43af165ea13555c8b0a5 "USB: xhci: Root hub support." -There will be merge conflicts because the check for HC_STATE_SUSPENDED -was moved into xhci_suspend in 3.8. - -Signed-off-by: Sarah Sharp -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/xhci-hub.c | 7 +++++++ - drivers/usb/host/xhci-ring.c | 9 +++++++++ - drivers/usb/host/xhci.c | 10 ++++++++++ - 3 files changed, 26 insertions(+) - ---- a/drivers/usb/host/xhci-hub.c -+++ b/drivers/usb/host/xhci-hub.c -@@ -984,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd - int max_ports; - __le32 __iomem **port_array; - struct xhci_bus_state *bus_state; -+ bool reset_change = false; - - max_ports = xhci_get_ports(hcd, &port_array); - bus_state = &xhci->bus_state[hcd_index(hcd)]; -@@ -1015,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd - buf[(i + 1) / 8] |= 1 << (i + 1) % 8; - status = 1; - } -+ if ((temp & PORT_RC)) -+ reset_change = true; -+ } -+ if (!status && !reset_change) { -+ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); -+ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - } - spin_unlock_irqrestore(&xhci->lock, flags); - return status ? retval : 0; ---- a/drivers/usb/host/xhci-ring.c -+++ b/drivers/usb/host/xhci-ring.c -@@ -1725,6 +1725,15 @@ cleanup: - if (bogus_port_status) - return; - -+ /* -+ * xHCI port-status-change events occur when the "or" of all the -+ * status-change bits in the portsc register changes from 0 to 1. -+ * New status changes won't cause an event if any other change -+ * bits are still set. When an event occurs, switch over to -+ * polling to avoid losing status changes. -+ */ -+ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); -+ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); - spin_unlock(&xhci->lock); - /* Pass this up to the core */ - usb_hcd_poll_rh_status(hcd); ---- a/drivers/usb/host/xhci.c -+++ b/drivers/usb/host/xhci.c -@@ -880,6 +880,11 @@ int xhci_suspend(struct xhci_hcd *xhci) - struct usb_hcd *hcd = xhci_to_hcd(xhci); - u32 command; - -+ /* Don't poll the roothubs on bus suspend. */ -+ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); -+ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); -+ del_timer_sync(&hcd->rh_timer); -+ - spin_lock_irq(&xhci->lock); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); -@@ -1064,6 +1069,11 @@ int xhci_resume(struct xhci_hcd *xhci, b - if (xhci->quirks & XHCI_COMP_MODE_QUIRK) - compliance_mode_recovery_timer_init(xhci); - -+ /* Re-enable port polling. */ -+ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); -+ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); -+ usb_hcd_poll_rh_status(hcd); -+ - return retval; - } - #endif /* CONFIG_PM */ -From 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Thu, 29 Nov 2012 15:05:57 +0100 -Subject: USB: hub: handle claim of enabled remote wakeup after reset - -From: Oliver Neukum - -commit 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 upstream. - -Some touchscreens have buggy firmware which claims -remote wakeup to be enabled after a reset. They nevertheless -crash if the feature is cleared by the host. -Add a check for reset resume before checking for -an enabled remote wakeup feature. On compliant -devices the feature must be cleared after a reset anyway. - -Signed-off-by: Oliver Neukum -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hub.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2960,7 +2960,7 @@ int usb_port_suspend(struct usb_device * - static int finish_port_resume(struct usb_device *udev) - { - int status = 0; -- u16 devstatus; -+ u16 devstatus = 0; - - /* caller owns the udev device lock */ - dev_dbg(&udev->dev, "%s\n", -@@ -3005,7 +3005,13 @@ static int finish_port_resume(struct usb - if (status) { - dev_dbg(&udev->dev, "gone after usb resume? status %d\n", - status); -- } else if (udev->actconfig) { -+ /* -+ * There are a few quirky devices which violate the standard -+ * by claiming to have remote wakeup enabled after a reset, -+ * which crash if the feature is cleared, hence check for -+ * udev->reset_resume -+ */ -+ } else if (udev->actconfig && !udev->reset_resume) { - le16_to_cpus(&devstatus); - if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, -From 55c1945edaac94c5338a3647bc2e85ff75d9cf36 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Mon, 17 Dec 2012 14:12:35 -0800 -Subject: xhci: Handle HS bulk/ctrl endpoints that don't NAK. - -From: Sarah Sharp - -commit 55c1945edaac94c5338a3647bc2e85ff75d9cf36 upstream. - -A high speed control or bulk endpoint may have bInterval set to zero, -which means it does not NAK. If bInterval is non-zero, it means the -endpoint NAKs at a rate of 2^(bInterval - 1). - -The xHCI code to compute the NAK interval does not handle the special -case of zero properly. The current code unconditionally subtracts one -from bInterval and uses it as an exponent. This causes a very large -bInterval to be used, and warning messages like these will be printed: - -usb 1-1: ep 0x1 - rounding interval to 32768 microframes, ep desc says 0 microframes - -This may cause the xHCI host hardware to reject the Configure Endpoint -command, which means the HS device will be unusable under xHCI ports. - -This patch should be backported to kernels as old as 2.6.31, that contain -commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in -xhci_get_endpoint_interval()". - -Reported-by: Vincent Pelletier -Suggested-by: Alan Stern -Signed-off-by: Sarah Sharp -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/xhci-mem.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/usb/host/xhci-mem.c -+++ b/drivers/usb/host/xhci-mem.c -@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_ - static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, - struct usb_host_endpoint *ep) - { -+ if (ep->desc.bInterval == 0) -+ return 0; - return xhci_microframes_to_exponent(udev, ep, - ep->desc.bInterval, 0, 15); - } -From 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe Mon Sep 17 00:00:00 2001 -From: Jan Beulich -Date: Wed, 19 Dec 2012 16:15:56 +0000 -Subject: USB: ehci: make debug port in-use detection functional again - -From: Jan Beulich - -commit 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe upstream. - -Debug port in-use determination must be done before the controller gets -reset the first time, i.e. before the call to ehci_setup() as of commit -1a49e2ac9651df7349867a5cf44e2c83de1046af. That commit effectively -rendered commit 9fa5780beea1274d498a224822397100022da7d4 useless. - -While moving that code around, also fix the BAR determination - the -respective capability field is a 3- rather than a 2-bit one -, and use -PCI_CAP_ID_DBG instead of the literal 0x0a. - -It's unclear to me whether the debug port functionality is important -enough to warrant fixing this in stable kernels too. - -Signed-off-by: Jan Beulich -Cc: Konrad Rzeszutek Wilk -Acked-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/ehci-pci.c | 39 ++++++++++++++++++++------------------- - 1 file changed, 20 insertions(+), 19 deletions(-) - ---- a/drivers/usb/host/ehci-pci.c -+++ b/drivers/usb/host/ehci-pci.c -@@ -192,6 +192,26 @@ static int ehci_pci_setup(struct usb_hcd - break; - } - -+ /* optional debug port, normally in the first BAR */ -+ temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); -+ if (temp) { -+ pci_read_config_dword(pdev, temp, &temp); -+ temp >>= 16; -+ if (((temp >> 13) & 7) == 1) { -+ u32 hcs_params = ehci_readl(ehci, -+ &ehci->caps->hcs_params); -+ -+ temp &= 0x1fff; -+ ehci->debug = hcd->regs + temp; -+ temp = ehci_readl(ehci, &ehci->debug->control); -+ ehci_info(ehci, "debug port %d%s\n", -+ HCS_DEBUG_PORT(hcs_params), -+ (temp & DBGP_ENABLED) ? " IN USE" : ""); -+ if (!(temp & DBGP_ENABLED)) -+ ehci->debug = NULL; -+ } -+ } -+ - retval = ehci_setup(hcd); - if (retval) - return retval; -@@ -226,25 +246,6 @@ static int ehci_pci_setup(struct usb_hcd - break; - } - -- /* optional debug port, normally in the first BAR */ -- temp = pci_find_capability(pdev, 0x0a); -- if (temp) { -- pci_read_config_dword(pdev, temp, &temp); -- temp >>= 16; -- if ((temp & (3 << 13)) == (1 << 13)) { -- temp &= 0x1fff; -- ehci->debug = hcd->regs + temp; -- temp = ehci_readl(ehci, &ehci->debug->control); -- ehci_info(ehci, "debug port %d%s\n", -- HCS_DEBUG_PORT(ehci->hcs_params), -- (temp & DBGP_ENABLED) -- ? " IN USE" -- : ""); -- if (!(temp & DBGP_ENABLED)) -- ehci->debug = NULL; -- } -- } -- - /* at least the Genesys GL880S needs fixup here */ - temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); - temp &= 0x0f; -From bc3b7756b5ff66828acf7bc24f148d28b8d61108 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Fri, 28 Dec 2012 17:09:03 +0800 -Subject: regulator: max8997: Use uV in voltage_map_desc - -From: Axel Lin - -commit bc3b7756b5ff66828acf7bc24f148d28b8d61108 upstream. - -Current code does integer division (min_vol = min_uV / 1000) before pass -min_vol to max8997_get_voltage_proper_val(). -So it is possible min_vol is truncated to a smaller value. - -For example, if the request min_uV is 800900 for ldo. -min_vol = 800900 / 1000 = 800 (mV) -Then max8997_get_voltage_proper_val returns 800 mV for this case which is lower -than the requested voltage. - -Use uV rather than mV in voltage_map_desc to prevent truncation by integer -division. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/regulator/max8997.c | 36 +++++++++++++++++------------------- - 1 file changed, 17 insertions(+), 19 deletions(-) - ---- a/drivers/regulator/max8997.c -+++ b/drivers/regulator/max8997.c -@@ -69,26 +69,26 @@ struct voltage_map_desc { - int step; - }; - --/* Voltage maps in mV */ -+/* Voltage maps in uV */ - static const struct voltage_map_desc ldo_voltage_map_desc = { -- .min = 800, .max = 3950, .step = 50, -+ .min = 800000, .max = 3950000, .step = 50000, - }; /* LDO1 ~ 18, 21 all */ - - static const struct voltage_map_desc buck1245_voltage_map_desc = { -- .min = 650, .max = 2225, .step = 25, -+ .min = 650000, .max = 2225000, .step = 25000, - }; /* Buck1, 2, 4, 5 */ - - static const struct voltage_map_desc buck37_voltage_map_desc = { -- .min = 750, .max = 3900, .step = 50, -+ .min = 750000, .max = 3900000, .step = 50000, - }; /* Buck3, 7 */ - --/* current map in mA */ -+/* current map in uA */ - static const struct voltage_map_desc charger_current_map_desc = { -- .min = 200, .max = 950, .step = 50, -+ .min = 200000, .max = 950000, .step = 50000, - }; - - static const struct voltage_map_desc topoff_current_map_desc = { -- .min = 50, .max = 200, .step = 10, -+ .min = 50000, .max = 200000, .step = 10000, - }; - - static const struct voltage_map_desc *reg_voltage_map[] = { -@@ -192,7 +192,7 @@ static int max8997_list_voltage(struct r - if (val > desc->max) - return -EINVAL; - -- return val * 1000; -+ return val; - } - - static int max8997_get_enable_register(struct regulator_dev *rdev, -@@ -483,7 +483,6 @@ static int max8997_set_voltage_ldobuck(s - { - struct max8997_data *max8997 = rdev_get_drvdata(rdev); - struct i2c_client *i2c = max8997->iodev->i2c; -- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const struct voltage_map_desc *desc; - int rid = rdev_get_id(rdev); - int i, reg, shift, mask, ret; -@@ -507,7 +506,7 @@ static int max8997_set_voltage_ldobuck(s - - desc = reg_voltage_map[rid]; - -- i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); -+ i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); - if (i < 0) - return i; - -@@ -555,7 +554,7 @@ static int max8997_set_voltage_ldobuck_t - case MAX8997_BUCK4: - case MAX8997_BUCK5: - return DIV_ROUND_UP(desc->step * (new_selector - old_selector), -- max8997->ramp_delay); -+ max8997->ramp_delay * 1000); - } - - return 0; -@@ -654,7 +653,6 @@ static int max8997_set_voltage_buck(stru - const struct voltage_map_desc *desc; - int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; - bool gpio_dvs_mode = false; -- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - - if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) - return -EINVAL; -@@ -679,7 +677,7 @@ static int max8997_set_voltage_buck(stru - selector); - - desc = reg_voltage_map[rid]; -- new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); -+ new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); - if (new_val < 0) - return new_val; - -@@ -977,8 +975,8 @@ static __devinit int max8997_pmic_probe( - max8997->buck1_vol[i] = ret = - max8997_get_voltage_proper_val( - &buck1245_voltage_map_desc, -- pdata->buck1_voltage[i] / 1000, -- pdata->buck1_voltage[i] / 1000 + -+ pdata->buck1_voltage[i], -+ pdata->buck1_voltage[i] + - buck1245_voltage_map_desc.step); - if (ret < 0) - goto err_out; -@@ -986,8 +984,8 @@ static __devinit int max8997_pmic_probe( - max8997->buck2_vol[i] = ret = - max8997_get_voltage_proper_val( - &buck1245_voltage_map_desc, -- pdata->buck2_voltage[i] / 1000, -- pdata->buck2_voltage[i] / 1000 + -+ pdata->buck2_voltage[i], -+ pdata->buck2_voltage[i] + - buck1245_voltage_map_desc.step); - if (ret < 0) - goto err_out; -@@ -995,8 +993,8 @@ static __devinit int max8997_pmic_probe( - max8997->buck5_vol[i] = ret = - max8997_get_voltage_proper_val( - &buck1245_voltage_map_desc, -- pdata->buck5_voltage[i] / 1000, -- pdata->buck5_voltage[i] / 1000 + -+ pdata->buck5_voltage[i], -+ pdata->buck5_voltage[i] + - buck1245_voltage_map_desc.step); - if (ret < 0) - goto err_out; -From adf6178ad5552a7f2f742a8c85343c50f080c412 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Fri, 28 Dec 2012 17:10:20 +0800 -Subject: regulator: max8998: Use uV in voltage_map_desc - -From: Axel Lin - -commit adf6178ad5552a7f2f742a8c85343c50f080c412 upstream. - -Integer division may truncate. -This happens when pdata->buckx_voltagex setting is not align with 1000 uV. -Thus use uV in voltage_map_desc, this ensures the selected voltage won't less -than pdata buckx_voltagex settings. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/regulator/max8998.c | 42 +++++++++++++++++++++--------------------- - 1 file changed, 21 insertions(+), 21 deletions(-) - ---- a/drivers/regulator/max8998.c -+++ b/drivers/regulator/max8998.c -@@ -51,39 +51,39 @@ struct voltage_map_desc { - int step; - }; - --/* Voltage maps */ -+/* Voltage maps in uV*/ - static const struct voltage_map_desc ldo23_voltage_map_desc = { -- .min = 800, .step = 50, .max = 1300, -+ .min = 800000, .step = 50000, .max = 1300000, - }; - static const struct voltage_map_desc ldo456711_voltage_map_desc = { -- .min = 1600, .step = 100, .max = 3600, -+ .min = 1600000, .step = 100000, .max = 3600000, - }; - static const struct voltage_map_desc ldo8_voltage_map_desc = { -- .min = 3000, .step = 100, .max = 3600, -+ .min = 3000000, .step = 100000, .max = 3600000, - }; - static const struct voltage_map_desc ldo9_voltage_map_desc = { -- .min = 2800, .step = 100, .max = 3100, -+ .min = 2800000, .step = 100000, .max = 3100000, - }; - static const struct voltage_map_desc ldo10_voltage_map_desc = { -- .min = 950, .step = 50, .max = 1300, -+ .min = 95000, .step = 50000, .max = 1300000, - }; - static const struct voltage_map_desc ldo1213_voltage_map_desc = { -- .min = 800, .step = 100, .max = 3300, -+ .min = 800000, .step = 100000, .max = 3300000, - }; - static const struct voltage_map_desc ldo1415_voltage_map_desc = { -- .min = 1200, .step = 100, .max = 3300, -+ .min = 1200000, .step = 100000, .max = 3300000, - }; - static const struct voltage_map_desc ldo1617_voltage_map_desc = { -- .min = 1600, .step = 100, .max = 3600, -+ .min = 1600000, .step = 100000, .max = 3600000, - }; - static const struct voltage_map_desc buck12_voltage_map_desc = { -- .min = 750, .step = 25, .max = 1525, -+ .min = 750000, .step = 25000, .max = 1525000, - }; - static const struct voltage_map_desc buck3_voltage_map_desc = { -- .min = 1600, .step = 100, .max = 3600, -+ .min = 1600000, .step = 100000, .max = 3600000, - }; - static const struct voltage_map_desc buck4_voltage_map_desc = { -- .min = 800, .step = 100, .max = 2300, -+ .min = 800000, .step = 100000, .max = 2300000, - }; - - static const struct voltage_map_desc *ldo_voltage_map[] = { -@@ -445,7 +445,7 @@ static int max8998_set_voltage_buck_time - if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) - return 0; - -- difference = (new_selector - old_selector) * desc->step; -+ difference = (new_selector - old_selector) * desc->step / 1000; - if (difference > 0) - return difference / ((val & 0x0f) + 1); - -@@ -702,7 +702,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck1_voltage1 / 1000)) -+ < pdata->buck1_voltage1) - i++; - max8998->buck1_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); -@@ -713,7 +713,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck1_voltage2 / 1000)) -+ < pdata->buck1_voltage2) - i++; - - max8998->buck1_vol[1] = i; -@@ -725,7 +725,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck1_voltage3 / 1000)) -+ < pdata->buck1_voltage3) - i++; - - max8998->buck1_vol[2] = i; -@@ -737,7 +737,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck1_voltage4 / 1000)) -+ < pdata->buck1_voltage4) - i++; - - max8998->buck1_vol[3] = i; -@@ -763,7 +763,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck2_voltage1 / 1000)) -+ < pdata->buck2_voltage1) - i++; - max8998->buck2_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); -@@ -774,7 +774,7 @@ static __devinit int max8998_pmic_probe( - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i -- < (pdata->buck2_voltage2 / 1000)) -+ < pdata->buck2_voltage2) - i++; - max8998->buck2_vol[1] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); -@@ -792,8 +792,8 @@ static __devinit int max8998_pmic_probe( - int count = (desc->max - desc->min) / desc->step + 1; - - regulators[index].n_voltages = count; -- regulators[index].min_uV = desc->min * 1000; -- regulators[index].uV_step = desc->step * 1000; -+ regulators[index].min_uV = desc->min; -+ regulators[index].uV_step = desc->step; - } - - config.dev = max8998->dev; -From 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Wed, 9 Jan 2013 19:34:57 +0800 -Subject: regulator: max8998: Ensure enough delay time for max8998_set_voltage_buck_time_sel - -From: Axel Lin - -commit 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 upstream. - -Use DIV_ROUND_UP to prevent truncation by integer division issue. -This ensures we return enough delay time. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/regulator/max8998.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/regulator/max8998.c -+++ b/drivers/regulator/max8998.c -@@ -447,7 +447,7 @@ static int max8998_set_voltage_buck_time - - difference = (new_selector - old_selector) * desc->step / 1000; - if (difference > 0) -- return difference / ((val & 0x0f) + 1); -+ return DIV_ROUND_UP(difference, (val & 0x0f) + 1); - - return 0; - } -From 9120963578320532dfb3a9a7947e8d05b39900b5 Mon Sep 17 00:00:00 2001 -From: Ralf Baechle -Date: Thu, 20 Dec 2012 12:47:51 +0100 -Subject: Revert "MIPS: Optimise TLB handlers for MIPS32/64 R2 cores." - -From: Ralf Baechle - -commit 9120963578320532dfb3a9a7947e8d05b39900b5 upstream. - -This reverts commit ff401e52100dcdc85e572d1ad376d3307b3fe28e. - -This breaks on MIPS64 R2 cores such as Broadcom's. - -Signed-off-by: Jayachandran C -Signed-off-by: Greg Kroah-Hartman - ---- - arch/mips/mm/tlbex.c | 16 ---------------- - 1 file changed, 16 deletions(-) - ---- a/arch/mips/mm/tlbex.c -+++ b/arch/mips/mm/tlbex.c -@@ -952,13 +952,6 @@ build_get_pgde32(u32 **p, unsigned int t - #endif - uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ - uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); -- -- if (cpu_has_mips_r2) { -- uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT)); -- uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT)); -- return; -- } -- - uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ - uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); - uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ -@@ -994,15 +987,6 @@ static void __cpuinit build_adjust_conte - - static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) - { -- if (cpu_has_mips_r2) { -- /* PTE ptr offset is obtained from BadVAddr */ -- UASM_i_MFC0(p, tmp, C0_BADVADDR); -- UASM_i_LW(p, ptr, 0, ptr); -- uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1); -- uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1); -- return; -- } -- - /* - * Bug workaround for the Nevada. It seems as if under certain - * circumstances the move from cp0_context might produce a -From e8088073c9610af017fd47fddd104a2c3afb32e8 Mon Sep 17 00:00:00 2001 -From: Joe Thornber -Date: Fri, 21 Dec 2012 20:23:31 +0000 -Subject: dm thin: fix race between simultaneous io and discards to same block - -From: Joe Thornber - -commit e8088073c9610af017fd47fddd104a2c3afb32e8 upstream. - -There is a race when discard bios and non-discard bios are issued -simultaneously to the same block. - -Discard support is expensive for all thin devices precisely because you -have to be careful to quiesce the area you're discarding. DM thin must -handle this conflicting IO pattern (simultaneous non-discard vs discard) -even though a sane application shouldn't be issuing such IO. - -The race manifests as follows: - -1. A non-discard bio is mapped in thin_bio_map. - This doesn't lock out parallel activity to the same block. - -2. A discard bio is issued to the same block as the non-discard bio. - -3. The discard bio is locked in a dm_bio_prison_cell in process_discard - to lock out parallel activity against the same block. - -4. The non-discard bio's mapping continues and its all_io_entry is - incremented so the bio is accounted for in the thin pool's all_io_ds - which is a dm_deferred_set used to track time locality of non-discard IO. - -5. The non-discard bio is finally locked in a dm_bio_prison_cell in - process_bio. - -The race can result in deadlock, leaving the block layer hanging waiting -for completion of a discard bio that never completes, e.g.: - -INFO: task ruby:15354 blocked for more than 120 seconds. -"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. -ruby D ffffffff8160f0e0 0 15354 15314 0x00000000 - ffff8802fb08bc58 0000000000000082 ffff8802fb08bfd8 0000000000012900 - ffff8802fb08a010 0000000000012900 0000000000012900 0000000000012900 - ffff8802fb08bfd8 0000000000012900 ffff8803324b9480 ffff88032c6f14c0 -Call Trace: - [] schedule+0x29/0x70 - [] schedule_timeout+0x195/0x220 - [] ? _dm_request+0x111/0x160 [dm_mod] - [] wait_for_common+0x11e/0x190 - [] ? try_to_wake_up+0x2b0/0x2b0 - [] wait_for_completion+0x1d/0x20 - [] blkdev_issue_discard+0x219/0x260 - [] blkdev_ioctl+0x6e9/0x7b0 - [] block_ioctl+0x3c/0x40 - [] do_vfs_ioctl+0x8c/0x340 - [] ? block_llseek+0x67/0xb0 - [] sys_ioctl+0xa1/0xb0 - [] ? sys_rt_sigprocmask+0x86/0xd0 - [] system_call_fastpath+0x16/0x1b - -The thinp-test-suite's test_discard_random_sectors reliably hits this -deadlock on fast SSD storage. - -The fix for this race is that the all_io_entry for a bio must be -incremented whilst the dm_bio_prison_cell is held for the bio's -associated virtual and physical blocks. That cell locking wasn't -occurring early enough in thin_bio_map. This patch fixes this. - -Care is taken to always call the new function inc_all_io_entry() with -the relevant cells locked, but they are generally unlocked before -calling issue() to try to avoid holding the cells locked across -generic_submit_request. - -Also, now that thin_bio_map may lock bios in a cell, process_bio() is no -longer the only thread that will do so. Because of this we must be sure -to use cell_defer_except() to release all non-holder entries, that -were added by the other thread, because they must be deferred. - -This patch depends on "dm thin: replace dm_cell_release_singleton with -cell_defer_except". - -Signed-off-by: Joe Thornber -Signed-off-by: Mike Snitzer -Signed-off-by: Alasdair G Kergon -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/md/dm-thin.c | 84 +++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 59 insertions(+), 25 deletions(-) - ---- a/drivers/md/dm-thin.c -+++ b/drivers/md/dm-thin.c -@@ -368,6 +368,17 @@ static int bio_triggers_commit(struct th - dm_thin_changed_this_transaction(tc->td); - } - -+static void inc_all_io_entry(struct pool *pool, struct bio *bio) -+{ -+ struct dm_thin_endio_hook *h; -+ -+ if (bio->bi_rw & REQ_DISCARD) -+ return; -+ -+ h = dm_get_mapinfo(bio)->ptr; -+ h->all_io_entry = dm_deferred_entry_inc(pool->all_io_ds); -+} -+ - static void issue(struct thin_c *tc, struct bio *bio) - { - struct pool *pool = tc->pool; -@@ -596,13 +607,15 @@ static void process_prepared_discard_pas - { - struct thin_c *tc = m->tc; - -+ inc_all_io_entry(tc->pool, m->bio); -+ cell_defer_except(tc, m->cell); -+ cell_defer_except(tc, m->cell2); -+ - if (m->pass_discard) - remap_and_issue(tc, m->bio, m->data_block); - else - bio_endio(m->bio, 0); - -- cell_defer_except(tc, m->cell); -- cell_defer_except(tc, m->cell2); - mempool_free(m, tc->pool->mapping_pool); - } - -@@ -710,6 +723,7 @@ static void schedule_copy(struct thin_c - h->overwrite_mapping = m; - m->bio = bio; - save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); -+ inc_all_io_entry(pool, bio); - remap_and_issue(tc, bio, data_dest); - } else { - struct dm_io_region from, to; -@@ -779,6 +793,7 @@ static void schedule_zero(struct thin_c - h->overwrite_mapping = m; - m->bio = bio; - save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); -+ inc_all_io_entry(pool, bio); - remap_and_issue(tc, bio, data_block); - } else { - int r; -@@ -961,13 +976,15 @@ static void process_discard(struct thin_ - wake_worker(pool); - } - } else { -+ inc_all_io_entry(pool, bio); -+ cell_defer_except(tc, cell); -+ cell_defer_except(tc, cell2); -+ - /* - * The DM core makes sure that the discard doesn't span - * a block boundary. So we submit the discard of a - * partial block appropriately. - */ -- cell_defer_except(tc, cell); -- cell_defer_except(tc, cell2); - if ((!lookup_result.shared) && pool->pf.discard_passdown) - remap_and_issue(tc, bio, lookup_result.block); - else -@@ -1039,8 +1056,9 @@ static void process_shared_bio(struct th - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; - - h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); -- -+ inc_all_io_entry(pool, bio); - cell_defer_except(tc, cell); -+ - remap_and_issue(tc, bio, lookup_result->block); - } - } -@@ -1055,7 +1073,9 @@ static void provision_block(struct thin_ - * Remap empty bios (flushes) immediately, without provisioning. - */ - if (!bio->bi_size) { -+ inc_all_io_entry(tc->pool, bio); - cell_defer_except(tc, cell); -+ - remap_and_issue(tc, bio, 0); - return; - } -@@ -1110,26 +1130,22 @@ static void process_bio(struct thin_c *t - r = dm_thin_find_block(tc->td, block, 1, &lookup_result); - switch (r) { - case 0: -- /* -- * We can release this cell now. This thread is the only -- * one that puts bios into a cell, and we know there were -- * no preceding bios. -- */ -- /* -- * TODO: this will probably have to change when discard goes -- * back in. -- */ -- cell_defer_except(tc, cell); -- -- if (lookup_result.shared) -+ if (lookup_result.shared) { - process_shared_bio(tc, bio, block, &lookup_result); -- else -+ cell_defer_except(tc, cell); -+ } else { -+ inc_all_io_entry(tc->pool, bio); -+ cell_defer_except(tc, cell); -+ - remap_and_issue(tc, bio, lookup_result.block); -+ } - break; - - case -ENODATA: - if (bio_data_dir(bio) == READ && tc->origin_dev) { -+ inc_all_io_entry(tc->pool, bio); - cell_defer_except(tc, cell); -+ - remap_to_origin_and_issue(tc, bio); - } else - provision_block(tc, bio, block, cell); -@@ -1155,8 +1171,10 @@ static void process_bio_read_only(struct - case 0: - if (lookup_result.shared && (rw == WRITE) && bio->bi_size) - bio_io_error(bio); -- else -+ else { -+ inc_all_io_entry(tc->pool, bio); - remap_and_issue(tc, bio, lookup_result.block); -+ } - break; - - case -ENODATA: -@@ -1166,6 +1184,7 @@ static void process_bio_read_only(struct - } - - if (tc->origin_dev) { -+ inc_all_io_entry(tc->pool, bio); - remap_to_origin_and_issue(tc, bio); - break; - } -@@ -1346,7 +1365,7 @@ static struct dm_thin_endio_hook *thin_h - - h->tc = tc; - h->shared_read_entry = NULL; -- h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds); -+ h->all_io_entry = NULL; - h->overwrite_mapping = NULL; - - return h; -@@ -1363,6 +1382,8 @@ static int thin_bio_map(struct dm_target - dm_block_t block = get_bio_block(tc, bio); - struct dm_thin_device *td = tc->td; - struct dm_thin_lookup_result result; -+ struct dm_bio_prison_cell *cell1, *cell2; -+ struct dm_cell_key key; - - map_context->ptr = thin_hook_bio(tc, bio); - -@@ -1399,12 +1420,25 @@ static int thin_bio_map(struct dm_target - * shared flag will be set in their case. - */ - thin_defer_bio(tc, bio); -- r = DM_MAPIO_SUBMITTED; -- } else { -- remap(tc, bio, result.block); -- r = DM_MAPIO_REMAPPED; -+ return DM_MAPIO_SUBMITTED; - } -- break; -+ -+ build_virtual_key(tc->td, block, &key); -+ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1)) -+ return DM_MAPIO_SUBMITTED; -+ -+ build_data_key(tc->td, result.block, &key); -+ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2)) { -+ cell_defer_except(tc, cell1); -+ return DM_MAPIO_SUBMITTED; -+ } -+ -+ inc_all_io_entry(tc->pool, bio); -+ cell_defer_except(tc, cell2); -+ cell_defer_except(tc, cell1); -+ -+ remap(tc, bio, result.block); -+ return DM_MAPIO_REMAPPED; - - case -ENODATA: - if (get_pool_mode(tc->pool) == PM_READ_ONLY) { -From ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Mon, 3 Dec 2012 12:59:04 +0100 -Subject: Revert: "rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails" - -From: Stanislaw Gruszka - -commit ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e upstream. - -This revert: - -commit be03d4a45c09ee5100d3aaaedd087f19bc20d01f -Author: Andreas Hartmann -Date: Tue Apr 17 00:25:28 2012 +0200 - - rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails - -To fix problem workaround by above commit use -IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL flag (see change log for -"mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL" patch). - -Resolve: https://bugzilla.kernel.org/show_bug.cgi?id=42828 -Bisected-by: Francisco Pina Martins -Signed-off-by: Stanislaw Gruszka -Signed-off-by: Johannes Berg -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- - drivers/net/wireless/rt2x00/rt2x00dev.c | 7 +++---- - 2 files changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/net/wireless/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -5036,7 +5036,8 @@ static int rt2800_probe_hw_mode(struct r - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_AMPDU_AGGREGATION | -- IEEE80211_HW_REPORTS_TX_ACK_STATUS; -+ IEEE80211_HW_REPORTS_TX_ACK_STATUS | -+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL; - - /* - * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -391,10 +391,9 @@ void rt2x00lib_txdone(struct queue_entry - tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - tx_info->status.ampdu_len = 1; - tx_info->status.ampdu_ack_len = success ? 1 : 0; -- /* -- * TODO: Need to tear down BA session here -- * if not successful. -- */ -+ -+ if (!success) -+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - } - - if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { -From 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 Mon Sep 17 00:00:00 2001 -From: Konstantin Khlebnikov -Date: Fri, 14 Dec 2012 15:03:10 +0400 -Subject: EDAC: Fix kernel panic on module unloading - -From: Konstantin Khlebnikov - -commit 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 upstream. - -This patch fixes use-after-free and double-free bugs in -edac_mc_sysfs_exit(). mci_pdev has single reference and put_device() -calls mc_attr_release() which calls kfree(). The following -device_del() works with already released memory. An another kfree() in -edac_mc_sysfs_exit() releses the same memory again. Great. - -Signed-off-by: Konstantin Khlebnikov -Cc: Denis Kirjanov -Cc: Mauro Carvalho Chehab -Link: http://lkml.kernel.org/r/20121214110310.11019.21098.stgit@zurg -Signed-off-by: Borislav Petkov -[ a partial 3.7.y backport ] -Signed-off-by: Borislav Petkov -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/edac/edac_mc_sysfs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/edac/edac_mc_sysfs.c -+++ b/drivers/edac/edac_mc_sysfs.c -@@ -1145,7 +1145,7 @@ int __init edac_mc_sysfs_init(void) - - void __exit edac_mc_sysfs_exit(void) - { -- put_device(mci_pdev); - device_del(mci_pdev); -+ put_device(mci_pdev); - edac_put_sysfs_subsys(); - } -From 539526b4137bc0e7a8806c38c8522f226814a0e6 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Sat, 8 Dec 2012 12:58:33 +0100 -Subject: drm/i915: disable cpt phase pointer fdi rx workaround - -From: Daniel Vetter - -commit 539526b4137bc0e7a8806c38c8522f226814a0e6 upstream. - -We've originally added this in - -commit 291427f5fdadec6e4be2924172e83588880e1539 -Author: Jesse Barnes -Date: Fri Jul 29 12:42:37 2011 -0700 - - drm/i915: apply phase pointer override on SNB+ too - -and then copy-pasted it over to ivb/ppt. The w/a was originally added -for ilk/ibx in - -commit 5b2adf897146edeac6a1e438fb67b5a53dbbdf34 -Author: Jesse Barnes -Date: Thu Oct 7 16:01:15 2010 -0700 - - drm/i915: add Ironlake clock gating workaround for FDI link training - -and fixed up a bit in - -commit 6f06ce184c765fd8d50669a8d12fdd566c920859 -Author: Jesse Barnes -Date: Tue Jan 4 15:09:38 2011 -0800 - - drm/i915: set phase sync pointer override enable before setting phase sync pointer - -It turns out that this w/a isn't actually required on cpt/ppt and -positively harmful on ivb/ppt when using fdi B/C links - it results in -a black screen occasionally, with seemingfully everything working as -it should. The only failure indication I've found in the hw is that -eventually (but not right after the modeset completes) a pipe underrun -is signalled. - -Big thanks to Arthur Runyan for all the ideas for registers to check -and changes to test, otherwise I couldn't ever have tracked this down! - -Cc: "Runyan, Arthur J" -Cc: stable@vger.kernel.org -Reviewed-by: Jesse Barnes -Signed-off-by: Daniel Vetter -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_display.c | 31 ------------------------------- - 1 file changed, 31 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -2302,18 +2302,6 @@ static void intel_fdi_normal_train(struc - FDI_FE_ERRC_ENABLE); - } - --static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- u32 flags = I915_READ(SOUTH_CHICKEN1); -- -- flags |= FDI_PHASE_SYNC_OVR(pipe); -- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ -- flags |= FDI_PHASE_SYNC_EN(pipe); -- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ -- POSTING_READ(SOUTH_CHICKEN1); --} -- - /* The FDI link training functions for ILK/Ibexpeak. */ - static void ironlake_fdi_link_train(struct drm_crtc *crtc) - { -@@ -2464,9 +2452,6 @@ static void gen6_fdi_link_train(struct d - POSTING_READ(reg); - udelay(150); - -- if (HAS_PCH_CPT(dev)) -- cpt_phase_pointer_enable(dev, pipe); -- - for (i = 0; i < 4; i++) { - reg = FDI_TX_CTL(pipe); - temp = I915_READ(reg); -@@ -2593,9 +2578,6 @@ static void ivb_manual_fdi_link_train(st - POSTING_READ(reg); - udelay(150); - -- if (HAS_PCH_CPT(dev)) -- cpt_phase_pointer_enable(dev, pipe); -- - for (i = 0; i < 4; i++) { - reg = FDI_TX_CTL(pipe); - temp = I915_READ(reg); -@@ -2737,17 +2719,6 @@ static void ironlake_fdi_pll_disable(str - udelay(100); - } - --static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- u32 flags = I915_READ(SOUTH_CHICKEN1); -- -- flags &= ~(FDI_PHASE_SYNC_EN(pipe)); -- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ -- flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); -- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ -- POSTING_READ(SOUTH_CHICKEN1); --} - static void ironlake_fdi_disable(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; -@@ -2777,8 +2748,6 @@ static void ironlake_fdi_disable(struct - I915_WRITE(FDI_RX_CHICKEN(pipe), - I915_READ(FDI_RX_CHICKEN(pipe) & - ~FDI_RX_PHASE_SYNC_POINTER_EN)); -- } else if (HAS_PCH_CPT(dev)) { -- cpt_phase_pointer_disable(dev, pipe); - } - - /* still set train pattern 1 */ -From e43a028752fed049e4bd94ef895542f96d79fa74 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Sat, 6 Oct 2012 03:56:35 +0200 -Subject: KVM: PPC: 44x: fix DCR read/write - -From: Alexander Graf - -commit e43a028752fed049e4bd94ef895542f96d79fa74 upstream. - -When remembering the direction of a DCR transaction, we should write -to the same variable that we interpret on later when doing vcpu_run -again. - -Signed-off-by: Alexander Graf -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - arch/powerpc/kvm/44x_emulate.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/powerpc/kvm/44x_emulate.c -+++ b/arch/powerpc/kvm/44x_emulate.c -@@ -76,6 +76,7 @@ int kvmppc_core_emulate_op(struct kvm_ru - run->dcr.dcrn = dcrn; - run->dcr.data = 0; - run->dcr.is_write = 0; -+ vcpu->arch.dcr_is_write = 0; - vcpu->arch.io_gpr = rt; - vcpu->arch.dcr_needed = 1; - kvmppc_account_exit(vcpu, DCR_EXITS); -@@ -94,6 +95,7 @@ int kvmppc_core_emulate_op(struct kvm_ru - run->dcr.dcrn = dcrn; - run->dcr.data = kvmppc_get_gpr(vcpu, rs); - run->dcr.is_write = 1; -+ vcpu->arch.dcr_is_write = 1; - vcpu->arch.dcr_needed = 1; - kvmppc_account_exit(vcpu, DCR_EXITS); - emulated = EMULATE_DO_DCR; -From 3751809df766c05bcce372fcfa4a886b9aaca44b Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Fri, 7 Dec 2012 19:50:07 -0600 -Subject: libceph: socket can close in any connection state - -From: Alex Elder - -(cherry picked from commit 7bb21d68c535ad8be38e14a715632ae398b37ac1) - -A connection's socket can close for any reason, independent of the -state of the connection (and without irrespective of the connection -mutex). As a result, the connectino can be in pretty much any state -at the time its socket is closed. - -Handle those other cases at the top of con_work(). Pull this whole -block of code into a separate function to reduce the clutter. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/messenger.c | 47 ++++++++++++++++++++++++++++++----------------- - 1 file changed, 30 insertions(+), 17 deletions(-) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -2262,6 +2262,35 @@ static void queue_con(struct ceph_connec - } - } - -+static bool con_sock_closed(struct ceph_connection *con) -+{ -+ if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) -+ return false; -+ -+#define CASE(x) \ -+ case CON_STATE_ ## x: \ -+ con->error_msg = "socket closed (con state " #x ")"; \ -+ break; -+ -+ switch (con->state) { -+ CASE(CLOSED); -+ CASE(PREOPEN); -+ CASE(CONNECTING); -+ CASE(NEGOTIATING); -+ CASE(OPEN); -+ CASE(STANDBY); -+ default: -+ pr_warning("%s con %p unrecognized state %lu\n", -+ __func__, con, con->state); -+ con->error_msg = "unrecognized con state"; -+ BUG(); -+ break; -+ } -+#undef CASE -+ -+ return true; -+} -+ - /* - * Do some work on a connection. Drop a connection ref when we're done. - */ -@@ -2273,24 +2302,8 @@ static void con_work(struct work_struct - - mutex_lock(&con->mutex); - restart: -- if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { -- switch (con->state) { -- case CON_STATE_CONNECTING: -- con->error_msg = "connection failed"; -- break; -- case CON_STATE_NEGOTIATING: -- con->error_msg = "negotiation failed"; -- break; -- case CON_STATE_OPEN: -- con->error_msg = "socket closed"; -- break; -- default: -- dout("unrecognized con state %d\n", (int)con->state); -- con->error_msg = "unrecognized con state"; -- BUG(); -- } -+ if (con_sock_closed(con)) - goto fault; -- } - - if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { - dout("con_work %p backing off\n", con); -From 5f64737fb44ee280362a1be280f26adb38c689e4 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Fri, 14 Dec 2012 16:47:41 -0600 -Subject: libceph: report connection fault with warning - -From: Alex Elder - -(cherry picked from commit 28362986f8743124b3a0fda20a8ed3e80309cce1) - -When a connection's socket disconnects, or if there's a protocol -error of some kind on the connection, a fault is signaled and -the connection is reset (closed and reopened, basically). We -currently get an error message on the log whenever this occurs. - -A ceph connection will attempt to reestablish a socket connection -repeatedly if a fault occurs. This means that these error messages -will get repeatedly added to the log, which is undesirable. - -Change the error message to be a warning, so they don't get -logged by default. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/messenger.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -2369,7 +2369,7 @@ fault: - static void ceph_fault(struct ceph_connection *con) - __releases(con->mutex) - { -- pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), -+ pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), - ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); - dout("fault %p state %lu to peer %s\n", - con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); -From d49d943a24d4addbb5c6d1e4feb45bb98b2885fa Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Thu, 6 Dec 2012 07:22:04 -0600 -Subject: libceph: init osd->o_node in create_osd() - -From: Alex Elder - -(cherry picked from commit f407731d12214e7686819018f3a1e9d7b6f83a02) - -The red-black node node in the ceph osd structure is not initialized -in create_osd(). Because this node can be the subject of a -RB_EMPTY_NODE() call later on, we should ensure the node is -initialized properly for that. Add a call to RB_CLEAR_NODE() -initialize it. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -647,6 +647,7 @@ static struct ceph_osd *create_osd(struc - atomic_set(&osd->o_ref, 1); - osd->o_osdc = osdc; - osd->o_osd = onum; -+ RB_CLEAR_NODE(&osd->o_node); - INIT_LIST_HEAD(&osd->o_requests); - INIT_LIST_HEAD(&osd->o_linger_requests); - INIT_LIST_HEAD(&osd->o_osd_lru); -From b4c0c6243efad1ae18a8aa17694952fd6c13bbaa Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Mon, 17 Dec 2012 12:23:48 -0600 -Subject: libceph: init event->node in ceph_osdc_create_event() - -From: Alex Elder - -(cherry picked from commit 3ee5234df68d253c415ba4f2db72ad250d9c21a9) - -The red-black node node in the ceph osd event structure is not -initialized in create_osdc_create_event(). Because this node can -be the subject of a RB_EMPTY_NODE() call later on, we should ensure -the node is initialized properly for that. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -1600,6 +1600,7 @@ int ceph_osdc_create_event(struct ceph_o - event->data = data; - event->osdc = osdc; - INIT_LIST_HEAD(&event->osd_node); -+ RB_CLEAR_NODE(&event->node); - kref_init(&event->kref); /* one ref for us */ - kref_get(&event->kref); /* one ref for the caller */ - init_completion(&event->completion); -From f660813d76b3634c39c2b3ed8715af7e9db14f9c Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Mon, 17 Dec 2012 12:23:48 -0600 -Subject: libceph: don't use rb_init_node() in ceph_osdc_alloc_request() - -From: Alex Elder - -(cherry picked from commit a978fa20fb657548561dddbfb605fe43654f0825) - -The red-black node in the ceph osd request structure is initialized -in ceph_osdc_alloc_request() using rbd_init_node(). We do need to -initialize this, because in __unregister_request() we call -RB_EMPTY_NODE(), which expects the node it's checking to have -been initialized. But rb_init_node() is apparently overkill, and -may in fact be on its way out. So use RB_CLEAR_NODE() instead. - -For a little more background, see this commit: - 4c199a93 rbtree: empty nodes have no color" - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc - kref_init(&req->r_kref); - init_completion(&req->r_completion); - init_completion(&req->r_safe_completion); -+ RB_CLEAR_NODE(&req->r_node); - INIT_LIST_HEAD(&req->r_unsafe_item); - INIT_LIST_HEAD(&req->r_linger_item); - INIT_LIST_HEAD(&req->r_linger_osd); -From c9ddd2cac5e5e9bf278a9c08976592972a2d15c1 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Thu, 6 Dec 2012 07:22:04 -0600 -Subject: libceph: register request before unregister linger - -From: Alex Elder - -(cherry picked from commit c89ce05e0c5a01a256100ac6a6019f276bdd1ca6) - -In kick_requests(), we need to register the request before we -unregister the linger request. Otherwise the unregister will -reset the request's osd pointer to NULL. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -1366,8 +1366,8 @@ static void kick_requests(struct ceph_os - - dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, - req->r_osd ? req->r_osd->o_osd : -1); -- __unregister_linger_request(osdc, req); - __register_request(osdc, req); -+ __unregister_linger_request(osdc, req); - } - mutex_unlock(&osdc->request_mutex); - -From d92a42b79c755e911495bd36316d2573804293ea Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Wed, 19 Dec 2012 15:52:36 -0600 -Subject: libceph: move linger requests sooner in kick_requests() - -From: Alex Elder - -(cherry picked from commit ab60b16d3c31b9bd9fd5b39f97dc42c52a50b67d) - -The kick_requests() function is called by ceph_osdc_handle_map() -when an osd map change has been indicated. Its purpose is to -re-queue any request whose target osd is different from what it -was when it was originally sent. - -It is structured as two loops, one for incomplete but registered -requests, and a second for handling completed linger requests. -As a special case, in the first loop if a request marked to linger -has not yet completed, it is moved from the request list to the -linger list. This is as a quick and dirty way to have the second -loop handle sending the request along with all the other linger -requests. - -Because of the way it's done now, however, this quick and dirty -solution can result in these incomplete linger requests never -getting re-sent as desired. The problem lies in the fact that -the second loop only arranges for a linger request to be sent -if it appears its target osd has changed. This is the proper -handling for *completed* linger requests (it avoids issuing -the same linger request twice to the same osd). - -But although the linger requests added to the list in the first loop -may have been sent, they have not yet completed, so they need to be -re-sent regardless of whether their target osd has changed. - -The first required fix is we need to avoid calling __map_request() -on any incomplete linger request. Otherwise the subsequent -__map_request() call in the second loop will find the target osd -has not changed and will therefore not re-send the request. - -Second, we need to be sure that a sent but incomplete linger request -gets re-sent. If the target osd is the same with the new osd map as -it was when the request was originally sent, this won't happen. -This can be fixed through careful handling when we move these -requests from the request list to the linger list, by unregistering -the request *before* it is registered as a linger request. This -works because a side-effect of unregistering the request is to make -the request's r_osd pointer be NULL, and *that* will ensure the -second loop actually re-sends the linger request. - -Processing of such a request is done at that point, so continue with -the next one once it's been moved. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 30 +++++++++++++++++++----------- - 1 file changed, 19 insertions(+), 11 deletions(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -1322,6 +1322,24 @@ static void kick_requests(struct ceph_os - for (p = rb_first(&osdc->requests); p; ) { - req = rb_entry(p, struct ceph_osd_request, r_node); - p = rb_next(p); -+ -+ /* -+ * For linger requests that have not yet been -+ * registered, move them to the linger list; they'll -+ * be sent to the osd in the loop below. Unregister -+ * the request before re-registering it as a linger -+ * request to ensure the __map_request() below -+ * will decide it needs to be sent. -+ */ -+ if (req->r_linger && list_empty(&req->r_linger_item)) { -+ dout("%p tid %llu restart on osd%d\n", -+ req, req->r_tid, -+ req->r_osd ? req->r_osd->o_osd : -1); -+ __unregister_request(osdc, req); -+ __register_linger_request(osdc, req); -+ continue; -+ } -+ - err = __map_request(osdc, req, force_resend); - if (err < 0) - continue; /* error */ -@@ -1336,17 +1354,6 @@ static void kick_requests(struct ceph_os - req->r_flags |= CEPH_OSD_FLAG_RETRY; - } - } -- if (req->r_linger && list_empty(&req->r_linger_item)) { -- /* -- * register as a linger so that we will -- * re-submit below and get a new tid -- */ -- dout("%p tid %llu restart on osd%d\n", -- req, req->r_tid, -- req->r_osd ? req->r_osd->o_osd : -1); -- __register_linger_request(osdc, req); -- __unregister_request(osdc, req); -- } - } - - list_for_each_entry_safe(req, nreq, &osdc->req_linger, -@@ -1354,6 +1361,7 @@ static void kick_requests(struct ceph_os - dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); - - err = __map_request(osdc, req, force_resend); -+ dout("__map_request returned %d\n", err); - if (err == 0) - continue; /* no change and no osd was specified */ - if (err < 0) -From 8cc1491a5d9e720f0b6f69244fc1548597bb868b Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Wed, 26 Dec 2012 14:31:40 -0600 -Subject: libceph: always reset osds when kicking - -From: Alex Elder - -(cherry picked from commit e6d50f67a6b1a6252a616e6e629473b5c4277218) - -When ceph_osdc_handle_map() is called to process a new osd map, -kick_requests() is called to ensure all affected requests are -updated if necessary to reflect changes in the osd map. This -happens in two cases: whenever an incremental map update is -processed; and when a full map update (or the last one if there is -more than one) gets processed. - -In the former case, the kick_requests() call is followed immediately -by a call to reset_changed_osds() to ensure any connections to osds -affected by the map change are reset. But for full map updates -this isn't done. - -Both cases should be doing this osd reset. - -Rather than duplicating the reset_changed_osds() call, move it into -the end of kick_requests(). - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -1308,7 +1308,7 @@ static void reset_changed_osds(struct ce - * Requeue requests whose mapping to an OSD has changed. If requests map to - * no osd, request a new map. - * -- * Caller should hold map_sem for read and request_mutex. -+ * Caller should hold map_sem for read. - */ - static void kick_requests(struct ceph_osd_client *osdc, int force_resend) - { -@@ -1383,6 +1383,7 @@ static void kick_requests(struct ceph_os - dout("%d requests for down osds, need new map\n", needmap); - ceph_monc_request_next_osdmap(&osdc->client->monc); - } -+ reset_changed_osds(osdc); - } - - -@@ -1439,7 +1440,6 @@ void ceph_osdc_handle_map(struct ceph_os - osdc->osdmap = newmap; - } - kick_requests(osdc, 0); -- reset_changed_osds(osdc); - } else { - dout("ignoring incremental map %u len %d\n", - epoch, maplen); -From b95ad0140dc8d2375bff4b0f30f6832cbb29e17c Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Wed, 26 Dec 2012 10:43:57 -0600 -Subject: libceph: WARN, don't BUG on unexpected connection states - -From: Alex Elder - -(cherry picked from commit 122070a2ffc91f87fe8e8493eb0ac61986c5557c) - -A number of assertions in the ceph messenger are implemented with -BUG_ON(), killing the system if connection's state doesn't match -what's expected. At this point our state model is (evidently) not -well understood enough for these assertions to trigger a BUG(). -Convert all BUG_ON(con->state...) calls to be WARN_ON(con->state...) -so we learn about these issues without killing the machine. - -We now recognize that a connection fault can occur due to a socket -closure at any time, regardless of the state of the connection. So -there is really nothing we can assert about the state of the -connection at that point so eliminate that assertion. - -Reported-by: Ugis -Tested-by: Ugis -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/messenger.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -561,7 +561,7 @@ void ceph_con_open(struct ceph_connectio - mutex_lock(&con->mutex); - dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); - -- BUG_ON(con->state != CON_STATE_CLOSED); -+ WARN_ON(con->state != CON_STATE_CLOSED); - con->state = CON_STATE_PREOPEN; - - con->peer_name.type = (__u8) entity_type; -@@ -1509,7 +1509,7 @@ static int process_banner(struct ceph_co - static void fail_protocol(struct ceph_connection *con) - { - reset_connection(con); -- BUG_ON(con->state != CON_STATE_NEGOTIATING); -+ WARN_ON(con->state != CON_STATE_NEGOTIATING); - con->state = CON_STATE_CLOSED; - } - -@@ -1635,7 +1635,7 @@ static int process_connect(struct ceph_c - return -1; - } - -- BUG_ON(con->state != CON_STATE_NEGOTIATING); -+ WARN_ON(con->state != CON_STATE_NEGOTIATING); - con->state = CON_STATE_OPEN; - - con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); -@@ -2132,7 +2132,6 @@ more: - if (ret < 0) - goto out; - -- BUG_ON(con->state != CON_STATE_CONNECTING); - con->state = CON_STATE_NEGOTIATING; - - /* -@@ -2160,7 +2159,7 @@ more: - goto more; - } - -- BUG_ON(con->state != CON_STATE_OPEN); -+ WARN_ON(con->state != CON_STATE_OPEN); - - if (con->in_base_pos < 0) { - /* -@@ -2374,7 +2373,7 @@ static void ceph_fault(struct ceph_conne - dout("fault %p state %lu to peer %s\n", - con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - -- BUG_ON(con->state != CON_STATE_CONNECTING && -+ WARN_ON(con->state != CON_STATE_CONNECTING && - con->state != CON_STATE_NEGOTIATING && - con->state != CON_STATE_OPEN); - -From 48e858340dae43189a4e55647f6eac736766f828 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Mon, 7 Jan 2013 10:27:13 +0100 -Subject: Revert "drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13" - -From: Daniel Vetter - -commit 48e858340dae43189a4e55647f6eac736766f828 upstream. - -This reverts commit 9756fe38d10b2bf90c81dc4d2f17d5632e135364. - -The bogus lvds output is actually a lvds->hdmi bridge, which we don't -really support. But unconditionally disabling it breaks some existing -setups. - -Reported-by: John Tapsell -References: http://permalink.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/17237 -Signed-off-by: Daniel Vetter -Cc: Luis Henriques -Signed-off-by: Greg Kroah-Hartman - - ---- - drivers/gpu/drm/i915/intel_lvds.c | 8 -------- - 1 file changed, 8 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -763,14 +763,6 @@ static const struct dmi_system_id intel_ - }, - { - .callback = intel_no_lvds_dmi_callback, -- .ident = "ZOTAC ZBOXSD-ID12/ID13", -- .matches = { -- DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), -- DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), -- }, -- }, -- { -- .callback = intel_no_lvds_dmi_callback, - .ident = "Gigabyte GA-D525TUD", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), -From f10a18433a1b3192e71eecffeaeca5f5f1694016 Mon Sep 17 00:00:00 2001 -From: Sage Weil -Date: Thu, 27 Dec 2012 20:27:04 -0600 -Subject: libceph: fix protocol feature mismatch failure path - - -From: Sage Weil - -(cherry picked from commit 0fa6ebc600bc8e830551aee47a0e929e818a1868) - -We should not set con->state to CLOSED here; that happens in -ceph_fault() in the caller, where it first asserts that the state -is not yet CLOSED. Avoids a BUG when the features don't match. - -Since the fail_protocol() has become a trivial wrapper, replace -calls to it with direct calls to reset_connection(). - -Signed-off-by: Sage Weil -Reviewed-by: Alex Elder -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/messenger.c | 14 ++++---------- - 1 file changed, 4 insertions(+), 10 deletions(-) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -506,6 +506,7 @@ static void reset_connection(struct ceph - { - /* reset connection, out_queue, msg_ and connect_seq */ - /* discard existing out_queue and msg_seq */ -+ dout("reset_connection %p\n", con); - ceph_msg_remove_list(&con->out_queue); - ceph_msg_remove_list(&con->out_sent); - -@@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_co - return 0; - } - --static void fail_protocol(struct ceph_connection *con) --{ -- reset_connection(con); -- WARN_ON(con->state != CON_STATE_NEGOTIATING); -- con->state = CON_STATE_CLOSED; --} -- - static int process_connect(struct ceph_connection *con) - { - u64 sup_feat = con->msgr->supported_features; -@@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_c - ceph_pr_addr(&con->peer_addr.in_addr), - sup_feat, server_feat, server_feat & ~sup_feat); - con->error_msg = "missing required protocol features"; -- fail_protocol(con); -+ reset_connection(con); - return -1; - - case CEPH_MSGR_TAG_BADPROTOVER: -@@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_c - le32_to_cpu(con->out_connect.protocol_version), - le32_to_cpu(con->in_reply.protocol_version)); - con->error_msg = "protocol version mismatch"; -- fail_protocol(con); -+ reset_connection(con); - return -1; - - case CEPH_MSGR_TAG_BADAUTHORIZER: -@@ -1631,7 +1625,7 @@ static int process_connect(struct ceph_c - ceph_pr_addr(&con->peer_addr.in_addr), - req_feat, server_feat, req_feat & ~server_feat); - con->error_msg = "missing required protocol features"; -- fail_protocol(con); -+ reset_connection(con); - return -1; - } - -From 71630f053c8da3b7d8e52c99ff2592f44dd28979 Mon Sep 17 00:00:00 2001 -From: Sage Weil -Date: Mon, 29 Oct 2012 11:01:42 -0700 -Subject: libceph: fix osdmap decode error paths - - -From: Sage Weil - -(cherry picked from commit 0ed7285e0001b960c888e5455ae982025210ed3d) - -Ensure that we set the err value correctly so that we do not pass a 0 -value to ERR_PTR and confuse the calling code. (In particular, -osd_client.c handle_map() will BUG(!newmap)). - -Signed-off-by: Sage Weil -Reviewed-by: Alex Elder -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osdmap.c | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) - ---- a/net/ceph/osdmap.c -+++ b/net/ceph/osdmap.c -@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void * - ceph_decode_32_safe(p, end, max, bad); - while (max--) { - ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); -+ err = -ENOMEM; - pi = kzalloc(sizeof(*pi), GFP_NOFS); - if (!pi) - goto bad; - pi->id = ceph_decode_32(p); -+ err = -EINVAL; - ev = ceph_decode_8(p); /* encoding version */ - if (ev > CEPH_PG_POOL_VERSION) { - pr_warning("got unknown v %d > %d of ceph_pg_pool\n", -@@ -664,8 +666,13 @@ struct ceph_osdmap *osdmap_decode(void * - __insert_pg_pool(&map->pg_pools, pi); - } - -- if (version >= 5 && __decode_pool_names(p, end, map) < 0) -- goto bad; -+ if (version >= 5) { -+ err = __decode_pool_names(p, end, map); -+ if (err < 0) { -+ dout("fail to decode pool names"); -+ goto bad; -+ } -+ } - - ceph_decode_32_safe(p, end, map->pool_max, bad); - -@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void * - return map; - - bad: -- dout("osdmap_decode fail\n"); -+ dout("osdmap_decode fail err %d\n", err); - ceph_osdmap_destroy(map); - return ERR_PTR(err); - } -@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_increme - if (ev > CEPH_PG_POOL_VERSION) { - pr_warning("got unknown v %d > %d of ceph_pg_pool\n", - ev, CEPH_PG_POOL_VERSION); -+ err = -EINVAL; - goto bad; - } - pi = __lookup_pg_pool(&map->pg_pools, pool); -@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_increme - if (err < 0) - goto bad; - } -- if (version >= 5 && __decode_pool_names(p, end, map) < 0) -- goto bad; -+ if (version >= 5) { -+ err = __decode_pool_names(p, end, map); -+ if (err < 0) -+ goto bad; -+ } - - /* old_pool */ - ceph_decode_32_safe(p, end, len, bad); -@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_increme - (void) __remove_pg_mapping(&map->pg_temp, pgid); - - /* insert */ -- if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { -- err = -EINVAL; -+ err = -EINVAL; -+ if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) - goto bad; -- } -+ err = -ENOMEM; - pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); -- if (!pg) { -- err = -ENOMEM; -+ if (!pg) - goto bad; -- } - pg->pgid = pgid; - pg->len = pglen; - for (j = 0; j < pglen; j++) -From f4a3fea610cb6a9fc9cb722a0765194e19b82e7b Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Fri, 7 Dec 2012 09:57:58 -0600 -Subject: libceph: avoid using freed osd in __kick_osd_requests() - - -From: Alex Elder - -(cherry picked from commit 685a7555ca69030739ddb57a47f0ea8ea80196a4) - -If an osd has no requests and no linger requests, __reset_osd() -will just remove it with a call to __remove_osd(). That drops -a reference to the osd, and therefore the osd may have been free -by the time __reset_osd() returns. That function offers no -indication this may have occurred, and as a result the osd will -continue to be used even when it's no longer valid. - -Change__reset_osd() so it returns an error (ENODEV) when it -deletes the osd being reset. And change __kick_osd_requests() so it -returns immediately (before referencing osd again) if __reset_osd() -returns *any* error. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -581,7 +581,7 @@ static void __kick_osd_requests(struct c - - dout("__kick_osd_requests osd%d\n", osd->o_osd); - err = __reset_osd(osdc, osd); -- if (err == -EAGAIN) -+ if (err) - return; - - list_for_each_entry(req, &osd->o_requests, r_osd_item) { -@@ -752,6 +752,7 @@ static int __reset_osd(struct ceph_osd_c - if (list_empty(&osd->o_requests) && - list_empty(&osd->o_linger_requests)) { - __remove_osd(osdc, osd); -+ ret = -ENODEV; - } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], - &osd->o_con.peer_addr, - sizeof(osd->o_con.peer_addr)) == 0 && -From aa852ff17166b53b1d29388af472bb9c32297f05 Mon Sep 17 00:00:00 2001 -From: Sage Weil -Date: Wed, 28 Nov 2012 12:28:24 -0800 -Subject: libceph: remove 'osdtimeout' option - - -From: Sage Weil - -(cherry picked from commit 83aff95eb9d60aff5497e9f44a2ae906b86d8e88) - -This would reset a connection with any OSD that had an outstanding -request that was taking more than N seconds. The idea was that if the -OSD was buggy, the client could compensate by resending the request. - -In reality, this only served to hide server bugs, and we haven't -actually seen such a bug in quite a while. Moreover, the userspace -client code never did this. - -More importantly, often the request is taking a long time because the -OSD is trying to recover, or overloaded, and killing the connection -and retrying would only make the situation worse by giving the OSD -more work to do. - -Signed-off-by: Sage Weil -Reviewed-by: Alex Elder -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/super.c | 2 - - include/linux/ceph/libceph.h | 2 - - net/ceph/ceph_common.c | 3 -- - net/ceph/osd_client.c | 47 +++---------------------------------------- - 4 files changed, 5 insertions(+), 49 deletions(-) - ---- a/fs/ceph/super.c -+++ b/fs/ceph/super.c -@@ -403,8 +403,6 @@ static int ceph_show_options(struct seq_ - seq_printf(m, ",mount_timeout=%d", opt->mount_timeout); - if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) - seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl); -- if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT) -- seq_printf(m, ",osdtimeout=%d", opt->osd_timeout); - if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) - seq_printf(m, ",osdkeepalivetimeout=%d", - opt->osd_keepalive_timeout); ---- a/include/linux/ceph/libceph.h -+++ b/include/linux/ceph/libceph.h -@@ -43,7 +43,6 @@ struct ceph_options { - struct ceph_entity_addr my_addr; - int mount_timeout; - int osd_idle_ttl; -- int osd_timeout; - int osd_keepalive_timeout; - - /* -@@ -63,7 +62,6 @@ struct ceph_options { - * defaults - */ - #define CEPH_MOUNT_TIMEOUT_DEFAULT 60 --#define CEPH_OSD_TIMEOUT_DEFAULT 60 /* seconds */ - #define CEPH_OSD_KEEPALIVE_DEFAULT 5 - #define CEPH_OSD_IDLE_TTL_DEFAULT 60 - ---- a/net/ceph/ceph_common.c -+++ b/net/ceph/ceph_common.c -@@ -305,7 +305,6 @@ ceph_parse_options(char *options, const - - /* start with defaults */ - opt->flags = CEPH_OPT_DEFAULT; -- opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; - opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; - opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ - opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ -@@ -391,7 +390,7 @@ ceph_parse_options(char *options, const - - /* misc */ - case Opt_osdtimeout: -- opt->osd_timeout = intval; -+ pr_warning("ignoring deprecated osdtimeout option\n"); - break; - case Opt_osdkeepalivetimeout: - opt->osd_keepalive_timeout = intval; ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -608,14 +608,6 @@ static void __kick_osd_requests(struct c - } - } - --static void kick_osd_requests(struct ceph_osd_client *osdc, -- struct ceph_osd *kickosd) --{ -- mutex_lock(&osdc->request_mutex); -- __kick_osd_requests(osdc, kickosd); -- mutex_unlock(&osdc->request_mutex); --} -- - /* - * If the osd connection drops, we need to resubmit all requests. - */ -@@ -629,7 +621,9 @@ static void osd_reset(struct ceph_connec - dout("osd_reset osd%d\n", osd->o_osd); - osdc = osd->o_osdc; - down_read(&osdc->map_sem); -- kick_osd_requests(osdc, osd); -+ mutex_lock(&osdc->request_mutex); -+ __kick_osd_requests(osdc, osd); -+ mutex_unlock(&osdc->request_mutex); - send_queued(osdc); - up_read(&osdc->map_sem); - } -@@ -1093,12 +1087,10 @@ static void handle_timeout(struct work_s - { - struct ceph_osd_client *osdc = - container_of(work, struct ceph_osd_client, timeout_work.work); -- struct ceph_osd_request *req, *last_req = NULL; -+ struct ceph_osd_request *req; - struct ceph_osd *osd; -- unsigned long timeout = osdc->client->options->osd_timeout * HZ; - unsigned long keepalive = - osdc->client->options->osd_keepalive_timeout * HZ; -- unsigned long last_stamp = 0; - struct list_head slow_osds; - dout("timeout\n"); - down_read(&osdc->map_sem); -@@ -1108,37 +1100,6 @@ static void handle_timeout(struct work_s - mutex_lock(&osdc->request_mutex); - - /* -- * reset osds that appear to be _really_ unresponsive. this -- * is a failsafe measure.. we really shouldn't be getting to -- * this point if the system is working properly. the monitors -- * should mark the osd as failed and we should find out about -- * it from an updated osd map. -- */ -- while (timeout && !list_empty(&osdc->req_lru)) { -- req = list_entry(osdc->req_lru.next, struct ceph_osd_request, -- r_req_lru_item); -- -- /* hasn't been long enough since we sent it? */ -- if (time_before(jiffies, req->r_stamp + timeout)) -- break; -- -- /* hasn't been long enough since it was acked? */ -- if (req->r_request->ack_stamp == 0 || -- time_before(jiffies, req->r_request->ack_stamp + timeout)) -- break; -- -- BUG_ON(req == last_req && req->r_stamp == last_stamp); -- last_req = req; -- last_stamp = req->r_stamp; -- -- osd = req->r_osd; -- BUG_ON(!osd); -- pr_warning(" tid %llu timed out on osd%d, will reset osd\n", -- req->r_tid, osd->o_osd); -- __kick_osd_requests(osdc, osd); -- } -- -- /* - * ping osds that are a bit slow. this ensures that if there - * is a break in the TCP connection we will notice, and reopen - * a connection with that osd (from the fault callback). -From a6bbcd6741d53b326a2a3a7edef6e15334de6ea3 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Thu, 29 Nov 2012 08:37:03 -0600 -Subject: ceph: don't reference req after put - - -From: Alex Elder - -(cherry picked from commit 7d5f24812bd182a2471cb69c1c2baf0648332e1f) - -In __unregister_request(), there is a call to list_del_init() -referencing a request that was the subject of a call to -ceph_osdc_put_request() on the previous line. This is not -safe, because the request structure could have been freed -by the time we reach the list_del_init(). - -Fix this by reversing the order of these lines. - -Signed-off-by: Alex Elder -Reviewed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -873,9 +873,9 @@ static void __unregister_request(struct - req->r_osd = NULL; - } - -+ list_del_init(&req->r_req_lru_item); - ceph_osdc_put_request(req); - -- list_del_init(&req->r_req_lru_item); - if (osdc->num_requests == 0) { - dout(" no requests, canceling timeout\n"); - __cancel_osd_timeout(osdc); -From 8824d0eb9dee3bad29e9dba796d5d7953cab6719 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Wed, 10 Oct 2012 21:19:13 -0700 -Subject: rbd: fix bug in rbd_dev_id_put() - - -From: Alex Elder - -(cherry picked from commit b213e0b1a62637b2a9395a34349b13d73ca2b90a) - -In rbd_dev_id_put(), there's a loop that's intended to determine -the maximum device id in use. But it isn't doing that at all, -the effect of how it's written is to simply use the just-put id -number, which ignores whole purpose of this function. - -Fix the bug. - -Signed-off-by: Alex Elder -Reviewed-by: Josh Durgin -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -2621,8 +2621,8 @@ static void rbd_dev_id_put(struct rbd_de - struct rbd_device *rbd_dev; - - rbd_dev = list_entry(tmp, struct rbd_device, node); -- if (rbd_id > max_id) -- max_id = rbd_id; -+ if (rbd_dev->dev_id > max_id) -+ max_id = rbd_dev->dev_id; - } - spin_unlock(&rbd_dev_list_lock); - -From cc8b5fcd343b3c99468fc9f0b4c3e03a7eafa7fc Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Wed, 10 Oct 2012 21:19:13 -0700 -Subject: rbd: zero return code in rbd_dev_image_id() - - -From: Alex Elder - -(cherry picked from commit a0ea3a40fd20b8c66381f747c454f89d6d1f50d4) - -When rbd_dev_probe() calls rbd_dev_image_id() it expects to get -a 0 return code if successful, but it is getting a positive value. - -The reason is that rbd_dev_image_id() returns the value it gets from -rbd_req_sync_exec(), which returns the number of bytes read in as a -result of the request. (This ultimately comes from -ceph_copy_from_page_vector() in rbd_req_sync_op()). - -Force the return value to 0 when successful in rbd_dev_image_id(). -Do the same in rbd_dev_v2_object_prefix(). - -Signed-off-by: Alex Elder -Reviewed-by: Josh Durgin -Reviewed-by: Dan Mick -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -2189,6 +2189,7 @@ static int rbd_dev_v2_object_prefix(stru - dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); - if (ret < 0) - goto out; -+ ret = 0; /* rbd_req_sync_exec() can return positive */ - - p = reply_buf; - rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, -@@ -2841,6 +2842,7 @@ static int rbd_dev_image_id(struct rbd_d - dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); - if (ret < 0) - goto out; -+ ret = 0; /* rbd_req_sync_exec() can return positive */ - - p = response; - rbd_dev->image_id = ceph_extract_encoded_string(&p, -From 9aca7b487cf1c996a13ff5abf0ea4ac560ea1dd4 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Mon, 22 Oct 2012 11:31:26 -0500 -Subject: rbd: fix read-only option name - - -From: Alex Elder - -(cherry picked from commit be466c1cc36621590ef17b05a6d342dfd33f7280) - -The name of the "read-only" mapping option was inadvertently changed -in this commit: - - f84344f3 rbd: separate mapping info in rbd_dev - -Revert that hunk to return it to what it should be. - -Signed-off-by: Alex Elder -Reviewed-by: Dan Mick -Reviewed-by: Josh Durgin -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -388,7 +388,7 @@ enum { - static match_table_t rbd_opts_tokens = { - /* int args above */ - /* string args above */ -- {Opt_read_only, "mapping.read_only"}, -+ {Opt_read_only, "read_only"}, - {Opt_read_only, "ro"}, /* Alternate spelling */ - {Opt_read_write, "read_write"}, - {Opt_read_write, "rw"}, /* Alternate spelling */ -From 1306be442fda1b7a92b879ab18a535f56da5ab0a Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Tue, 3 Jul 2012 16:01:19 -0500 -Subject: rbd: increase maximum snapshot name length - - -From: Alex Elder - -(cherry picked from commit d4b125e9eb43babd14538ba61718e3db71a98d29) - -Change RBD_MAX_SNAP_NAME_LEN to be based on NAME_MAX. That is a -practical limit for the length of a snapshot name (based on the -presence of a directory using the name under /sys/bus/rbd to -represent the snapshot). - -The /sys entry is created by prefixing it with "snap_"; define that -prefix symbolically, and take its length into account in defining -the snapshot name length limit. - -Enforce the limit in rbd_add_parse_args(). Also delete a dout() -call in that function that was not meant to be committed. - -Signed-off-by: Alex Elder -Reviewed-by: Dan Mick -Reviewed-by: Josh Durgin -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -61,7 +61,10 @@ - - #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ - --#define RBD_MAX_SNAP_NAME_LEN 32 -+#define RBD_SNAP_DEV_NAME_PREFIX "snap_" -+#define RBD_MAX_SNAP_NAME_LEN \ -+ (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) -+ - #define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */ - #define RBD_MAX_OPT_LEN 1024 - -@@ -2073,7 +2076,7 @@ static int rbd_register_snap_dev(struct - dev->type = &rbd_snap_device_type; - dev->parent = parent; - dev->release = rbd_snap_dev_release; -- dev_set_name(dev, "snap_%s", snap->name); -+ dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name); - dout("%s: registering device for snapshot %s\n", __func__, snap->name); - - ret = device_register(dev); -@@ -2766,8 +2769,13 @@ static char *rbd_add_parse_args(struct r - if (!rbd_dev->image_name) - goto out_err; - -- /* Snapshot name is optional */ -+ /* Snapshot name is optional; default is to use "head" */ -+ - len = next_token(&buf); -+ if (len > RBD_MAX_SNAP_NAME_LEN) { -+ err_ptr = ERR_PTR(-ENAMETOOLONG); -+ goto out_err; -+ } - if (!len) { - buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */ - len = sizeof (RBD_SNAP_HEAD_NAME) - 1; -@@ -2778,8 +2786,6 @@ static char *rbd_add_parse_args(struct r - memcpy(snap_name, buf, len); - *(snap_name + len) = '\0'; - --dout(" SNAP_NAME is <%s>, len is %zd\n", snap_name, len); -- - return snap_name; - - out_err: -From 21bc037520c252304c04d3bb8131fb3d4ba5b2c5 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Thu, 25 Oct 2012 23:34:40 -0500 -Subject: rbd: remove snapshots on error in rbd_add() - - -From: Alex Elder - -(cherry picked from commit 41f38c2b2f8b66b176a0e548ef06294343a7bfa2) - -If rbd_dev_snaps_update() has ever been called for an rbd device -structure there could be snapshot structures on its snaps list. -In rbd_add(), this function is called but a subsequent error -path neglected to clean up any of these snapshots. - -Add a call to rbd_remove_all_snaps() in the appropriate spot to -remedy this. Change a couple of error labels to be a little -clearer while there. - -Drop the leading underscores from the function name; there's nothing -special about that function that they might signify. As suggested -in review, the leading underscores in __rbd_remove_snap_dev() have -been removed as well. - -Signed-off-by: Alex Elder -Reviewed-by: Josh Durgin -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 20 +++++++++++--------- - 1 file changed, 11 insertions(+), 9 deletions(-) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -221,7 +221,7 @@ static int rbd_dev_snaps_update(struct r - static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); - - static void rbd_dev_release(struct device *dev); --static void __rbd_remove_snap_dev(struct rbd_snap *snap); -+static void rbd_remove_snap_dev(struct rbd_snap *snap); - - static ssize_t rbd_add(struct bus_type *bus, const char *buf, - size_t count); -@@ -1710,13 +1710,13 @@ static int rbd_read_header(struct rbd_de - return ret; - } - --static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) -+static void rbd_remove_all_snaps(struct rbd_device *rbd_dev) - { - struct rbd_snap *snap; - struct rbd_snap *next; - - list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) -- __rbd_remove_snap_dev(snap); -+ rbd_remove_snap_dev(snap); - } - - /* -@@ -2060,7 +2060,7 @@ static bool rbd_snap_registered(struct r - return ret; - } - --static void __rbd_remove_snap_dev(struct rbd_snap *snap) -+static void rbd_remove_snap_dev(struct rbd_snap *snap) - { - list_del(&snap->node); - if (device_is_registered(&snap->dev)) -@@ -2442,7 +2442,7 @@ static int rbd_dev_snaps_update(struct r - - if (rbd_dev->mapping.snap_id == snap->id) - rbd_dev->mapping.snap_exists = false; -- __rbd_remove_snap_dev(snap); -+ rbd_remove_snap_dev(snap); - dout("%ssnap id %llu has been removed\n", - rbd_dev->mapping.snap_id == snap->id ? - "mapped " : "", -@@ -3053,11 +3053,11 @@ static ssize_t rbd_add(struct bus_type * - /* no need to lock here, as rbd_dev is not registered yet */ - rc = rbd_dev_snaps_update(rbd_dev); - if (rc) -- goto err_out_header; -+ goto err_out_probe; - - rc = rbd_dev_set_mapping(rbd_dev, snap_name); - if (rc) -- goto err_out_header; -+ goto err_out_snaps; - - /* generate unique id: find highest unique id, add one */ - rbd_dev_id_get(rbd_dev); -@@ -3121,7 +3121,9 @@ err_out_blkdev: - unregister_blkdev(rbd_dev->major, rbd_dev->name); - err_out_id: - rbd_dev_id_put(rbd_dev); --err_out_header: -+err_out_snaps: -+ rbd_remove_all_snaps(rbd_dev); -+err_out_probe: - rbd_header_free(&rbd_dev->header); - err_out_client: - kfree(rbd_dev->header_name); -@@ -3219,7 +3221,7 @@ static ssize_t rbd_remove(struct bus_typ - goto done; - } - -- __rbd_remove_all_snaps(rbd_dev); -+ rbd_remove_all_snaps(rbd_dev); - rbd_bus_del_dev(rbd_dev); - - done: -From 730406993ec6d044a81115fc19091ba6abfcbb15 Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Fri, 16 Nov 2012 09:29:16 -0600 -Subject: rbd: do not allow remove of mounted-on image - - -From: Alex Elder - -(cherry picked from commit 42382b709bd1d143b9f0fa93e0a3a1f2f4210707) - -There is no check in rbd_remove() to see if anybody holds open the -image being removed. That's not cool. - -Add a simple open count that goes up and down with opens and closes -(releases) of the device, and don't allow an rbd image to be removed -if the count is non-zero. - -Protect the updates of the open count value with ctl_mutex to ensure -the underlying rbd device doesn't get removed while concurrently -being opened. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -207,6 +207,7 @@ struct rbd_device { - - /* sysfs related */ - struct device dev; -+ unsigned long open_count; - }; - - static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ -@@ -280,8 +281,11 @@ static int rbd_open(struct block_device - if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only) - return -EROFS; - -+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - rbd_get_dev(rbd_dev); - set_device_ro(bdev, rbd_dev->mapping.read_only); -+ rbd_dev->open_count++; -+ mutex_unlock(&ctl_mutex); - - return 0; - } -@@ -290,7 +294,11 @@ static int rbd_release(struct gendisk *d - { - struct rbd_device *rbd_dev = disk->private_data; - -+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); -+ rbd_assert(rbd_dev->open_count > 0); -+ rbd_dev->open_count--; - rbd_put_dev(rbd_dev); -+ mutex_unlock(&ctl_mutex); - - return 0; - } -@@ -3221,6 +3229,11 @@ static ssize_t rbd_remove(struct bus_typ - goto done; - } - -+ if (rbd_dev->open_count) { -+ ret = -EBUSY; -+ goto done; -+ } -+ - rbd_remove_all_snaps(rbd_dev); - rbd_bus_del_dev(rbd_dev); - -From 965f03ad3d796d03ec16f9809cb0096a64f6523d Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Fri, 9 Nov 2012 15:05:54 -0600 -Subject: rbd: get rid of RBD_MAX_SEG_NAME_LEN - - -From: Alex Elder - -(cherry picked from commit 2fd82b9e92c2a718ae81fc987b4468ceeee6979b) - -RBD_MAX_SEG_NAME_LEN represents the maximum length of an rbd object -name (i.e., one of the objects providing storage backing an rbd -image). - -Another symbol, MAX_OBJ_NAME_SIZE, is used in the osd client code to -define the maximum length of any object name in an osd request. - -Right now they disagree, with RBD_MAX_SEG_NAME_LEN being too big. - -There's no real benefit at this point to defining the rbd object -name length limit separate from any other object name, so just -get rid of RBD_MAX_SEG_NAME_LEN and use MAX_OBJ_NAME_SIZE in its -place. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - drivers/block/rbd.c | 6 +++--- - drivers/block/rbd_types.h | 2 -- - 2 files changed, 3 insertions(+), 5 deletions(-) - ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -706,13 +706,13 @@ static char *rbd_segment_name(struct rbd - u64 segment; - int ret; - -- name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); -+ name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO); - if (!name) - return NULL; - segment = offset >> rbd_dev->header.obj_order; -- ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx", -+ ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx", - rbd_dev->header.object_prefix, segment); -- if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) { -+ if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { - pr_err("error formatting segment name for #%llu (%d)\n", - segment, ret); - kfree(name); ---- a/drivers/block/rbd_types.h -+++ b/drivers/block/rbd_types.h -@@ -46,8 +46,6 @@ - #define RBD_MIN_OBJ_ORDER 16 - #define RBD_MAX_OBJ_ORDER 30 - --#define RBD_MAX_SEG_NAME_LEN 128 -- - #define RBD_COMP_NONE 0 - #define RBD_CRYPT_NONE 0 - -From 942784e7a6e2ef8f861043f65b054eb3ef10b2fd Mon Sep 17 00:00:00 2001 -From: Alex Elder -Date: Thu, 6 Dec 2012 09:37:23 -0600 -Subject: rbd: remove linger unconditionally - - -From: Alex Elder - -(cherry picked from commit 61c74035626beb25a39b0273ccf7d75510bc36a1) - -In __unregister_linger_request(), the request is being removed -from the osd client's req_linger list only when the request -has a non-null osd pointer. It should be done whether or not -the request currently has an osd. - -This is most likely a non-issue because I believe the request -will always have an osd when this function is called. - -Signed-off-by: Alex Elder -Reviewed-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - net/ceph/osd_client.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/ceph/osd_client.c -+++ b/net/ceph/osd_client.c -@@ -907,8 +907,8 @@ static void __unregister_linger_request( - struct ceph_osd_request *req) - { - dout("__unregister_linger_request %p\n", req); -+ list_del_init(&req->r_linger_item); - if (req->r_osd) { -- list_del_init(&req->r_linger_item); - list_del_init(&req->r_linger_osd); - - if (list_empty(&req->r_osd->o_requests) && -From 76c834d784c36bda3a8d56f5cdf3e1282b0979f9 Mon Sep 17 00:00:00 2001 -From: "Yan, Zheng" -Date: Mon, 19 Nov 2012 10:49:04 +0800 -Subject: ceph: Don't update i_max_size when handling non-auth cap - - -From: "Yan, Zheng" - -(cherry picked from commit 5e62ad30157d0da04cf40c6d1a2f4bc840948b9c) - -The cap from non-auth mds doesn't have a meaningful max_size value. - -Signed-off-by: Yan, Zheng -Signed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/caps.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/ceph/caps.c -+++ b/fs/ceph/caps.c -@@ -2388,7 +2388,7 @@ static void handle_cap_grant(struct inod - &atime); - - /* max size increase? */ -- if (max_size != ci->i_max_size) { -+ if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { - dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); - ci->i_max_size = max_size; - if (max_size >= ci->i_wanted_max_size) { -From 0fd2af5e838e87cf449c657b6e19535b64da6c4c Mon Sep 17 00:00:00 2001 -From: "Yan, Zheng" -Date: Mon, 19 Nov 2012 10:49:06 +0800 -Subject: ceph: Fix infinite loop in __wake_requests - - -From: "Yan, Zheng" - -(cherry picked from commit ed75ec2cd19b47efcd292b6e23f58e56f4c5bc34) - -__wake_requests() will enter infinite loop if we use it to wake -requests in the session->s_waiting list. __wake_requests() deletes -requests from the list and __do_request() adds requests back to -the list. - -Signed-off-by: Yan, Zheng -Signed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/mds_client.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/fs/ceph/mds_client.c -+++ b/fs/ceph/mds_client.c -@@ -1876,9 +1876,14 @@ finish: - static void __wake_requests(struct ceph_mds_client *mdsc, - struct list_head *head) - { -- struct ceph_mds_request *req, *nreq; -+ struct ceph_mds_request *req; -+ LIST_HEAD(tmp_list); - -- list_for_each_entry_safe(req, nreq, head, r_wait) { -+ list_splice_init(head, &tmp_list); -+ -+ while (!list_empty(&tmp_list)) { -+ req = list_entry(tmp_list.next, -+ struct ceph_mds_request, r_wait); - list_del_init(&req->r_wait); - __do_request(mdsc, req); - } -From f409f158fb190ab9915fd94dce367e462a0c02f6 Mon Sep 17 00:00:00 2001 -From: "Yan, Zheng" -Date: Mon, 19 Nov 2012 10:49:07 +0800 -Subject: ceph: Don't add dirty inode to dirty list if caps is in migration - - -From: "Yan, Zheng" - -(cherry picked from commit 0685235ffd9dbdb9ccbda587f8a3c83ad1d5a921) - -Add dirty inode to cap_dirty_migrating list instead, this can avoid -ceph_flush_dirty_caps() entering infinite loop. - -Signed-off-by: Yan, Zheng -Signed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/caps.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - ---- a/fs/ceph/caps.c -+++ b/fs/ceph/caps.c -@@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_i - if (!ci->i_head_snapc) - ci->i_head_snapc = ceph_get_snap_context( - ci->i_snap_realm->cached_context); -- dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode, -- ci->i_head_snapc); -+ dout(" inode %p now dirty snapc %p auth cap %p\n", -+ &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); - BUG_ON(!list_empty(&ci->i_dirty_item)); - spin_lock(&mdsc->cap_dirty_lock); -- list_add(&ci->i_dirty_item, &mdsc->cap_dirty); -+ if (ci->i_auth_cap) -+ list_add(&ci->i_dirty_item, &mdsc->cap_dirty); -+ else -+ list_add(&ci->i_dirty_item, -+ &mdsc->cap_dirty_migrating); - spin_unlock(&mdsc->cap_dirty_lock); - if (ci->i_flushing_caps == 0) { - ihold(inode); -From 0e6789acaba2e40768a778a1e553c92723a19a30 Mon Sep 17 00:00:00 2001 -From: "Yan, Zheng" -Date: Mon, 19 Nov 2012 10:49:08 +0800 -Subject: ceph: Fix __ceph_do_pending_vmtruncate - - -From: "Yan, Zheng" - -(cherry picked from commit a85f50b6ef93fbbb2ae932ce9b2376509d172796) - -we should set i_truncate_pending to 0 after page cache is truncated -to i_truncate_size - -Signed-off-by: Yan, Zheng -Signed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/inode.c | 15 +++++++++------ - 1 file changed, 9 insertions(+), 6 deletions(-) - ---- a/fs/ceph/inode.c -+++ b/fs/ceph/inode.c -@@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct - { - struct ceph_inode_info *ci = ceph_inode(inode); - u64 to; -- int wrbuffer_refs, wake = 0; -+ int wrbuffer_refs, finish = 0; - - retry: - spin_lock(&ci->i_ceph_lock); -@@ -1498,15 +1498,18 @@ retry: - truncate_inode_pages(inode->i_mapping, to); - - spin_lock(&ci->i_ceph_lock); -- ci->i_truncate_pending--; -- if (ci->i_truncate_pending == 0) -- wake = 1; -+ if (to == ci->i_truncate_size) { -+ ci->i_truncate_pending = 0; -+ finish = 1; -+ } - spin_unlock(&ci->i_ceph_lock); -+ if (!finish) -+ goto retry; - - if (wrbuffer_refs == 0) - ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); -- if (wake) -- wake_up_all(&ci->i_cap_wq); -+ -+ wake_up_all(&ci->i_cap_wq); - } - - -From 0747d15ddb5eac0e83376e2722e3654ae01d252f Mon Sep 17 00:00:00 2001 -From: "Yan, Zheng" -Date: Mon, 19 Nov 2012 10:49:09 +0800 -Subject: ceph: call handle_cap_grant() for cap import message - - -From: "Yan, Zheng" - -(cherry picked from commit 0e5e1774a92e6fe9c511585de8f078b4c4c68dbb) - -If client sends cap message that requests new max size during -exporting caps, the exporting MDS will drop the message quietly. -So the client may wait for the reply that updates the max size -forever. call handle_cap_grant() for cap import message can -avoid this issue. - -Signed-off-by: Yan, Zheng -Signed-off-by: Sage Weil -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/caps.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/fs/ceph/caps.c -+++ b/fs/ceph/caps.c -@@ -2749,6 +2749,7 @@ static void handle_cap_import(struct cep - - /* make sure we re-request max_size, if necessary */ - spin_lock(&ci->i_ceph_lock); -+ ci->i_wanted_max_size = 0; /* reset */ - ci->i_requested_max_size = 0; - spin_unlock(&ci->i_ceph_lock); - } -@@ -2844,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_se - case CEPH_CAP_OP_IMPORT: - handle_cap_import(mdsc, inode, h, session, - snaptrace, snaptrace_len); -- ceph_check_caps(ceph_inode(inode), 0, session); -- goto done_unlocked; - } - - /* the rest require a cap */ -@@ -2862,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_se - switch (op) { - case CEPH_CAP_OP_REVOKE: - case CEPH_CAP_OP_GRANT: -+ case CEPH_CAP_OP_IMPORT: - handle_cap_grant(inode, h, session, cap, msg->middle); - goto done_unlocked; - -From 9fa5ba96f32fbea354457fc7ece06b2ee81b1b71 Mon Sep 17 00:00:00 2001 -From: David Zafman -Date: Mon, 3 Dec 2012 19:14:05 -0800 -Subject: libceph: Unlock unprocessed pages in start_read() error path - - -From: David Zafman - -(cherry picked from commit 8884d53dd63b1d9315b343564fcbe1ede004a99e) - -Function start_read() can get an error before processing all pages. -It must not only release the remaining pages, but unlock them too. - -This fixes http://tracker.newdream.net/issues/3370 - -Signed-off-by: David Zafman -Reviewed-by: Alex Elder -Signed-off-by: Greg Kroah-Hartman ---- - fs/ceph/addr.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/fs/ceph/addr.c -+++ b/fs/ceph/addr.c -@@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_ - kfree(req->r_pages); - } - -+static void ceph_unlock_page_vector(struct page **pages, int num_pages) -+{ -+ int i; -+ -+ for (i = 0; i < num_pages; i++) -+ unlock_page(pages[i]); -+} -+ - /* - * start an async read(ahead) operation. return nr_pages we submitted - * a read for on success, or negative error code. -@@ -347,6 +355,7 @@ static int start_read(struct inode *inod - return nr_pages; - - out_pages: -+ ceph_unlock_page_vector(pages, nr_pages); - ceph_release_page_vector(pages, nr_pages); - out: - ceph_osdc_put_request(req); -From 45e2b5f640b3766da3eda48f6c35f088155c06f3 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Fri, 23 Nov 2012 18:16:34 +0100 -Subject: drm/i915: force restore on lid open - -From: Daniel Vetter - -commit 45e2b5f640b3766da3eda48f6c35f088155c06f3 upstream. - -There seem to be indeed some awkwards machines around, mostly those -without OpRegion support, where the firmware changes the display hw -state behind our backs when closing the lid. - -This force-restore logic has been originally introduced in - -commit c1c7af60892070e4b82ad63bbfb95ae745056de0 -Author: Jesse Barnes -Date: Thu Sep 10 15:28:03 2009 -0700 - - drm/i915: force mode set at lid open time - -but after the modeset-rework we've disabled it in the vain hope that -it's no longer required: - -commit 3b7a89fce3e3dc96b549d6d829387b4439044d0d -Author: Daniel Vetter -Date: Mon Sep 17 22:27:21 2012 +0200 - - drm/i915: fix OOPS in lid_notify - -Alas, no. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54677 -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 -Tested-by: Krzysztof Mazur -Reviewed-by: Jesse Barnes -Signed-off-by: Daniel Vetter -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_drv.c | 2 +- - drivers/gpu/drm/i915/i915_drv.h | 3 ++- - drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++--- - drivers/gpu/drm/i915/intel_lvds.c | 2 +- - 4 files changed, 16 insertions(+), 6 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -552,7 +552,7 @@ static int i915_drm_thaw(struct drm_devi - mutex_unlock(&dev->struct_mutex); - - intel_modeset_init_hw(dev); -- intel_modeset_setup_hw_state(dev); -+ intel_modeset_setup_hw_state(dev, false); - drm_mode_config_reset(dev); - drm_irq_install(dev); - } ---- a/drivers/gpu/drm/i915/i915_drv.h -+++ b/drivers/gpu/drm/i915/i915_drv.h -@@ -1595,7 +1595,8 @@ extern void intel_modeset_init(struct dr - extern void intel_modeset_gem_init(struct drm_device *dev); - extern void intel_modeset_cleanup(struct drm_device *dev); - extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); --extern void intel_modeset_setup_hw_state(struct drm_device *dev); -+extern void intel_modeset_setup_hw_state(struct drm_device *dev, -+ bool force_restore); - extern bool intel_fbc_enabled(struct drm_device *dev); - extern void intel_disable_fbc(struct drm_device *dev); - extern bool ironlake_set_drps(struct drm_device *dev, u8 val); ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -8250,7 +8250,8 @@ static void intel_sanitize_encoder(struc - - /* Scan out the current hw modeset state, sanitizes it and maps it into the drm - * and i915 state tracking structures. */ --void intel_modeset_setup_hw_state(struct drm_device *dev) -+void intel_modeset_setup_hw_state(struct drm_device *dev, -+ bool force_restore) - { - struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe; -@@ -8321,7 +8322,15 @@ void intel_modeset_setup_hw_state(struct - intel_sanitize_crtc(crtc); - } - -- intel_modeset_update_staged_output_state(dev); -+ if (force_restore) { -+ for_each_pipe(pipe) { -+ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); -+ intel_set_mode(&crtc->base, &crtc->base.mode, -+ crtc->base.x, crtc->base.y, crtc->base.fb); -+ } -+ } else { -+ intel_modeset_update_staged_output_state(dev); -+ } - - intel_modeset_check_state(dev); - } -@@ -8332,7 +8341,7 @@ void intel_modeset_gem_init(struct drm_d - - intel_setup_overlay(dev); - -- intel_modeset_setup_hw_state(dev); -+ intel_modeset_setup_hw_state(dev, false); - } - - void intel_modeset_cleanup(struct drm_device *dev) ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -526,7 +526,7 @@ static int intel_lid_notify(struct notif - dev_priv->modeset_on_lid = 0; - - mutex_lock(&dev->mode_config.mutex); -- intel_modeset_check_state(dev); -+ intel_modeset_setup_hw_state(dev, true); - mutex_unlock(&dev->mode_config.mutex); - - return NOTIFY_OK; -From 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 Mon Sep 17 00:00:00 2001 -From: Krzysztof Mazur -Date: Wed, 19 Dec 2012 11:03:41 +0100 -Subject: i915: ensure that VGA plane is disabled - -From: Krzysztof Mazur - -commit 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 upstream. - -Some broken systems (like HP nc6120) in some cases, usually after LID -close/open, enable VGA plane, making display unusable (black screen on LVDS, -some strange mode on VGA output). We used to disable VGA plane only once at -startup. Now we also check, if VGA plane is still disabled while changing -mode, and fix that if something changed it. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 -Signed-off-by: Krzysztof Mazur -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -8248,6 +8248,23 @@ static void intel_sanitize_encoder(struc - * the crtc fixup. */ - } - -+static void i915_redisable_vga(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 vga_reg; -+ -+ if (HAS_PCH_SPLIT(dev)) -+ vga_reg = CPU_VGACNTRL; -+ else -+ vga_reg = VGACNTRL; -+ -+ if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { -+ DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); -+ I915_WRITE(vga_reg, VGA_DISP_DISABLE); -+ POSTING_READ(vga_reg); -+ } -+} -+ - /* Scan out the current hw modeset state, sanitizes it and maps it into the drm - * and i915 state tracking structures. */ - void intel_modeset_setup_hw_state(struct drm_device *dev, -@@ -8328,6 +8345,8 @@ void intel_modeset_setup_hw_state(struct - intel_set_mode(&crtc->base, &crtc->base.mode, - crtc->base.x, crtc->base.y, crtc->base.fb); - } -+ -+ i915_redisable_vga(dev); - } else { - intel_modeset_update_staged_output_state(dev); - } -From 3490ea5de6ac4af309c3df8a26a5cca61306334c Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Mon, 7 Jan 2013 10:11:40 +0000 -Subject: drm/i915: Treat crtc->mode.clock == 0 as disabled - -From: Chris Wilson - -commit 3490ea5de6ac4af309c3df8a26a5cca61306334c upstream. - -Prevent a divide-by-zero by consistently treating an 'active' CRTC -without a mode set as actually disabled. - -This looks to have been first introduced with - -commit 24929352481f085c5f85d4d4cbc919ddf106d381 -Author: Daniel Vetter -Date: Mon Jul 2 20:28:59 2012 +0200 - - drm/i915: read out the modeset hw state at load and resume time - -but then combined with - -commit b0a2658acb5bf9ca86b4aab011b7106de3af0add -Author: Daniel Vetter -Date: Tue Dec 18 09:37:54 2012 +0100 - - drm/i915: don't disable disconnected outputs - -it finally started oopsing. - -Signed-off-by: Chris Wilson -Reported-and-tested-by: Alexey Zaytsev -Tested-by: Sedat Dilek -Cc: Daniel Vetter -Cc: Jesse Barnes -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_pm.c | 23 +++++++++++++++-------- - 1 file changed, 15 insertions(+), 8 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_pm.c -+++ b/drivers/gpu/drm/i915/intel_pm.c -@@ -44,6 +44,14 @@ - * i915.i915_enable_fbc parameter - */ - -+static bool intel_crtc_active(struct drm_crtc *crtc) -+{ -+ /* Be paranoid as we can arrive here with only partial -+ * state retrieved from the hardware during setup. -+ */ -+ return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; -+} -+ - static void i8xx_disable_fbc(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device - * - going to an unsupported config (interlace, pixel multiply, etc.) - */ - list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { -- if (tmp_crtc->enabled && -- !to_intel_crtc(tmp_crtc)->primary_disabled && -- tmp_crtc->fb) { -+ if (intel_crtc_active(tmp_crtc) && -+ !to_intel_crtc(tmp_crtc)->primary_disabled) { - if (crtc) { - DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); - dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; -@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_c - struct drm_crtc *crtc, *enabled = NULL; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- if (crtc->enabled && crtc->fb) { -+ if (intel_crtc_active(crtc)) { - if (enabled) - return NULL; - enabled = crtc; -@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_d - int entries, tlb_miss; - - crtc = intel_get_crtc_for_plane(dev, plane); -- if (crtc->fb == NULL || !crtc->enabled) { -+ if (!intel_crtc_active(crtc)) { - *cursor_wm = cursor->guard_size; - *plane_wm = display->guard_size; - return false; -@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(st - int entries; - - crtc = intel_get_crtc_for_plane(dev, plane); -- if (crtc->fb == NULL || !crtc->enabled) -+ if (!intel_crtc_active(crtc)) - return false; - - clock = crtc->mode.clock; /* VESA DOT Clock */ -@@ -1478,7 +1485,7 @@ static void i9xx_update_wm(struct drm_de - - fifo_size = dev_priv->display.get_fifo_size(dev, 1); - crtc = intel_get_crtc_for_plane(dev, 1); -- if (crtc->enabled && crtc->fb) { -+ if (intel_crtc_active(crtc)) { - planeb_wm = intel_calculate_wm(crtc->mode.clock, - wm_info, fifo_size, - crtc->fb->bits_per_pixel / 8, -@@ -1923,7 +1930,7 @@ sandybridge_compute_sprite_wm(struct drm - int entries, tlb_miss; - - crtc = intel_get_crtc_for_plane(dev, plane); -- if (crtc->fb == NULL || !crtc->enabled) { -+ if (!intel_crtc_active(crtc)) { - *sprite_wm = display->guard_size; - return false; - } From bd5d1b44eb9e9875152861cfe49983910acf3938 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 21 Jan 2013 15:22:27 -0500 Subject: [PATCH 153/492] Linux v3.7.4 --- kernel.spec | 11 ++-- sources | 2 +- ...-corruption-in-xen_failsafe_callback.patch | 62 ------------------- 3 files changed, 5 insertions(+), 70 deletions(-) delete mode 100644 xen-fix-stack-corruption-in-xen_failsafe_callback.patch diff --git a/kernel.spec b/kernel.spec index 07f96cf16..d8d3bf0d1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -777,9 +777,6 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886946 Patch21234: iwlegacy-fix-IBSS-cleanup.patch -#rhbz 896051 896038 CVE-2013-0190 -Patch21250: xen-fix-stack-corruption-in-xen_failsafe_callback.patch - # END OF PATCH DEFINITIONS %endif @@ -1488,9 +1485,6 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886948 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch -#rhbz 896051 896038 CVE-2013-0190 -ApplyPatch xen-fix-stack-corruption-in-xen_failsafe_callback.patch - # END OF PATCH APPLICATIONS %endif @@ -2347,6 +2341,9 @@ fi # ||----w | # || || %changelog +* Mon Jan 21 2013 Josh Boyer - 3.7.4-201 +- Linux v3.7.4 + * Fri Jan 18 2013 Justin M. Forbes 3.7.3-201 - Linux v3.7.3 diff --git a/sources b/sources index df992bd44..373e02c6f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -d4aa39ec9610e9fbd7bb4f5aff2c5db8 patch-3.7.3.xz +87640faf7264639e1300829d1b292076 patch-3.7.4.xz diff --git a/xen-fix-stack-corruption-in-xen_failsafe_callback.patch b/xen-fix-stack-corruption-in-xen_failsafe_callback.patch deleted file mode 100644 index 9d83ea0c9..000000000 --- a/xen-fix-stack-corruption-in-xen_failsafe_callback.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 38174c8c07ad638cd18285ba402b59076849dc21 Mon Sep 17 00:00:00 2001 -From: Andrew Cooper -Date: Thu, 10 Jan 2013 17:16:30 +0000 -Subject: [PATCH] xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests. - -There has been an error on the xen_failsafe_callback path for failed -iret, which causes the stack pointer to be wrong when entering the -iret_exc error path. This can result in the kernel crashing. - -In the classic kernel case, the relevant code looked a little like: - - popl %eax # Error code from hypervisor - jz 5f - addl $16,%esp - jmp iret_exc # Hypervisor said iret fault -5: addl $16,%esp - # Hypervisor said segment selector fault - -Here, there are two identical addls on either option of a branch which -appears to have been optimised by hoisting it above the jz, and -converting it to an lea, which leaves the flags register unaffected. - -In the PVOPS case, the code looks like: - - popl_cfi %eax # Error from the hypervisor - lea 16(%esp),%esp # Add $16 before choosing fault path - CFI_ADJUST_CFA_OFFSET -16 - jz 5f - addl $16,%esp # Incorrectly adjust %esp again - jmp iret_exc - -It is possible unprivileged userspace applications to cause this -behaviour, for example by loading an LDT code selector, then changing -the code selector to be not-present. At this point, there is a race -condition where it is possible for the hypervisor to return back to -userspace from an interrupt, fault on its own iret, and inject a -failsafe_callback into the kernel. - -This bug has been present since the introduction of Xen PVOPS support -in commit 5ead97c84 (xen: Core Xen implementation), in 2.6.23. - -Signed-off-by: Frediano Ziglio -Signed-off-by: Andrew Cooper ---- - arch/x86/kernel/entry_32.S | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - -diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S -index ff84d54..6ed91d9 100644 ---- a/arch/x86/kernel/entry_32.S -+++ b/arch/x86/kernel/entry_32.S -@@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback) - lea 16(%esp),%esp - CFI_ADJUST_CFA_OFFSET -16 - jz 5f -- addl $16,%esp - jmp iret_exc - 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ - SAVE_ALL --- -1.7.2.5 - From 56666ff9ae1ef1ac4119177d0eaab5051e634cb0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 22 Jan 2013 13:40:20 -0500 Subject: [PATCH 154/492] Fix libata settings bug (rhbz 902523) --- kernel.spec | 11 +- ...ace-sata_settings-with-devslp_timing.patch | 131 ++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 libata-replace-sata_settings-with-devslp_timing.patch diff --git a/kernel.spec b/kernel.spec index d8d3bf0d1..9fce006e8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -777,6 +777,9 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886946 Patch21234: iwlegacy-fix-IBSS-cleanup.patch +#rhbz 902523 +Patch21236: libata-replace-sata_settings-with-devslp_timing.patch + # END OF PATCH DEFINITIONS %endif @@ -1485,6 +1488,9 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886948 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch +#rhbz 902523 +ApplyPatch libata-replace-sata_settings-with-devslp_timing.patch + # END OF PATCH APPLICATIONS %endif @@ -2341,6 +2347,9 @@ fi # ||----w | # || || %changelog +* Tue Jan 22 2013 Josh Boyer +- Fix libata settings bug (rhbz 902523) + * Mon Jan 21 2013 Josh Boyer - 3.7.4-201 - Linux v3.7.4 diff --git a/libata-replace-sata_settings-with-devslp_timing.patch b/libata-replace-sata_settings-with-devslp_timing.patch new file mode 100644 index 000000000..f620a20bd --- /dev/null +++ b/libata-replace-sata_settings-with-devslp_timing.patch @@ -0,0 +1,131 @@ +From 803739d25c2343da6d2f95eebdcbc08bf67097d4 Mon Sep 17 00:00:00 2001 +From: Shane Huang +Date: Mon, 17 Dec 2012 23:18:59 +0800 +Subject: [PATCH] [libata] replace sata_settings with devslp_timing + +NCQ capability was used to check availability of SATA Settings page +from Identify Device Data Log, which contains DevSlp timing variables. +It does not work on some HDDs and leads to error messages. + +IDENTIFY word 78 bit 5(Hardware Feature Control) can't work either +because it is only the sufficient condition of Identify Device data +log, not the necessary condition. + +This patch replaced ata_device->sata_settings with ->devslp_timing +to only save DevSlp timing variables(8 bytes), instead of the whole +SATA Settings page(512 bytes). + +Addresses https://bugzilla.kernel.org/show_bug.cgi?id=51881 + +Reported-by: Borislav Petkov +Signed-off-by: Shane Huang +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Garzik +--- + drivers/ata/libahci.c | 6 +++--- + drivers/ata/libata-core.c | 22 +++++++++++++--------- + include/linux/ata.h | 8 +++++--- + include/linux/libata.h | 4 ++-- + 4 files changed, 23 insertions(+), 17 deletions(-) + +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 320712a..6cd7805 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) + /* Use the nominal value 10 ms if the read MDAT is zero, + * the nominal value of DETO is 20 ms. + */ +- if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & ++ if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & + ATA_LOG_DEVSLP_VALID_MASK) { +- mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & ++ mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & + ATA_LOG_DEVSLP_MDAT_MASK; + if (!mdat) + mdat = 10; +- deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; ++ deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; + if (!deto) + deto = 20; + } else { +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 9e8b99a..46cd3f4 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) + } + } + +- /* check and mark DevSlp capability */ +- if (ata_id_has_devslp(dev->id)) +- dev->flags |= ATA_DFLAG_DEVSLP; +- +- /* Obtain SATA Settings page from Identify Device Data Log, +- * which contains DevSlp timing variables etc. +- * Exclude old devices with ata_id_has_ncq() ++ /* Check and mark DevSlp capability. Get DevSlp timing variables ++ * from SATA Settings page of Identify Device Data Log. + */ +- if (ata_id_has_ncq(dev->id)) { ++ if (ata_id_has_devslp(dev->id)) { ++ u8 sata_setting[ATA_SECT_SIZE]; ++ int i, j; ++ ++ dev->flags |= ATA_DFLAG_DEVSLP; + err_mask = ata_read_log_page(dev, + ATA_LOG_SATA_ID_DEV_DATA, + ATA_LOG_SATA_SETTINGS, +- dev->sata_settings, ++ sata_setting, + 1); + if (err_mask) + ata_dev_dbg(dev, + "failed to get Identify Device Data, Emask 0x%x\n", + err_mask); ++ else ++ for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { ++ j = ATA_LOG_DEVSLP_OFFSET + i; ++ dev->devslp_timing[i] = sata_setting[j]; ++ } + } + + dev->cdb_len = 16; +diff --git a/include/linux/ata.h b/include/linux/ata.h +index 408da95..8f7a3d6 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -297,10 +297,12 @@ enum { + ATA_LOG_SATA_NCQ = 0x10, + ATA_LOG_SATA_ID_DEV_DATA = 0x30, + ATA_LOG_SATA_SETTINGS = 0x08, +- ATA_LOG_DEVSLP_MDAT = 0x30, ++ ATA_LOG_DEVSLP_OFFSET = 0x30, ++ ATA_LOG_DEVSLP_SIZE = 0x08, ++ ATA_LOG_DEVSLP_MDAT = 0x00, + ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, +- ATA_LOG_DEVSLP_DETO = 0x31, +- ATA_LOG_DEVSLP_VALID = 0x37, ++ ATA_LOG_DEVSLP_DETO = 0x01, ++ ATA_LOG_DEVSLP_VALID = 0x07, + ATA_LOG_DEVSLP_VALID_MASK = 0x80, + + /* READ/WRITE LONG (obsolete) */ +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 83ba0ab..649e5f8 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -652,8 +652,8 @@ struct ata_device { + u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ + }; + +- /* Identify Device Data Log (30h), SATA Settings (page 08h) */ +- u8 sata_settings[ATA_SECT_SIZE]; ++ /* DEVSLP Timing Variables from Identify Device Data Log */ ++ u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; + + /* error history */ + int spdn_cnt; +-- +1.7.7.6 + From 2ddf29a0b536852dc4d8c6342fd395fc193accd3 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 22 Jan 2013 20:20:54 +0000 Subject: [PATCH 155/492] Apply ARM errata fix, disable HVC_DCC and VIRTIO_CONSOLE on ARM --- ...-set_debug-on-pl310-r3p0-and-earlier.patch | 31 +++++++++++++++++++ config-armv7 | 5 ++- kernel.spec | 13 ++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch diff --git a/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch b/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch new file mode 100644 index 000000000..662ebe666 --- /dev/null +++ b/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch @@ -0,0 +1,31 @@ +From: Rob Herring + +PL310 errata work-arounds using .set_debug function are only needed on +r3p0 and earlier, so check the rev and only set .set_debug on older revs. + +Avoiding debug register accesses fixes aborts on non-secure platforms +like highbank. It is assumed that non-secure platforms needing these +work-arounds have already implemented .set_debug with secure monitor +calls. + +Signed-off-by: Rob Herring +--- + arch/arm/mm/cache-l2x0.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c +index 8a97e64..6cf2fd1 100644 +--- a/arch/arm/mm/cache-l2x0.c ++++ b/arch/arm/mm/cache-l2x0.c +@@ -334,7 +334,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) + /* Unmapped register. */ + sync_reg_offset = L2X0_DUMMY_REG; + #endif +- outer_cache.set_debug = pl310_set_debug; ++ if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0) ++ outer_cache.set_debug = pl310_set_debug; + break; + case L2X0_CACHE_ID_PART_L210: + ways = (aux >> 13) & 0xf; +-- +1.7.10.4 diff --git a/config-armv7 b/config-armv7 index f143f3dee..5d6d294ab 100644 --- a/config-armv7 +++ b/config-armv7 @@ -48,7 +48,7 @@ CONFIG_HIGHPTE=y # CONFIG_ARM_LPAE is not set # CONFIG_THUMB2_KERNEL is not set # CONFIG_XEN is not set -CONFIG_HVC_DCC=y +# CONFIG_HVC_DCC is not set # CONFIG_ARM_VIRT_EXT is not set @@ -144,6 +144,9 @@ CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# disable VIRTIO console on because not doing real virt and it breaks vexpress on qemu +# CONFIG_VIRTIO_CONSOLE is not set + CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y diff --git a/kernel.spec b/kernel.spec index 9fce006e8..0049b3219 100644 --- a/kernel.spec +++ b/kernel.spec @@ -743,9 +743,12 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-read_current_timer.patch -Patch21001: arm-fix-omapdrm.patch -Patch21003: arm-alignment-faults.patch +# http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/137164.html +Patch21001: arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch +Patch21002: arm-alignment-faults.patch + # OMAP +Patch21003: arm-fix-omapdrm.patch # ARM tegra Patch21004: arm-tegra-nvec-kconfig.patch @@ -1343,6 +1346,8 @@ ApplyPatch vmbugon-warnon.patch # #ApplyPatch arm-read_current_timer.patch #ApplyPatch arm-fix-omapdrm.patch + +ApplyPatch arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-sdhci-module-fix.patch @@ -2347,6 +2352,10 @@ fi # ||----w | # || || %changelog +* Tue Jan 22 2013 Peter Robinson +- Apply ARM errata fix +- disable HVC_DCC and VIRTIO_CONSOLE on ARM + * Tue Jan 22 2013 Josh Boyer - Fix libata settings bug (rhbz 902523) From d483733654fa663cd710f8b43218672573f3add9 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 22 Jan 2013 17:30:40 -0600 Subject: [PATCH 156/492] drm/i915: Invalidate the relocation presumed_offsets along the slow path --- ...on-presumed_offsets-along-slow-patch.patch | 67 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch diff --git a/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch b/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch new file mode 100644 index 000000000..be557dc9d --- /dev/null +++ b/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch @@ -0,0 +1,67 @@ +commit 262b6d363fcff16359c93bd58c297f961f6e6273 +Author: Chris Wilson +Date: Tue Jan 15 16:17:54 2013 +0000 + + drm/i915: Invalidate the relocation presumed_offsets along the slow path + + In the slow path, we are forced to copy the relocations prior to + acquiring the struct mutex in order to handle pagefaults. We forgo + copying the new offsets back into the relocation entries in order to + prevent a recursive locking bug should we trigger a pagefault whilst + holding the mutex for the reservations of the execbuffer. Therefore, we + need to reset the presumed_offsets just in case the objects are rebound + back into their old locations after relocating for this exexbuffer - if + that were to happen we would assume the relocations were valid and leave + the actual pointers to the kernels dangling, instant hang. + + Fixes regression from commit bcf50e2775bbc3101932d8e4ab8c7902aa4163b4 + Author: Chris Wilson + Date: Sun Nov 21 22:07:12 2010 +0000 + + drm/i915: Handle pagefaults in execbuffer user relocations + + Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 + Signed-off-by: Chris Wilson + Cc: Daniel Vetter + Cc: stable@vger.kernel.org + Signed-off-by: Daniel Vetter + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index d6a994a..26d08bb 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, + total = 0; + for (i = 0; i < count; i++) { + struct drm_i915_gem_relocation_entry __user *user_relocs; ++ u64 invalid_offset = (u64)-1; ++ int j; + + user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; + +@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, + goto err; + } + ++ /* As we do not update the known relocation offsets after ++ * relocating (due to the complexities in lock handling), ++ * we need to mark them as invalid now so that we force the ++ * relocation processing next time. Just in case the target ++ * object is evicted and then rebound into its old ++ * presumed_offset before the next execbuffer - if that ++ * happened we would make the mistake of assuming that the ++ * relocations were valid. ++ */ ++ for (j = 0; j < exec[i].relocation_count; j++) { ++ if (copy_to_user(&user_relocs[j].presumed_offset, ++ &invalid_offset, ++ sizeof(invalid_offset))) { ++ ret = -EFAULT; ++ mutex_lock(&dev->struct_mutex); ++ goto err; ++ } ++ } ++ + reloc_offset[i] = total; + total += exec[i].relocation_count; + } diff --git a/kernel.spec b/kernel.spec index 0049b3219..6b649bbab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -783,6 +783,9 @@ Patch21234: iwlegacy-fix-IBSS-cleanup.patch #rhbz 902523 Patch21236: libata-replace-sata_settings-with-devslp_timing.patch +# i915 hang fixes +Patch21237: drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch + # END OF PATCH DEFINITIONS %endif @@ -1496,6 +1499,9 @@ ApplyPatch iwlegacy-fix-IBSS-cleanup.patch #rhbz 902523 ApplyPatch libata-replace-sata_settings-with-devslp_timing.patch +#i915 +ApplyPatch drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch + # END OF PATCH APPLICATIONS %endif @@ -2352,6 +2358,9 @@ fi # ||----w | # || || %changelog +* Tue Jan 22 2013 Justin M. Forbes - 3.7.4-203 +- Add i915 bugfix from airlied + * Tue Jan 22 2013 Peter Robinson - Apply ARM errata fix - disable HVC_DCC and VIRTIO_CONSOLE on ARM From 79cfaf9c9adcad220c94fcabb6fc3f19f1a51ce9 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 23 Jan 2013 10:54:21 -0500 Subject: [PATCH 157/492] Remove warnings about empty IPI masks. Conflicts: kernel.spec --- kernel.spec | 7 +++++++ silence-empty-ipi-mask-warning.patch | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 silence-empty-ipi-mask-warning.patch diff --git a/kernel.spec b/kernel.spec index 6b649bbab..d62adf1ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -685,6 +685,7 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch +Patch540: silence-empty-ipi-mask-warning.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1412,6 +1413,9 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch +# no-one cares about these warnings. +ApplyPatch silence-empty-ipi-mask-warning.patch + # Changes to upstream defaults. @@ -2358,6 +2362,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 23 2013 Dave Jones +- Remove warnings about empty IPI masks. + * Tue Jan 22 2013 Justin M. Forbes - 3.7.4-203 - Add i915 bugfix from airlied diff --git a/silence-empty-ipi-mask-warning.patch b/silence-empty-ipi-mask-warning.patch new file mode 100644 index 000000000..65a637c06 --- /dev/null +++ b/silence-empty-ipi-mask-warning.patch @@ -0,0 +1,11 @@ +--- linux-3.6.noarch/arch/x86/kernel/apic/ipi.c~ 2013-01-23 10:48:14.716069615 -0500 ++++ linux-3.6.noarch/arch/x86/kernel/apic/ipi.c 2013-01-23 10:48:26.217046545 -0500 +@@ -106,7 +106,7 @@ void default_send_IPI_mask_logical(const + unsigned long mask = cpumask_bits(cpumask)[0]; + unsigned long flags; + +- if (WARN_ONCE(!mask, "empty IPI mask")) ++ if (!mask) + return; + + local_irq_save(flags); From dd35eb31a1c81eabe3b59c84590982791b0807f4 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 23 Jan 2013 10:20:08 -0600 Subject: [PATCH 158/492] brcmsmac fixes from upstream (rhbz 892428) --- brcmsmac-updates-rhbz892428.patch | 28 ++++++++++++++++++++++++++++ kernel.spec | 13 +++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 brcmsmac-updates-rhbz892428.patch diff --git a/brcmsmac-updates-rhbz892428.patch b/brcmsmac-updates-rhbz892428.patch new file mode 100644 index 000000000..8b5e08f04 --- /dev/null +++ b/brcmsmac-updates-rhbz892428.patch @@ -0,0 +1,28 @@ +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c +index 426b9a9..d7ce1ac 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c +@@ -361,7 +361,7 @@ static uint prevtxd(struct dma_info *di, uint i) + + static uint nextrxd(struct dma_info *di, uint i) + { +- return txd(di, i + 1); ++ return rxd(di, i + 1); + } + + static uint ntxdactive(struct dma_info *di, uint h, uint t) +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c +index 5710dc0..25c5410 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -232,8 +232,8 @@ + + #define MAX_DMA_SEGS 4 + +-/* Max # of entries in Tx FIFO based on 4kb page size */ +-#define NTXD 256 ++/* # of entries in Tx FIFO */ ++#define NTXD 64 + /* Max # of entries in Rx FIFO based on 4kb page size */ + #define NRXD 256 + diff --git a/kernel.spec b/kernel.spec index d62adf1ad..a7cfae9aa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -784,9 +784,12 @@ Patch21234: iwlegacy-fix-IBSS-cleanup.patch #rhbz 902523 Patch21236: libata-replace-sata_settings-with-devslp_timing.patch -# i915 hang fixes +#i915 hang fixes Patch21237: drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch +#rhbz 892428 +Patch21238: brcmsmac-updates-rhbz892428.patch + # END OF PATCH DEFINITIONS %endif @@ -1506,6 +1509,9 @@ ApplyPatch libata-replace-sata_settings-with-devslp_timing.patch #i915 ApplyPatch drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch +#rhbz 892428 +ApplyPatch brcmsmac-updates-rhbz892428.patch + # END OF PATCH APPLICATIONS %endif @@ -2362,6 +2368,9 @@ fi # ||----w | # || || %changelog +* Wed Jan 23 2013 Justin M. Forbes - 3.7.4-204 +- brcmsmac fixes from upstream (rhbz 892428) + * Wed Jan 23 2013 Dave Jones - Remove warnings about empty IPI masks. From 70cf0f26dd677a6c59b474c1ea886687c50f4715 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 25 Jan 2013 11:00:40 -0600 Subject: [PATCH 159/492] Turn off THP for 32bit --- config-x86-32-generic | 2 ++ config-x86-generic | 2 -- config-x86_64-generic | 2 ++ kernel.spec | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config-x86-32-generic b/config-x86-32-generic index 1216d47e6..3273fd151 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -94,6 +94,8 @@ CONFIG_X86_TRAMPOLINE=y CONFIG_PCI_DIRECT=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set + # SHPC has half-arsed PCI probing, which makes it load on too many systems # CONFIG_HOTPLUG_PCI_SHPC is not set diff --git a/config-x86-generic b/config-x86-generic index 2bcd498eb..15c0e4695 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -390,8 +390,6 @@ CONFIG_X86_RESERVE_LOW=64 CONFIG_PCH_GBE=m CONFIG_PCH_PHUB=m -CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_CRYPTO_AES_NI_INTEL=y CONFIG_CRYPTO_SERPENT_SSE2_586=m diff --git a/config-x86_64-generic b/config-x86_64-generic index 6003f11c0..2e4195d5b 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -27,6 +27,8 @@ CONFIG_AMD_IOMMU_V2=m CONFIG_SWIOTLB=y # CONFIG_CALGARY_IOMMU is not set +CONFIG_TRANSPARENT_HUGEPAGE=y + CONFIG_KEXEC_JUMP=y CONFIG_ACPI_BLACKLIST_YEAR=0 diff --git a/kernel.spec b/kernel.spec index a7cfae9aa..7138fa801 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2368,6 +2368,9 @@ fi # ||----w | # || || %changelog +* Fri Jan 25 2013 Justin M. Forbes +- Turn off THP for 32bit + * Wed Jan 23 2013 Justin M. Forbes - 3.7.4-204 - brcmsmac fixes from upstream (rhbz 892428) From 556ae3e8059eda4b3f60a16c184727ef3673786b Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 27 Jan 2013 18:23:16 +0000 Subject: [PATCH 160/492] Build and package dtbs on ARM --- kernel.spec | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel.spec b/kernel.spec index 7138fa801..4f41071bc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1646,6 +1646,10 @@ BuildKernel() { %ifarch %{arm} # http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/091404.html make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} KALLSYMS_EXTRA_PASS=1 + + make -s ARCH=$Arch V=1 dtbs + mkdir -p $RPM_BUILD_ROOT/%{image_install_path}/dtb-$KernelVer + install -m 644 arch/arm/boot/*.dtb $RPM_BUILD_ROOT/boot/dtb-$KernelVer/ %else make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} %endif @@ -2317,6 +2321,9 @@ fi %defattr(-,root,root)\ /%{image_install_path}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-%{KVERREL}%{?2:.%{2}}\ /%{image_install_path}/.vmlinuz-%{KVERREL}%{?2:.%{2}}.hmac \ +%ifarch %{arm}\ +/%{image_install_path}/dtb-%{KVERREL}%{?2:.%{2}} \ +%endif\ %attr(600,root,root) /boot/System.map-%{KVERREL}%{?2:.%{2}}\ /boot/config-%{KVERREL}%{?2:.%{2}}\ %dir /lib/modules/%{KVERREL}%{?2:.%{2}}\ @@ -2368,6 +2375,9 @@ fi # ||----w | # || || %changelog +* Sun Jan 27 2013 Peter Robinson +- Build and package dtbs on ARM + * Fri Jan 25 2013 Justin M. Forbes - Turn off THP for 32bit From 8f91a689b6340a5cae562d81e18b25957a1fbfee Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 27 Jan 2013 22:41:31 +0000 Subject: [PATCH 161/492] Drop highbank/imx obsoletes as it removes old kernels so no rollback. highbank/imx provides kernel so it will upgrade and rotate out --- kernel.spec | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index 4f41071bc..b56b52fc2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -528,11 +528,6 @@ ExclusiveOS: Linux %kernel_reqprovconf -%ifarch %{arm} -Obsoletes: kernel-highbank -Obsoletes: kernel-imx -%endif - # # List the packages used during the kernel build # From 274e5201ef05abf397580e3aeff9b35639cdc73b Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 28 Jan 2013 11:25:09 +0000 Subject: [PATCH 162/492] Enable FB options for qemu vexpress on unified --- config-armv7 | 6 ++++++ kernel.spec | 1 + 2 files changed, 7 insertions(+) diff --git a/config-armv7 b/config-armv7 index 5d6d294ab..c865cb15f 100644 --- a/config-armv7 +++ b/config-armv7 @@ -163,7 +163,13 @@ CONFIG_OC_ETM=y CONFIG_SATA_HIGHBANK=m # versatile +CONFIG_FB=y CONFIG_FB_ARMCLCD=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_IMAGEBLIT=m +CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_I2C_VERSATILE=m CONFIG_OC_ETM=y CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y diff --git a/kernel.spec b/kernel.spec index b56b52fc2..ee9ff3689 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2372,6 +2372,7 @@ fi %changelog * Sun Jan 27 2013 Peter Robinson - Build and package dtbs on ARM +- Enable FB options for qemu vexpress on unified * Fri Jan 25 2013 Justin M. Forbes - Turn off THP for 32bit From 4eae979b3dc0d9daa4812a598c4e0405566f086e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 28 Jan 2013 07:43:06 -0500 Subject: [PATCH 163/492] Linux v3.7.5 --- ...on-presumed_offsets-along-slow-patch.patch | 67 --------- kernel.spec | 19 +-- ...ace-sata_settings-with-devslp_timing.patch | 131 ------------------ sources | 2 +- 4 files changed, 6 insertions(+), 213 deletions(-) delete mode 100644 drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch delete mode 100644 libata-replace-sata_settings-with-devslp_timing.patch diff --git a/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch b/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch deleted file mode 100644 index be557dc9d..000000000 --- a/drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch +++ /dev/null @@ -1,67 +0,0 @@ -commit 262b6d363fcff16359c93bd58c297f961f6e6273 -Author: Chris Wilson -Date: Tue Jan 15 16:17:54 2013 +0000 - - drm/i915: Invalidate the relocation presumed_offsets along the slow path - - In the slow path, we are forced to copy the relocations prior to - acquiring the struct mutex in order to handle pagefaults. We forgo - copying the new offsets back into the relocation entries in order to - prevent a recursive locking bug should we trigger a pagefault whilst - holding the mutex for the reservations of the execbuffer. Therefore, we - need to reset the presumed_offsets just in case the objects are rebound - back into their old locations after relocating for this exexbuffer - if - that were to happen we would assume the relocations were valid and leave - the actual pointers to the kernels dangling, instant hang. - - Fixes regression from commit bcf50e2775bbc3101932d8e4ab8c7902aa4163b4 - Author: Chris Wilson - Date: Sun Nov 21 22:07:12 2010 +0000 - - drm/i915: Handle pagefaults in execbuffer user relocations - - Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 - Signed-off-by: Chris Wilson - Cc: Daniel Vetter - Cc: stable@vger.kernel.org - Signed-off-by: Daniel Vetter - -diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -index d6a994a..26d08bb 100644 ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, - total = 0; - for (i = 0; i < count; i++) { - struct drm_i915_gem_relocation_entry __user *user_relocs; -+ u64 invalid_offset = (u64)-1; -+ int j; - - user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; - -@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, - goto err; - } - -+ /* As we do not update the known relocation offsets after -+ * relocating (due to the complexities in lock handling), -+ * we need to mark them as invalid now so that we force the -+ * relocation processing next time. Just in case the target -+ * object is evicted and then rebound into its old -+ * presumed_offset before the next execbuffer - if that -+ * happened we would make the mistake of assuming that the -+ * relocations were valid. -+ */ -+ for (j = 0; j < exec[i].relocation_count; j++) { -+ if (copy_to_user(&user_relocs[j].presumed_offset, -+ &invalid_offset, -+ sizeof(invalid_offset))) { -+ ret = -EFAULT; -+ mutex_lock(&dev->struct_mutex); -+ goto err; -+ } -+ } -+ - reloc_offset[i] = total; - total += exec[i].relocation_count; - } diff --git a/kernel.spec b/kernel.spec index ee9ff3689..c7c166118 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -776,12 +776,6 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886946 Patch21234: iwlegacy-fix-IBSS-cleanup.patch -#rhbz 902523 -Patch21236: libata-replace-sata_settings-with-devslp_timing.patch - -#i915 hang fixes -Patch21237: drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch - #rhbz 892428 Patch21238: brcmsmac-updates-rhbz892428.patch @@ -1498,12 +1492,6 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 886948 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch -#rhbz 902523 -ApplyPatch libata-replace-sata_settings-with-devslp_timing.patch - -#i915 -ApplyPatch drm-invalidate-relocation-presumed_offsets-along-slow-patch.patch - #rhbz 892428 ApplyPatch brcmsmac-updates-rhbz892428.patch @@ -2370,6 +2358,9 @@ fi # ||----w | # || || %changelog +* Mon Jan 28 2013 Josh Boyer +- Linux v3.7.5 + * Sun Jan 27 2013 Peter Robinson - Build and package dtbs on ARM - Enable FB options for qemu vexpress on unified diff --git a/libata-replace-sata_settings-with-devslp_timing.patch b/libata-replace-sata_settings-with-devslp_timing.patch deleted file mode 100644 index f620a20bd..000000000 --- a/libata-replace-sata_settings-with-devslp_timing.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 803739d25c2343da6d2f95eebdcbc08bf67097d4 Mon Sep 17 00:00:00 2001 -From: Shane Huang -Date: Mon, 17 Dec 2012 23:18:59 +0800 -Subject: [PATCH] [libata] replace sata_settings with devslp_timing - -NCQ capability was used to check availability of SATA Settings page -from Identify Device Data Log, which contains DevSlp timing variables. -It does not work on some HDDs and leads to error messages. - -IDENTIFY word 78 bit 5(Hardware Feature Control) can't work either -because it is only the sufficient condition of Identify Device data -log, not the necessary condition. - -This patch replaced ata_device->sata_settings with ->devslp_timing -to only save DevSlp timing variables(8 bytes), instead of the whole -SATA Settings page(512 bytes). - -Addresses https://bugzilla.kernel.org/show_bug.cgi?id=51881 - -Reported-by: Borislav Petkov -Signed-off-by: Shane Huang -Cc: stable@vger.kernel.org -Signed-off-by: Jeff Garzik ---- - drivers/ata/libahci.c | 6 +++--- - drivers/ata/libata-core.c | 22 +++++++++++++--------- - include/linux/ata.h | 8 +++++--- - include/linux/libata.h | 4 ++-- - 4 files changed, 23 insertions(+), 17 deletions(-) - -diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c -index 320712a..6cd7805 100644 ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) - /* Use the nominal value 10 ms if the read MDAT is zero, - * the nominal value of DETO is 20 ms. - */ -- if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & -+ if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & - ATA_LOG_DEVSLP_VALID_MASK) { -- mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & -+ mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & - ATA_LOG_DEVSLP_MDAT_MASK; - if (!mdat) - mdat = 10; -- deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; -+ deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; - if (!deto) - deto = 20; - } else { -diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c -index 9e8b99a..46cd3f4 100644 ---- a/drivers/ata/libata-core.c -+++ b/drivers/ata/libata-core.c -@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) - } - } - -- /* check and mark DevSlp capability */ -- if (ata_id_has_devslp(dev->id)) -- dev->flags |= ATA_DFLAG_DEVSLP; -- -- /* Obtain SATA Settings page from Identify Device Data Log, -- * which contains DevSlp timing variables etc. -- * Exclude old devices with ata_id_has_ncq() -+ /* Check and mark DevSlp capability. Get DevSlp timing variables -+ * from SATA Settings page of Identify Device Data Log. - */ -- if (ata_id_has_ncq(dev->id)) { -+ if (ata_id_has_devslp(dev->id)) { -+ u8 sata_setting[ATA_SECT_SIZE]; -+ int i, j; -+ -+ dev->flags |= ATA_DFLAG_DEVSLP; - err_mask = ata_read_log_page(dev, - ATA_LOG_SATA_ID_DEV_DATA, - ATA_LOG_SATA_SETTINGS, -- dev->sata_settings, -+ sata_setting, - 1); - if (err_mask) - ata_dev_dbg(dev, - "failed to get Identify Device Data, Emask 0x%x\n", - err_mask); -+ else -+ for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { -+ j = ATA_LOG_DEVSLP_OFFSET + i; -+ dev->devslp_timing[i] = sata_setting[j]; -+ } - } - - dev->cdb_len = 16; -diff --git a/include/linux/ata.h b/include/linux/ata.h -index 408da95..8f7a3d6 100644 ---- a/include/linux/ata.h -+++ b/include/linux/ata.h -@@ -297,10 +297,12 @@ enum { - ATA_LOG_SATA_NCQ = 0x10, - ATA_LOG_SATA_ID_DEV_DATA = 0x30, - ATA_LOG_SATA_SETTINGS = 0x08, -- ATA_LOG_DEVSLP_MDAT = 0x30, -+ ATA_LOG_DEVSLP_OFFSET = 0x30, -+ ATA_LOG_DEVSLP_SIZE = 0x08, -+ ATA_LOG_DEVSLP_MDAT = 0x00, - ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, -- ATA_LOG_DEVSLP_DETO = 0x31, -- ATA_LOG_DEVSLP_VALID = 0x37, -+ ATA_LOG_DEVSLP_DETO = 0x01, -+ ATA_LOG_DEVSLP_VALID = 0x07, - ATA_LOG_DEVSLP_VALID_MASK = 0x80, - - /* READ/WRITE LONG (obsolete) */ -diff --git a/include/linux/libata.h b/include/linux/libata.h -index 83ba0ab..649e5f8 100644 ---- a/include/linux/libata.h -+++ b/include/linux/libata.h -@@ -652,8 +652,8 @@ struct ata_device { - u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ - }; - -- /* Identify Device Data Log (30h), SATA Settings (page 08h) */ -- u8 sata_settings[ATA_SECT_SIZE]; -+ /* DEVSLP Timing Variables from Identify Device Data Log */ -+ u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; - - /* error history */ - int spdn_cnt; --- -1.7.7.6 - diff --git a/sources b/sources index 373e02c6f..17024d936 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -87640faf7264639e1300829d1b292076 patch-3.7.4.xz +c100b62e571bfb80e8c290e811c0963c patch-3.7.5.xz From 82e26bd9bba2ca3c107ae3c5cdf24f22852f087b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 28 Jan 2013 09:28:39 -0500 Subject: [PATCH 164/492] Add patch to fix iwlwifi issues (rhbz 863424) --- ...x-the-reclaimed-packet-tracking-upon.patch | 68 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 75 insertions(+) create mode 100644 Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch diff --git a/Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch b/Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch new file mode 100644 index 000000000..302774b45 --- /dev/null +++ b/Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch @@ -0,0 +1,68 @@ +From ae023b2795d36f0f077e157428eb7eafa29ee412 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Mon, 21 Jan 2013 13:12:57 +0200 +Subject: [PATCH] Revert "iwlwifi: fix the reclaimed packet tracking upon + flush queue" + +This reverts commit f590dcec944552f9a4a61155810f3abd17d6465d +which has been reported to cause issues. + +See https://lkml.org/lkml/2013/1/20/4 for further details. + +Cc: stable@vger.kernel.org [3.7] +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- + drivers/net/wireless/iwlwifi/dvm/tx.c | 24 +++++++----------------- + 1 files changed, 7 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c +index 31534f7..2797964 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -1153,6 +1153,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, + next_reclaimed = ssn; + } + ++ if (tid != IWL_TID_NON_QOS) { ++ priv->tid_data[sta_id][tid].next_reclaimed = ++ next_reclaimed; ++ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", ++ next_reclaimed); ++ } ++ + iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); + + iwlagn_check_ratid_empty(priv, sta_id, tid); +@@ -1203,28 +1210,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, + if (!is_agg) + iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); + +- /* +- * W/A for FW bug - the seq_ctl isn't updated when the +- * queues are flushed. Fetch it from the packet itself +- */ +- if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { +- next_reclaimed = le16_to_cpu(hdr->seq_ctrl); +- next_reclaimed = +- SEQ_TO_SN(next_reclaimed + 0x10); +- } +- + is_offchannel_skb = + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); + freed++; + } + +- if (tid != IWL_TID_NON_QOS) { +- priv->tid_data[sta_id][tid].next_reclaimed = +- next_reclaimed; +- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", +- next_reclaimed); +- } +- + WARN_ON(!is_agg && freed != 1); + + /* +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index c7c166118..ff2fa2dad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,9 @@ Patch21234: iwlegacy-fix-IBSS-cleanup.patch #rhbz 892428 Patch21238: brcmsmac-updates-rhbz892428.patch +#rhbz 863424 +Patch21239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch + # END OF PATCH DEFINITIONS %endif @@ -1495,6 +1498,9 @@ ApplyPatch iwlegacy-fix-IBSS-cleanup.patch #rhbz 892428 ApplyPatch brcmsmac-updates-rhbz892428.patch +#rhbz 863424 +ApplyPatch Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch + # END OF PATCH APPLICATIONS %endif @@ -2360,6 +2366,7 @@ fi %changelog * Mon Jan 28 2013 Josh Boyer - Linux v3.7.5 +- Add patch to fix iwlwifi issues (rhbz 863424) * Sun Jan 27 2013 Peter Robinson - Build and package dtbs on ARM From bedfc3999fdffa3097cc8f20eeb3742421993944 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 28 Jan 2013 13:53:56 -0500 Subject: [PATCH 165/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index ff2fa2dad..4303fd218 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2364,7 +2364,7 @@ fi # ||----w | # || || %changelog -* Mon Jan 28 2013 Josh Boyer +* Mon Jan 28 2013 Josh Boyer - 3.7.5-201 - Linux v3.7.5 - Add patch to fix iwlwifi issues (rhbz 863424) From 07ef26cdeb716c5488c412624d9c8fe9b88e7de8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Jan 2013 08:41:36 -0500 Subject: [PATCH 166/492] Backport driver for Cypress PS/2 trackpad (rhbz 799564) --- ...dd-support-for-Cypress-PS2-Trackpads.patch | 1063 +++++++++++++++++ ...ease-struct-ps2dev-cmdbuf-to-8-bytes.patch | 30 + kernel.spec | 13 +- 3 files changed, 1105 insertions(+), 1 deletion(-) create mode 100644 Input-add-support-for-Cypress-PS2-Trackpads.patch create mode 100644 Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch diff --git a/Input-add-support-for-Cypress-PS2-Trackpads.patch b/Input-add-support-for-Cypress-PS2-Trackpads.patch new file mode 100644 index 000000000..8c5e569f9 --- /dev/null +++ b/Input-add-support-for-Cypress-PS2-Trackpads.patch @@ -0,0 +1,1063 @@ +From 0799a924bc93ba46a23e8e7e6b1431ab585fd2ea Mon Sep 17 00:00:00 2001 +From: Dudley Du +Date: Sat, 5 Jan 2013 00:14:22 -0800 +Subject: [PATCH] Input: add support for Cypress PS/2 Trackpads + +This driver, submitted on behalf of Cypress Semiconductor Corporation and +additional contributors, provides support for the Cypress PS/2 Trackpad. + +Original code contributed by Dudley Du (Cypress Semiconductor Corporation), +modified by Kamal Mostafa and Kyle Fazzari. + +BugLink: http://launchpad.net/bugs/978807 + +Signed-off-by: Dudley Du +Signed-off-by: Kamal Mostafa +Signed-off-by: Kyle Fazzari +Signed-off-by: Mario Limonciello +Signed-off-by: Tim Gardner +Acked-by: Herton Krzesinski +Reviewed-by: Henrik Rydberg +Reviewed-by: Dudley Du +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/Kconfig | 10 + + drivers/input/mouse/Makefile | 1 + + drivers/input/mouse/cypress_ps2.c | 725 ++++++++++++++++++++++++++++++++++++ + drivers/input/mouse/cypress_ps2.h | 191 ++++++++++ + drivers/input/mouse/psmouse-base.c | 32 ++ + drivers/input/mouse/psmouse.h | 1 + + 6 files changed, 960 insertions(+), 0 deletions(-) + create mode 100644 drivers/input/mouse/cypress_ps2.c + create mode 100644 drivers/input/mouse/cypress_ps2.h + +diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig +index cd6268c..88954dd 100644 +--- a/drivers/input/mouse/Kconfig ++++ b/drivers/input/mouse/Kconfig +@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS + + If unsure, say Y. + ++config MOUSE_PS2_CYPRESS ++ bool "Cypress PS/2 mouse protocol extension" if EXPERT ++ default y ++ depends on MOUSE_PS2 ++ help ++ Say Y here if you have a Cypress PS/2 Trackpad connected to ++ your system. ++ ++ If unsure, say Y. ++ + config MOUSE_PS2_LIFEBOOK + bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT + default y +diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile +index 46ba755..323e352 100644 +--- a/drivers/input/mouse/Makefile ++++ b/drivers/input/mouse/Makefile +@@ -32,3 +32,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o + psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o + psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o + psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o ++psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o +diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c +new file mode 100644 +index 0000000..1673dc6 +--- /dev/null ++++ b/drivers/input/mouse/cypress_ps2.c +@@ -0,0 +1,725 @@ ++/* ++ * Cypress Trackpad PS/2 mouse driver ++ * ++ * Copyright (c) 2012 Cypress Semiconductor Corporation. ++ * ++ * Author: ++ * Dudley Du ++ * ++ * Additional contributors include: ++ * Kamal Mostafa ++ * Kyle Fazzari ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cypress_ps2.h" ++ ++#undef CYTP_DEBUG_VERBOSE /* define this and DEBUG for more verbose dump */ ++ ++static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ cytp->pkt_size = n; ++} ++ ++static const unsigned char cytp_rate[] = {10, 20, 40, 60, 100, 200}; ++static const unsigned char cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; ++ ++static int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { ++ psmouse_dbg(psmouse, ++ "sending command 0x%02x failed, resp 0x%02x\n", ++ value & 0xff, ps2dev->nak); ++ if (ps2dev->nak == CYTP_PS2_RETRY) ++ return CYTP_PS2_RETRY; ++ else ++ return CYTP_PS2_ERROR; ++ } ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", ++ value & 0xff); ++#endif ++ ++ return 0; ++} ++ ++static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, ++ unsigned char data) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ ps2_begin_command(ps2dev); ++ ++ do { ++ /* ++ * Send extension command byte (0xE8 or 0xF3). ++ * If sending the command fails, send recovery command ++ * to make the device return to the ready state. ++ */ ++ rc = cypress_ps2_sendbyte(psmouse, cmd & 0xff); ++ if (rc == CYTP_PS2_RETRY) { ++ rc = cypress_ps2_sendbyte(psmouse, 0x00); ++ if (rc == CYTP_PS2_RETRY) ++ rc = cypress_ps2_sendbyte(psmouse, 0x0a); ++ } ++ if (rc == CYTP_PS2_ERROR) ++ continue; ++ ++ rc = cypress_ps2_sendbyte(psmouse, data); ++ if (rc == CYTP_PS2_RETRY) ++ rc = cypress_ps2_sendbyte(psmouse, data); ++ if (rc == CYTP_PS2_ERROR) ++ continue; ++ else ++ break; ++ } while (--tries > 0); ++ ++ ps2_end_command(ps2dev); ++ ++ return rc; ++} ++ ++static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, ++ unsigned char cmd, ++ unsigned char *param) ++{ ++ int rc; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ enum psmouse_state old_state; ++ int pktsize; ++ ++ ps2_begin_command(&psmouse->ps2dev); ++ ++ old_state = psmouse->state; ++ psmouse->state = PSMOUSE_CMD_MODE; ++ psmouse->pktcnt = 0; ++ ++ pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3; ++ memset(param, 0, pktsize); ++ ++ rc = cypress_ps2_sendbyte(psmouse, 0xe9); ++ if (rc < 0) ++ goto out; ++ ++ wait_event_timeout(ps2dev->wait, ++ (psmouse->pktcnt >= pktsize), ++ msecs_to_jiffies(CYTP_CMD_TIMEOUT)); ++ ++ memcpy(param, psmouse->packet, pktsize); ++ ++ psmouse_dbg(psmouse, "Command 0x%02x response data (0x): %*ph\n", ++ cmd, pktsize, param); ++ ++out: ++ psmouse->state = old_state; ++ psmouse->pktcnt = 0; ++ ++ ps2_end_command(&psmouse->ps2dev); ++ ++ return rc; ++} ++ ++static bool cypress_verify_cmd_state(struct psmouse *psmouse, ++ unsigned char cmd, unsigned char *param) ++{ ++ bool rate_match = false; ++ bool resolution_match = false; ++ int i; ++ ++ /* callers will do further checking. */ ++ if (cmd == CYTP_CMD_READ_CYPRESS_ID || ++ cmd == CYTP_CMD_STANDARD_MODE || ++ cmd == CYTP_CMD_READ_TP_METRICS) ++ return true; ++ ++ if ((~param[0] & DFLT_RESP_BITS_VALID) == DFLT_RESP_BITS_VALID && ++ (param[0] & DFLT_RESP_BIT_MODE) == DFLT_RESP_STREAM_MODE) { ++ for (i = 0; i < sizeof(cytp_resolution); i++) ++ if (cytp_resolution[i] == param[1]) ++ resolution_match = true; ++ ++ for (i = 0; i < sizeof(cytp_rate); i++) ++ if (cytp_rate[i] == param[2]) ++ rate_match = true; ++ ++ if (resolution_match && rate_match) ++ return true; ++ } ++ ++ psmouse_dbg(psmouse, "verify cmd state failed.\n"); ++ return false; ++} ++ ++static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, ++ unsigned char *param) ++{ ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n", ++ cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd), ++ DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd)); ++ ++ do { ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_DD(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_CC(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_BB(cmd)); ++ cypress_ps2_ext_cmd(psmouse, ++ PSMOUSE_CMD_SETRES, DECODE_CMD_AA(cmd)); ++ ++ rc = cypress_ps2_read_cmd_status(psmouse, cmd, param); ++ if (rc) ++ continue; ++ ++ if (cypress_verify_cmd_state(psmouse, cmd, param)) ++ return 0; ++ ++ } while (--tries > 0); ++ ++ return -EIO; ++} ++ ++int cypress_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) ++ return -ENODEV; ++ ++ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ ++ if (param[0] != 0x33 || param[1] != 0xCC) ++ return -ENODEV; ++ ++ if (set_properties) { ++ psmouse->vendor = "Cypress"; ++ psmouse->name = "Trackpad"; ++ } ++ ++ return 0; ++} ++ ++static int cypress_read_fw_version(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) ++ return -ENODEV; ++ ++ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ ++ if (param[0] != 0x33 || param[1] != 0xCC) ++ return -ENODEV; ++ ++ cytp->fw_version = param[2] & FW_VERSION_MASX; ++ cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; ++ ++ psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); ++ psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", ++ cytp->tp_metrics_supported); ++ ++ return 0; ++} ++ ++static int cypress_read_tp_metrics(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[8]; ++ ++ /* set default values for tp metrics. */ ++ cytp->tp_width = CYTP_DEFAULT_WIDTH; ++ cytp->tp_high = CYTP_DEFAULT_HIGH; ++ cytp->tp_max_abs_x = CYTP_ABS_MAX_X; ++ cytp->tp_max_abs_y = CYTP_ABS_MAX_Y; ++ cytp->tp_min_pressure = CYTP_MIN_PRESSURE; ++ cytp->tp_max_pressure = CYTP_MAX_PRESSURE; ++ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; ++ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; ++ ++ memset(param, 0, sizeof(param)); ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { ++ /* Update trackpad parameters. */ ++ cytp->tp_max_abs_x = (param[1] << 8) | param[0]; ++ cytp->tp_max_abs_y = (param[3] << 8) | param[2]; ++ cytp->tp_min_pressure = param[4]; ++ cytp->tp_max_pressure = param[5]; ++ } ++ ++ if (!cytp->tp_max_pressure || ++ cytp->tp_max_pressure < cytp->tp_min_pressure || ++ !cytp->tp_width || !cytp->tp_high || ++ !cytp->tp_max_abs_x || ++ cytp->tp_max_abs_x < cytp->tp_width || ++ !cytp->tp_max_abs_y || ++ cytp->tp_max_abs_y < cytp->tp_high) ++ return -EINVAL; ++ ++ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; ++ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ psmouse_dbg(psmouse, "Dump trackpad hardware configuration as below:\n"); ++ psmouse_dbg(psmouse, "cytp->tp_width = %d\n", cytp->tp_width); ++ psmouse_dbg(psmouse, "cytp->tp_high = %d\n", cytp->tp_high); ++ psmouse_dbg(psmouse, "cytp->tp_max_abs_x = %d\n", cytp->tp_max_abs_x); ++ psmouse_dbg(psmouse, "cytp->tp_max_abs_y = %d\n", cytp->tp_max_abs_y); ++ psmouse_dbg(psmouse, "cytp->tp_min_pressure = %d\n", cytp->tp_min_pressure); ++ psmouse_dbg(psmouse, "cytp->tp_max_pressure = %d\n", cytp->tp_max_pressure); ++ psmouse_dbg(psmouse, "cytp->tp_res_x = %d\n", cytp->tp_res_x); ++ psmouse_dbg(psmouse, "cytp->tp_res_y = %d\n", cytp->tp_res_y); ++ ++ psmouse_dbg(psmouse, "tp_type_APA = %d\n", ++ (param[6] & TP_METRICS_BIT_APA) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_type_MTG = %d\n", ++ (param[6] & TP_METRICS_BIT_MTG) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_palm = %d\n", ++ (param[6] & TP_METRICS_BIT_PALM) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_stubborn = %d\n", ++ (param[6] & TP_METRICS_BIT_STUBBORN) ? 1 : 0); ++ psmouse_dbg(psmouse, "tp_1f_jitter = %d\n", ++ (param[6] & TP_METRICS_BIT_1F_JITTER) >> 2); ++ psmouse_dbg(psmouse, "tp_2f_jitter = %d\n", ++ (param[6] & TP_METRICS_BIT_2F_JITTER) >> 4); ++ psmouse_dbg(psmouse, "tp_1f_spike = %d\n", ++ param[7] & TP_METRICS_BIT_1F_SPIKE); ++ psmouse_dbg(psmouse, "tp_2f_spike = %d\n", ++ (param[7] & TP_METRICS_BIT_2F_SPIKE) >> 2); ++ psmouse_dbg(psmouse, "tp_abs_packet_format_set = %d\n", ++ (param[7] & TP_METRICS_BIT_ABS_PKT_FORMAT_SET) >> 4); ++#endif ++ ++ return 0; ++} ++ ++static int cypress_query_hardware(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ int ret; ++ ++ ret = cypress_read_fw_version(psmouse); ++ if (ret) ++ return ret; ++ ++ if (cytp->tp_metrics_supported) { ++ ret = cypress_read_tp_metrics(psmouse); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int cypress_set_absolute_mode(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ unsigned char param[3]; ++ ++ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) ++ return -1; ++ ++ cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) ++ | CYTP_BIT_ABS_PRESSURE; ++ cypress_set_packet_size(psmouse, 5); ++ ++ return 0; ++} ++ ++/* ++ * Reset trackpad device. ++ * This is also the default mode when trackpad powered on. ++ */ ++static void cypress_reset(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ cytp->mode = 0; ++ ++ psmouse_reset(psmouse); ++} ++ ++static int cypress_set_input_params(struct input_dev *input, ++ struct cytp_data *cytp) ++{ ++ int ret; ++ ++ if (!cytp->tp_res_x || !cytp->tp_res_y) ++ return -EINVAL; ++ ++ __set_bit(EV_ABS, input->evbit); ++ input_set_abs_params(input, ABS_X, 0, cytp->tp_max_abs_x, 0, 0); ++ input_set_abs_params(input, ABS_Y, 0, cytp->tp_max_abs_y, 0, 0); ++ input_set_abs_params(input, ABS_PRESSURE, ++ cytp->tp_min_pressure, cytp->tp_max_pressure, 0, 0); ++ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); ++ ++ /* finger position */ ++ input_set_abs_params(input, ABS_MT_POSITION_X, 0, cytp->tp_max_abs_x, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cytp->tp_max_abs_y, 0, 0); ++ input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); ++ ++ ret = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, ++ INPUT_MT_DROP_UNUSED|INPUT_MT_TRACK); ++ if (ret < 0) ++ return ret; ++ ++ __set_bit(INPUT_PROP_SEMI_MT, input->propbit); ++ ++ input_abs_set_res(input, ABS_X, cytp->tp_res_x); ++ input_abs_set_res(input, ABS_Y, cytp->tp_res_y); ++ ++ input_abs_set_res(input, ABS_MT_POSITION_X, cytp->tp_res_x); ++ input_abs_set_res(input, ABS_MT_POSITION_Y, cytp->tp_res_y); ++ ++ __set_bit(BTN_TOUCH, input->keybit); ++ __set_bit(BTN_TOOL_FINGER, input->keybit); ++ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); ++ __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); ++ __set_bit(BTN_TOOL_QUADTAP, input->keybit); ++ __set_bit(BTN_TOOL_QUINTTAP, input->keybit); ++ ++ __clear_bit(EV_REL, input->evbit); ++ __clear_bit(REL_X, input->relbit); ++ __clear_bit(REL_Y, input->relbit); ++ ++ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); ++ __set_bit(EV_KEY, input->evbit); ++ __set_bit(BTN_LEFT, input->keybit); ++ __set_bit(BTN_RIGHT, input->keybit); ++ __set_bit(BTN_MIDDLE, input->keybit); ++ ++ input_set_drvdata(input, cytp); ++ ++ return 0; ++} ++ ++static int cypress_get_finger_count(unsigned char header_byte) ++{ ++ unsigned char bits6_7; ++ int finger_count; ++ ++ bits6_7 = header_byte >> 6; ++ finger_count = bits6_7 & 0x03; ++ ++ if (finger_count == 1) ++ return 1; ++ ++ if (header_byte & ABS_HSCROLL_BIT) { ++ /* HSCROLL gets added on to 0 finger count. */ ++ switch (finger_count) { ++ case 0: return 4; ++ case 2: return 5; ++ default: ++ /* Invalid contact (e.g. palm). Ignore it. */ ++ return -1; ++ } ++ } ++ ++ return finger_count; ++} ++ ++ ++static int cypress_parse_packet(struct psmouse *psmouse, ++ struct cytp_data *cytp, struct cytp_report_data *report_data) ++{ ++ unsigned char *packet = psmouse->packet; ++ unsigned char header_byte = packet[0]; ++ int contact_cnt; ++ ++ memset(report_data, 0, sizeof(struct cytp_report_data)); ++ ++ contact_cnt = cypress_get_finger_count(header_byte); ++ ++ if (contact_cnt < 0) /* e.g. palm detect */ ++ return -EINVAL; ++ ++ report_data->contact_cnt = contact_cnt; ++ ++ report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; ++ ++ if (report_data->contact_cnt == 1) { ++ report_data->contacts[0].x = ++ ((packet[1] & 0x70) << 4) | packet[2]; ++ report_data->contacts[0].y = ++ ((packet[1] & 0x07) << 8) | packet[3]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[0].z = packet[4]; ++ ++ } else if (report_data->contact_cnt >= 2) { ++ report_data->contacts[0].x = ++ ((packet[1] & 0x70) << 4) | packet[2]; ++ report_data->contacts[0].y = ++ ((packet[1] & 0x07) << 8) | packet[3]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[0].z = packet[4]; ++ ++ report_data->contacts[1].x = ++ ((packet[5] & 0xf0) << 4) | packet[6]; ++ report_data->contacts[1].y = ++ ((packet[5] & 0x0f) << 8) | packet[7]; ++ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) ++ report_data->contacts[1].z = report_data->contacts[0].z; ++ } ++ ++ report_data->left = (header_byte & BTN_LEFT_BIT) ? 1 : 0; ++ report_data->right = (header_byte & BTN_RIGHT_BIT) ? 1 : 0; ++ ++ /* ++ * This is only true if one of the mouse buttons were tapped. Make ++ * sure it doesn't turn into a click. The regular tap-to-click ++ * functionality will handle that on its own. If we don't do this, ++ * disabling tap-to-click won't affect the mouse button zones. ++ */ ++ if (report_data->tap) ++ report_data->left = 0; ++ ++#ifdef CYTP_DEBUG_VERBOSE ++ { ++ int i; ++ int n = report_data->contact_cnt; ++ psmouse_dbg(psmouse, "Dump parsed report data as below:\n"); ++ psmouse_dbg(psmouse, "contact_cnt = %d\n", ++ report_data->contact_cnt); ++ if (n > CYTP_MAX_MT_SLOTS) ++ n = CYTP_MAX_MT_SLOTS; ++ for (i = 0; i < n; i++) ++ psmouse_dbg(psmouse, "contacts[%d] = {%d, %d, %d}\n", i, ++ report_data->contacts[i].x, ++ report_data->contacts[i].y, ++ report_data->contacts[i].z); ++ psmouse_dbg(psmouse, "left = %d\n", report_data->left); ++ psmouse_dbg(psmouse, "right = %d\n", report_data->right); ++ psmouse_dbg(psmouse, "middle = %d\n", report_data->middle); ++ } ++#endif ++ ++ return 0; ++} ++ ++static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) ++{ ++ int i; ++ struct input_dev *input = psmouse->dev; ++ struct cytp_data *cytp = psmouse->private; ++ struct cytp_report_data report_data; ++ struct cytp_contact *contact; ++ struct input_mt_pos pos[CYTP_MAX_MT_SLOTS]; ++ int slots[CYTP_MAX_MT_SLOTS]; ++ int n; ++ ++ if (cypress_parse_packet(psmouse, cytp, &report_data)) ++ return; ++ ++ n = report_data.contact_cnt; ++ ++ if (n > CYTP_MAX_MT_SLOTS) ++ n = CYTP_MAX_MT_SLOTS; ++ ++ for (i = 0; i < n; i++) { ++ contact = &report_data.contacts[i]; ++ pos[i].x = contact->x; ++ pos[i].y = contact->y; ++ } ++ ++ input_mt_assign_slots(input, slots, pos, n); ++ ++ for (i = 0; i < n; i++) { ++ contact = &report_data.contacts[i]; ++ input_mt_slot(input, slots[i]); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, true); ++ input_report_abs(input, ABS_MT_POSITION_X, contact->x); ++ input_report_abs(input, ABS_MT_POSITION_Y, contact->y); ++ input_report_abs(input, ABS_MT_PRESSURE, contact->z); ++ } ++ ++ input_mt_sync_frame(input); ++ ++ input_mt_report_finger_count(input, report_data.contact_cnt); ++ ++ input_report_key(input, BTN_LEFT, report_data.left); ++ input_report_key(input, BTN_RIGHT, report_data.right); ++ input_report_key(input, BTN_MIDDLE, report_data.middle); ++ ++ input_sync(input); ++} ++ ++static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) ++{ ++ int contact_cnt; ++ int index = psmouse->pktcnt - 1; ++ unsigned char *packet = psmouse->packet; ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (index < 0 || index > cytp->pkt_size) ++ return PSMOUSE_BAD_DATA; ++ ++ if (index == 0 && (packet[0] & 0xfc) == 0) { ++ /* call packet process for reporting finger leave. */ ++ cypress_process_packet(psmouse, 1); ++ return PSMOUSE_FULL_PACKET; ++ } ++ ++ /* ++ * Perform validation (and adjust packet size) based only on the ++ * first byte; allow all further bytes through. ++ */ ++ if (index != 0) ++ return PSMOUSE_GOOD_DATA; ++ ++ /* ++ * If absolute/relative mode bit has not been set yet, just pass ++ * the byte through. ++ */ ++ if ((cytp->mode & CYTP_BIT_ABS_REL_MASK) == 0) ++ return PSMOUSE_GOOD_DATA; ++ ++ if ((packet[0] & 0x08) == 0x08) ++ return PSMOUSE_BAD_DATA; ++ ++ contact_cnt = cypress_get_finger_count(packet[0]); ++ ++ if (contact_cnt < 0) ++ return PSMOUSE_BAD_DATA; ++ ++ if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) ++ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); ++ else ++ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 8 : 5); ++ ++ return PSMOUSE_GOOD_DATA; ++} ++ ++static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (psmouse->pktcnt >= cytp->pkt_size) { ++ cypress_process_packet(psmouse, 0); ++ return PSMOUSE_FULL_PACKET; ++ } ++ ++ return cypress_validate_byte(psmouse); ++} ++ ++static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) ++{ ++ struct cytp_data *cytp = psmouse->private; ++ ++ if (rate >= 80) { ++ psmouse->rate = 80; ++ cytp->mode |= CYTP_BIT_HIGH_RATE; ++ } else { ++ psmouse->rate = 40; ++ cytp->mode &= ~CYTP_BIT_HIGH_RATE; ++ } ++ ++ ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, ++ PSMOUSE_CMD_SETRATE); ++} ++ ++static void cypress_disconnect(struct psmouse *psmouse) ++{ ++ cypress_reset(psmouse); ++ kfree(psmouse->private); ++ psmouse->private = NULL; ++} ++ ++static int cypress_reconnect(struct psmouse *psmouse) ++{ ++ int tries = CYTP_PS2_CMD_TRIES; ++ int rc; ++ ++ do { ++ cypress_reset(psmouse); ++ rc = cypress_detect(psmouse, false); ++ } while (rc && (--tries > 0)); ++ ++ if (rc) { ++ psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); ++ return -1; ++ } ++ ++ if (cypress_set_absolute_mode(psmouse)) { ++ psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int cypress_init(struct psmouse *psmouse) ++{ ++ struct cytp_data *cytp; ++ ++ cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL); ++ psmouse->private = (void *)cytp; ++ if (cytp == NULL) ++ return -ENOMEM; ++ ++ cypress_reset(psmouse); ++ ++ psmouse->pktsize = 8; ++ ++ if (cypress_query_hardware(psmouse)) { ++ psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); ++ goto err_exit; ++ } ++ ++ if (cypress_set_absolute_mode(psmouse)) { ++ psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); ++ goto err_exit; ++ } ++ ++ if (cypress_set_input_params(psmouse->dev, cytp) < 0) { ++ psmouse_err(psmouse, "init: Unable to set input params.\n"); ++ goto err_exit; ++ } ++ ++ psmouse->model = 1; ++ psmouse->protocol_handler = cypress_protocol_handler; ++ psmouse->set_rate = cypress_set_rate; ++ psmouse->disconnect = cypress_disconnect; ++ psmouse->reconnect = cypress_reconnect; ++ psmouse->cleanup = cypress_reset; ++ psmouse->resync_time = 0; ++ ++ return 0; ++ ++err_exit: ++ /* ++ * Reset Cypress Trackpad as a standard mouse. Then ++ * let psmouse driver commmunicating with it as default PS2 mouse. ++ */ ++ cypress_reset(psmouse); ++ ++ psmouse->private = NULL; ++ kfree(cytp); ++ ++ return -1; ++} ++ ++bool cypress_supported(void) ++{ ++ return true; ++} +diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h +new file mode 100644 +index 0000000..4720f21 +--- /dev/null ++++ b/drivers/input/mouse/cypress_ps2.h +@@ -0,0 +1,191 @@ ++#ifndef _CYPRESS_PS2_H ++#define _CYPRESS_PS2_H ++ ++#include "psmouse.h" ++ ++#define CMD_BITS_MASK 0x03 ++#define COMPOSIT(x, s) (((x) & CMD_BITS_MASK) << (s)) ++ ++#define ENCODE_CMD(aa, bb, cc, dd) \ ++ (COMPOSIT((aa), 6) | COMPOSIT((bb), 4) | COMPOSIT((cc), 2) | COMPOSIT((dd), 0)) ++#define CYTP_CMD_ABS_NO_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 0) ++#define CYTP_CMD_ABS_WITH_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 1) ++#define CYTP_CMD_SMBUS_MODE ENCODE_CMD(0, 1, 1, 0) ++#define CYTP_CMD_STANDARD_MODE ENCODE_CMD(0, 2, 0, 0) /* not implemented yet. */ ++#define CYTP_CMD_CYPRESS_REL_MODE ENCODE_CMD(1, 1, 1, 1) /* not implemented yet. */ ++#define CYTP_CMD_READ_CYPRESS_ID ENCODE_CMD(0, 0, 0, 0) ++#define CYTP_CMD_READ_TP_METRICS ENCODE_CMD(0, 0, 0, 1) ++#define CYTP_CMD_SET_HSCROLL_WIDTH(w) ENCODE_CMD(1, 1, 0, (w)) ++#define CYTP_CMD_SET_HSCROLL_MASK ENCODE_CMD(1, 1, 0, 0) ++#define CYTP_CMD_SET_VSCROLL_WIDTH(w) ENCODE_CMD(1, 2, 0, (w)) ++#define CYTP_CMD_SET_VSCROLL_MASK ENCODE_CMD(1, 2, 0, 0) ++#define CYTP_CMD_SET_PALM_GEOMETRY(e) ENCODE_CMD(1, 2, 1, (e)) ++#define CYTP_CMD_PALM_GEMMETRY_MASK ENCODE_CMD(1, 2, 1, 0) ++#define CYTP_CMD_SET_PALM_SENSITIVITY(s) ENCODE_CMD(1, 2, 2, (s)) ++#define CYTP_CMD_PALM_SENSITIVITY_MASK ENCODE_CMD(1, 2, 2, 0) ++#define CYTP_CMD_SET_MOUSE_SENSITIVITY(s) ENCODE_CMD(1, 3, ((s) >> 2), (s)) ++#define CYTP_CMD_MOUSE_SENSITIVITY_MASK ENCODE_CMD(1, 3, 0, 0) ++#define CYTP_CMD_REQUEST_BASELINE_STATUS ENCODE_CMD(2, 0, 0, 1) ++#define CYTP_CMD_REQUEST_RECALIBRATION ENCODE_CMD(2, 0, 0, 3) ++ ++#define DECODE_CMD_AA(x) (((x) >> 6) & CMD_BITS_MASK) ++#define DECODE_CMD_BB(x) (((x) >> 4) & CMD_BITS_MASK) ++#define DECODE_CMD_CC(x) (((x) >> 2) & CMD_BITS_MASK) ++#define DECODE_CMD_DD(x) ((x) & CMD_BITS_MASK) ++ ++/* Cypress trackpad working mode. */ ++#define CYTP_BIT_ABS_PRESSURE (1 << 3) ++#define CYTP_BIT_ABS_NO_PRESSURE (1 << 2) ++#define CYTP_BIT_CYPRESS_REL (1 << 1) ++#define CYTP_BIT_STANDARD_REL (1 << 0) ++#define CYTP_BIT_REL_MASK (CYTP_BIT_CYPRESS_REL | CYTP_BIT_STANDARD_REL) ++#define CYTP_BIT_ABS_MASK (CYTP_BIT_ABS_PRESSURE | CYTP_BIT_ABS_NO_PRESSURE) ++#define CYTP_BIT_ABS_REL_MASK (CYTP_BIT_ABS_MASK | CYTP_BIT_REL_MASK) ++ ++#define CYTP_BIT_HIGH_RATE (1 << 4) ++/* ++ * report mode bit is set, firmware working in Remote Mode. ++ * report mode bit is cleared, firmware working in Stream Mode. ++ */ ++#define CYTP_BIT_REPORT_MODE (1 << 5) ++ ++/* scrolling width values for set HSCROLL and VSCROLL width command. */ ++#define SCROLL_WIDTH_NARROW 1 ++#define SCROLL_WIDTH_NORMAL 2 ++#define SCROLL_WIDTH_WIDE 3 ++ ++#define PALM_GEOMETRY_ENABLE 1 ++#define PALM_GEOMETRY_DISABLE 0 ++ ++#define TP_METRICS_MASK 0x80 ++#define FW_VERSION_MASX 0x7f ++#define FW_VER_HIGH_MASK 0x70 ++#define FW_VER_LOW_MASK 0x0f ++ ++/* Times to retry a ps2_command and millisecond delay between tries. */ ++#define CYTP_PS2_CMD_TRIES 3 ++#define CYTP_PS2_CMD_DELAY 500 ++ ++/* time out for PS/2 command only in milliseconds. */ ++#define CYTP_CMD_TIMEOUT 200 ++#define CYTP_DATA_TIMEOUT 30 ++ ++#define CYTP_EXT_CMD 0xe8 ++#define CYTP_PS2_RETRY 0xfe ++#define CYTP_PS2_ERROR 0xfc ++ ++#define CYTP_RESP_RETRY 0x01 ++#define CYTP_RESP_ERROR 0xfe ++ ++ ++#define CYTP_105001_WIDTH 97 /* Dell XPS 13 */ ++#define CYTP_105001_HIGH 59 ++#define CYTP_DEFAULT_WIDTH (CYTP_105001_WIDTH) ++#define CYTP_DEFAULT_HIGH (CYTP_105001_HIGH) ++ ++#define CYTP_ABS_MAX_X 1600 ++#define CYTP_ABS_MAX_Y 900 ++#define CYTP_MAX_PRESSURE 255 ++#define CYTP_MIN_PRESSURE 0 ++ ++/* header byte bits of relative package. */ ++#define BTN_LEFT_BIT 0x01 ++#define BTN_RIGHT_BIT 0x02 ++#define BTN_MIDDLE_BIT 0x04 ++#define REL_X_SIGN_BIT 0x10 ++#define REL_Y_SIGN_BIT 0x20 ++ ++/* header byte bits of absolute package. */ ++#define ABS_VSCROLL_BIT 0x10 ++#define ABS_HSCROLL_BIT 0x20 ++#define ABS_MULTIFINGER_TAP 0x04 ++#define ABS_EDGE_MOTION_MASK 0x80 ++ ++#define DFLT_RESP_BITS_VALID 0x88 /* SMBus bit should not be set. */ ++#define DFLT_RESP_SMBUS_BIT 0x80 ++#define DFLT_SMBUS_MODE 0x80 ++#define DFLT_PS2_MODE 0x00 ++#define DFLT_RESP_BIT_MODE 0x40 ++#define DFLT_RESP_REMOTE_MODE 0x40 ++#define DFLT_RESP_STREAM_MODE 0x00 ++#define DFLT_RESP_BIT_REPORTING 0x20 ++#define DFLT_RESP_BIT_SCALING 0x10 ++ ++#define TP_METRICS_BIT_PALM 0x80 ++#define TP_METRICS_BIT_STUBBORN 0x40 ++#define TP_METRICS_BIT_2F_JITTER 0x30 ++#define TP_METRICS_BIT_1F_JITTER 0x0c ++#define TP_METRICS_BIT_APA 0x02 ++#define TP_METRICS_BIT_MTG 0x01 ++#define TP_METRICS_BIT_ABS_PKT_FORMAT_SET 0xf0 ++#define TP_METRICS_BIT_2F_SPIKE 0x0c ++#define TP_METRICS_BIT_1F_SPIKE 0x03 ++ ++/* bits of first byte response of E9h-Status Request command. */ ++#define RESP_BTN_RIGHT_BIT 0x01 ++#define RESP_BTN_MIDDLE_BIT 0x02 ++#define RESP_BTN_LEFT_BIT 0x04 ++#define RESP_SCALING_BIT 0x10 ++#define RESP_ENABLE_BIT 0x20 ++#define RESP_REMOTE_BIT 0x40 ++#define RESP_SMBUS_BIT 0x80 ++ ++#define CYTP_MAX_MT_SLOTS 2 ++ ++struct cytp_contact { ++ int x; ++ int y; ++ int z; /* also named as touch pressure. */ ++}; ++ ++/* The structure of Cypress Trackpad event data. */ ++struct cytp_report_data { ++ int contact_cnt; ++ struct cytp_contact contacts[CYTP_MAX_MT_SLOTS]; ++ unsigned int left:1; ++ unsigned int right:1; ++ unsigned int middle:1; ++ unsigned int tap:1; /* multi-finger tap detected. */ ++}; ++ ++/* The structure of Cypress Trackpad device private data. */ ++struct cytp_data { ++ int fw_version; ++ ++ int pkt_size; ++ int mode; ++ ++ int tp_min_pressure; ++ int tp_max_pressure; ++ int tp_width; /* X direction physical size in mm. */ ++ int tp_high; /* Y direction physical size in mm. */ ++ int tp_max_abs_x; /* Max X absolute units that can be reported. */ ++ int tp_max_abs_y; /* Max Y absolute units that can be reported. */ ++ ++ int tp_res_x; /* X resolution in units/mm. */ ++ int tp_res_y; /* Y resolution in units/mm. */ ++ ++ int tp_metrics_supported; ++}; ++ ++ ++#ifdef CONFIG_MOUSE_PS2_CYPRESS ++int cypress_detect(struct psmouse *psmouse, bool set_properties); ++int cypress_init(struct psmouse *psmouse); ++bool cypress_supported(void); ++#else ++inline int cypress_detect(struct psmouse *psmouse, bool set_properties) ++{ ++ return -ENOSYS; ++} ++inline int cypress_init(struct psmouse *psmouse) ++{ ++ return -ENOSYS; ++} ++inline bool cypress_supported(void) ++{ ++ return 0; ++} ++#endif /* CONFIG_MOUSE_PS2_CYPRESS */ ++ ++#endif /* _CYPRESS_PS2_H */ +diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c +index 22fe254..cff065f 100644 +--- a/drivers/input/mouse/psmouse-base.c ++++ b/drivers/input/mouse/psmouse-base.c +@@ -34,6 +34,7 @@ + #include "touchkit_ps2.h" + #include "elantech.h" + #include "sentelic.h" ++#include "cypress_ps2.h" + + #define DRIVER_DESC "PS/2 mouse driver" + +@@ -759,6 +760,28 @@ static int psmouse_extensions(struct psmouse *psmouse, + } + + /* ++ * Try Cypress Trackpad. ++ * Must try it before Finger Sensing Pad because Finger Sensing Pad probe ++ * upsets some modules of Cypress Trackpads. ++ */ ++ if (max_proto > PSMOUSE_IMEX && ++ cypress_detect(psmouse, set_properties) == 0) { ++ if (cypress_supported()) { ++ if (cypress_init(psmouse) == 0) ++ return PSMOUSE_CYPRESS; ++ ++ /* ++ * Finger Sensing Pad probe upsets some modules of ++ * Cypress Trackpad, must avoid Finger Sensing Pad ++ * probe if Cypress Trackpad device detected. ++ */ ++ return PSMOUSE_PS2; ++ } ++ ++ max_proto = PSMOUSE_IMEX; ++ } ++ ++/* + * Try ALPS TouchPad + */ + if (max_proto > PSMOUSE_IMEX) { +@@ -896,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { + .alias = "thinkps", + .detect = thinking_detect, + }, ++#ifdef CONFIG_MOUSE_PS2_CYPRESS ++ { ++ .type = PSMOUSE_CYPRESS, ++ .name = "CyPS/2", ++ .alias = "cypress", ++ .detect = cypress_detect, ++ .init = cypress_init, ++ }, ++#endif + { + .type = PSMOUSE_GENPS, + .name = "GenPS/2", +diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h +index fe1df23..2f0b39d 100644 +--- a/drivers/input/mouse/psmouse.h ++++ b/drivers/input/mouse/psmouse.h +@@ -95,6 +95,7 @@ enum psmouse_type { + PSMOUSE_ELANTECH, + PSMOUSE_FSP, + PSMOUSE_SYNAPTICS_RELATIVE, ++ PSMOUSE_CYPRESS, + PSMOUSE_AUTO /* This one should always be last */ + }; + +-- +1.7.7.6 + diff --git a/Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch b/Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch new file mode 100644 index 000000000..c3548aa07 --- /dev/null +++ b/Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch @@ -0,0 +1,30 @@ +From 80524f083e2c3e70057f5bb476db92baa14cb22b Mon Sep 17 00:00:00 2001 +From: Kamal Mostafa +Date: Tue, 20 Nov 2012 23:04:35 -0800 +Subject: [PATCH] Input: increase struct ps2dev cmdbuf[] to 8 bytes + +Cypress PS/2 Trackpad (drivers/input/mouse/cypress_ps2.c) needs +this larger cmdbuf[] to handle 8-byte packet responses. + +Signed-off-by: Kamal Mostafa +Signed-off-by: Dmitry Torokhov +--- + include/linux/libps2.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/include/linux/libps2.h b/include/linux/libps2.h +index 79603a6..4ad06e8 100644 +--- a/include/linux/libps2.h ++++ b/include/linux/libps2.h +@@ -36,7 +36,7 @@ struct ps2dev { + wait_queue_head_t wait; + + unsigned long flags; +- unsigned char cmdbuf[6]; ++ unsigned char cmdbuf[8]; + unsigned char cmdcnt; + unsigned char nak; + }; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 4303fd218..e1d177bee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -782,6 +782,10 @@ Patch21238: brcmsmac-updates-rhbz892428.patch #rhbz 863424 Patch21239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch +#rhbz 799564 +Patch21240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch +Patch21241: Input-add-support-for-Cypress-PS2-Trackpads.patch + # END OF PATCH DEFINITIONS %endif @@ -1501,6 +1505,10 @@ ApplyPatch brcmsmac-updates-rhbz892428.patch #rhbz 863424 ApplyPatch Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch +#rhbz 799564 +ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch +ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch + # END OF PATCH APPLICATIONS %endif @@ -2364,6 +2372,9 @@ fi # ||----w | # || || %changelog +* Tue Jan 29 2013 Josh Boyer +- Backport driver for Cypress PS/2 trackpad (rhbz 799564) + * Mon Jan 28 2013 Josh Boyer - 3.7.5-201 - Linux v3.7.5 - Add patch to fix iwlwifi issues (rhbz 863424) From bd4318b80d3d41a33240ae3d7bd87e92112dbb65 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Feb 2013 09:20:20 -0500 Subject: [PATCH 167/492] Linux v3.7.6 - Update secure-boot patchset --- iwlegacy-fix-IBSS-cleanup.patch | 104 - kernel.spec | 18 +- ...12.patch => secure-boot-3.7-20130204.patch | 1756 ++++++++--------- sources | 2 +- 4 files changed, 819 insertions(+), 1061 deletions(-) delete mode 100644 iwlegacy-fix-IBSS-cleanup.patch rename secure-boot-20121212.patch => secure-boot-3.7-20130204.patch (80%) diff --git a/iwlegacy-fix-IBSS-cleanup.patch b/iwlegacy-fix-IBSS-cleanup.patch deleted file mode 100644 index 5533aed75..000000000 --- a/iwlegacy-fix-IBSS-cleanup.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 658f1bd2dd632209df00ec66349e15941ffdd83b Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Wed, 16 Jan 2013 10:28:09 +0000 -Subject: [PATCH 3.8] iwlegacy: fix IBSS cleanup - -We do not correctly change interface type when switching from -IBSS mode to STA mode, that results in microcode errors. - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=886946 - -Reported-by: Jaroslav Skarvada -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlegacy/common.c | 35 ++++++++++++++-------------------- - 1 file changed, 14 insertions(+), 21 deletions(-) - -diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c -index 7e16d10..90b8970 100644 ---- a/drivers/net/wireless/iwlegacy/common.c -+++ b/drivers/net/wireless/iwlegacy/common.c -@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) - - memset(&il->staging, 0, sizeof(il->staging)); - -- if (!il->vif) { -+ switch (il->iw_mode) { -+ case NL80211_IFTYPE_UNSPECIFIED: - il->staging.dev_type = RXON_DEV_TYPE_ESS; -- } else if (il->vif->type == NL80211_IFTYPE_STATION) { -+ break; -+ case NL80211_IFTYPE_STATION: - il->staging.dev_type = RXON_DEV_TYPE_ESS; - il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; -- } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { -+ break; -+ case NL80211_IFTYPE_ADHOC: - il->staging.dev_type = RXON_DEV_TYPE_IBSS; - il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - il->staging.filter_flags = - RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; -- } else { -+ break; -+ default: - IL_ERR("Unsupported interface type %d\n", il->vif->type); - return; - } -@@ -4550,8 +4554,7 @@ out: - EXPORT_SYMBOL(il_mac_add_interface); - - static void --il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, -- bool mode_change) -+il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) - { - lockdep_assert_held(&il->mutex); - -@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, - il_force_scan_end(il); - } - -- if (!mode_change) -- il_set_mode(il); -- -+ il_set_mode(il); - } - - void -@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) - - WARN_ON(il->vif != vif); - il->vif = NULL; -- -- il_teardown_interface(il, vif, false); -+ il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; -+ il_teardown_interface(il, vif); - memset(il->bssid, 0, ETH_ALEN); - - D_MAC80211("leave\n"); -@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - } - - /* success */ -- il_teardown_interface(il, vif, true); - vif->type = newtype; - vif->p2p = false; -- err = il_set_mode(il); -- WARN_ON(err); -- /* -- * We've switched internally, but submitting to the -- * device may have failed for some reason. Mask this -- * error, because otherwise mac80211 will not switch -- * (and set the interface type back) and we'll be -- * out of sync with it. -- */ -+ il->iw_mode = newtype; -+ il_teardown_interface(il, vif); - err = 0; - - out: --- -1.8.0.2 - diff --git a/kernel.spec b/kernel.spec index e1d177bee..0f74ab6f8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -690,7 +690,7 @@ Patch800: linux-2.6-crash-driver.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20121212.patch +Patch1000: secure-boot-3.7-20130204.patch Patch1001: efivarfs-3.7.patch # Improve PCI support on UEFI @@ -773,9 +773,6 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 886946 -Patch21234: iwlegacy-fix-IBSS-cleanup.patch - #rhbz 892428 Patch21238: brcmsmac-updates-rhbz892428.patch @@ -1429,7 +1426,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.7.patch -ApplyPatch secure-boot-20121212.patch +ApplyPatch secure-boot-3.7-20130204.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1496,9 +1493,6 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 886948 -ApplyPatch iwlegacy-fix-IBSS-cleanup.patch - #rhbz 892428 ApplyPatch brcmsmac-updates-rhbz892428.patch @@ -2372,6 +2366,10 @@ fi # ||----w | # || || %changelog +* Mon Feb 04 2013 Josh Boyer +- Linux v3.7.6 +- Update secure-boot patchset + * Tue Jan 29 2013 Josh Boyer - Backport driver for Cypress PS/2 trackpad (rhbz 799564) diff --git a/secure-boot-20121212.patch b/secure-boot-3.7-20130204.patch similarity index 80% rename from secure-boot-20121212.patch rename to secure-boot-3.7-20130204.patch index 61f796e85..653ac672a 100644 --- a/secure-boot-20121212.patch +++ b/secure-boot-3.7-20130204.patch @@ -1,7 +1,7 @@ -From d510ea864f470d96aafb75d0de7f09450407095e Mon Sep 17 00:00:00 2001 +From 428db98d65770561ec5b8e9fc1931acf2210c5dd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/20] Secure boot: Add new capability +Subject: [PATCH 01/17] Secure boot: Add new capability Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. @@ -32,13 +32,787 @@ index ba478fa..7109e65 100644 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) -- -1.8.0.1 +1.8.1 -From a07ae01ac4b304ac7f0e2b5d4193519f1a9eee8d Mon Sep 17 00:00:00 2001 +From 57902a5335b6f1f0aad56c669c874b45e9dd4ee8 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:05 -0400 +Subject: [PATCH 02/17] SELinux: define mapping for new Secure Boot capability + +Add the name of the new Secure Boot capability. This allows SELinux +policies to properly map CAP_COMPROMISE_KERNEL to the appropriate +capability class. + +Signed-off-by: Josh Boyer +--- + security/selinux/include/classmap.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h +index df2de54..70e2834 100644 +--- a/security/selinux/include/classmap.h ++++ b/security/selinux/include/classmap.h +@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { + { "memprotect", { "mmap_zero", NULL } }, + { "peer", { "recv", NULL } }, + { "capability2", +- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", +- NULL } }, ++ { "mac_override", "mac_admin", "syslog", "wake_alarm", ++ "block_suspend", "compromise_kernel", NULL } }, + { "kernel_service", { "use_as_override", "create_files_as", NULL } }, + { "tun_socket", + { COMMON_SOCK_PERMS, NULL } }, +-- +1.8.1 + + +From 7e2d1d442399258426c0724e7fd6adc6fd8a8590 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:02 -0400 +Subject: [PATCH 03/17] Secure boot: Add a dummy kernel parameter that will + switch on Secure Boot mode + +This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset +in the init_cred struct, which everything else inherits from. This works on +any machine and can be used to develop even if the box doesn't have UEFI. + +Signed-off-by: Josh Boyer +--- + Documentation/kernel-parameters.txt | 7 +++++++ + kernel/cred.c | 17 +++++++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 9776f06..0d6c28d 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + Note: increases power consumption, thus should only be + enabled if running jitter sensitive (HPC/RT) workloads. + ++ secureboot_enable= ++ [KNL] Enables an emulated UEFI Secure Boot mode. This ++ locks down various aspects of the kernel guarded by the ++ CAP_COMPROMISE_KERNEL capability. This includes things ++ like /dev/mem, IO port access, and other areas. It can ++ be used on non-UEFI machines for testing purposes. ++ + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be +diff --git a/kernel/cred.c b/kernel/cred.c +index 48cea3d..3f5be65 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -623,6 +623,23 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++void __init secureboot_enable() ++{ ++ pr_info("Secure boot enabled\n"); ++ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); ++ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++} ++ ++/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ ++static int __init secureboot_enable_opt(char *str) ++{ ++ int sb_enable = !!simple_strtol(str, NULL, 0); ++ if (sb_enable) ++ secureboot_enable(); ++ return 1; ++} ++__setup("secureboot_enable=", secureboot_enable_opt); ++ + /** + * prepare_kernel_cred - Prepare a set of credentials for a kernel service + * @daemon: A userspace daemon to be used as a reference +-- +1.8.1 + + +From 6be9cea6bf2cf06898efa300644ea9e6ad9c5a18 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:03 -0400 +Subject: [PATCH 04/17] efi: Enable secure boot lockdown automatically when + enabled in firmware + +The firmware has a set of flags that indicate whether secure boot is enabled +and enforcing. Use them to indicate whether the kernel should lock itself +down. We also indicate the machine is in secure boot mode by adding the +EFI_SECURE_BOOT bit for use with efi_enabled. + +Signed-off-by: Matthew Garrett +Signed-off-by: Josh Boyer +--- + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ + arch/x86/include/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 5 +++++ + include/linux/cred.h | 2 ++ + include/linux/efi.h | 1 + + 6 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt +index cf5437d..7f9ed48 100644 +--- a/Documentation/x86/zero-page.txt ++++ b/Documentation/x86/zero-page.txt +@@ -27,6 +27,8 @@ Offset Proto Name Meaning + 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) + 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer + (below) ++1EB/001 ALL kbd_status Numlock is enabled ++1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns + 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures + 2D0/A00 ALL e820_map E820 memory map table + (array of struct e820entry) +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index ccae7e2..4983e43 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -731,6 +731,36 @@ fail: + return status; + } + ++static int get_secure_boot(efi_system_table_t *_table) ++{ ++ u8 sb, setup; ++ unsigned long datasize = sizeof(sb); ++ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; ++ efi_status_t status; ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SecureBoot", &var_guid, NULL, &datasize, &sb); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (sb == 0) ++ return 0; ++ ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SetupMode", &var_guid, NULL, &datasize, ++ &setup); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (setup == 1) ++ return 0; ++ ++ return 1; ++} ++ + /* + * Because the x86 boot code expects to be passed a boot_params we + * need to create one ourselves (usually the bootloader would create +@@ -1025,6 +1055,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, + if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + goto fail; + ++ boot_params->secure_boot = get_secure_boot(sys_table); ++ + setup_graphics(boot_params); + + status = efi_call_phys3(sys_table->boottime->allocate_pool, +diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h +index 2ad874c..c7338e0 100644 +--- a/arch/x86/include/asm/bootparam.h ++++ b/arch/x86/include/asm/bootparam.h +@@ -114,7 +114,8 @@ struct boot_params { + __u8 eddbuf_entries; /* 0x1e9 */ + __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ + __u8 kbd_status; /* 0x1eb */ +- __u8 _pad6[5]; /* 0x1ec */ ++ __u8 secure_boot; /* 0x1ec */ ++ __u8 _pad6[4]; /* 0x1ed */ + struct setup_header hdr; /* setup header */ /* 0x1f1 */ + __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; + __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index aeacb0e..a196a7e 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1042,6 +1042,11 @@ void __init setup_arch(char **cmdline_p) + + io_delay_init(); + ++ if (boot_params.secure_boot) { ++ set_bit(EFI_SECURE_BOOT, &x86_efi_facility); ++ secureboot_enable(); ++ } ++ + /* + * Parse the ACPI tables for possible boot-time SMP configuration. + */ +diff --git a/include/linux/cred.h b/include/linux/cred.h +index ebbed2c..a24faf1 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -170,6 +170,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); + extern int set_create_files_as(struct cred *, struct inode *); + extern void __init cred_init(void); + ++extern void secureboot_enable(void); ++ + /* + * check for validity of credentials + */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index b424f64..fef4ca6 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -551,6 +551,7 @@ extern int __init efi_setup_pcdp_console(char *); + #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ + #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ + #define EFI_64BIT 5 /* Is the firmware 64-bit? */ ++#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */ + + #ifdef CONFIG_EFI + # ifdef CONFIG_X86 +-- +1.8.1 + + +From 2d03e24bded4e30a14656795eb8e052bbaa5ee27 Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:30:54 -0400 +Subject: [PATCH 05/17] Add EFI signature data types + +Add the data types that are used for containing hashes, keys and certificates +for cryptographic verification. + +Signed-off-by: David Howells +--- + include/linux/efi.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index fef4ca6..a5dab3c 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + ++#define EFI_CERT_SHA256_GUID \ ++ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) ++ ++#define EFI_CERT_X509_GUID \ ++ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +@@ -447,6 +453,20 @@ typedef struct { + + #define EFI_INVALID_TABLE_ADDR (~0UL) + ++typedef struct { ++ efi_guid_t signature_owner; ++ u8 signature_data[]; ++} efi_signature_data_t; ++ ++typedef struct { ++ efi_guid_t signature_type; ++ u32 signature_list_size; ++ u32 signature_header_size; ++ u32 signature_size; ++ u8 signature_header[]; ++ /* efi_signature_data_t signatures[][] */ ++} efi_signature_list_t; ++ + /* + * All runtime access to EFI goes through this structure: + */ +-- +1.8.1 + + +From 2152dae45a6f98592ed5a6da8416a4a799bda3dd Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:36:28 -0400 +Subject: [PATCH 06/17] Add an EFI signature blob parser and key loader. + +X.509 certificates are loaded into the specified keyring as asymmetric type +keys. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 8 +++ + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++ + include/linux/efi.h | 4 ++ + 4 files changed, 121 insertions(+) + create mode 100644 crypto/asymmetric_keys/efi_parser.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 6d2c2ea..ace9c30 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER + data and provides the ability to instantiate a crypto key from a + public key packet found inside the certificate. + ++config EFI_SIGNATURE_LIST_PARSER ++ bool "EFI signature list parser" ++ depends on EFI ++ select X509_CERTIFICATE_PARSER ++ help ++ This option provides support for parsing EFI signature lists for ++ X.509 certificates and turning them into keys. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 0727204..cd8388e 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o + + # + # X.509 Certificate handling +diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c +new file mode 100644 +index 0000000..636feb1 +--- /dev/null ++++ b/crypto/asymmetric_keys/efi_parser.c +@@ -0,0 +1,108 @@ ++/* EFI signature/key/certificate list parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "EFI: "fmt ++#include ++#include ++#include ++#include ++#include ++ ++static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; ++ ++/** ++ * parse_efi_signature_list - Parse an EFI signature list for certificates ++ * @data: The data blob to parse ++ * @size: The size of the data blob ++ * @keyring: The keyring to add extracted keys to ++ */ ++int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) ++{ ++ unsigned offs = 0; ++ size_t lsize, esize, hsize, elsize; ++ ++ pr_devel("-->%s(,%zu)\n", __func__, size); ++ ++ while (size > 0) { ++ efi_signature_list_t list; ++ const efi_signature_data_t *elem; ++ key_ref_t key; ++ ++ if (size < sizeof(list)) ++ return -EBADMSG; ++ ++ memcpy(&list, data, sizeof(list)); ++ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", ++ offs, ++ list.signature_type.b, list.signature_list_size, ++ list.signature_header_size, list.signature_size); ++ ++ lsize = list.signature_list_size; ++ hsize = list.signature_header_size; ++ esize = list.signature_size; ++ elsize = lsize - sizeof(list) - hsize; ++ ++ if (lsize > size) { ++ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", ++ __func__, offs); ++ return -EBADMSG; ++ } ++ if (lsize < sizeof(list) || ++ lsize - sizeof(list) < hsize || ++ esize < sizeof(*elem) || ++ elsize < esize || ++ elsize % esize != 0) { ++ pr_devel("- bad size combo @%x\n", offs); ++ return -EBADMSG; ++ } ++ ++ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { ++ data += lsize; ++ size -= lsize; ++ offs += lsize; ++ continue; ++ } ++ ++ data += sizeof(list) + hsize; ++ size -= sizeof(list) + hsize; ++ offs += sizeof(list) + hsize; ++ ++ for (; elsize > 0; elsize -= esize) { ++ elem = data; ++ ++ pr_devel("ELEM[%04x]\n", offs); ++ ++ key = key_create_or_update( ++ make_key_ref(keyring, 1), ++ "asymmetric", ++ NULL, ++ &elem->signature_data, ++ esize - sizeof(*elem), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ ++ if (IS_ERR(key)) ++ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("Loaded cert '%s' linked to '%s'\n", ++ key_ref_to_ptr(key)->description, ++ keyring->description); ++ ++ data += esize; ++ size -= esize; ++ offs += esize; ++ } ++ } ++ ++ return 0; ++} +diff --git a/include/linux/efi.h b/include/linux/efi.h +index a5dab3c..7bfc4f2 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -536,6 +536,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); + extern void efi_reserve_boot_services(void); + extern struct efi_memory_map memmap; + ++struct key; ++extern int __init parse_efi_signature_list(const void *data, size_t size, ++ struct key *keyring); ++ + /** + * efi_range_is_wc - check the WC bit on an address range + * @start: starting kvirt address +-- +1.8.1 + + +From bb1024f03b0a4cb05bac6503b933279a905bc5fb Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:36:24 -0400 +Subject: [PATCH 07/17] MODSIGN: Add module certificate blacklist keyring + +This adds an additional keyring that is used to store certificates that +are blacklisted. This keyring is searched first when loading signed modules +and if the module's certificate is found, it will refuse to load. This is +useful in cases where third party certificates are used for module signing. + +Signed-off-by: Josh Boyer +--- + init/Kconfig | 8 ++++++++ + kernel/modsign_pubkey.c | 17 +++++++++++++++++ + kernel/module-internal.h | 3 +++ + kernel/module_signing.c | 12 ++++++++++++ + 4 files changed, 40 insertions(+) + +diff --git a/init/Kconfig b/init/Kconfig +index 6fdd6e3..7a9bf00 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE + Reject unsigned modules or signed modules for which we don't have a + key. Without this, such modules will simply taint the kernel. + ++config MODULE_SIG_BLACKLIST ++ bool "Support for blacklisting module signature certificates" ++ depends on MODULE_SIG ++ help ++ This adds support for keeping a blacklist of certificates that ++ should not pass module signature verification. If a module is ++ signed with something in this keyring, the load will be rejected. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +index 767e559..d99cd51 100644 +--- a/kernel/modsign_pubkey.c ++++ b/kernel/modsign_pubkey.c +@@ -17,6 +17,9 @@ + #include "module-internal.h" + + struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++struct key *modsign_blacklist; ++#endif + + extern __initdata const u8 modsign_certificate_list[]; + extern __initdata const u8 modsign_certificate_list_end[]; +@@ -52,6 +55,20 @@ static __init int module_verify_init(void) + if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) + panic("Can't instantiate module signing keyring\n"); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", ++ KUIDT_INIT(0), KGIDT_INIT(0), ++ current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_blacklist)) ++ panic("Can't allocate module signing blacklist keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module blacklist keyring\n"); ++#endif ++ + return 0; + } + +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 24f9247..51a8380 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -10,5 +10,8 @@ + */ + + extern struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++extern struct key *modsign_blacklist; ++#endif + + extern int mod_verify_sig(const void *mod, unsigned long *_modlen); +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index f2970bd..5423195 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ key = keyring_search(make_key_ref(modsign_blacklist, 1), ++ &key_type_asymmetric, id); ++ if (!IS_ERR(key)) { ++ /* module is signed with a cert in the blacklist. reject */ ++ pr_err("Module key '%s' is in blacklist\n", id); ++ key_ref_put(key); ++ kfree(id); ++ return ERR_PTR(-EKEYREJECTED); ++ } ++#endif ++ + key = keyring_search(make_key_ref(modsign_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) +-- +1.8.1 + + +From 10f89ba8724e88046cd05aef20e80a935d3968f6 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:42:16 -0400 +Subject: [PATCH 08/17] MODSIGN: Import certificates from UEFI Secure Boot + +Secure Boot stores a list of allowed certificates in the 'db' variable. +This imports those certificates into the module signing keyring. This +allows for a third party signing certificate to be used in conjunction +with signed modules. By importing the public certificate into the 'db' +variable, a user can allow a module signed with that certificate to +load. The shim UEFI bootloader has a similar certificate list stored +in the 'MokListRT' variable. We import those as well. + +In the opposite case, Secure Boot maintains a list of disallowed +certificates in the 'dbx' variable. We load those certificates into +the newly introduced module blacklist keyring and forbid any module +signed with those from loading. + +Signed-off-by: Josh Boyer +--- + include/linux/efi.h | 6 ++++ + init/Kconfig | 9 ++++++ + kernel/Makefile | 3 ++ + kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 108 insertions(+) + create mode 100644 kernel/modsign_uefi.c + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 7bfc4f2..014a013 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -318,6 +318,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_CERT_X509_GUID \ + EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) + ++#define EFI_IMAGE_SECURITY_DATABASE_GUID \ ++ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) ++ ++#define EFI_SHIM_LOCK_GUID \ ++ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +diff --git a/init/Kconfig b/init/Kconfig +index 7a9bf00..51aa170 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST + should not pass module signature verification. If a module is + signed with something in this keyring, the load will be rejected. + ++config MODULE_SIG_UEFI ++ bool "Allow modules signed with certs stored in UEFI" ++ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI ++ select EFI_SIGNATURE_LIST_PARSER ++ help ++ This will import certificates stored in UEFI and allow modules ++ signed with those to be loaded. It will also disallow loading ++ of modules stored in the UEFI dbx variable. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/Makefile b/kernel/Makefile +index 86e3285..12e17ab 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o ++obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o + + $(obj)/configs.o: $(obj)/config_data.h + ++$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar ++ + # config_data.h contains the same information as ikconfig.h but gzipped. + # Info from config_data can be extracted from /proc/config* + targets += config_data.gz +diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c +new file mode 100644 +index 0000000..b9237d7 +--- /dev/null ++++ b/kernel/modsign_uefi.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) ++{ ++ efi_status_t status; ++ unsigned long lsize = 4; ++ unsigned long tmpdb[4]; ++ void *db = NULL; ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); ++ if (status != EFI_BUFFER_TOO_SMALL) { ++ pr_err("Couldn't get size: 0x%lx\n", status); ++ return NULL; ++ } ++ ++ db = kmalloc(lsize, GFP_KERNEL); ++ if (!db) { ++ pr_err("Couldn't allocate memory for uefi cert list\n"); ++ goto out; ++ } ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, db); ++ if (status != EFI_SUCCESS) { ++ kfree(db); ++ db = NULL; ++ pr_err("Error reading db var: 0x%lx\n", status); ++ } ++out: ++ *size = lsize; ++ return db; ++} ++ ++/* ++ * * Load the certs contained in the UEFI databases ++ * */ ++static int __init load_uefi_certs(void) ++{ ++ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; ++ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; ++ void *db = NULL, *dbx = NULL, *mok = NULL; ++ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; ++ int rc = 0; ++ ++ /* Check if SB is enabled and just return if not */ ++ if (!efi_enabled(EFI_SECURE_BOOT)) ++ return 0; ++ ++ /* Get db, MokListRT, and dbx. They might not exist, so it isn't ++ * an error if we can't get them. ++ */ ++ db = get_cert_list(L"db", &secure_var, &dbsize); ++ if (!db) { ++ pr_err("MODSIGN: Couldn't get UEFI db list\n"); ++ } else { ++ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse db signatures: %d\n", rc); ++ kfree(db); ++ } ++ ++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); ++ if (!mok) { ++ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); ++ } else { ++ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); ++ kfree(mok); ++ } ++ ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); ++ if (!dbx) { ++ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); ++ } else { ++ rc = parse_efi_signature_list(dbx, dbxsize, ++ modsign_blacklist); ++ if (rc) ++ pr_err("Couldn't parse dbx signatures: %d\n", rc); ++ kfree(dbx); ++ } ++ ++ return rc; ++} ++late_initcall(load_uefi_certs); +-- +1.8.1 + + +From db76f49f8ded0df6aaff8ae2531ff1aaeff04440 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 02/20] PCI: Lock down BAR access in secure boot environments +Subject: [PATCH 09/17] PCI: Lock down BAR access in secure boot environments Any hardware that can potentially generate DMA has to be locked down from userspace in order to avoid it being possible for an attacker to cause @@ -133,13 +907,13 @@ index e1c1ec5..97e785f 100644 dev = pci_get_bus_and_slot(bus, dfn); -- -1.8.0.1 +1.8.1 -From 1b5a1b53577992b32a3f51b18aa07cb9b300a3b1 Mon Sep 17 00:00:00 2001 +From 0d71d1586db8d8f6f2f362953fc747528f0dbb2a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 03/20] x86: Lock down IO port access in secure boot +Subject: [PATCH 10/17] x86: Lock down IO port access in secure boot environments IO port access would permit users to gain access to PCI configuration @@ -190,13 +964,13 @@ index 0537903..47501fc 100644 return -EFAULT; while (count-- > 0 && i < 65536) { -- -1.8.0.1 +1.8.1 -From 09c266136915eb1f4a9b36423b7ba65e3d024de4 Mon Sep 17 00:00:00 2001 +From cbe40e9c220c6c49774e04d6e4df437a2f450aba Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 04/20] ACPI: Limit access to custom_method +Subject: [PATCH 11/17] ACPI: Limit access to custom_method It must be impossible for even root to get code executed in kernel context under a secure boot environment. custom_method effectively allows arbitrary @@ -222,13 +996,13 @@ index 5d42c24..247d58b 100644 /* parse the table header to get the table length */ if (count <= sizeof(struct acpi_table_header)) -- -1.8.0.1 +1.8.1 -From f3e9cb16e5ab3e680ec3ef464682c52371bbbbe3 Mon Sep 17 00:00:00 2001 +From 48da61f5b2a04df0a7df6d9e443a6705e2bc6ef9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 05/20] asus-wmi: Restrict debugfs interface +Subject: [PATCH 12/17] asus-wmi: Restrict debugfs interface We have no way of validating what all of the Asus WMI methods do on a given machine, and there's a risk that some will allow hardware state to @@ -275,13 +1049,13 @@ index c0e9ff4..3c10167 100644 1, asus->debug.method_id, &input, &output); -- -1.8.0.1 +1.8.1 -From 23372d2a40135aca7a6d73511bd88790b598b489 Mon Sep 17 00:00:00 2001 +From 293d2f88602d7d951c23e379c66d0adc440de47c Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 06/20] Restrict /dev/mem and /dev/kmem in secure boot setups +Subject: [PATCH 13/17] Restrict /dev/mem and /dev/kmem in secure boot setups Allowing users to write to address space makes it possible for the kernel to be subverted. Restrict this when we need to protect the kernel. @@ -316,206 +1090,13 @@ index 47501fc..8817cdc 100644 unsigned long to_write = min_t(unsigned long, count, (unsigned long)high_memory - p); -- -1.8.0.1 +1.8.1 -From a0c80b01e80a1f6484a2a2811b4a212322494614 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 07/20] Secure boot: Add a dummy kernel parameter that will - switch on Secure Boot mode - -This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset -in the init_cred struct, which everything else inherits from. This works on -any machine and can be used to develop even if the box doesn't have UEFI. - -Signed-off-by: Josh Boyer ---- - Documentation/kernel-parameters.txt | 7 +++++++ - kernel/cred.c | 17 +++++++++++++++++ - 2 files changed, 24 insertions(+) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 9776f06..0d6c28d 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - Note: increases power consumption, thus should only be - enabled if running jitter sensitive (HPC/RT) workloads. - -+ secureboot_enable= -+ [KNL] Enables an emulated UEFI Secure Boot mode. This -+ locks down various aspects of the kernel guarded by the -+ CAP_COMPROMISE_KERNEL capability. This includes things -+ like /dev/mem, IO port access, and other areas. It can -+ be used on non-UEFI machines for testing purposes. -+ - security= [SECURITY] Choose a security module to enable at boot. - If this boot parameter is not specified, only the first - security module asking for security registration will be -diff --git a/kernel/cred.c b/kernel/cred.c -index 48cea3d..3f5be65 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -623,6 +623,23 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+void __init secureboot_enable() -+{ -+ pr_info("Secure boot enabled\n"); -+ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); -+ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+} -+ -+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -+static int __init secureboot_enable_opt(char *str) -+{ -+ int sb_enable = !!simple_strtol(str, NULL, 0); -+ if (sb_enable) -+ secureboot_enable(); -+ return 1; -+} -+__setup("secureboot_enable=", secureboot_enable_opt); -+ - /** - * prepare_kernel_cred - Prepare a set of credentials for a kernel service - * @daemon: A userspace daemon to be used as a reference --- -1.8.0.1 - - -From 640f088c49da87a344417f58d3faa72d63a4f6ed Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 08/20] efi: Enable secure boot lockdown automatically when - enabled in firmware - -The firmware has a set of flags that indicate whether secure boot is enabled -and enforcing. Use them to indicate whether the kernel should lock itself -down. - -Signed-off-by: Matthew Garrett ---- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ - arch/x86/include/asm/bootparam.h | 3 ++- - arch/x86/kernel/setup.c | 3 +++ - include/linux/cred.h | 2 ++ - 5 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt -index cf5437d..7f9ed48 100644 ---- a/Documentation/x86/zero-page.txt -+++ b/Documentation/x86/zero-page.txt -@@ -27,6 +27,8 @@ Offset Proto Name Meaning - 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) - 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer - (below) -+1EB/001 ALL kbd_status Numlock is enabled -+1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns - 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures - 2D0/A00 ALL e820_map E820 memory map table - (array of struct e820entry) -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index e87b0ca..260cace 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -732,6 +732,36 @@ fail: - return status; - } - -+static int get_secure_boot(efi_system_table_t *_table) -+{ -+ u8 sb, setup; -+ unsigned long datasize = sizeof(sb); -+ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; -+ efi_status_t status; -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SecureBoot", &var_guid, NULL, &datasize, &sb); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (sb == 0) -+ return 0; -+ -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SetupMode", &var_guid, NULL, &datasize, -+ &setup); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (setup == 1) -+ return 0; -+ -+ return 1; -+} -+ - /* - * Because the x86 boot code expects to be passed a boot_params we - * need to create one ourselves (usually the bootloader would create -@@ -1026,6 +1056,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, - if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) - goto fail; - -+ boot_params->secure_boot = get_secure_boot(sys_table); -+ - setup_graphics(boot_params); - - status = efi_call_phys3(sys_table->boottime->allocate_pool, -diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h -index 2ad874c..c7338e0 100644 ---- a/arch/x86/include/asm/bootparam.h -+++ b/arch/x86/include/asm/bootparam.h -@@ -114,7 +114,8 @@ struct boot_params { - __u8 eddbuf_entries; /* 0x1e9 */ - __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ - __u8 kbd_status; /* 0x1eb */ -- __u8 _pad6[5]; /* 0x1ec */ -+ __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad6[4]; /* 0x1ed */ - struct setup_header hdr; /* setup header */ /* 0x1f1 */ - __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; - __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index ca45696..800673d 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -962,6 +962,9 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -+ if (boot_params.secure_boot) -+ secureboot_enable(); -+ - /* - * Parse the ACPI tables for possible boot-time SMP configuration. - */ -diff --git a/include/linux/cred.h b/include/linux/cred.h -index ebbed2c..a24faf1 100644 ---- a/include/linux/cred.h -+++ b/include/linux/cred.h -@@ -170,6 +170,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); - extern int set_create_files_as(struct cred *, struct inode *); - extern void __init cred_init(void); - -+extern void secureboot_enable(void); -+ - /* - * check for validity of credentials - */ --- -1.8.0.1 - - -From 994d895b5b684fc53c3b43dda9aee460c1f526f2 Mon Sep 17 00:00:00 2001 +From ca1c6f1c294f4ca76599603b801e84945d6f0277 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 09/20] acpi: Ignore acpi_rsdp kernel parameter in a secure +Subject: [PATCH 14/17] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment This option allows userspace to pass the RSDP address to the kernel. This @@ -528,7 +1109,7 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 9eaf708..f94341b 100644 +index 251435a..b67cf29 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); @@ -541,46 +1122,13 @@ index 9eaf708..f94341b 100644 #endif -- -1.8.0.1 +1.8.1 -From c80aaf3eee3cb6b0d1a051e418ee99cd238c868c Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 10/20] SELinux: define mapping for new Secure Boot capability - -Add the name of the new Secure Boot capability. This allows SELinux -policies to properly map CAP_COMPROMISE_KERNEL to the appropriate -capability class. - -Signed-off-by: Josh Boyer ---- - security/selinux/include/classmap.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index df2de54..70e2834 100644 ---- a/security/selinux/include/classmap.h -+++ b/security/selinux/include/classmap.h -@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { - { "memprotect", { "mmap_zero", NULL } }, - { "peer", { "recv", NULL } }, - { "capability2", -- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", -- NULL } }, -+ { "mac_override", "mac_admin", "syslog", "wake_alarm", -+ "block_suspend", "compromise_kernel", NULL } }, - { "kernel_service", { "use_as_override", "create_files_as", NULL } }, - { "tun_socket", - { COMMON_SOCK_PERMS, NULL } }, --- -1.8.0.1 - - -From 26352bcb92468233dd960b5d02ba1db344df72b9 Mon Sep 17 00:00:00 2001 +From 1e5b3f2c3ea547cd281bf5754fbc7717431db5fe Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 11/20] kexec: Disable in a secure boot environment +Subject: [PATCH 15/17] kexec: Disable in a secure boot environment kexec could be used as a vector for a malicious user to use a signed kernel to circumvent the secure boot trust model. In the long run we'll want to @@ -606,54 +1154,13 @@ index 5e4bd78..dd464e0 100644 /* -- -1.8.0.1 +1.8.1 -From c03c68adceaec9656c55c47190fb4243bf903b40 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 25 Jun 2012 21:29:46 -0400 -Subject: [PATCH 12/20] Documentation: kernel-parameters.txt remove - capability.disable - -Remove the documentation for capability.disable. The code supporting this -parameter was removed with: - - commit 5915eb53861c5776cfec33ca4fcc1fd20d66dd27 - Author: Miklos Szeredi - Date: Thu Jul 3 20:56:05 2008 +0200 - - security: remove dummy module - -Signed-off-by: Josh Boyer ---- - Documentation/kernel-parameters.txt | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 0d6c28d..d9af501 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - possible to determine what the correct size should be. - This option provides an override for these situations. - -- capability.disable= -- [SECURITY] Disable capabilities. This would normally -- be used only if an alternative security model is to be -- configured. Potentially dangerous and should only be -- used if you are entirely sure of the consequences. -- - ccw_timeout_log [S390] - See Documentation/s390/CommonIO for details. - --- -1.8.0.1 - - -From 3f1bda64d2c7b369e2833bd32cd1f3ba6c90348f Mon Sep 17 00:00:00 2001 +From c399cdb725681eba45239b3ae9218f0fc813e678 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH 13/20] modsign: Always enforce module signing in a Secure Boot +Subject: [PATCH 16/17] MODSIGN: Always enforce module signing in a Secure Boot environment If a machine is booted into a Secure Boot environment, we need to @@ -693,7 +1200,7 @@ index 3f5be65..a381e27 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index 6e48c3a..6d5d2aa 100644 +index 3e544f4..7a9a802 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ @@ -709,619 +1216,13 @@ index 6e48c3a..6d5d2aa 100644 static int param_set_bool_enable_only(const char *val, const struct kernel_param *kp) -- -1.8.0.1 +1.8.1 -From e6e3ec77b2fa037b32829e7f5ee468ad8a62dd05 Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 14/20] Add EFI signature data types, such as are used for - containing hashes, keys and certificates for cryptographic verification. - -Signed-off-by: David Howells ---- - include/linux/efi.h | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 337aefb..a01f8a7 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -317,6 +317,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - #define EFI_FILE_SYSTEM_GUID \ - EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -+#define EFI_CERT_SHA256_GUID \ -+ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) -+ -+#define EFI_CERT_X509_GUID \ -+ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -@@ -452,6 +458,20 @@ typedef struct { - - #define EFI_INVALID_TABLE_ADDR (~0UL) - -+typedef struct { -+ efi_guid_t signature_owner; -+ u8 signature_data[]; -+} efi_signature_data_t; -+ -+typedef struct { -+ efi_guid_t signature_type; -+ u32 signature_list_size; -+ u32 signature_header_size; -+ u32 signature_size; -+ u8 signature_header[]; -+ /* efi_signature_data_t signatures[][] */ -+} efi_signature_list_t; -+ - /* - * All runtime access to EFI goes through this structure: - */ --- -1.8.0.1 - - -From c2542256f632a22232cf02d5fd64568a5afa4516 Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 15/20] Add an EFI signature blob parser and key loader. X.509 - certificates are loaded into the specified keyring as asymmetric type keys. - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Kconfig | 7 +++ - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/efi_parser.c | 107 ++++++++++++++++++++++++++++++++++++ - include/linux/efi.h | 4 ++ - 4 files changed, 119 insertions(+) - create mode 100644 crypto/asymmetric_keys/efi_parser.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 6d2c2ea..eb53fc3 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -35,4 +35,11 @@ config X509_CERTIFICATE_PARSER - data and provides the ability to instantiate a crypto key from a - public key packet found inside the certificate. - -+config EFI_SIGNATURE_LIST_PARSER -+ bool "EFI signature list parser" -+ select X509_CERTIFICATE_PARSER -+ help -+ This option provides support for parsing EFI signature lists for -+ X.509 certificates and turning them into keys. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 0727204..cd8388e 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o - - # - # X.509 Certificate handling -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c -new file mode 100644 -index 0000000..59b859a ---- /dev/null -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -0,0 +1,107 @@ -+/* EFI signature/key/certificate list parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "EFI: "fmt -+#include -+#include -+#include -+#include -+#include -+ -+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; -+ -+/** -+ * parse_efi_signature_list - Parse an EFI signature list for certificates -+ * @data: The data blob to parse -+ * @size: The size of the data blob -+ * @keyring: The keyring to add extracted keys to -+ */ -+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) -+{ -+ unsigned offs = 0; -+ size_t lsize, esize, hsize, elsize; -+ -+ pr_devel("-->%s(,%zu)\n", __func__, size); -+ -+ while (size > 0) { -+ efi_signature_list_t list; -+ const efi_signature_data_t *elem; -+ key_ref_t key; -+ -+ if (size < sizeof(list)) -+ return -EBADMSG; -+ -+ memcpy(&list, data, sizeof(list)); -+ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", -+ offs, -+ list.signature_type.b, list.signature_list_size, -+ list.signature_header_size, list.signature_size); -+ -+ lsize = list.signature_list_size; -+ hsize = list.signature_header_size; -+ esize = list.signature_size; -+ elsize = lsize - sizeof(list) - hsize; -+ -+ if (lsize > size) { -+ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", -+ __func__, offs); -+ return -EBADMSG; -+ } -+ if (lsize < sizeof(list) || -+ lsize - sizeof(list) < hsize || -+ esize < sizeof(*elem) || -+ elsize < esize || -+ elsize % esize != 0) { -+ pr_devel("- bad size combo @%x\n", offs); -+ continue; -+ } -+ -+ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { -+ data += lsize; -+ size -= lsize; -+ offs += lsize; -+ continue; -+ } -+ -+ data += sizeof(list) + hsize; -+ size -= sizeof(list) + hsize; -+ offs += sizeof(list) + hsize; -+ -+ for (; elsize > 0; elsize -= esize) { -+ elem = data; -+ -+ pr_devel("ELEM[%04x]\n", offs); -+ -+ key = key_create_or_update( -+ make_key_ref(keyring, 1), -+ "asymmetric", -+ NULL, -+ &elem->signature_data, -+ esize - sizeof(*elem), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ -+ if (IS_ERR(key)) -+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("Loaded cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ -+ data += esize; -+ size -= esize; -+ offs += esize; -+ } -+ } -+ -+ return 0; -+} -diff --git a/include/linux/efi.h b/include/linux/efi.h -index a01f8a7..44a7faa 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -541,6 +541,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); - extern void efi_reserve_boot_services(void); - extern struct efi_memory_map memmap; - -+struct key; -+extern int __init parse_efi_signature_list(const void *data, size_t size, -+ struct key *keyring); -+ - /** - * efi_range_is_wc - check the WC bit on an address range - * @start: starting kvirt address --- -1.8.0.1 - - -From a418e6fdd2aa946a30cf1bee5c9540d03d626981 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:29:49 -0400 -Subject: [PATCH 16/20] EFI: Add in-kernel variable to determine if Secure Boot - is enabled - -There are a few cases where in-kernel functions may need to know if -Secure Boot is enabled. The added capability check cannot be used as the -kernel can't drop it's own capabilites, so we add a global variable -similar to efi_enabled so they can determine if Secure Boot is enabled. - -Signed-off-by: Josh Boyer ---- - arch/x86/kernel/setup.c | 6 +++++- - arch/x86/platform/efi/efi.c | 2 ++ - include/linux/efi.h | 3 +++ - 3 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 800673d..cf8823b 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -962,8 +962,12 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -- if (boot_params.secure_boot) -+ if (boot_params.secure_boot) { - secureboot_enable(); -+#ifdef CONFIG_EFI -+ secure_boot_enabled = 1; -+#endif -+ } - - /* - * Parse the ACPI tables for possible boot-time SMP configuration. -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index ad44391..d22bfeb 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -54,6 +54,8 @@ - int efi_enabled; - EXPORT_SYMBOL(efi_enabled); - -+int secure_boot_enabled; -+ - struct efi __read_mostly efi = { - .mps = EFI_INVALID_TABLE_ADDR, - .acpi = EFI_INVALID_TABLE_ADDR, -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 44a7faa..b5403ae 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -578,11 +578,14 @@ extern int __init efi_setup_pcdp_console(char *); - # ifdef CONFIG_X86 - extern int efi_enabled; - extern bool efi_64bit; -+ extern int secure_boot_enabled; - # else - # define efi_enabled 1 -+# define secure_boot_enabled 0 - # endif - #else - # define efi_enabled 0 -+# define secure_boot_enabled 0 - #endif - - /* --- -1.8.0.1 - - -From f6d05f0974f6a7667ebbbf91624678bcf32169ae Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 17/20] MODSIGN: Add module certificate blacklist keyring - -This adds an additional keyring that is used to store certificates that -are blacklisted. This keyring is searched first when loading signed modules -and if the module's certificate is found, it will refuse to load. This is -useful in cases where third party certificates are used for module signing. - -Signed-off-by: Josh Boyer ---- - init/Kconfig | 8 ++++++++ - kernel/modsign_pubkey.c | 17 +++++++++++++++++ - kernel/module-internal.h | 3 +++ - kernel/module_signing.c | 14 +++++++++++++- - 4 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/init/Kconfig b/init/Kconfig -index 6fdd6e3..7a9bf00 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. - -+config MODULE_SIG_BLACKLIST -+ bool "Support for blacklisting module signature certificates" -+ depends on MODULE_SIG -+ help -+ This adds support for keeping a blacklist of certificates that -+ should not pass module signature verification. If a module is -+ signed with something in this keyring, the load will be rejected. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 767e559..3bfb7ed 100644 ---- a/kernel/modsign_pubkey.c -+++ b/kernel/modsign_pubkey.c -@@ -17,6 +17,9 @@ - #include "module-internal.h" - - struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+struct key *modsign_blacklist; -+#endif - - extern __initdata const u8 modsign_certificate_list[]; - extern __initdata const u8 modsign_certificate_list_end[]; -@@ -52,6 +55,20 @@ static __init int module_verify_init(void) - if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) - panic("Can't instantiate module signing keyring\n"); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", -+ KUIDT_INIT(0), KGIDT_INIT(0), -+ current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_blacklist)) -+ panic("Can't allocate module signing blacklist keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing blacklist keyring\n"); -+#endif -+ - return 0; - } - -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 24f9247..51a8380 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -10,5 +10,8 @@ - */ - - extern struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+extern struct key *modsign_blacklist; -+#endif - - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index f2970bd..8ab83a6 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, - static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - const u8 *key_id, size_t key_id_len) - { -- key_ref_t key; -+ key_ref_t key, blacklist; - size_t i; - char *id, *q; - -@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - - pr_debug("Look up: \"%s\"\n", id); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ blacklist = keyring_search(make_key_ref(modsign_blacklist, 1), -+ &key_type_asymmetric, id); -+ if (!IS_ERR(blacklist)) { -+ /* module is signed with a cert in the blacklist. reject */ -+ pr_err("Module key '%s' is in blacklist\n", id); -+ key_ref_put(blacklist); -+ kfree(id); -+ return ERR_PTR(-EKEYREJECTED); -+ } -+#endif -+ - key = keyring_search(make_key_ref(modsign_keyring, 1), - &key_type_asymmetric, id); - if (IS_ERR(key)) --- -1.8.0.1 - - -From ff0ed221fe8d5a46a9bc36323ca8fb6f75c22a83 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot - -Secure Boot stores a list of allowed certificates in the 'db' variable. -This imports those certificates into the module signing keyring. This -allows for a third party signing certificate to be used in conjunction -with signed modules. By importing the public certificate into the 'db' -variable, a user can allow a module signed with that certificate to -load. The shim UEFI bootloader has a similar certificate list stored -in the 'MokListRT' variable. We import those as well. - -In the opposite case, Secure Boot maintains a list of disallowed -certificates in the 'dbx' variable. We load those certificates into -the newly introduced module blacklist keyring and forbid any module -signed with those from loading. - -Signed-off-by: Josh Boyer ---- - include/linux/efi.h | 6 ++++ - init/Kconfig | 9 ++++++ - kernel/Makefile | 3 ++ - kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 108 insertions(+) - create mode 100644 kernel/modsign_uefi.c - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index b5403ae..bba53e3 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -323,6 +323,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - #define EFI_CERT_X509_GUID \ - EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) - -+#define EFI_IMAGE_SECURITY_DATABASE_GUID \ -+ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) -+ -+#define EFI_SHIM_LOCK_GUID \ -+ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -diff --git a/init/Kconfig b/init/Kconfig -index 7a9bf00..51aa170 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST - should not pass module signature verification. If a module is - signed with something in this keyring, the load will be rejected. - -+config MODULE_SIG_UEFI -+ bool "Allow modules signed with certs stored in UEFI" -+ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI -+ select EFI_SIGNATURE_LIST_PARSER -+ help -+ This will import certificates stored in UEFI and allow modules -+ signed with those to be loaded. It will also disallow loading -+ of modules stored in the UEFI dbx variable. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/Makefile b/kernel/Makefile -index 86e3285..12e17ab 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o -+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o - - $(obj)/configs.o: $(obj)/config_data.h - -+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar -+ - # config_data.h contains the same information as ikconfig.h but gzipped. - # Info from config_data can be extracted from /proc/config* - targets += config_data.gz -diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c -new file mode 100644 -index 0000000..76a5a34 ---- /dev/null -+++ b/kernel/modsign_uefi.c -@@ -0,0 +1,90 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "module-internal.h" -+ -+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) -+{ -+ efi_status_t status; -+ unsigned long lsize = 4; -+ unsigned long tmpdb[4]; -+ void *db = NULL; -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); -+ if (status != EFI_BUFFER_TOO_SMALL) { -+ pr_err("Couldn't get size: 0x%lx\n", status); -+ return NULL; -+ } -+ -+ db = kmalloc(lsize, GFP_KERNEL); -+ if (!db) { -+ pr_err("Couldn't allocate memory for uefi cert list\n"); -+ goto out; -+ } -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, db); -+ if (status != EFI_SUCCESS) { -+ kfree(db); -+ db = NULL; -+ pr_err("Error reading db var: 0x%lx\n", status); -+ } -+out: -+ *size = lsize; -+ return db; -+} -+ -+/* -+ * * Load the certs contained in the UEFI databases -+ * */ -+static int __init load_uefi_certs(void) -+{ -+ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; -+ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; -+ void *db = NULL, *dbx = NULL, *mok = NULL; -+ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; -+ int rc = 0; -+ -+ /* Check if SB is enabled and just return if not */ -+ if (!secure_boot_enabled) -+ return 0; -+ -+ /* Get db, MokListRT, and dbx. They might not exist, so it isn't -+ * an error if we can't get them. -+ */ -+ db = get_cert_list(L"db", &secure_var, &dbsize); -+ if (!db) { -+ pr_err("MODSIGN: Couldn't get UEFI db list\n"); -+ } else { -+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse db signatures: %d\n", rc); -+ kfree(db); -+ } -+ -+ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); -+ if (!mok) { -+ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); -+ } else { -+ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); -+ kfree(mok); -+ } -+ -+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); -+ if (!dbx) { -+ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); -+ } else { -+ rc = parse_efi_signature_list(dbx, dbxsize, -+ modsign_blacklist); -+ if (rc) -+ pr_err("Couldn't parse dbx signatures: %d\n", rc); -+ kfree(dbx); -+ } -+ -+ return rc; -+} -+late_initcall(load_uefi_certs); --- -1.8.0.1 - - -From e45330362517d08579cdaddc718febe68e2cae06 Mon Sep 17 00:00:00 2001 +From 8e236de2ec08dceb9ce1e8ab07926e85440deb6b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH] hibernate: Disable in a Secure Boot environment +Subject: [PATCH 17/17] hibernate: Disable in a Secure Boot environment There is currently no way to verify the resume image when returning from hibernate. This might compromise the secure boot trust model, @@ -1336,7 +1237,7 @@ Signed-off-by: Josh Boyer 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index b26f5f1..26bdfa8 100644 +index b26f5f1..7f63cb4 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -28,6 +28,7 @@ @@ -1371,7 +1272,7 @@ index b26f5f1..26bdfa8 100644 int i; char *start = buf; -+ if (secure_boot_enabled) { ++ if (efi_enabled(EFI_SECURE_BOOT)) { + buf += sprintf(buf, "[%s]\n", "disabled"); + return buf-start; + } @@ -1390,7 +1291,7 @@ index b26f5f1..26bdfa8 100644 len = p ? p - buf : n; diff --git a/kernel/power/main.c b/kernel/power/main.c -index 1c16f91..8e3456d 100644 +index f458238..734bc26 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,6 +15,7 @@ @@ -1406,7 +1307,7 @@ index 1c16f91..8e3456d 100644 #endif #ifdef CONFIG_HIBERNATION - s += sprintf(s, "%s\n", "disk"); -+ if (!secure_boot_enabled) { ++ if (!efi_enabled(EFI_SECURE_BOOT)) { + s += sprintf(s, "%s\n", "disk"); + } else { + s += sprintf(s, "\n"); @@ -1429,42 +1330,5 @@ index 4ed81e7..b11a0f4 100644 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -- -1.8.0.2 - - -From 81adc779dba0f45f10b5ff307bd55832305f1112 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 12 Dec 2012 11:48:49 -0500 -Subject: [PATCH 20/20] Don't soft lockup on bad EFI signature lists - -If a signature list is read from an UEFI variable and that contains bogus -data, we can go into an infinite loop in efi_parse_signature_list. Notably, -if one of the entries in the list has a signature_size that is larger than -the actual signature size, it will fail the elsize < esize test. Simply -continuing in the loop without modifying the data or size variables just -leads to the same list entry being parsed repeatedly. - -Since the data is bogus, but we can't tell which value is actually -incorrect, we need to stop parsing the list. Just return -EBADMSG instead. - -Signed-off-by: Josh Boyer ---- - crypto/asymmetric_keys/efi_parser.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c -index 59b859a..a0b8a3a 100644 ---- a/crypto/asymmetric_keys/efi_parser.c -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -61,7 +61,7 @@ int __init parse_efi_signature_list(const void *data, size_t size, struct key *k - elsize < esize || - elsize % esize != 0) { - pr_devel("- bad size combo @%x\n", offs); -- continue; -+ return -EBADMSG; - } - - if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { --- -1.8.0.1 +1.8.1 diff --git a/sources b/sources index 17024d936..d3b6270f8 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -c100b62e571bfb80e8c290e811c0963c patch-3.7.5.xz +ec61c44f37585a768d41c0439101ef9c patch-3.7.6.xz From 0f4abb52b4575d9d64c5cbf41b160ba63395c931 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Feb 2013 09:49:15 -0500 Subject: [PATCH 168/492] Fix rtlwifi scheduling while atomic from Larry Finger (rhbz 903881) --- kernel.spec | 7 ++ rtlwifi-Fix-scheduling-while-atomic-bug.patch | 65 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 rtlwifi-Fix-scheduling-while-atomic-bug.patch diff --git a/kernel.spec b/kernel.spec index 0f74ab6f8..61eb82706 100644 --- a/kernel.spec +++ b/kernel.spec @@ -783,6 +783,9 @@ Patch21239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch Patch21240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch Patch21241: Input-add-support-for-Cypress-PS2-Trackpads.patch +#rhbz 903881 +Patch21246: rtlwifi-Fix-scheduling-while-atomic-bug.patch + # END OF PATCH DEFINITIONS %endif @@ -1503,6 +1506,9 @@ ApplyPatch Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch +#rhbz 903881 +ApplyPatch rtlwifi-Fix-scheduling-while-atomic-bug.patch + # END OF PATCH APPLICATIONS %endif @@ -2369,6 +2375,7 @@ fi * Mon Feb 04 2013 Josh Boyer - Linux v3.7.6 - Update secure-boot patchset +- Fix rtlwifi scheduling while atomic from Larry Finger (rhbz 903881) * Tue Jan 29 2013 Josh Boyer - Backport driver for Cypress PS/2 trackpad (rhbz 799564) diff --git a/rtlwifi-Fix-scheduling-while-atomic-bug.patch b/rtlwifi-Fix-scheduling-while-atomic-bug.patch new file mode 100644 index 000000000..d05b104b5 --- /dev/null +++ b/rtlwifi-Fix-scheduling-while-atomic-bug.patch @@ -0,0 +1,65 @@ +Kernel commits 41affd5 and 6539306 changed the locking in rtl_lps_leave() +from a spinlock to a mutex by doing the calls indirectly from a work queue +to reduce the time that interrupts were disabled. This change was fine for +most systems; however a scheduling while atomic bug was reported in +https://bugzilla.redhat.com/show_bug.cgi?id=903881. The backtrace indicates +that routine rtl_is_special(), which calls rtl_lps_leave() in three places +was entered in atomic context. These direct calls are replaced by putting a +request on the appropriate work queue. + +Signed-off-by: Larry Finger +Reported-and-tested-by: Nathaniel Doherty +Cc: Nathaniel Doherty +Cc: Stanislaw Gruszka +Cc: Stable +--- + +John, + +If DaveM will still accept bug fixes for 3.8, please push this one. It +is unlikely to have any side effects. + +Thanks, + +Larry +--- + + base.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +Index: wireless-testing-new/drivers/net/wireless/rtlwifi/base.c +=================================================================== +--- wireless-testing-new.orig/drivers/net/wireless/rtlwifi/base.c ++++ wireless-testing-new/drivers/net/wireless/rtlwifi/base.c +@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_ + is_tx ? "Tx" : "Rx"); + + if (is_tx) { +- rtl_lps_leave(hw); ++ schedule_work(&rtlpriv-> ++ works.lps_leave_work); + ppsc->last_delaylps_stamp_jiffies = + jiffies; + } +@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_ + } + } else if (ETH_P_ARP == ether_type) { + if (is_tx) { +- rtl_lps_leave(hw); ++ schedule_work(&rtlpriv->works.lps_leave_work); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + +@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_ + "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); + + if (is_tx) { +- rtl_lps_leave(hw); ++ schedule_work(&rtlpriv->works.lps_leave_work); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 2256aa8a758261bef7a3f183f3fe100cbdc10742 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 6 Feb 2013 09:57:47 -0500 Subject: [PATCH 169/492] Add patch to fix ath9k dma stop checks (rhbz 892811) --- ath9k_rx_dma_stop_check.patch | 28 ++++++++++++++++++++++++++++ kernel.spec | 11 ++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 ath9k_rx_dma_stop_check.patch diff --git a/ath9k_rx_dma_stop_check.patch b/ath9k_rx_dma_stop_check.patch new file mode 100644 index 000000000..606eb1c63 --- /dev/null +++ b/ath9k_rx_dma_stop_check.patch @@ -0,0 +1,28 @@ +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -689,7 +689,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw + { + #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ + struct ath_common *common = ath9k_hw_common(ah); +- u32 mac_status, last_mac_status = 0; ++ u32 mac_status = 0, last_mac_status = 0; + int i; + + /* Enable access to the DMA observation bus */ +@@ -719,6 +719,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw + } + + if (i == 0) { ++ if (!AR_SREV_9300_20_OR_LATER(ah) && ++ (mac_status & 0x700) == 0) { ++ /* ++ * DMA is idle but the MAC is still stuck ++ * processing events ++ */ ++ *reset = true; ++ return true; ++ } ++ + ath_err(common, + "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", + AH_RX_STOP_DMA_TIMEOUT / 1000, diff --git a/kernel.spec b/kernel.spec index 61eb82706..0fdce5b12 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -786,6 +786,9 @@ Patch21241: Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 903881 Patch21246: rtlwifi-Fix-scheduling-while-atomic-bug.patch +#rhbz 892811 +Patch21247: ath9k_rx_dma_stop_check.patch + # END OF PATCH DEFINITIONS %endif @@ -1509,6 +1512,9 @@ ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 903881 ApplyPatch rtlwifi-Fix-scheduling-while-atomic-bug.patch +#rhbz 892811 +ApplyPatch ath9k_rx_dma_stop_check.patch + # END OF PATCH APPLICATIONS %endif @@ -2372,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Wed Feb 06 2013 Josh Boyer +- Add patch to fix ath9k dma stop checks (rhbz 892811) + * Mon Feb 04 2013 Josh Boyer - Linux v3.7.6 - Update secure-boot patchset From 7234330c31b86e736dc925070c327f3ee143603d Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 7 Feb 2013 09:35:27 +0000 Subject: [PATCH 170/492] Minor ARM build fixes --- config-arm-generic | 3 ++- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-arm-generic b/config-arm-generic index d268b4d73..79e37a716 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -9,10 +9,10 @@ CONFIG_ARM=y CONFIG_ARM_THUMB=y CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y CONFIG_VFP=y CONFIG_ARM_UNWIND=y # CONFIG_ARCH_MULTI_V7 is not set +# CONFIG_OABI_COMPAT is not set CONFIG_SMP=y CONFIG_NR_CPUS=4 @@ -333,6 +333,7 @@ CONFIG_EXTCON_GPIO=m # CONFIG_GPIO_EM is not set # CONFIG_HVC_DCC is not set # CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_VIRTIO_CONSOLE is not set # Possibly part of Snowball # CONFIG_MFD_T7L66XB is not set diff --git a/kernel.spec b/kernel.spec index 0fdce5b12..8b55ace85 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2378,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 7 2013 Peter Robinson +- Minor ARM build fixes + * Wed Feb 06 2013 Josh Boyer - Add patch to fix ath9k dma stop checks (rhbz 892811) From 31d643927c2fb58f59da275ced9f7d443e02a334 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Feb 2013 08:32:00 -0500 Subject: [PATCH 171/492] Add patch to honor MokSBState (rhbz 907406) --- kernel.spec | 5 ++- secure-boot-3.7-20130204.patch | 58 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 8b55ace85..f1c927edc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2378,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Mon Feb 11 2013 Josh Boyer +- Add patch to honor MokSBState (rhbz 907406) + * Thu Feb 7 2013 Peter Robinson - Minor ARM build fixes diff --git a/secure-boot-3.7-20130204.patch b/secure-boot-3.7-20130204.patch index 653ac672a..c6765f6bd 100644 --- a/secure-boot-3.7-20130204.patch +++ b/secure-boot-3.7-20130204.patch @@ -1332,3 +1332,61 @@ index 4ed81e7..b11a0f4 100644 -- 1.8.1 +From 04a46ceeb9eb2dca0364ce836614de722e988c81 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 5 Feb 2013 19:25:05 -0500 +Subject: [PATCH] efi: Disable secure boot if shim is in insecure mode + +A user can manually tell the shim boot loader to disable validation of +images it loads. When a user does this, it creates a UEFI variable called +MokSBState that does not have the runtime attribute set. Given that the +user explicitly disabled validation, we can honor that and not enable +secure boot mode if that variable is set. + +Signed-off-by: Josh Boyer +--- + arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 96bd86b..6e1331c 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -851,8 +851,9 @@ fail: + + static int get_secure_boot(efi_system_table_t *_table) + { +- u8 sb, setup; ++ u8 sb, setup, moksbstate; + unsigned long datasize = sizeof(sb); ++ u32 attr; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; + efi_status_t status; + +@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table) + if (setup == 1) + return 0; + ++ /* See if a user has put shim into insecure_mode. If so, and the variable ++ * doesn't have the runtime attribute set, we might as well honor that. ++ */ ++ var_guid = EFI_SHIM_LOCK_GUID; ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"MokSBState", &var_guid, &attr, &datasize, ++ &moksbstate); ++ ++ /* If it fails, we don't care why. Default to secure */ ++ if (status != EFI_SUCCESS) ++ return 1; ++ ++ if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) { ++ if (moksbstate == 1) ++ return 0; ++ } ++ + return 1; + } + +-- +1.8.1 + From 4c338c68e65c5e890e0eae1c53de9a1dea16f499 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Feb 2013 10:20:06 -0500 Subject: [PATCH 172/492] Add patch from Kees Cook to restrict MSR writting in secure boot mode --- kernel.spec | 1 + secure-boot-3.7-20130204.patch | 91 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/kernel.spec b/kernel.spec index f1c927edc..55e26a8b1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2379,6 +2379,7 @@ fi # || || %changelog * Mon Feb 11 2013 Josh Boyer +- Add patch from Kees Cook to restrict MSR writting in secure boot mode - Add patch to honor MokSBState (rhbz 907406) * Thu Feb 7 2013 Peter Robinson diff --git a/secure-boot-3.7-20130204.patch b/secure-boot-3.7-20130204.patch index c6765f6bd..621be74be 100644 --- a/secure-boot-3.7-20130204.patch +++ b/secure-boot-3.7-20130204.patch @@ -1390,3 +1390,94 @@ index 96bd86b..6e1331c 100644 -- 1.8.1 + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.99.210 with SMTP id es18csp140114oab; + Fri, 8 Feb 2013 11:12:52 -0800 (PST) +X-Received: by 10.66.86.71 with SMTP id n7mr19917975paz.77.1360350771724; + Fri, 08 Feb 2013 11:12:51 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id e5si41603022pax.261.2013.02.08.11.12.50; + Fri, 08 Feb 2013 11:12:51 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-efi-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1760288Ab3BHTM0 (ORCPT + + 14 others); Fri, 8 Feb 2013 14:12:26 -0500 +Received: from smtp.outflux.net ([198.145.64.163]:49396 "EHLO smtp.outflux.net" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1760349Ab3BHTMY (ORCPT ); + Fri, 8 Feb 2013 14:12:24 -0500 +Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) + by vinyl.outflux.net (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id r18JCEtT006197; + Fri, 8 Feb 2013 11:12:14 -0800 +Date: Fri, 8 Feb 2013 11:12:13 -0800 +From: Kees Cook +To: linux-kernel@vger.kernel.org +Cc: Matthew Garrett , + "H. Peter Anvin" , + Thomas Gleixner , + Ingo Molnar , x86@kernel.org, + linux-efi@vger.kernel.org, linux-security-module@vger.kernel.org +Subject: [PATCH] x86: Lock down MSR writing in secure boot +Message-ID: <20130208191213.GA25081@www.outflux.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +X-MIMEDefang-Filter: outflux$Revision: 1.316 $ +X-HELO: www.outflux.net +X-Scanned-By: MIMEDefang 2.71 on 10.2.0.1 +Sender: linux-efi-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-efi@vger.kernel.org + +Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is +set since it could lead to execution of arbitrary code in kernel mode. + +Signed-off-by: Kees Cook +--- +This would be used on top of Matthew Garrett's existing "Secure boot +policy support" patch series. +--- + arch/x86/kernel/msr.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c +index 4929502..adaab3d 100644 +--- a/arch/x86/kernel/msr.c ++++ b/arch/x86/kernel/msr.c +@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, + int err = 0; + ssize_t bytes = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + +@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) + err = -EBADF; + break; + } ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ err = -EPERM; ++ break; ++ } + if (copy_from_user(®s, uregs, sizeof regs)) { + err = -EFAULT; + break; +-- +1.7.9.5 + + +-- +Kees Cook +Chrome OS Security +-- +To unsubscribe from this list: send the line "unsubscribe linux-efi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html From ffb7a52581c24ce0a66b8a54637e65167debb6b2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 12 Feb 2013 10:00:26 -0600 Subject: [PATCH 173/492] Linux v3.7.7 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 55e26a8b1..b7adea984 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2378,6 +2378,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 12 2013 Justin M. Forbes +- Linux v3.7.7 + * Mon Feb 11 2013 Josh Boyer - Add patch from Kees Cook to restrict MSR writting in secure boot mode - Add patch to honor MokSBState (rhbz 907406) diff --git a/sources b/sources index d3b6270f8..c686ded5b 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -ec61c44f37585a768d41c0439101ef9c patch-3.7.6.xz +e232d2535bbd36fe05c203bacc5b72ea patch-3.7.7.xz From a13d73af42ae9b0dd312e9cf96eb7d02653a6a4e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Feb 2013 11:49:36 -0500 Subject: [PATCH 174/492] Silence brcmsmac warnings. (Fixed in 3.8, but not backporting to 3.7) --- kernel.spec | 7 +++++++ silence-brcmsmac-warning.patch | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 silence-brcmsmac-warning.patch diff --git a/kernel.spec b/kernel.spec index b7adea984..cd613c73a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,6 +789,8 @@ Patch21246: rtlwifi-Fix-scheduling-while-atomic-bug.patch #rhbz 892811 Patch21247: ath9k_rx_dma_stop_check.patch +Patch23000: silence-brcmsmac-warning.patch + # END OF PATCH DEFINITIONS %endif @@ -1515,6 +1517,8 @@ ApplyPatch rtlwifi-Fix-scheduling-while-atomic-bug.patch #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch +ApplyPatch silence-brcmsmac-warning.patch + # END OF PATCH APPLICATIONS %endif @@ -2378,6 +2382,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 12 2013 Dave Jones +- Silence brcmsmac warnings. (Fixed in 3.8, but not backporting to 3.7) + * Tue Feb 12 2013 Justin M. Forbes - Linux v3.7.7 diff --git a/silence-brcmsmac-warning.patch b/silence-brcmsmac-warning.patch new file mode 100644 index 000000000..b1915e9f1 --- /dev/null +++ b/silence-brcmsmac-warning.patch @@ -0,0 +1,14 @@ +This is fixed in 3.8, but is too much to backport for now. +As there's no point in abrt telling us this is broken, we'll just silence it. + +--- linux-3.7.7-201.fc18.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c~ 2013-02-12 11:36:18.787973130 -0500 ++++ linux-3.7.7-201.fc18.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c 2013-02-12 11:37:02.950969879 -0500 +@@ -7993,8 +7993,6 @@ void brcms_c_wait_for_tx_completion(stru + if (--timeout == 0) + break; + } +- +- WARN_ON_ONCE(timeout == 0); + } + + void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) From 477047eeedcfb2fc06a2e443fa5585b97437aa73 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Feb 2013 11:51:07 -0500 Subject: [PATCH 175/492] fix patch numbering --- kernel.spec | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/kernel.spec b/kernel.spec index cd613c73a..2bcc58a0a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -763,31 +763,31 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch Patch22112: USB-report-submission-of-active-URBs.patch #rhbz 859485 -Patch21226: vt-Drop-K_OFF-for-VC_MUTE.patch +Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz CVE-2012-4530 868285 880147 -Patch21229: exec-use-eloop-for-max-recursion-depth.patch +Patch22229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 851278 -Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch -Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch -Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch +Patch22231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch +Patch22232: 8139cp-set-ring-address-after-enabling-C-mode.patch +Patch22233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 892428 -Patch21238: brcmsmac-updates-rhbz892428.patch +Patch22238: brcmsmac-updates-rhbz892428.patch #rhbz 863424 -Patch21239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch +Patch22239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch #rhbz 799564 -Patch21240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch -Patch21241: Input-add-support-for-Cypress-PS2-Trackpads.patch +Patch22240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch +Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 903881 -Patch21246: rtlwifi-Fix-scheduling-while-atomic-bug.patch +Patch22246: rtlwifi-Fix-scheduling-while-atomic-bug.patch #rhbz 892811 -Patch21247: ath9k_rx_dma_stop_check.patch +Patch22247: ath9k_rx_dma_stop_check.patch Patch23000: silence-brcmsmac-warning.patch From e647299c724761a480febdf557b67ad15d607693 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Feb 2013 11:59:02 -0500 Subject: [PATCH 176/492] mm: Check if PUD is large when validating a kernel address --- kernel.spec | 7 +++ validate-pud-largepage.patch | 102 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 validate-pud-largepage.patch diff --git a/kernel.spec b/kernel.spec index 2bcc58a0a..1bd574b6c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,8 @@ Patch22247: ath9k_rx_dma_stop_check.patch Patch23000: silence-brcmsmac-warning.patch +Patch23100: validate-pud-largepage.patch + # END OF PATCH DEFINITIONS %endif @@ -1519,6 +1521,8 @@ ApplyPatch ath9k_rx_dma_stop_check.patch ApplyPatch silence-brcmsmac-warning.patch +ApplyPatch validate-pud-largepage.patch + # END OF PATCH APPLICATIONS %endif @@ -2382,6 +2386,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 12 2013 Dave Jones +- mm: Check if PUD is large when validating a kernel address + * Tue Feb 12 2013 Dave Jones - Silence brcmsmac warnings. (Fixed in 3.8, but not backporting to 3.7) diff --git a/validate-pud-largepage.patch b/validate-pud-largepage.patch new file mode 100644 index 000000000..db6711201 --- /dev/null +++ b/validate-pud-largepage.patch @@ -0,0 +1,102 @@ +Date: Mon, 11 Feb 2013 14:52:36 +0000 +From: Mel Gorman +To: Ingo Molnar , Andrew Morton +Cc: Mel Gorman , linux-kernel@vger.kernel.org, linux-mm@kvack.org +Subject: [PATCH] x86: mm: Check if PUD is large when validating a kernel address +Message-ID: <20130211145236.GX21389@suse.de> +MIME-Version: 1.0 + +A user reported the following oops when a backup process read +/proc/kcore. + + BUG: unable to handle kernel paging request at ffffbb00ff33b000 + IP: [] kern_addr_valid+0xbe/0x110 + PGD 0 + Oops: 0000 [#1] SMP + CPU 6 + Modules linked in: af_packet nfs lockd fscache auth_rpcgss nfs_acl sunrpc 8021q garp stp llc cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf microcode fuse nls_iso8859_1 nls_cp437 vfat fat loop dm_mod ioatdma ipv6 ipv6_lib igb dca i7core_edac edac_core i2c_i801 i2c_core cdc_ether usbnet bnx2 mii iTCO_wdt iTCO_vendor_support shpchp rtc_cmos pci_hotplug tpm_tis sg tpm pcspkr tpm_bios serio_raw button ext3 jbd mbcache uhci_hcd ehci_hcd usbcore sd_mod crc_t10dif usb_common processor thermal_sys hwmon scsi_dh_emc scsi_dh_rdac scsi_dh_alua scsi_dh_hp_sw scsi_dh ata_generic ata_piix libata megaraid_sas scsi_mod + + Pid: 16196, comm: Hibackp Not tainted 3.0.13-0.27-default #1 IBM System x3550 M3 -[7944 K3G]-/94Y7614 + RIP: 0010:[] [] kern_addr_valid+0xbe/0x110 + RSP: 0018:ffff88094165fe80 EFLAGS: 00010246 + RAX: 00003300ff33b000 RBX: ffff880100000000 RCX: 0000000000000000 + RDX: 0000000100000000 RSI: ffff880000000000 RDI: ff32b300ff33b400 + RBP: 0000000000001000 R08: 00003ffffffff000 R09: 0000000000000000 + R10: 22302e31223d6e6f R11: 0000000000000246 R12: 0000000000001000 + R13: 0000000000003000 R14: 0000000000571be0 R15: ffff88094165ff50 + FS: 00007ff152d33700(0000) GS:ffff88097f2c0000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b + CR2: ffffbb00ff33b000 CR3: 00000009405a3000 CR4: 00000000000006e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 + Process Hibackp (pid: 16196, threadinfo ffff88094165e000, task ffff8808eb9ba600) + Stack: + ffffffff811b8aaa 0000000000004000 ffff880943fea480 ffff8808ef2bae50 + ffff880943d32980 fffffffffffffffb ffff8808ef2bae40 ffff88094165ff50 + 0000000000004000 000000000056ebe0 ffffffff811ad847 000000000056ebe0 + Call Trace: + [] read_kcore+0x17a/0x370 + [] proc_reg_read+0x77/0xc0 + [] vfs_read+0xc7/0x130 + [] sys_read+0x53/0xa0 + [] system_call_fastpath+0x16/0x1b + +Investigation determined that the bug triggered when reading system RAM +at the 4G mark. On this system, that was the first address using 1G pages +for the virt->phys direct mapping so the PUD is pointing to a physical +address, not a PMD page. The problem is that the page table walker in +kern_addr_valid() is not checking pud_large() and treats the physical +address as if it was a PMD. If it happens to look like pmd_none then it'll +silently fail, probably returning zeros instead of real data. If the data +happens to look like a present PMD though, it will be walked resulting in +the oops above. This patch adds the necessary pud_large() check. + +Unfortunately the problem was not readily reproducible and now they are +running the backup program without accessing /proc/kcore so the patch has +not been validated but I think it makes sense. If reviewers agree then it +should also be included in -stable back as far as 3.0-stable. + +Cc: stable@vger.kernel.org +Signed-off-by: Mel Gorman +--- + arch/x86/include/asm/pgtable.h | 5 +++++ + arch/x86/mm/init_64.c | 3 +++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 5199db2..1c1a955 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -142,6 +142,11 @@ static inline unsigned long pmd_pfn(pmd_t pmd) + return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; + } + ++static inline unsigned long pud_pfn(pud_t pud) ++{ ++ return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT; ++} ++ + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) + + static inline int pmd_large(pmd_t pte) +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index 2ead3c8..75c9a6a 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -831,6 +831,9 @@ int kern_addr_valid(unsigned long addr) + if (pud_none(*pud)) + return 0; + ++ if (pud_large(*pud)) ++ return pfn_valid(pud_pfn(*pud)); ++ + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + return 0; + +-- +To unsubscribe, send a message with 'unsubscribe linux-mm' in +the body to majordomo@kvack.org. For more info on Linux MM, +see: http://www.linux-mm.org/ . +Don't email: email@kvack.org + From 8de5b02e00c2b540fea3186c927c1943352a2904 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Feb 2013 13:40:09 -0500 Subject: [PATCH 177/492] Add networking queue for next stable release. --- kernel.spec | 7 + net_37.mbox | 2939 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2946 insertions(+) create mode 100644 net_37.mbox diff --git a/kernel.spec b/kernel.spec index 1bd574b6c..86fd1f72c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -793,6 +793,8 @@ Patch23000: silence-brcmsmac-warning.patch Patch23100: validate-pud-largepage.patch +Patch23200: net_37.mbox + # END OF PATCH DEFINITIONS %endif @@ -1523,6 +1525,8 @@ ApplyPatch silence-brcmsmac-warning.patch ApplyPatch validate-pud-largepage.patch +ApplyPatch net_37.mbox + # END OF PATCH APPLICATIONS %endif @@ -2386,6 +2390,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 12 2013 Dave Jones +- Add networking queue for next stable release. + * Tue Feb 12 2013 Dave Jones - mm: Check if PUD is large when validating a kernel address diff --git a/net_37.mbox b/net_37.mbox new file mode 100644 index 000000000..742400e11 --- /dev/null +++ b/net_37.mbox @@ -0,0 +1,2939 @@ +From 3e79c606d6a4504e2608cf03b6d4dd0c6b6dc008 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Mon, 7 Jan 2013 21:17:00 +0000 +Subject: [PATCH 01/44] net: prevent setting ttl=0 via IP_TTL + +[ Upstream commit c9be4a5c49cf51cc70a993f004c5bb30067a65ce ] + +A regression is introduced by the following commit: + + commit 4d52cfbef6266092d535237ba5a4b981458ab171 + Author: Eric Dumazet + Date: Tue Jun 2 00:42:16 2009 -0700 + + net: ipv4/ip_sockglue.c cleanups + + Pure cleanups + +but it is not a pure cleanup... + + - if (val != -1 && (val < 1 || val>255)) + + if (val != -1 && (val < 0 || val > 255)) + +Since there is no reason provided to allow ttl=0, change it back. + +Reported-by: nitin padalia +Cc: nitin padalia +Cc: Eric Dumazet +Cc: David S. Miller +Signed-off-by: Cong Wang +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/ip_sockglue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 14bbfcf..e95d72b 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -590,7 +590,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, + case IP_TTL: + if (optlen < 1) + goto e_inval; +- if (val != -1 && (val < 0 || val > 255)) ++ if (val != -1 && (val < 1 || val > 255)) + goto e_inval; + inet->uc_ttl = val; + break; +-- +1.7.11.7 + + +From a91ced21d91a2b96ccd2b6e4524df45ff8c9201c Mon Sep 17 00:00:00 2001 +From: Romain Kuntz +Date: Wed, 9 Jan 2013 15:02:26 +0100 +Subject: [PATCH 02/44] ipv6: fix the noflags test in + addrconf_get_prefix_route + +[ Upstream commit 85da53bf1c336bb07ac038fb951403ab0478d2c5 ] + +The tests on the flags in addrconf_get_prefix_route() does no make +much sense: the 'noflags' parameter contains the set of flags that +must not match with the route flags, so the test must be done +against 'noflags', and not against 'flags'. + +Signed-off-by: Romain Kuntz +Acked-by: YOSHIFUJI Hideaki +Signed-off-by: David S. Miller +--- + net/ipv6/addrconf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 0424e4e..a468a36 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1723,7 +1723,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, + continue; + if ((rt->rt6i_flags & flags) != flags) + continue; +- if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) ++ if ((rt->rt6i_flags & noflags) != 0) + continue; + dst_hold(&rt->dst); + break; +-- +1.7.11.7 + + +From 43a18605f87a654eb6673ffb8ff99df13420d544 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Thu, 10 Jan 2013 23:19:10 +0000 +Subject: [PATCH 03/44] net, wireless: overwrite default_ethtool_ops + +[ Upstream commit d07d7507bfb4e23735c9b83e397c43e1e8a173e8 ] + +Since: + +commit 2c60db037034d27f8c636403355d52872da92f81 +Author: Eric Dumazet +Date: Sun Sep 16 09:17:26 2012 +0000 + + net: provide a default dev->ethtool_ops + +wireless core does not correctly assign ethtool_ops. + +After alloc_netdev*() call, some cfg80211 drivers provide they own +ethtool_ops, but some do not. For them, wireless core provide generic +cfg80211_ethtool_ops, which is assigned in NETDEV_REGISTER notify call: + + if (!dev->ethtool_ops) + dev->ethtool_ops = &cfg80211_ethtool_ops; + +But after Eric's commit, dev->ethtool_ops is no longer NULL (on cfg80211 +drivers without custom ethtool_ops), but points to &default_ethtool_ops. + +In order to fix the problem, provide function which will overwrite +default_ethtool_ops and use it by wireless core. + +Signed-off-by: Stanislaw Gruszka +Acked-by: Johannes Berg +Acked-by: Ben Hutchings +Signed-off-by: David S. Miller +--- + include/linux/netdevice.h | 3 +++ + net/core/dev.c | 8 ++++++++ + net/wireless/core.c | 3 +-- + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index a848ffc..825fb7e 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -60,6 +60,9 @@ struct wireless_dev; + #define SET_ETHTOOL_OPS(netdev,ops) \ + ( (netdev)->ethtool_ops = (ops) ) + ++extern void netdev_set_default_ethtool_ops(struct net_device *dev, ++ const struct ethtool_ops *ops); ++ + /* hardware address assignment types */ + #define NET_ADDR_PERM 0 /* address is permanent (default) */ + #define NET_ADDR_RANDOM 1 /* address is generated randomly */ +diff --git a/net/core/dev.c b/net/core/dev.c +index e5942bf..3470794 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6012,6 +6012,14 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) + + static const struct ethtool_ops default_ethtool_ops; + ++void netdev_set_default_ethtool_ops(struct net_device *dev, ++ const struct ethtool_ops *ops) ++{ ++ if (dev->ethtool_ops == &default_ethtool_ops) ++ dev->ethtool_ops = ops; ++} ++EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); ++ + /** + * alloc_netdev_mqs - allocate network device + * @sizeof_priv: size of private data to allocate space for +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 3f72530..d1531e5 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -856,8 +856,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + /* allow mac80211 to determine the timeout */ + wdev->ps_timeout = -1; + +- if (!dev->ethtool_ops) +- dev->ethtool_ops = &cfg80211_ethtool_ops; ++ netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops); + + if ((wdev->iftype == NL80211_IFTYPE_STATION || + wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || +-- +1.7.11.7 + + +From 10a209641c46d1b7fab2e45148ac83a2e3ec9bab Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 13 Jan 2013 18:21:51 +0000 +Subject: [PATCH 04/44] tcp: fix a panic on UP machines in + reqsk_fastopen_remove + +[ Upstream commit cce894bb824429fd312706c7012acae43e725865 ] + +spin_is_locked() on a non !SMP build is kind of useless. + +BUG_ON(!spin_is_locked(xx)) is guaranteed to crash. + +Just remove this check in reqsk_fastopen_remove() as +the callers do hold the socket lock. + +Reported-by: Ketan Kulkarni +Signed-off-by: Eric Dumazet +Cc: Jerry Chu +Cc: Yuchung Cheng +Cc: Dave Taht +Acked-by: H.K. Jerry Chu +Signed-off-by: David S. Miller +--- + net/core/request_sock.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/core/request_sock.c b/net/core/request_sock.c +index c31d9e8..4425148 100644 +--- a/net/core/request_sock.c ++++ b/net/core/request_sock.c +@@ -186,8 +186,6 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, + struct fastopen_queue *fastopenq = + inet_csk(lsk)->icsk_accept_queue.fastopenq; + +- BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk)); +- + tcp_sk(sk)->fastopen_rsk = NULL; + spin_lock_bh(&fastopenq->lock); + fastopenq->qlen--; +-- +1.7.11.7 + + +From d9c9e8ef86d318c97b88dc4efcf46530a0b46543 Mon Sep 17 00:00:00 2001 +From: Stephen Hemminger +Date: Wed, 16 Jan 2013 09:55:57 -0800 +Subject: [PATCH 05/44] MAINTAINERS: Stephen Hemminger email change + +[ Upstream commit adbbf69d1a54abf424e91875746a610dcc80017d ] + +I changed my email because the vyatta.com mail server is now +redirected to brocade.com; and the Brocade mail system +is not friendly to Linux desktop users. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +--- + MAINTAINERS | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 9386a63..4eb1deb 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2898,7 +2898,7 @@ S: Maintained + F: drivers/net/ethernet/i825xx/eexpress.* + + ETHERNET BRIDGE +-M: Stephen Hemminger ++M: Stephen Hemminger + L: bridge@lists.linux-foundation.org + L: netdev@vger.kernel.org + W: http://www.linuxfoundation.org/en/Net:Bridge +@@ -4739,7 +4739,7 @@ S: Maintained + + MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) + M: Mirko Lindner +-M: Stephen Hemminger ++M: Stephen Hemminger + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/ethernet/marvell/sk* +@@ -4993,7 +4993,7 @@ S: Supported + F: drivers/infiniband/hw/nes/ + + NETEM NETWORK EMULATOR +-M: Stephen Hemminger ++M: Stephen Hemminger + L: netem@lists.linux-foundation.org + S: Maintained + F: net/sched/sch_netem.c +-- +1.7.11.7 + + +From bb1e86b0fd4ee8fa047dee973bad46363420a80a Mon Sep 17 00:00:00 2001 +From: Romain KUNTZ +Date: Wed, 16 Jan 2013 12:47:40 +0000 +Subject: [PATCH 06/44] ipv6: fix header length calculation in + ip6_append_data() + +[ Upstream commit 7efdba5bd9a2f3e2059beeb45c9fa55eefe1bced ] + +Commit 299b0767 (ipv6: Fix IPsec slowpath fragmentation problem) +has introduced a error in the header length calculation that +provokes corrupted packets when non-fragmentable extensions +headers (Destination Option or Routing Header Type 2) are used. + +rt->rt6i_nfheader_len is the length of the non-fragmentable +extension header, and it should be substracted to +rt->dst.header_len, and not to exthdrlen, as it was done before +commit 299b0767. + +This patch reverts to the original and correct behavior. It has +been successfully tested with and without IPsec on packets +that include non-fragmentable extensions headers. + +Signed-off-by: Romain Kuntz +Acked-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index aece3e7..8dea314 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1279,10 +1279,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + if (dst_allfrag(rt->dst.path)) + cork->flags |= IPCORK_ALLFRAG; + cork->length = 0; +- exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; ++ exthdrlen = (opt ? opt->opt_flen : 0); + length += exthdrlen; + transhdrlen += exthdrlen; +- dst_exthdrlen = rt->dst.header_len; ++ dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; + } else { + rt = (struct rt6_info *)cork->dst; + fl6 = &inet->cork.fl.u.ip6; +-- +1.7.11.7 + + +From f6296b4042c585592d4251b423f9d2bc6bfdf2cb Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 17 Jan 2013 13:30:49 -0800 +Subject: [PATCH 07/44] macvlan: fix macvlan_get_size() + +[ Upstream commit 01fe944f1024bd4e5c327ddbe8d657656b66af2f ] + +commit df8ef8f3aaa (macvlan: add FDB bridge ops and macvlan flags) +forgot to update macvlan_get_size() after the addition of +IFLA_MACVLAN_FLAGS + +Signed-off-by: Eric Dumazet +Cc: John Fastabend +Signed-off-by: David S. Miller +--- + drivers/net/macvlan.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index 68a43fe..d3fb97d 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -822,7 +822,10 @@ static int macvlan_changelink(struct net_device *dev, + + static size_t macvlan_get_size(const struct net_device *dev) + { +- return nla_total_size(4); ++ return (0 ++ + nla_total_size(4) /* IFLA_MACVLAN_MODE */ ++ + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ ++ ); + } + + static int macvlan_fill_info(struct sk_buff *skb, +-- +1.7.11.7 + + +From e8002481da092b921028dfb8c82873f5b8f378d3 Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Wed, 16 Jan 2013 13:36:37 +0000 +Subject: [PATCH 08/44] net: calxedaxgmac: throw away overrun frames + +[ Upstream commit d6fb3be544b46a7611a3373fcaa62b5b0be01888 ] + +The xgmac driver assumes 1 frame per descriptor. If a frame larger than +the descriptor's buffer size is received, the frame will spill over into +the next descriptor. So check for received frames that span more than one +descriptor and discard them. This prevents a crash if we receive erroneous +large packets. + +Signed-off-by: Rob Herring +Cc: netdev@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/calxeda/xgmac.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c +index 16814b3..e29c1b6 100644 +--- a/drivers/net/ethernet/calxeda/xgmac.c ++++ b/drivers/net/ethernet/calxeda/xgmac.c +@@ -546,6 +546,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) + return -1; + } + ++ /* All frames should fit into a single buffer */ ++ if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) ++ return -1; ++ + /* Check if packet has checksum already */ + if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && + !(ext_status & RXDESC_IP_PAYLOAD_MASK)) +-- +1.7.11.7 + + +From cea9757b2a648469443228917fb352b0d06d215d Mon Sep 17 00:00:00 2001 +From: Yan Burman +Date: Thu, 17 Jan 2013 05:30:42 +0000 +Subject: [PATCH 09/44] net/mlx4_en: Fix bridged vSwitch configuration for non + SRIOV mode + +[ Upstream commit 213815a1e6ae70b9648483b110bc5081795f99e8 ] + +Commit 5b4c4d36860e "mlx4_en: Allow communication between functions on +same host" introduced a regression under which a bridge acting as vSwitch +whose uplink is an mlx4 Ethernet device become non-operative in native +(non sriov) mode. This happens since broadcast ARP requests sent by VMs +were loopback-ed by the HW and hence the bridge learned VM source MACs +on both the VM and the uplink ports. + +The fix is to place the DMAC in the send WQE only under SRIOV/eSwitch +configuration or when the device is in selftest. + +Reviewed-by: Or Gerlitz +Signed-off-by: Yan Burman +Signed-off-by: Amir Vadai +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlx4/en_tx.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index b35094c..fc1ac65 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -629,10 +629,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) + ring->tx_csum++; + } + +- /* Copy dst mac address to wqe */ +- ethh = (struct ethhdr *)skb->data; +- tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); +- tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); ++ if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { ++ /* Copy dst mac address to wqe. This allows loopback in eSwitch, ++ * so that VFs and PF can communicate with each other ++ */ ++ ethh = (struct ethhdr *)skb->data; ++ tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); ++ tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); ++ } ++ + /* Handle LSO (TSO) packets */ + if (lso_header_size) { + /* Mark opcode as LSO */ +-- +1.7.11.7 + + +From 71558617a4904a27b7dd35dfb82c9029b87af357 Mon Sep 17 00:00:00 2001 +From: Or Gerlitz +Date: Thu, 17 Jan 2013 05:30:43 +0000 +Subject: [PATCH 10/44] net/mlx4_core: Set number of msix vectors under SRIOV + mode to firmware defaults + +[ Upstream commit ca4c7b35f75492de7fbf5ee95be07481c348caee ] + +The lines + + if (mlx4_is_mfunc(dev)) { + nreq = 2; + } else { + +which hard code the number of requested msi-x vectors under multi-function +mode to two can be removed completely, since the firmware sets num_eqs and +reserved_eqs appropriately Thus, the code line: + + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, nreq); + +is by itself sufficient and correct for all cases. Currently, for mfunc +mode num_eqs = 32 and reserved_eqs = 28, hence four vectors will be enabled. + +This triples (one vector is used for the async events and commands EQ) the +horse power provided for processing of incoming packets on netdev RSS scheme, +IO initiators/targets commands processing flows, etc. + +Reviewed-by: Jack Morgenstein +Signed-off-by: Amir Vadai +Signed-off-by: Or Gerlitz +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlx4/main.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c +index 2aa80af..d4b3935 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/main.c ++++ b/drivers/net/ethernet/mellanox/mlx4/main.c +@@ -1702,15 +1702,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) + int i; + + if (msi_x) { +- /* In multifunction mode each function gets 2 msi-X vectors +- * one for data path completions anf the other for asynch events +- * or command completions */ +- if (mlx4_is_mfunc(dev)) { +- nreq = 2; +- } else { +- nreq = min_t(int, dev->caps.num_eqs - +- dev->caps.reserved_eqs, nreq); +- } ++ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, ++ nreq); + + entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); + if (!entries) +-- +1.7.11.7 + + +From 9e1626d8ecc01327036f8ad064a326a2ad31ae93 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 19 Jan 2013 16:10:37 +0000 +Subject: [PATCH 11/44] tcp: fix incorrect LOCKDROPPEDICMPS counter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit b74aa930ef49a3c0d8e4c1987f89decac768fb2c ] + +commit 563d34d057 (tcp: dont drop MTU reduction indications) +added an error leading to incorrect accounting of +LINUX_MIB_LOCKDROPPEDICMPS + +If socket is owned by the user, we want to increment +this SNMP counter, unless the message is a +(ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED) one. + +Reported-by: Maciej Å»enczykowski +Signed-off-by: Eric Dumazet +Cc: Neal Cardwell +Signed-off-by: Maciej Å»enczykowski +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_ipv4.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index bc3cb46..e637770 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -380,11 +380,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) + * We do take care of PMTU discovery (RFC1191) special case : + * we can receive locally generated ICMP messages while socket is held. + */ +- if (sock_owned_by_user(sk) && +- type != ICMP_DEST_UNREACH && +- code != ICMP_FRAG_NEEDED) +- NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); +- ++ if (sock_owned_by_user(sk)) { ++ if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)) ++ NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); ++ } + if (sk->sk_state == TCP_CLOSE) + goto out; + +-- +1.7.11.7 + + +From 67ee774cb516f0fe5259760c59a807de18fd78d8 Mon Sep 17 00:00:00 2001 +From: Tilman Schmidt +Date: Mon, 21 Jan 2013 11:57:21 +0000 +Subject: [PATCH 12/44] isdn/gigaset: fix zero size border case in debug dump + +[ Upstream commit d721a1752ba544df8d7d36959038b26bc92bdf80 ] + +If subtracting 12 from l leaves zero we'd do a zero size allocation, +leading to an oops later when we try to set the NUL terminator. + +Reported-by: Dan Carpenter +Signed-off-by: Tilman Schmidt +Signed-off-by: David S. Miller +--- + drivers/isdn/gigaset/capi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c +index 68452b7..03a0a01 100644 +--- a/drivers/isdn/gigaset/capi.c ++++ b/drivers/isdn/gigaset/capi.c +@@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, + CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, + CAPIMSG_CONTROL(data)); + l -= 12; ++ if (l <= 0) ++ return; + dbgline = kmalloc(3 * l, GFP_ATOMIC); + if (!dbgline) + return; +-- +1.7.11.7 + + +From a7640c96407dd3f44a8f709f9ae880bc6211b04b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 22 Jan 2013 06:33:05 +0000 +Subject: [PATCH 13/44] netxen: fix off by one bug in + netxen_release_tx_buffer() + +[ Upstream commit a05948f296ce103989b28a2606e47d2e287c3c89 ] + +Christoph Paasch found netxen could trigger a BUG in its dismantle +phase, in netxen_release_tx_buffer(), using full size TSO packets. + +cmd_buf->frag_count includes the skb->data part, so the loop must +start at index 1 instead of 0, or else we can make an out +of bound access to cmd_buff->frag_array[MAX_SKB_FRAGS + 2] + +Christoph provided the fixes in netxen_map_tx_skb() function. +In case of a dma mapping error, its better to clear the dma fields +so that we don't try to unmap them again in netxen_release_tx_buffer() + +Reported-by: Christoph Paasch +Signed-off-by: Eric Dumazet +Tested-by: Christoph Paasch +Cc: Sony Chacko +Cc: Rajesh Borundia +Signed-off-by: Christoph Paasch +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 2 +- + drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +index bc165f4..695667d 100644 +--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c ++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +@@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) + buffrag->length, PCI_DMA_TODEVICE); + buffrag->dma = 0ULL; + } +- for (j = 0; j < cmd_buf->frag_count; j++) { ++ for (j = 1; j < cmd_buf->frag_count; j++) { + buffrag++; + if (buffrag->dma) { + pci_unmap_page(adapter->pdev, buffrag->dma, +diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +index df45061..1b55ca1 100644 +--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c ++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +@@ -1963,10 +1963,12 @@ unwind: + while (--i >= 0) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); ++ nf->dma = 0ULL; + } + + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); ++ nf->dma = 0ULL; + + out_err: + return -ENOMEM; +-- +1.7.11.7 + + +From 6aaa957c972243891f2edb3905765deffa37dbff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +Date: Mon, 21 Jan 2013 22:30:35 +0000 +Subject: [PATCH 14/44] r8169: remove the obsolete and incorrect AMD + workaround +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 5d0feaff230c0abfe4a112e6f09f096ed99e0b2d ] + +This was introduced in commit 6dccd16 "r8169: merge with version +6.001.00 of Realtek's r8169 driver". I did not find the version +6.001.00 online, but in 6.002.00 or any later r8169 from Realtek +this hunk is no longer present. + +Also commit 05af214 "r8169: fix Ethernet Hangup for RTL8110SC +rev d" claims to have fixed this issue otherwise. + +The magic compare mask of 0xfffe000 is dubious as it masks +parts of the Reserved part, and parts of the VLAN tag. But this +does not make much sense as the VLAN tag parts are perfectly +valid there. In matter of fact this seems to be triggered with +any VLAN tagged packet as RxVlanTag bit is matched. I would +suspect 0xfffe0000 was intended to test reserved part only. + +Finally, this hunk is evil as it can cause more packets to be +handled than what was NAPI quota causing net/core/dev.c: +net_rx_action(): WARN_ON_ONCE(work > weight) to trigger, and +mess up the NAPI state causing device to hang. + +As result, any system using VLANs and having high receive +traffic (so that NAPI poll budget limits rtl_rx) would result +in device hang. + +Signed-off-by: Timo Teräs +Acked-by: Francois Romieu +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/r8169.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index 927aa33..6afe74e 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -6064,13 +6064,6 @@ process_pkt: + tp->rx_stats.bytes += pkt_size; + u64_stats_update_end(&tp->rx_stats.syncp); + } +- +- /* Work around for AMD plateform. */ +- if ((desc->opts2 & cpu_to_le32(0xfffe000)) && +- (tp->mac_version == RTL_GIGA_MAC_VER_05)) { +- desc->opts2 = 0; +- cur_rx++; +- } + } + + count = cur_rx - tp->cur_rx; +-- +1.7.11.7 + + +From 24d7fa8b3e9f8f9834e8af9f13a49647cbfda7a2 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 25 Jan 2013 07:44:41 +0000 +Subject: [PATCH 15/44] net: loopback: fix a dst refcounting issue + +[ Upstream commit 794ed393b707f01858f5ebe2ae5eabaf89d00022 ] + +Ben Greear reported crashes in ip_rcv_finish() on a stress +test involving many macvlans. + +We tracked the bug to a dst use after free. ip_rcv_finish() +was calling dst->input() and got garbage for dst->input value. + +It appears the bug is in loopback driver, lacking +a skb_dst_force() before calling netif_rx(). + +As a result, a non refcounted dst, normally protected by a +RCU read_lock section, was escaping this section and could +be freed before the packet being processed. + + [] loopback_xmit+0x64/0x83 + [] dev_hard_start_xmit+0x26c/0x35e + [] dev_queue_xmit+0x2c4/0x37c + [] ? dev_hard_start_xmit+0x35e/0x35e + [] ? eth_header+0x28/0xb6 + [] neigh_resolve_output+0x176/0x1a7 + [] ip_finish_output2+0x297/0x30d + [] ? ip_finish_output2+0x137/0x30d + [] ip_finish_output+0x63/0x68 + [] ip_output+0x61/0x67 + [] dst_output+0x17/0x1b + [] ip_local_out+0x1e/0x23 + [] ip_queue_xmit+0x315/0x353 + [] ? ip_send_unicast_reply+0x2cc/0x2cc + [] tcp_transmit_skb+0x7ca/0x80b + [] tcp_connect+0x53c/0x587 + [] ? getnstimeofday+0x44/0x7d + [] ? ktime_get_real+0x11/0x3e + [] tcp_v4_connect+0x3c2/0x431 + [] __inet_stream_connect+0x84/0x287 + [] ? inet_stream_connect+0x22/0x49 + [] ? _local_bh_enable_ip+0x84/0x9f + [] ? local_bh_enable+0xd/0x11 + [] ? lock_sock_nested+0x6e/0x79 + [] ? inet_stream_connect+0x22/0x49 + [] inet_stream_connect+0x33/0x49 + [] sys_connect+0x75/0x98 + +This bug was introduced in linux-2.6.35, in commit +7fee226ad2397b (net: add a noref bit on skb dst) + +skb_dst_force() is enforced in dev_queue_xmit() for devices having a +qdisc. + +Reported-by: Ben Greear +Signed-off-by: Eric Dumazet +Tested-by: Ben Greear +Signed-off-by: David S. Miller +--- + drivers/net/loopback.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index 81f8f9e..fcbf680 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, + + skb_orphan(skb); + ++ /* Before queueing this packet to netif_rx(), ++ * make sure dst is refcounted. ++ */ ++ skb_dst_force(skb); ++ + skb->protocol = eth_type_trans(skb, dev); + + /* it's OK to use per_cpu_ptr() because BHs are off */ +-- +1.7.11.7 + + +From f6d1707cdb200b651c019f693d636154cce43248 Mon Sep 17 00:00:00 2001 +From: Pravin B Shelar +Date: Wed, 23 Jan 2013 11:45:42 +0000 +Subject: [PATCH 16/44] IP_GRE: Fix kernel panic in IP_GRE with GRE csum. + +[ Upstream commit 5465740ace36f179de5bb0ccb5d46ddeb945e309 ] + +Due to IP_GRE GSO support, GRE can recieve non linear skb which +results in panic in case of GRE_CSUM. Following patch fixes it by +using correct csum API. + +Bug introduced in commit 6b78f16e4bdde3936b (gre: add GSO support) + +Signed-off-by: Pravin B Shelar +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/ip_gre.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 7240f8e..07538a7 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -972,8 +972,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev + ptr--; + } + if (tunnel->parms.o_flags&GRE_CSUM) { ++ int offset = skb_transport_offset(skb); ++ + *ptr = 0; +- *(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr)); ++ *(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset, ++ skb->len - offset, ++ 0)); + } + } + +-- +1.7.11.7 + + +From 443811a0868d9d9815f4bbe1aabea6be7f25f906 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Sun, 27 Jan 2013 21:14:08 +0000 +Subject: [PATCH 17/44] pktgen: correctly handle failures when adding a device + +[ Upstream commit 604dfd6efc9b79bce432f2394791708d8e8f6efc ] + +The return value of pktgen_add_device() is not checked, so +even if we fail to add some device, for example, non-exist one, +we still see "OK:...". This patch fixes it. + +After this patch, I got: + + # echo "add_device non-exist" > /proc/net/pktgen/kpktgend_0 + -bash: echo: write error: No such device + # cat /proc/net/pktgen/kpktgend_0 + Running: + Stopped: + Result: ERROR: can not add device non-exist + # echo "add_device eth0" > /proc/net/pktgen/kpktgend_0 + # cat /proc/net/pktgen/kpktgend_0 + Running: + Stopped: eth0 + Result: OK: add_device=eth0 + +(Candidate for -stable) + +Cc: David S. Miller +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +--- + net/core/pktgen.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index d1dc14c..21350db 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -1795,10 +1795,13 @@ static ssize_t pktgen_thread_write(struct file *file, + return -EFAULT; + i += len; + mutex_lock(&pktgen_thread_lock); +- pktgen_add_device(t, f); ++ ret = pktgen_add_device(t, f); + mutex_unlock(&pktgen_thread_lock); +- ret = count; +- sprintf(pg_result, "OK: add_device=%s", f); ++ if (!ret) { ++ ret = count; ++ sprintf(pg_result, "OK: add_device=%s", f); ++ } else ++ sprintf(pg_result, "ERROR: can not add device %s", f); + goto out; + } + +-- +1.7.11.7 + + +From 9159b16b6d82f3051602f0ee51701458a6a58432 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Tue, 29 Jan 2013 22:26:08 +0000 +Subject: [PATCH 18/44] ipv6: do not create neighbor entries for local + delivery + +[ Upstream commit bd30e947207e2ea0ff2c08f5b4a03025ddce48d3 ] + +They will be created at output, if ever needed. This avoids creating +empty neighbor entries when TPROXYing/Forwarding packets for addresses +that are not even directly reachable. + +Note that IPv4 already handles it this way. No neighbor entries are +created for local input. + +Tested by myself and customer. + +Signed-off-by: Jiri Pirko +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +--- + net/ipv6/route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index b1e6cf0..b140ef2 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -872,7 +872,7 @@ restart: + dst_hold(&rt->dst); + read_unlock_bh(&table->tb6_lock); + +- if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP)) ++ if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL))) + nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); + else if (!(rt->dst.flags & DST_HOST)) + nrt = rt6_alloc_clone(rt, &fl6->daddr); +-- +1.7.11.7 + + +From aaf884494fda8734dcd8f42602e646e2238d01f6 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 29 Jan 2013 22:58:04 -0500 +Subject: [PATCH 19/44] via-rhine: Fix bugs in NAPI support. + +[ Upstream commit 559bcac35facfed49ab4f408e162971612dcfdf3 ] + +1) rhine_tx() should use dev_kfree_skb() not dev_kfree_skb_irq() + +2) rhine_slow_event_task's NAPI triggering logic is racey, it + should just hit the interrupt mask register. This is the + same as commit 7dbb491878a2c51d372a8890fa45a8ff80358af1 + ("r8169: avoid NAPI scheduling delay.") made to fix the same + problem in the r8169 driver. From Francois Romieu. + +Reported-by: Jamie Gloudon +Tested-by: Jamie Gloudon +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/via/via-rhine.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c +index 0459c09..046526e0 100644 +--- a/drivers/net/ethernet/via/via-rhine.c ++++ b/drivers/net/ethernet/via/via-rhine.c +@@ -1802,7 +1802,7 @@ static void rhine_tx(struct net_device *dev) + rp->tx_skbuff[entry]->len, + PCI_DMA_TODEVICE); + } +- dev_kfree_skb_irq(rp->tx_skbuff[entry]); ++ dev_kfree_skb(rp->tx_skbuff[entry]); + rp->tx_skbuff[entry] = NULL; + entry = (++rp->dirty_tx) % TX_RING_SIZE; + } +@@ -2011,11 +2011,7 @@ static void rhine_slow_event_task(struct work_struct *work) + if (intr_status & IntrPCIErr) + netif_warn(rp, hw, dev, "PCI error\n"); + +- napi_disable(&rp->napi); +- rhine_irq_disable(rp); +- /* Slow and safe. Consider __napi_schedule as a replacement ? */ +- napi_enable(&rp->napi); +- napi_schedule(&rp->napi); ++ iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable); + + out_unlock: + mutex_unlock(&rp->task_lock); +-- +1.7.11.7 + + +From 4c26aa283f7673e08076645d776d1155ea24d01d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 1 Feb 2013 07:21:41 +0000 +Subject: [PATCH 20/44] packet: fix leakage of tx_ring memory + +[ Upstream commit 9665d5d62487e8e7b1f546c00e11107155384b9a ] + +When releasing a packet socket, the routine packet_set_ring() is reused +to free rings instead of allocating them. But when calling it for the +first time, it fills req->tp_block_nr with the value of rb->pg_vec_len +which in the second invocation makes it bail out since req->tp_block_nr +is greater zero but req->tp_block_size is zero. + +This patch solves the problem by passing a zeroed auto-variable to +packet_set_ring() upon each invocation from packet_release(). + +As far as I can tell, this issue exists even since 69e3c75 (net: TX_RING +and packet mmap), i.e. the original inclusion of TX ring support into +af_packet, but applies only to sockets with both RX and TX ring +allocated, which is probably why this was unnoticed all the time. + +Signed-off-by: Phil Sutter +Cc: Johann Baudy +Cc: Daniel Borkmann +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +--- + net/packet/af_packet.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 94060ed..5db6316 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2335,13 +2335,15 @@ static int packet_release(struct socket *sock) + + packet_flush_mclist(sk); + +- memset(&req_u, 0, sizeof(req_u)); +- +- if (po->rx_ring.pg_vec) ++ if (po->rx_ring.pg_vec) { ++ memset(&req_u, 0, sizeof(req_u)); + packet_set_ring(sk, &req_u, 1, 0); ++ } + +- if (po->tx_ring.pg_vec) ++ if (po->tx_ring.pg_vec) { ++ memset(&req_u, 0, sizeof(req_u)); + packet_set_ring(sk, &req_u, 1, 1); ++ } + + fanout_release(sk); + +-- +1.7.11.7 + + +From 7cc84ac7f54b5d6e70c62bf62cedd52047efb24b Mon Sep 17 00:00:00 2001 +From: Tommi Rantala +Date: Wed, 6 Feb 2013 03:24:02 +0000 +Subject: [PATCH 21/44] ipv6/ip6_gre: fix error case handling in + ip6gre_tunnel_xmit() + +[ Upstream commit 41ab3e31bd50b42c85ac0aa0469642866aee2a9a ] + +ip6gre_tunnel_xmit() is leaking the skb when we hit this error branch, +and the -1 return value from this function is bogus. Use the error +handling we already have in place in ip6gre_tunnel_xmit() for this error +case to fix this. + +Signed-off-by: Tommi Rantala +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_gre.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index d5cb3c4..a23350c 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -976,7 +976,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb, + int ret; + + if (!ip6_tnl_xmit_ctl(t)) +- return -1; ++ goto tx_err; + + switch (skb->protocol) { + case htons(ETH_P_IP): +-- +1.7.11.7 + + +From 09d6e93572bb278ea5a0cfaa63e18c01b25a9c7e Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Fri, 8 Feb 2013 00:19:11 +0000 +Subject: [PATCH 22/44] atm/iphase: rename fregt_t -> ffreg_t + +[ Upstream commit ab54ee80aa7585f9666ff4dd665441d7ce41f1e8 ] + +We have conflicting type qualifiers for "freg_t" in s390's ptrace.h and the +iphase atm device driver, which causes the compile error below. +Unfortunately the s390 typedef can't be renamed, since it's a user visible api, +nor can I change the include order in s390 code to avoid the conflict. + +So simply rename the iphase typedef to a new name. Fixes this compile error: + +In file included from drivers/atm/iphase.c:66:0: +drivers/atm/iphase.h:639:25: error: conflicting type qualifiers for 'freg_t' +In file included from next/arch/s390/include/asm/ptrace.h:9:0, + from next/arch/s390/include/asm/lowcore.h:12, + from next/arch/s390/include/asm/thread_info.h:30, + from include/linux/thread_info.h:54, + from include/linux/preempt.h:9, + from include/linux/spinlock.h:50, + from include/linux/seqlock.h:29, + from include/linux/time.h:5, + from include/linux/stat.h:18, + from include/linux/module.h:10, + from drivers/atm/iphase.c:43: +next/arch/s390/include/uapi/asm/ptrace.h:197:3: note: previous declaration of 'freg_t' was here + +Signed-off-by: Heiko Carstens +Acked-by: chas williams - CONTRACTOR +Signed-off-by: David S. Miller +--- + drivers/atm/iphase.h | 146 +++++++++++++++++++++++++-------------------------- + 1 file changed, 73 insertions(+), 73 deletions(-) + +diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h +index 6a0955e..53ecac5 100644 +--- a/drivers/atm/iphase.h ++++ b/drivers/atm/iphase.h +@@ -636,82 +636,82 @@ struct rx_buf_desc { + #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE + #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE + +-typedef volatile u_int freg_t; ++typedef volatile u_int ffreg_t; + typedef u_int rreg_t; + + typedef struct _ffredn_t { +- freg_t idlehead_high; /* Idle cell header (high) */ +- freg_t idlehead_low; /* Idle cell header (low) */ +- freg_t maxrate; /* Maximum rate */ +- freg_t stparms; /* Traffic Management Parameters */ +- freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ +- freg_t rm_type; /* */ +- u_int filler5[0x17 - 0x06]; +- freg_t cmd_reg; /* Command register */ +- u_int filler18[0x20 - 0x18]; +- freg_t cbr_base; /* CBR Pointer Base */ +- freg_t vbr_base; /* VBR Pointer Base */ +- freg_t abr_base; /* ABR Pointer Base */ +- freg_t ubr_base; /* UBR Pointer Base */ +- u_int filler24; +- freg_t vbrwq_base; /* VBR Wait Queue Base */ +- freg_t abrwq_base; /* ABR Wait Queue Base */ +- freg_t ubrwq_base; /* UBR Wait Queue Base */ +- freg_t vct_base; /* Main VC Table Base */ +- freg_t vcte_base; /* Extended Main VC Table Base */ +- u_int filler2a[0x2C - 0x2A]; +- freg_t cbr_tab_beg; /* CBR Table Begin */ +- freg_t cbr_tab_end; /* CBR Table End */ +- freg_t cbr_pointer; /* CBR Pointer */ +- u_int filler2f[0x30 - 0x2F]; +- freg_t prq_st_adr; /* Packet Ready Queue Start Address */ +- freg_t prq_ed_adr; /* Packet Ready Queue End Address */ +- freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ +- freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ +- freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ +- freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ +- freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ +- freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ +- u_int filler38[0x40 - 0x38]; +- freg_t queue_base; /* Base address for PRQ and TCQ */ +- freg_t desc_base; /* Base address of descriptor table */ +- u_int filler42[0x45 - 0x42]; +- freg_t mode_reg_0; /* Mode register 0 */ +- freg_t mode_reg_1; /* Mode register 1 */ +- freg_t intr_status_reg;/* Interrupt Status register */ +- freg_t mask_reg; /* Mask Register */ +- freg_t cell_ctr_high1; /* Total cell transfer count (high) */ +- freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ +- freg_t state_reg; /* Status register */ +- u_int filler4c[0x58 - 0x4c]; +- freg_t curr_desc_num; /* Contains the current descriptor num */ +- freg_t next_desc; /* Next descriptor */ +- freg_t next_vc; /* Next VC */ +- u_int filler5b[0x5d - 0x5b]; +- freg_t present_slot_cnt;/* Present slot count */ +- u_int filler5e[0x6a - 0x5e]; +- freg_t new_desc_num; /* New descriptor number */ +- freg_t new_vc; /* New VC */ +- freg_t sched_tbl_ptr; /* Schedule table pointer */ +- freg_t vbrwq_wptr; /* VBR wait queue write pointer */ +- freg_t vbrwq_rptr; /* VBR wait queue read pointer */ +- freg_t abrwq_wptr; /* ABR wait queue write pointer */ +- freg_t abrwq_rptr; /* ABR wait queue read pointer */ +- freg_t ubrwq_wptr; /* UBR wait queue write pointer */ +- freg_t ubrwq_rptr; /* UBR wait queue read pointer */ +- freg_t cbr_vc; /* CBR VC */ +- freg_t vbr_sb_vc; /* VBR SB VC */ +- freg_t abr_sb_vc; /* ABR SB VC */ +- freg_t ubr_sb_vc; /* UBR SB VC */ +- freg_t vbr_next_link; /* VBR next link */ +- freg_t abr_next_link; /* ABR next link */ +- freg_t ubr_next_link; /* UBR next link */ +- u_int filler7a[0x7c-0x7a]; +- freg_t out_rate_head; /* Out of rate head */ +- u_int filler7d[0xca-0x7d]; /* pad out to full address space */ +- freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ +- freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ +- u_int fillercc[0x100-0xcc]; /* pad out to full address space */ ++ ffreg_t idlehead_high; /* Idle cell header (high) */ ++ ffreg_t idlehead_low; /* Idle cell header (low) */ ++ ffreg_t maxrate; /* Maximum rate */ ++ ffreg_t stparms; /* Traffic Management Parameters */ ++ ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ ++ ffreg_t rm_type; /* */ ++ u_int filler5[0x17 - 0x06]; ++ ffreg_t cmd_reg; /* Command register */ ++ u_int filler18[0x20 - 0x18]; ++ ffreg_t cbr_base; /* CBR Pointer Base */ ++ ffreg_t vbr_base; /* VBR Pointer Base */ ++ ffreg_t abr_base; /* ABR Pointer Base */ ++ ffreg_t ubr_base; /* UBR Pointer Base */ ++ u_int filler24; ++ ffreg_t vbrwq_base; /* VBR Wait Queue Base */ ++ ffreg_t abrwq_base; /* ABR Wait Queue Base */ ++ ffreg_t ubrwq_base; /* UBR Wait Queue Base */ ++ ffreg_t vct_base; /* Main VC Table Base */ ++ ffreg_t vcte_base; /* Extended Main VC Table Base */ ++ u_int filler2a[0x2C - 0x2A]; ++ ffreg_t cbr_tab_beg; /* CBR Table Begin */ ++ ffreg_t cbr_tab_end; /* CBR Table End */ ++ ffreg_t cbr_pointer; /* CBR Pointer */ ++ u_int filler2f[0x30 - 0x2F]; ++ ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ ++ ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ ++ ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ ++ ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ ++ ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ ++ ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ ++ ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ ++ ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ ++ u_int filler38[0x40 - 0x38]; ++ ffreg_t queue_base; /* Base address for PRQ and TCQ */ ++ ffreg_t desc_base; /* Base address of descriptor table */ ++ u_int filler42[0x45 - 0x42]; ++ ffreg_t mode_reg_0; /* Mode register 0 */ ++ ffreg_t mode_reg_1; /* Mode register 1 */ ++ ffreg_t intr_status_reg;/* Interrupt Status register */ ++ ffreg_t mask_reg; /* Mask Register */ ++ ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ ++ ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ ++ ffreg_t state_reg; /* Status register */ ++ u_int filler4c[0x58 - 0x4c]; ++ ffreg_t curr_desc_num; /* Contains the current descriptor num */ ++ ffreg_t next_desc; /* Next descriptor */ ++ ffreg_t next_vc; /* Next VC */ ++ u_int filler5b[0x5d - 0x5b]; ++ ffreg_t present_slot_cnt;/* Present slot count */ ++ u_int filler5e[0x6a - 0x5e]; ++ ffreg_t new_desc_num; /* New descriptor number */ ++ ffreg_t new_vc; /* New VC */ ++ ffreg_t sched_tbl_ptr; /* Schedule table pointer */ ++ ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ ++ ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ ++ ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ ++ ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ ++ ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ ++ ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ ++ ffreg_t cbr_vc; /* CBR VC */ ++ ffreg_t vbr_sb_vc; /* VBR SB VC */ ++ ffreg_t abr_sb_vc; /* ABR SB VC */ ++ ffreg_t ubr_sb_vc; /* UBR SB VC */ ++ ffreg_t vbr_next_link; /* VBR next link */ ++ ffreg_t abr_next_link; /* ABR next link */ ++ ffreg_t ubr_next_link; /* UBR next link */ ++ u_int filler7a[0x7c-0x7a]; ++ ffreg_t out_rate_head; /* Out of rate head */ ++ u_int filler7d[0xca-0x7d]; /* pad out to full address space */ ++ ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ ++ ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ ++ u_int fillercc[0x100-0xcc]; /* pad out to full address space */ + } ffredn_t; + + typedef struct _rfredn_t { +-- +1.7.11.7 + + +From 5ef9a447aa4e6a1da43a04b98befa5643c806c1b Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Wed, 6 Feb 2013 23:41:35 +0000 +Subject: [PATCH 23/44] xen/netback: shutdown the ring if it contains garbage. + +[ Upstream commit 48856286b64e4b66ec62b94e504d0b29c1ade664 ] + +A buggy or malicious frontend should not be able to confuse netback. +If we spot anything which is not as it should be then shutdown the +device and don't try to continue with the ring in a potentially +hostile state. Well behaved and non-hostile frontends will not be +penalised. + +As well as making the existing checks for such errors fatal also add a +new check that ensures that there isn't an insane number of requests +on the ring (i.e. more than would fit in the ring). If the ring +contains garbage then previously is was possible to loop over this +insane number, getting an error each time and therefore not generating +any more pending requests and therefore not exiting the loop in +xen_netbk_tx_build_gops for an externded period. + +Also turn various netdev_dbg calls which no precipitate a fatal error +into netdev_err, they are rate limited because the device is shutdown +afterwards. + +This fixes at least one known DoS/softlockup of the backend domain. + +Signed-off-by: Ian Campbell +Reviewed-by: Konrad Rzeszutek Wilk +Acked-by: Jan Beulich +Signed-off-by: David S. Miller +--- + drivers/net/xen-netback/common.h | 3 ++ + drivers/net/xen-netback/interface.c | 23 ++++++++------ + drivers/net/xen-netback/netback.c | 62 +++++++++++++++++++++++++++---------- + 3 files changed, 62 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h +index 94b79c3..9d7f172 100644 +--- a/drivers/net/xen-netback/common.h ++++ b/drivers/net/xen-netback/common.h +@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); + /* Notify xenvif that ring now has space to send an skb to the frontend */ + void xenvif_notify_tx_completion(struct xenvif *vif); + ++/* Prevent the device from generating any further traffic. */ ++void xenvif_carrier_off(struct xenvif *vif); ++ + /* Returns number of ring slots required to send an skb to the frontend */ + unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); + +diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c +index b7d41f8..b8c5193 100644 +--- a/drivers/net/xen-netback/interface.c ++++ b/drivers/net/xen-netback/interface.c +@@ -343,17 +343,22 @@ err: + return err; + } + +-void xenvif_disconnect(struct xenvif *vif) ++void xenvif_carrier_off(struct xenvif *vif) + { + struct net_device *dev = vif->dev; +- if (netif_carrier_ok(dev)) { +- rtnl_lock(); +- netif_carrier_off(dev); /* discard queued packets */ +- if (netif_running(dev)) +- xenvif_down(vif); +- rtnl_unlock(); +- xenvif_put(vif); +- } ++ ++ rtnl_lock(); ++ netif_carrier_off(dev); /* discard queued packets */ ++ if (netif_running(dev)) ++ xenvif_down(vif); ++ rtnl_unlock(); ++ xenvif_put(vif); ++} ++ ++void xenvif_disconnect(struct xenvif *vif) ++{ ++ if (netif_carrier_ok(vif->dev)) ++ xenvif_carrier_off(vif); + + atomic_dec(&vif->refcnt); + wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index f2d6b78..c2e3336 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -888,6 +888,13 @@ static void netbk_tx_err(struct xenvif *vif, + xenvif_put(vif); + } + ++static void netbk_fatal_tx_err(struct xenvif *vif) ++{ ++ netdev_err(vif->dev, "fatal error; disabling device\n"); ++ xenvif_carrier_off(vif); ++ xenvif_put(vif); ++} ++ + static int netbk_count_requests(struct xenvif *vif, + struct xen_netif_tx_request *first, + struct xen_netif_tx_request *txp, +@@ -901,19 +908,22 @@ static int netbk_count_requests(struct xenvif *vif, + + do { + if (frags >= work_to_do) { +- netdev_dbg(vif->dev, "Need more frags\n"); ++ netdev_err(vif->dev, "Need more frags\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + + if (unlikely(frags >= MAX_SKB_FRAGS)) { +- netdev_dbg(vif->dev, "Too many frags\n"); ++ netdev_err(vif->dev, "Too many frags\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + + memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), + sizeof(*txp)); + if (txp->size > first->size) { +- netdev_dbg(vif->dev, "Frags galore\n"); ++ netdev_err(vif->dev, "Frag is bigger than frame.\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + +@@ -921,8 +931,9 @@ static int netbk_count_requests(struct xenvif *vif, + frags++; + + if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { +- netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", ++ netdev_err(vif->dev, "txp->offset: %x, size: %u\n", + txp->offset, txp->size); ++ netbk_fatal_tx_err(vif); + return -frags; + } + } while ((txp++)->flags & XEN_NETTXF_more_data); +@@ -1095,7 +1106,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, + + do { + if (unlikely(work_to_do-- <= 0)) { +- netdev_dbg(vif->dev, "Missing extra info\n"); ++ netdev_err(vif->dev, "Missing extra info\n"); ++ netbk_fatal_tx_err(vif); + return -EBADR; + } + +@@ -1104,8 +1116,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, + if (unlikely(!extra.type || + extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + vif->tx.req_cons = ++cons; +- netdev_dbg(vif->dev, ++ netdev_err(vif->dev, + "Invalid extra type: %d\n", extra.type); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + +@@ -1121,13 +1134,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, + struct xen_netif_extra_info *gso) + { + if (!gso->u.gso.size) { +- netdev_dbg(vif->dev, "GSO size must not be zero.\n"); ++ netdev_err(vif->dev, "GSO size must not be zero.\n"); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { +- netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); ++ netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + +@@ -1264,9 +1279,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + + /* Get a netif from the list with work to do. */ + vif = poll_net_schedule_list(netbk); ++ /* This can sometimes happen because the test of ++ * list_empty(net_schedule_list) at the top of the ++ * loop is unlocked. Just go back and have another ++ * look. ++ */ + if (!vif) + continue; + ++ if (vif->tx.sring->req_prod - vif->tx.req_cons > ++ XEN_NETIF_TX_RING_SIZE) { ++ netdev_err(vif->dev, ++ "Impossible number of requests. " ++ "req_prod %d, req_cons %d, size %ld\n", ++ vif->tx.sring->req_prod, vif->tx.req_cons, ++ XEN_NETIF_TX_RING_SIZE); ++ netbk_fatal_tx_err(vif); ++ continue; ++ } ++ + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); + if (!work_to_do) { + xenvif_put(vif); +@@ -1294,17 +1325,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + work_to_do = xen_netbk_get_extras(vif, extras, + work_to_do); + idx = vif->tx.req_cons; +- if (unlikely(work_to_do < 0)) { +- netbk_tx_err(vif, &txreq, idx); ++ if (unlikely(work_to_do < 0)) + continue; +- } + } + + ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); +- if (unlikely(ret < 0)) { +- netbk_tx_err(vif, &txreq, idx - ret); ++ if (unlikely(ret < 0)) + continue; +- } ++ + idx += ret; + + if (unlikely(txreq.size < ETH_HLEN)) { +@@ -1316,11 +1344,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + + /* No crossing a page as the payload mustn't fragment. */ + if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { +- netdev_dbg(vif->dev, ++ netdev_err(vif->dev, + "txreq.offset: %x, size: %u, end: %lu\n", + txreq.offset, txreq.size, + (txreq.offset&~PAGE_MASK) + txreq.size); +- netbk_tx_err(vif, &txreq, idx); ++ netbk_fatal_tx_err(vif); + continue; + } + +@@ -1348,8 +1376,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (netbk_set_skb_gso(vif, skb, gso)) { ++ /* Failure in netbk_set_skb_gso is fatal. */ + kfree_skb(skb); +- netbk_tx_err(vif, &txreq, idx); + continue; + } + } +-- +1.7.11.7 + + +From 10948f5aa9992de84e022e218b494586fe92d547 Mon Sep 17 00:00:00 2001 +From: Matthew Daley +Date: Wed, 6 Feb 2013 23:41:36 +0000 +Subject: [PATCH 24/44] xen/netback: don't leak pages on failure in + xen_netbk_tx_check_gop. + +[ Upstream commit 7d5145d8eb2b9791533ffe4dc003b129b9696c48 ] + +Signed-off-by: Matthew Daley +Reviewed-by: Konrad Rzeszutek Wilk +Acked-by: Ian Campbell +Acked-by: Jan Beulich +Signed-off-by: David S. Miller +--- + drivers/net/xen-netback/netback.c | 38 +++++++++++++------------------------- + 1 file changed, 13 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index c2e3336..bf692df 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) + atomic_dec(&netbk->netfront_count); + } + +-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); ++static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, ++ u8 status); + static void make_tx_response(struct xenvif *vif, + struct xen_netif_tx_request *txp, + s8 st); +@@ -1007,30 +1008,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + { + struct gnttab_copy *gop = *gopp; + u16 pending_idx = *((u16 *)skb->data); +- struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; +- struct xenvif *vif = pending_tx_info[pending_idx].vif; +- struct xen_netif_tx_request *txp; + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int i, err, start; + + /* Check status of header. */ + err = gop->status; +- if (unlikely(err)) { +- pending_ring_idx_t index; +- index = pending_index(netbk->pending_prod++); +- txp = &pending_tx_info[pending_idx].req; +- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- netbk->pending_ring[index] = pending_idx; +- xenvif_put(vif); +- } ++ if (unlikely(err)) ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + /* Skip first skb fragment if it is on same page as header fragment. */ + start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); + + for (i = start; i < nr_frags; i++) { + int j, newerr; +- pending_ring_idx_t index; + + pending_idx = frag_get_pending_idx(&shinfo->frags[i]); + +@@ -1039,16 +1030,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + if (likely(!newerr)) { + /* Had a previous error? Invalidate this fragment. */ + if (unlikely(err)) +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + continue; + } + + /* Error on this fragment: respond to client with an error. */ +- txp = &netbk->pending_tx_info[pending_idx].req; +- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- index = pending_index(netbk->pending_prod++); +- netbk->pending_ring[index] = pending_idx; +- xenvif_put(vif); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + /* Not the first error? Preceding frags already invalidated. */ + if (err) +@@ -1056,10 +1043,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + + /* First error: invalidate header and preceding fragments. */ + pending_idx = *((u16 *)skb->data); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + for (j = start; j < i; j++) { + pending_idx = frag_get_pending_idx(&shinfo->frags[j]); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + + /* Remember the error: invalidate all subsequent fragments. */ +@@ -1093,7 +1080,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) + + /* Take an extra reference to offset xen_netbk_idx_release */ + get_page(netbk->mmap_pages[pending_idx]); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + } + +@@ -1476,7 +1463,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) + txp->size -= data_len; + } else { + /* Schedule a response immediately. */ +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + + if (txp->flags & XEN_NETTXF_csum_blank) +@@ -1528,7 +1515,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) + xen_netbk_tx_submit(netbk); + } + +-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) ++static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, ++ u8 status) + { + struct xenvif *vif; + struct pending_tx_info *pending_tx_info; +@@ -1542,7 +1530,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) + + vif = pending_tx_info->vif; + +- make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); ++ make_tx_response(vif, &pending_tx_info->req, status); + + index = pending_index(netbk->pending_prod++); + netbk->pending_ring[index] = pending_idx; +-- +1.7.11.7 + + +From 2e0b7c1781a94640566dccf9d7441d500fa69e40 Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Wed, 6 Feb 2013 23:41:37 +0000 +Subject: [PATCH 25/44] xen/netback: free already allocated memory on failure + in xen_netbk_get_requests + +[ Upstream commit 4cc7c1cb7b11b6f3515bd9075527576a1eecc4aa ] + +Signed-off-by: Ian Campbell +Signed-off-by: David S. Miller +--- + drivers/net/xen-netback/netback.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index bf692df..dcb2d4d 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -978,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, + pending_idx = netbk->pending_ring[index]; + page = xen_netbk_alloc_page(netbk, skb, pending_idx); + if (!page) +- return NULL; ++ goto err; + + gop->source.u.ref = txp->gref; + gop->source.domid = vif->domid; +@@ -1000,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, + } + + return gop; ++err: ++ /* Unwind, freeing all pages and sending error responses. */ ++ while (i-- > start) { ++ xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), ++ XEN_NETIF_RSP_ERROR); ++ } ++ /* The head too, if necessary. */ ++ if (start) ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); ++ ++ return NULL; + } + + static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, +-- +1.7.11.7 + + +From d5b2f3542a1f9c7b5092816b87db08e9f08f1551 Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Wed, 6 Feb 2013 23:41:38 +0000 +Subject: [PATCH 26/44] netback: correct netbk_tx_err to handle wrap around. + +[ Upstream commit b9149729ebdcfce63f853aa54a404c6a8f6ebbf3 ] + +Signed-off-by: Ian Campbell +Acked-by: Jan Beulich +Signed-off-by: David S. Miller +--- + drivers/net/xen-netback/netback.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index dcb2d4d..2b9520c 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -880,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif, + + do { + make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- if (cons >= end) ++ if (cons == end) + break; + txp = RING_GET_REQUEST(&vif->tx, cons++); + } while (1); +-- +1.7.11.7 + + +From 28ecceda6c2f58f14379e35a0caec5f9b57cc798 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Wed, 16 Jan 2013 20:55:01 +0000 +Subject: [PATCH 27/44] ipv4: Remove output route check in ipv4_mtu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 38d523e2948162776903349c89d65f7b9370dadb ] + +The output route check was introduced with git commit 261663b0 +(ipv4: Don't use the cached pmtu informations for input routes) +during times when we cached the pmtu informations on the +inetpeer. Now the pmtu informations are back in the routes, +so this check is obsolete. It also had some unwanted side effects, +as reported by Timo Teras and Lukas Tribus. + +Signed-off-by: Steffen Klassert +Acked-by: Timo Teräs +Signed-off-by: David S. Miller +--- + net/ipv4/route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index df25142..11d28e3 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1120,7 +1120,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) + if (!mtu || time_after_eq(jiffies, rt->dst.expires)) + mtu = dst_metric_raw(dst, RTAX_MTU); + +- if (mtu && rt_is_output_route(rt)) ++ if (mtu) + return mtu; + + mtu = dst->dev->mtu; +-- +1.7.11.7 + + +From d282905a8f4d2f86ffca23f2bbee1697fdf832aa Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Wed, 16 Jan 2013 20:58:10 +0000 +Subject: [PATCH 28/44] ipv4: Don't update the pmtu on mtu locked routes + +[ Upstream commit fa1e492aa3cbafba9f8fc6d05e5b08a3091daf4a ] + +Routes with locked mtu should not use learned pmtu informations, +so do not update the pmtu on these routes. + +Reported-by: Julian Anastasov +Signed-off-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv4/route.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 11d28e3..0660d6f 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -912,6 +912,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) + struct dst_entry *dst = &rt->dst; + struct fib_result res; + ++ if (dst_metric_locked(dst, RTAX_MTU)) ++ return; ++ + if (dst->dev->mtu < mtu) + return; + +-- +1.7.11.7 + + +From 7e5337b6085429c382297b71d3099ec56b82829d Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Wed, 16 Jan 2013 22:09:49 +0000 +Subject: [PATCH 29/44] ipv6: Add an error handler for icmp6 + +[ Upstream commit 6f809da27c94425e07be4a64d5093e1df95188e9 ] + +pmtu and redirect events are now handled in the protocols error handler, +so add an error handler for icmp6 to do this. It is needed in the case +when we have no socket context. Based on a patch by Duan Jiong. + +Reported-by: Duan Jiong +Signed-off-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv6/icmp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index 24d69db..4d844d7 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -81,10 +81,22 @@ static inline struct sock *icmpv6_sk(struct net *net) + return net->ipv6.icmp_sk[smp_processor_id()]; + } + ++static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ++ u8 type, u8 code, int offset, __be32 info) ++{ ++ struct net *net = dev_net(skb->dev); ++ ++ if (type == ICMPV6_PKT_TOOBIG) ++ ip6_update_pmtu(skb, net, info, 0, 0); ++ else if (type == NDISC_REDIRECT) ++ ip6_redirect(skb, net, 0, 0); ++} ++ + static int icmpv6_rcv(struct sk_buff *skb); + + static const struct inet6_protocol icmpv6_protocol = { + .handler = icmpv6_rcv, ++ .err_handler = icmpv6_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + }; + +-- +1.7.11.7 + + +From 5d7f31144c2e375a5a241bc76648ccd8a6d5e6c9 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Mon, 21 Jan 2013 01:59:11 +0000 +Subject: [PATCH 30/44] ipv4: Invalidate the socket cached route on pmtu + events if possible + +[ Upstream commit 9cb3a50c5f63ed745702972f66eaee8767659acd ] + +The route lookup in ipv4_sk_update_pmtu() might return a route +different from the route we cached at the socket. This is because +standart routes are per cpu, so each cpu has it's own struct rtable. +This means that we do not invalidate the socket cached route if the +NET_RX_SOFTIRQ is not served by the same cpu that the sending socket +uses. As a result, the cached route reused until we disconnect. + +With this patch we invalidate the socket cached route if possible. +If the socket is owened by the user, we can't update the cached +route directly. A followup patch will implement socket release +callback functions for datagram sockets to handle this case. + +Reported-by: Yurij M. Plotnikov +Signed-off-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv4/route.c | 42 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 41 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 0660d6f..fc6a6b4 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -965,7 +965,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, + } + EXPORT_SYMBOL_GPL(ipv4_update_pmtu); + +-void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) ++static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + { + const struct iphdr *iph = (const struct iphdr *) skb->data; + struct flowi4 fl4; +@@ -978,6 +978,46 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + ip_rt_put(rt); + } + } ++ ++void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) ++{ ++ const struct iphdr *iph = (const struct iphdr *) skb->data; ++ struct flowi4 fl4; ++ struct rtable *rt; ++ struct dst_entry *dst; ++ ++ bh_lock_sock(sk); ++ rt = (struct rtable *) __sk_dst_get(sk); ++ ++ if (sock_owned_by_user(sk) || !rt) { ++ __ipv4_sk_update_pmtu(skb, sk, mtu); ++ goto out; ++ } ++ ++ __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); ++ ++ if (!__sk_dst_check(sk, 0)) { ++ rt = ip_route_output_flow(sock_net(sk), &fl4, sk); ++ if (IS_ERR(rt)) ++ goto out; ++ } ++ ++ __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); ++ ++ dst = dst_check(&rt->dst, 0); ++ if (!dst) { ++ rt = ip_route_output_flow(sock_net(sk), &fl4, sk); ++ if (IS_ERR(rt)) ++ goto out; ++ ++ dst = &rt->dst; ++ } ++ ++ __sk_dst_set(sk, dst); ++ ++out: ++ bh_unlock_sock(sk); ++} + EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); + + void ipv4_redirect(struct sk_buff *skb, struct net *net, +-- +1.7.11.7 + + +From 250a2bac5bcef490f775aa2680c3934915aeb51a Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Mon, 21 Jan 2013 02:00:03 +0000 +Subject: [PATCH 31/44] ipv4: Add a socket release callback for datagram + sockets + +[ Upstream commit 8141ed9fcedb278f4a3a78680591bef1e55f75fb ] + +This implements a socket release callback function to check +if the socket cached route got invalid during the time +we owned the socket. The function is used from udp, raw +and ping sockets. + +Signed-off-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + include/net/ip.h | 2 ++ + net/ipv4/datagram.c | 25 +++++++++++++++++++++++++ + net/ipv4/ping.c | 1 + + net/ipv4/raw.c | 1 + + net/ipv4/udp.c | 1 + + 5 files changed, 30 insertions(+) + +diff --git a/include/net/ip.h b/include/net/ip.h +index 0707fb9..a68f838 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -143,6 +143,8 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) + extern int ip4_datagram_connect(struct sock *sk, + struct sockaddr *uaddr, int addr_len); + ++extern void ip4_datagram_release_cb(struct sock *sk); ++ + struct ip_reply_arg { + struct kvec iov[1]; + int flags; +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index 424fafb..b28e863 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -85,3 +85,28 @@ out: + return err; + } + EXPORT_SYMBOL(ip4_datagram_connect); ++ ++void ip4_datagram_release_cb(struct sock *sk) ++{ ++ const struct inet_sock *inet = inet_sk(sk); ++ const struct ip_options_rcu *inet_opt; ++ __be32 daddr = inet->inet_daddr; ++ struct flowi4 fl4; ++ struct rtable *rt; ++ ++ if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0)) ++ return; ++ ++ rcu_read_lock(); ++ inet_opt = rcu_dereference(inet->inet_opt); ++ if (inet_opt && inet_opt->opt.srr) ++ daddr = inet_opt->opt.faddr; ++ rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, ++ inet->inet_saddr, inet->inet_dport, ++ inet->inet_sport, sk->sk_protocol, ++ RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); ++ if (!IS_ERR(rt)) ++ __sk_dst_set(sk, &rt->dst); ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(ip4_datagram_release_cb); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 8f3d054..6f9c072 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -738,6 +738,7 @@ struct proto ping_prot = { + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, ++ .release_cb = ip4_datagram_release_cb, + .hash = ping_v4_hash, + .unhash = ping_v4_unhash, + .get_port = ping_v4_get_port, +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 73d1e4d..6f08991 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -894,6 +894,7 @@ struct proto raw_prot = { + .recvmsg = raw_recvmsg, + .bind = raw_bind, + .backlog_rcv = raw_rcv_skb, ++ .release_cb = ip4_datagram_release_cb, + .hash = raw_hash_sk, + .unhash = raw_unhash_sk, + .obj_size = sizeof(struct raw_sock), +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 79c8dbe..1f4d405 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1952,6 +1952,7 @@ struct proto udp_prot = { + .recvmsg = udp_recvmsg, + .sendpage = udp_sendpage, + .backlog_rcv = __udp_queue_rcv_skb, ++ .release_cb = ip4_datagram_release_cb, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, + .rehash = udp_v4_rehash, +-- +1.7.11.7 + + +From db28ad52a9a7c7fff4063d733e39169c663b2d2e Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Tue, 22 Jan 2013 00:01:28 +0000 +Subject: [PATCH 32/44] ipv4: Fix route refcount on pmtu discovery + +[ Upstream commit b44108dbdbaa07c609bb5755e8dd6c2035236251 ] + +git commit 9cb3a50c (ipv4: Invalidate the socket cached route on +pmtu events if possible) introduced a refcount problem. We don't +get a refcount on the route if we get it from__sk_dst_get(), but +we need one if we want to reuse this route because __sk_dst_set() +releases the refcount of the old route. This patch adds proper +refcount handling for that case. We introduce a 'new' flag to +indicate that we are going to use a new route and we release the +old route only if we replace it by a new one. + +Reported-by: Julian Anastasov +Signed-off-by: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv4/route.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index fc6a6b4..0fdfe4c 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -985,6 +985,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + struct flowi4 fl4; + struct rtable *rt; + struct dst_entry *dst; ++ bool new = false; + + bh_lock_sock(sk); + rt = (struct rtable *) __sk_dst_get(sk); +@@ -1000,20 +1001,26 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) + goto out; ++ ++ new = true; + } + + __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); + + dst = dst_check(&rt->dst, 0); + if (!dst) { ++ if (new) ++ dst_release(&rt->dst); ++ + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) + goto out; + +- dst = &rt->dst; ++ new = true; + } + +- __sk_dst_set(sk, dst); ++ if (new) ++ __sk_dst_set(sk, &rt->dst); + + out: + bh_unlock_sock(sk); +-- +1.7.11.7 + + +From 9fdbfac789ac6ee2eade40d045576f701b5ea3ee Mon Sep 17 00:00:00 2001 +From: Neil Horman +Date: Thu, 17 Jan 2013 11:15:08 +0000 +Subject: [PATCH 33/44] sctp: refactor sctp_outq_teardown to insure proper + re-initalization + +[ Upstream commit 2f94aabd9f6c925d77aecb3ff020f1cc12ed8f86 ] + +Jamie Parsons reported a problem recently, in which the re-initalization of an +association (The duplicate init case), resulted in a loss of receive window +space. He tracked down the root cause to sctp_outq_teardown, which discarded +all the data on an outq during a re-initalization of the corresponding +association, but never reset the outq->outstanding_data field to zero. I wrote, +and he tested this fix, which does a proper full re-initalization of the outq, +fixing this problem, and hopefully future proofing us from simmilar issues down +the road. + +Signed-off-by: Neil Horman +Reported-by: Jamie Parsons +Tested-by: Jamie Parsons +CC: Jamie Parsons +CC: Vlad Yasevich +CC: "David S. Miller" +CC: netdev@vger.kernel.org +Acked-by: Vlad Yasevich +Signed-off-by: David S. Miller +--- + net/sctp/outqueue.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c +index 1b4a7f8..bcaa4c8 100644 +--- a/net/sctp/outqueue.c ++++ b/net/sctp/outqueue.c +@@ -224,7 +224,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) + + /* Free the outqueue structure and any related pending chunks. + */ +-void sctp_outq_teardown(struct sctp_outq *q) ++static void __sctp_outq_teardown(struct sctp_outq *q) + { + struct sctp_transport *transport; + struct list_head *lchunk, *temp; +@@ -277,8 +277,6 @@ void sctp_outq_teardown(struct sctp_outq *q) + sctp_chunk_free(chunk); + } + +- q->error = 0; +- + /* Throw away any leftover control chunks. */ + list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { + list_del_init(&chunk->list); +@@ -286,11 +284,17 @@ void sctp_outq_teardown(struct sctp_outq *q) + } + } + ++void sctp_outq_teardown(struct sctp_outq *q) ++{ ++ __sctp_outq_teardown(q); ++ sctp_outq_init(q->asoc, q); ++} ++ + /* Free the outqueue structure and any related pending chunks. */ + void sctp_outq_free(struct sctp_outq *q) + { + /* Throw away leftover chunks. */ +- sctp_outq_teardown(q); ++ __sctp_outq_teardown(q); + + /* If we were kmalloc()'d, free the memory. */ + if (q->malloced) +-- +1.7.11.7 + + +From b6eafd305aecd134d3333b2ebff487e86bd39eae Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Fri, 8 Feb 2013 03:04:34 +0000 +Subject: [PATCH 34/44] net: sctp: sctp_setsockopt_auth_key: use kzfree + instead of kfree + +[ Upstream commit 6ba542a291a5e558603ac51cda9bded347ce7627 ] + +In sctp_setsockopt_auth_key, we create a temporary copy of the user +passed shared auth key for the endpoint or association and after +internal setup, we free it right away. Since it's sensitive data, we +should zero out the key before returning the memory back to the +allocator. Thus, use kzfree instead of kfree, just as we do in +sctp_auth_key_put(). + +Signed-off-by: Daniel Borkmann +Signed-off-by: David S. Miller +--- + net/sctp/socket.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 406d957..9261d9a 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -3388,7 +3388,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, + + ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); + out: +- kfree(authkey); ++ kzfree(authkey); + return ret; + } + +-- +1.7.11.7 + + +From de6cbc343521cd56514d53fc249fbbd03532d04c Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Fri, 8 Feb 2013 03:04:35 +0000 +Subject: [PATCH 35/44] net: sctp: sctp_endpoint_free: zero out secret key + data + +[ Upstream commit b5c37fe6e24eec194bb29d22fdd55d73bcc709bf ] + +On sctp_endpoint_destroy, previously used sensitive keying material +should be zeroed out before the memory is returned, as we already do +with e.g. auth keys when released. + +Signed-off-by: Daniel Borkmann +Acked-by: Vlad Yasevich +Signed-off-by: David S. Miller +--- + net/sctp/endpointola.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c +index 1859e2b..80a7264 100644 +--- a/net/sctp/endpointola.c ++++ b/net/sctp/endpointola.c +@@ -249,6 +249,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) + /* Final destructor for endpoint. */ + static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + { ++ int i; ++ + SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); + + /* Free up the HMAC transform. */ +@@ -271,6 +273,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + sctp_inq_free(&ep->base.inqueue); + sctp_bind_addr_free(&ep->base.bind_addr); + ++ for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i) ++ memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE); ++ + /* Remove and free the port */ + if (sctp_sk(ep->base.sk)->bind_hash) + sctp_put_port(ep->base.sk); +-- +1.7.11.7 + + +From a8963d813f812a9c13baed12ec4c06a1c3443e7c Mon Sep 17 00:00:00 2001 +From: Yuchung Cheng +Date: Thu, 31 Jan 2013 11:16:46 -0800 +Subject: [PATCH 36/44] tcp: detect SYN/data drop when F-RTO is disabled + +[ Upstream commit 66555e92fb7a619188c02cceae4bbc414f15f96d ] + +On receiving the SYN-ACK, Fast Open checks icsk_retransmit for SYN +retransmission to detect SYN/data drops. But if F-RTO is disabled, +icsk_retransmit is reset at step D of tcp_fastretrans_alert() ( +under tcp_ack()) before tcp_rcv_fastopen_synack(). The fix is to use +total_retrans instead which accounts for SYN retransmission regardless +the use of F-RTO. + +Signed-off-by: Yuchung Cheng +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_input.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 181fc82..765db33 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5639,8 +5639,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, + * the remote receives only the retransmitted (regular) SYNs: either + * the original SYN-data or the corresponding SYN-ACK is lost. + */ +- syn_drop = (cookie->len <= 0 && data && +- inet_csk(sk)->icsk_retransmits); ++ syn_drop = (cookie->len <= 0 && data && tp->total_retrans); + + tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); + +-- +1.7.11.7 + + +From 8bee456022dadde41b6fe3c551f7e46af777df10 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 2 Feb 2013 05:23:16 +0000 +Subject: [PATCH 37/44] tcp: fix an infinite loop in tcp_slow_start() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 973ec449bb4f2b8c514bacbcb4d9506fc31c8ce3 ] + +Since commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()), +a nul snd_cwnd triggers an infinite loop in tcp_slow_start() + +Avoid this infinite loop and log a one time error for further +analysis. FRTO code is suspected to cause this bug. + +Reported-by: Pasi Kärkkäinen +Signed-off-by: Eric Dumazet +Cc: Neal Cardwell +Cc: Yuchung Cheng +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_cong.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c +index 1432cdb..fc582a7 100644 +--- a/net/ipv4/tcp_cong.c ++++ b/net/ipv4/tcp_cong.c +@@ -309,6 +309,12 @@ void tcp_slow_start(struct tcp_sock *tp) + { + int cnt; /* increase in packets */ + unsigned int delta = 0; ++ u32 snd_cwnd = tp->snd_cwnd; ++ ++ if (unlikely(!snd_cwnd)) { ++ pr_err_once("snd_cwnd is nul, please report this bug.\n"); ++ snd_cwnd = 1U; ++ } + + /* RFC3465: ABC Slow start + * Increase only after a full MSS of bytes is acked +@@ -323,7 +329,7 @@ void tcp_slow_start(struct tcp_sock *tp) + if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh) + cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */ + else +- cnt = tp->snd_cwnd; /* exponential increase */ ++ cnt = snd_cwnd; /* exponential increase */ + + /* RFC3465: ABC + * We MAY increase by 2 if discovered delayed ack +@@ -333,11 +339,11 @@ void tcp_slow_start(struct tcp_sock *tp) + tp->bytes_acked = 0; + + tp->snd_cwnd_cnt += cnt; +- while (tp->snd_cwnd_cnt >= tp->snd_cwnd) { +- tp->snd_cwnd_cnt -= tp->snd_cwnd; ++ while (tp->snd_cwnd_cnt >= snd_cwnd) { ++ tp->snd_cwnd_cnt -= snd_cwnd; + delta++; + } +- tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp); ++ tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp); + } + EXPORT_SYMBOL_GPL(tcp_slow_start); + +-- +1.7.11.7 + + +From 704e9be40e69eed1a96363ce2a6707801f5ff174 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 3 Feb 2013 09:13:05 +0000 +Subject: [PATCH 38/44] tcp: frto should not set snd_cwnd to 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 2e5f421211ff76c17130b4597bc06df4eeead24f ] + +Commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()) +uncovered a bug in FRTO code : +tcp_process_frto() is setting snd_cwnd to 0 if the number +of in flight packets is 0. + +As Neal pointed out, if no packet is in flight we lost our +chance to disambiguate whether a loss timeout was spurious. + +We should assume it was a proper loss. + +Reported-by: Pasi Kärkkäinen +Signed-off-by: Neal Cardwell +Signed-off-by: Eric Dumazet +Cc: Ilpo Järvinen +Cc: Yuchung Cheng +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_input.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 765db33..3a5f691 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3484,7 +3484,8 @@ static bool tcp_process_frto(struct sock *sk, int flag) + ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) + tp->undo_marker = 0; + +- if (!before(tp->snd_una, tp->frto_highmark)) { ++ if (!before(tp->snd_una, tp->frto_highmark) || ++ !tcp_packets_in_flight(tp)) { + tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); + return true; + } +-- +1.7.11.7 + + +From cd3789e7ba292f27f25e9076dd23b97cf30d89b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Mon, 4 Feb 2013 02:14:25 +0000 +Subject: [PATCH 39/44] tcp: fix for zero packets_in_flight was too broad +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 6731d2095bd4aef18027c72ef845ab1087c3ba63 ] + +There are transients during normal FRTO procedure during which +the packets_in_flight can go to zero between write_queue state +updates and firing the resulting segments out. As FRTO processing +occurs during that window the check must be more precise to +not match "spuriously" :-). More specificly, e.g., when +packets_in_flight is zero but FLAG_DATA_ACKED is true the problematic +branch that set cwnd into zero would not be taken and new segments +might be sent out later. + +Signed-off-by: Ilpo Järvinen +Tested-by: Eric Dumazet +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_input.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 3a5f691..beabc80 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3484,8 +3484,7 @@ static bool tcp_process_frto(struct sock *sk, int flag) + ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) + tp->undo_marker = 0; + +- if (!before(tp->snd_una, tp->frto_highmark) || +- !tcp_packets_in_flight(tp)) { ++ if (!before(tp->snd_una, tp->frto_highmark)) { + tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); + return true; + } +@@ -3505,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag) + } + } else { + if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { ++ if (!tcp_packets_in_flight(tp)) { ++ tcp_enter_frto_loss(sk, 2, flag); ++ return true; ++ } ++ + /* Prevent sending of new data. */ + tp->snd_cwnd = min(tp->snd_cwnd, + tcp_packets_in_flight(tp)); +-- +1.7.11.7 + + +From a037491fdc5e5ca2b6f21366b1165555e285c71d Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Sun, 2 Dec 2012 11:49:27 +0000 +Subject: [PATCH 40/44] tcp: don't abort splice() after small transfers + +[ Upstream commit 02275a2ee7c0ea475b6f4a6428f5df592bc9d30b ] + +TCP coalescing added a regression in splice(socket->pipe) performance, +for some workloads because of the way tcp_read_sock() is implemented. + +The reason for this is the break when (offset + 1 != skb->len). + +As we released the socket lock, this condition is possible if TCP stack +added a fragment to the skb, which can happen with TCP coalescing. + +So let's go back to the beginning of the loop when this happens, +to give a chance to splice more frags per system call. + +Doing so fixes the issue and makes GRO 10% faster than LRO +on CPU-bound splice() workloads instead of the opposite. + +Signed-off-by: Willy Tarreau +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/tcp.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index e457c7a..91de64d 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1490,15 +1490,19 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + copied += used; + offset += used; + } +- /* +- * If recv_actor drops the lock (e.g. TCP splice ++ /* If recv_actor drops the lock (e.g. TCP splice + * receive) the skb pointer might be invalid when + * getting here: tcp_collapse might have deleted it + * while aggregating skbs from the socket queue. + */ +- skb = tcp_recv_skb(sk, seq-1, &offset); +- if (!skb || (offset+1 != skb->len)) ++ skb = tcp_recv_skb(sk, seq - 1, &offset); ++ if (!skb) + break; ++ /* TCP coalescing might have appended data to the skb. ++ * Try to splice more frags ++ */ ++ if (offset + 1 != skb->len) ++ continue; + } + if (tcp_hdr(skb)->fin) { + sk_eat_skb(sk, skb, false); +-- +1.7.11.7 + + +From 1f2037984ea99422150679b62f18e9d41f2e9b71 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 10 Jan 2013 07:06:10 +0000 +Subject: [PATCH 41/44] tcp: splice: fix an infinite loop in tcp_read_sock() + +[ Upstream commit ff905b1e4aad8ccbbb0d42f7137f19482742ff07 ] + +commit 02275a2ee7c0 (tcp: don't abort splice() after small transfers) +added a regression. + +[ 83.843570] INFO: rcu_sched self-detected stall on CPU +[ 83.844575] INFO: rcu_sched detected stalls on CPUs/tasks: { 6} (detected by 0, t=21002 jiffies, g=4457, c=4456, q=13132) +[ 83.844582] Task dump for CPU 6: +[ 83.844584] netperf R running task 0 8966 8952 0x0000000c +[ 83.844587] 0000000000000000 0000000000000006 0000000000006c6c 0000000000000000 +[ 83.844589] 000000000000006c 0000000000000096 ffffffff819ce2bc ffffffffffffff10 +[ 83.844592] ffffffff81088679 0000000000000010 0000000000000246 ffff880c4b9ddcd8 +[ 83.844594] Call Trace: +[ 83.844596] [] ? vprintk_emit+0x1c9/0x4c0 +[ 83.844601] [] ? schedule+0x29/0x70 +[ 83.844606] [] ? tcp_splice_data_recv+0x42/0x50 +[ 83.844610] [] ? tcp_read_sock+0xda/0x260 +[ 83.844613] [] ? tcp_prequeue_process+0xb0/0xb0 +[ 83.844615] [] ? tcp_splice_read+0xc0/0x250 +[ 83.844618] [] ? sock_splice_read+0x22/0x30 +[ 83.844622] [] ? do_splice_to+0x7b/0xa0 +[ 83.844627] [] ? sys_splice+0x59c/0x5d0 +[ 83.844630] [] ? putname+0x2b/0x40 +[ 83.844633] [] ? do_sys_open+0x174/0x1e0 +[ 83.844636] [] ? system_call_fastpath+0x16/0x1b + +if recv_actor() returns 0, we should stop immediately, +because looping wont give a chance to drain the pipe. + +Signed-off-by: Eric Dumazet +Cc: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/ipv4/tcp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 91de64d..6e92233 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1481,7 +1481,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + break; + } + used = recv_actor(desc, skb, offset, len); +- if (used < 0) { ++ if (used <= 0) { + if (!copied) + copied = used; + break; +-- +1.7.11.7 + + +From a2252d0dd0d7345a6266c6c1c5c3e7ff7025c207 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 9 Jan 2013 20:59:09 +0000 +Subject: [PATCH 42/44] tcp: fix splice() and tcp collapsing interaction + +[ Upstream commit f26845b43c75d3f32f98d194c1327b5b1e6b3fb0 ] + +Under unusual circumstances, TCP collapse can split a big GRO TCP packet +while its being used in a splice(socket->pipe) operation. + +skb_splice_bits() releases the socket lock before calling +splice_to_pipe(). + +[ 1081.353685] WARNING: at net/ipv4/tcp.c:1330 tcp_cleanup_rbuf+0x4d/0xfc() +[ 1081.371956] Hardware name: System x3690 X5 -[7148Z68]- +[ 1081.391820] cleanup rbuf bug: copied AD3BCF1 seq AD370AF rcvnxt AD3CF13 + +To fix this problem, we must eat skbs in tcp_recv_skb(). + +Remove the inline keyword from tcp_recv_skb() definition since +it has three call sites. + +Reported-by: Christian Becker +Cc: Willy Tarreau +Signed-off-by: Eric Dumazet +Tested-by: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/ipv4/tcp.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 6e92233..667e8a0 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1427,12 +1427,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) + } + #endif + +-static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) ++static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) + { + struct sk_buff *skb; + u32 offset; + +- skb_queue_walk(&sk->sk_receive_queue, skb) { ++ while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { + offset = seq - TCP_SKB_CB(skb)->seq; + if (tcp_hdr(skb)->syn) + offset--; +@@ -1440,6 +1440,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) + *off = offset; + return skb; + } ++ /* This looks weird, but this can happen if TCP collapsing ++ * splitted a fat GRO packet, while we released socket lock ++ * in skb_splice_bits() ++ */ ++ sk_eat_skb(sk, skb, false); + } + return NULL; + } +@@ -1519,8 +1524,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + tcp_rcv_space_adjust(sk); + + /* Clean up data we have read: This will do ACK frames. */ +- if (copied > 0) ++ if (copied > 0) { ++ tcp_recv_skb(sk, seq, &offset); + tcp_cleanup_rbuf(sk, copied); ++ } + return copied; + } + EXPORT_SYMBOL(tcp_read_sock); +-- +1.7.11.7 + + +From 6d0823b619aa6fc4280d61438626b7c6c9bb31ee Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 5 Jan 2013 21:31:18 +0000 +Subject: [PATCH 43/44] net: splice: avoid high order page splitting + +[ Upstream commit 82bda6195615891181115f579a480aa5001ce7e9 ] + +splice() can handle pages of any order, but network code tries hard to +split them in PAGE_SIZE units. Not quite successfully anyway, as +__splice_segment() assumed poff < PAGE_SIZE. This is true for +the skb->data part, not necessarily for the fragments. + +This patch removes this logic to give the pages as they are in the skb. + +Signed-off-by: Eric Dumazet +Cc: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/core/skbuff.c | 38 +++++++++----------------------------- + 1 file changed, 9 insertions(+), 29 deletions(-) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 3f0636c..5b1b915 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -1677,20 +1677,6 @@ static bool spd_fill_page(struct splice_pipe_desc *spd, + return false; + } + +-static inline void __segment_seek(struct page **page, unsigned int *poff, +- unsigned int *plen, unsigned int off) +-{ +- unsigned long n; +- +- *poff += off; +- n = *poff / PAGE_SIZE; +- if (n) +- *page = nth_page(*page, n); +- +- *poff = *poff % PAGE_SIZE; +- *plen -= off; +-} +- + static bool __splice_segment(struct page *page, unsigned int poff, + unsigned int plen, unsigned int *off, + unsigned int *len, struct sk_buff *skb, +@@ -1698,6 +1684,8 @@ static bool __splice_segment(struct page *page, unsigned int poff, + struct sock *sk, + struct pipe_inode_info *pipe) + { ++ unsigned int flen; ++ + if (!*len) + return true; + +@@ -1708,24 +1696,16 @@ static bool __splice_segment(struct page *page, unsigned int poff, + } + + /* ignore any bits we already processed */ +- if (*off) { +- __segment_seek(&page, &poff, &plen, *off); +- *off = 0; +- } +- +- do { +- unsigned int flen = min(*len, plen); ++ poff += *off; ++ plen -= *off; ++ *off = 0; + +- /* the linear region may spread across several pages */ +- flen = min_t(unsigned int, flen, PAGE_SIZE - poff); ++ flen = min(*len, plen); + +- if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) +- return true; +- +- __segment_seek(&page, &poff, &plen, flen); +- *len -= flen; ++ if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) ++ return true; + +- } while (*len && plen); ++ *len -= flen; + + return false; + } +-- +1.7.11.7 + + +From 6a1308f7cb927c58898aed1fa44a0df8bf1d8e4c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 11 Jan 2013 14:46:37 +0000 +Subject: [PATCH 44/44] net: splice: fix __splice_segment() + +[ Upstream commit bc9540c637c3d8712ccbf9dcf28621f380ed5e64 ] + +commit 9ca1b22d6d2 (net: splice: avoid high order page splitting) +forgot that skb->head could need a copy into several page frags. + +This could be the case for loopback traffic mostly. + +Also remove now useless skb argument from linear_to_page() +and __splice_segment() prototypes. + +Signed-off-by: Eric Dumazet +Cc: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/core/skbuff.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 5b1b915..1899d83 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -1620,7 +1620,7 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) + + static struct page *linear_to_page(struct page *page, unsigned int *len, + unsigned int *offset, +- struct sk_buff *skb, struct sock *sk) ++ struct sock *sk) + { + struct page_frag *pfrag = sk_page_frag(sk); + +@@ -1653,14 +1653,14 @@ static bool spd_can_coalesce(const struct splice_pipe_desc *spd, + static bool spd_fill_page(struct splice_pipe_desc *spd, + struct pipe_inode_info *pipe, struct page *page, + unsigned int *len, unsigned int offset, +- struct sk_buff *skb, bool linear, ++ bool linear, + struct sock *sk) + { + if (unlikely(spd->nr_pages == MAX_SKB_FRAGS)) + return true; + + if (linear) { +- page = linear_to_page(page, len, &offset, skb, sk); ++ page = linear_to_page(page, len, &offset, sk); + if (!page) + return true; + } +@@ -1679,13 +1679,11 @@ static bool spd_fill_page(struct splice_pipe_desc *spd, + + static bool __splice_segment(struct page *page, unsigned int poff, + unsigned int plen, unsigned int *off, +- unsigned int *len, struct sk_buff *skb, ++ unsigned int *len, + struct splice_pipe_desc *spd, bool linear, + struct sock *sk, + struct pipe_inode_info *pipe) + { +- unsigned int flen; +- + if (!*len) + return true; + +@@ -1700,12 +1698,16 @@ static bool __splice_segment(struct page *page, unsigned int poff, + plen -= *off; + *off = 0; + +- flen = min(*len, plen); +- +- if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) +- return true; ++ do { ++ unsigned int flen = min(*len, plen); + +- *len -= flen; ++ if (spd_fill_page(spd, pipe, page, &flen, poff, ++ linear, sk)) ++ return true; ++ poff += flen; ++ plen -= flen; ++ *len -= flen; ++ } while (*len && plen); + + return false; + } +@@ -1728,7 +1730,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, + if (__splice_segment(virt_to_page(skb->data), + (unsigned long) skb->data & (PAGE_SIZE - 1), + skb_headlen(skb), +- offset, len, skb, spd, ++ offset, len, spd, + skb_head_is_locked(skb), + sk, pipe)) + return true; +@@ -1741,7 +1743,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, + + if (__splice_segment(skb_frag_page(f), + f->page_offset, skb_frag_size(f), +- offset, len, skb, spd, false, sk, pipe)) ++ offset, len, spd, false, sk, pipe)) + return true; + } + +-- +1.7.11.7 + From 056a8e65ffe6f5311ee6ee4cd9e9ae3f41f6b0e2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Feb 2013 09:24:55 -0500 Subject: [PATCH 178/492] CVE-2013-0228 xen: xen_iret() invalid %ds local DoS (rhbz 910848 906309) --- kernel.spec | 11 +- ...-usable-in-xen_iret-for-32-bit-PVOPS.patch | 131 ++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch diff --git a/kernel.spec b/kernel.spec index 86fd1f72c..c9224292c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -789,6 +789,9 @@ Patch22246: rtlwifi-Fix-scheduling-while-atomic-bug.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch +#rhbz 906309 910848 CVE-2013-0228 +Patch21248: xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch + Patch23000: silence-brcmsmac-warning.patch Patch23100: validate-pud-largepage.patch @@ -1527,6 +1530,9 @@ ApplyPatch validate-pud-largepage.patch ApplyPatch net_37.mbox +#rhbz 906309 910848 CVE-2013-0228 +ApplyPatch xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch + # END OF PATCH APPLICATIONS %endif @@ -2390,6 +2396,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 14 2013 Josh Boyer +- CVE-2013-0228 xen: xen_iret() invalid %ds local DoS (rhbz 910848 906309) + * Tue Feb 12 2013 Dave Jones - Add networking queue for next stable release. diff --git a/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch b/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch new file mode 100644 index 000000000..d3b2b5602 --- /dev/null +++ b/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch @@ -0,0 +1,131 @@ +From 13d2b4d11d69a92574a55bfd985cfb0ca77aebdc Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Thu, 24 Jan 2013 13:11:10 +0000 +Subject: [PATCH] x86/xen: don't assume %ds is usable in xen_iret for 32-bit + PVOPS. + +This fixes CVE-2013-0228 / XSA-42 + +Drew Jones while working on CVE-2013-0190 found that that unprivileged guest user +in 32bit PV guest can use to crash the > guest with the panic like this: + +------------- +general protection fault: 0000 [#1] SMP +last sysfs file: /sys/devices/vbd-51712/block/xvda/dev +Modules linked in: sunrpc ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 +iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 +xt_state nf_conntrack ip6table_filter ip6_tables ipv6 xen_netfront ext4 +mbcache jbd2 xen_blkfront dm_mirror dm_region_hash dm_log dm_mod [last +unloaded: scsi_wait_scan] + +Pid: 1250, comm: r Not tainted 2.6.32-356.el6.i686 #1 +EIP: 0061:[] EFLAGS: 00010086 CPU: 0 +EIP is at xen_iret+0x12/0x2b +EAX: eb8d0000 EBX: 00000001 ECX: 08049860 EDX: 00000010 +ESI: 00000000 EDI: 003d0f00 EBP: b77f8388 ESP: eb8d1fe0 + DS: 0000 ES: 007b FS: 0000 GS: 00e0 SS: 0069 +Process r (pid: 1250, ti=eb8d0000 task=c2953550 task.ti=eb8d0000) +Stack: + 00000000 0027f416 00000073 00000206 b77f8364 0000007b 00000000 00000000 +Call Trace: +Code: c3 8b 44 24 18 81 4c 24 38 00 02 00 00 8d 64 24 30 e9 03 00 00 00 +8d 76 00 f7 44 24 08 00 00 02 80 75 33 50 b8 00 e0 ff ff 21 e0 <8b> 40 +10 8b 04 85 a0 f6 ab c0 8b 80 0c b0 b3 c0 f6 44 24 0d 02 +EIP: [] xen_iret+0x12/0x2b SS:ESP 0069:eb8d1fe0 +general protection fault: 0000 [#2] +---[ end trace ab0d29a492dcd330 ]--- +Kernel panic - not syncing: Fatal exception +Pid: 1250, comm: r Tainted: G D --------------- +2.6.32-356.el6.i686 #1 +Call Trace: + [] ? panic+0x6e/0x122 + [] ? oops_end+0xbc/0xd0 + [] ? do_general_protection+0x0/0x210 + [] ? error_code+0x73/ +------------- + +Petr says: " + I've analysed the bug and I think that xen_iret() cannot cope with + mangled DS, in this case zeroed out (null selector/descriptor) by either + xen_failsafe_callback() or RESTORE_REGS because the corresponding LDT + entry was invalidated by the reproducer. " + +Jan took a look at the preliminary patch and came up a fix that solves +this problem: + +"This code gets called after all registers other than those handled by +IRET got already restored, hence a null selector in %ds or a non-null +one that got loaded from a code or read-only data descriptor would +cause a kernel mode fault (with the potential of crashing the kernel +as a whole, if panic_on_oops is set)." + +The way to fix this is to realize that the we can only relay on the +registers that IRET restores. The two that are guaranteed are the +%cs and %ss as they are always fixed GDT selectors. Also they are +inaccessible from user mode - so they cannot be altered. This is +the approach taken in this patch. + +Another alternative option suggested by Jan would be to relay on +the subtle realization that using the %ebp or %esp relative references uses +the %ss segment. In which case we could switch from using %eax to %ebp and +would not need the %ss over-rides. That would also require one extra +instruction to compensate for the one place where the register is used +as scaled index. However Andrew pointed out that is too subtle and if +further work was to be done in this code-path it could escape folks attention +and lead to accidents. + +Reviewed-by: Petr Matousek +Reported-by: Petr Matousek +Reviewed-by: Andrew Cooper +Signed-off-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +--- + arch/x86/xen/xen-asm_32.S | 14 +++++++------- + 1 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S +index f9643fc..33ca6e4 100644 +--- a/arch/x86/xen/xen-asm_32.S ++++ b/arch/x86/xen/xen-asm_32.S +@@ -89,11 +89,11 @@ ENTRY(xen_iret) + */ + #ifdef CONFIG_SMP + GET_THREAD_INFO(%eax) +- movl TI_cpu(%eax), %eax +- movl __per_cpu_offset(,%eax,4), %eax +- mov xen_vcpu(%eax), %eax ++ movl %ss:TI_cpu(%eax), %eax ++ movl %ss:__per_cpu_offset(,%eax,4), %eax ++ mov %ss:xen_vcpu(%eax), %eax + #else +- movl xen_vcpu, %eax ++ movl %ss:xen_vcpu, %eax + #endif + + /* check IF state we're restoring */ +@@ -106,11 +106,11 @@ ENTRY(xen_iret) + * resuming the code, so we don't have to be worried about + * being preempted to another CPU. + */ +- setz XEN_vcpu_info_mask(%eax) ++ setz %ss:XEN_vcpu_info_mask(%eax) + xen_iret_start_crit: + + /* check for unmasked and pending */ +- cmpw $0x0001, XEN_vcpu_info_pending(%eax) ++ cmpw $0x0001, %ss:XEN_vcpu_info_pending(%eax) + + /* + * If there's something pending, mask events again so we can +@@ -118,7 +118,7 @@ xen_iret_start_crit: + * touch XEN_vcpu_info_mask. + */ + jne 1f +- movb $1, XEN_vcpu_info_mask(%eax) ++ movb $1, %ss:XEN_vcpu_info_mask(%eax) + + 1: popl %eax + +-- +1.7.7.6 + From 517a475937bc134dd5c154bb28e020c7364319e0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Feb 2013 09:41:40 -0500 Subject: [PATCH 179/492] Add patch to fix corruption on newer M6116 SATA bridges (rhbz 909591) --- kernel.spec | 7 +++++++ usb-cypress-supertop.patch | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 usb-cypress-supertop.patch diff --git a/kernel.spec b/kernel.spec index c9224292c..5c37dc65a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -798,6 +798,9 @@ Patch23100: validate-pud-largepage.patch Patch23200: net_37.mbox +#rhbz 909591 +Patch21255: usb-cypress-supertop.patch + # END OF PATCH DEFINITIONS %endif @@ -1533,6 +1536,9 @@ ApplyPatch net_37.mbox #rhbz 906309 910848 CVE-2013-0228 ApplyPatch xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch +#rhbz 909591 +ApplyPatch usb-cypress-supertop.patch + # END OF PATCH APPLICATIONS %endif @@ -2397,6 +2403,7 @@ fi # || || %changelog * Thu Feb 14 2013 Josh Boyer +- Add patch to fix corruption on newer M6116 SATA bridges (rhbz 909591) - CVE-2013-0228 xen: xen_iret() invalid %ds local DoS (rhbz 910848 906309) * Tue Feb 12 2013 Dave Jones diff --git a/usb-cypress-supertop.patch b/usb-cypress-supertop.patch new file mode 100644 index 000000000..3887dc59c --- /dev/null +++ b/usb-cypress-supertop.patch @@ -0,0 +1,38 @@ +From 1cd59b0d0b82c66135bf10ed3a87213a87e318ab Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 14 Feb 2013 09:29:55 -0500 +Subject: [PATCH] USB: usb-storage: unusual_devs update for Super TOP SATA + bridge + +The current entry in unusual_cypress.h for the Super TOP SATA bridge devices +seems to be causing corruption on newer revisions of this device. This has +been reported in Arch Linux and Fedora. The original patch was tested on +devices with bcdDevice of 1.60, whereas the newer devices report bcdDevice +as 2.20. Limit the UNUSUAL_DEV entry to devices less than 2.20. + +This fixes https://bugzilla.redhat.com/show_bug.cgi?id=909591 + +Reported-by: Carsten S. +Tested-by: Carsten S. +CC: +Signed-off-by: Josh Boyer +--- + drivers/usb/storage/unusual_cypress.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h +index 2c85530..65a6a75 100644 +--- a/drivers/usb/storage/unusual_cypress.h ++++ b/drivers/usb/storage/unusual_cypress.h +@@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, + "Cypress ISD-300LP", + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), + +-UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, ++UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219, + "Super Top", + "USB 2.0 SATA BRIDGE", + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), +-- +1.8.1.2 + From 6df90aad480c125ac23770db517391eb39d31132 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 14 Feb 2013 14:16:59 -0500 Subject: [PATCH 180/492] i915: Hush asserts during TV detection, just useless noise - i915: Fix LVDS downclock to not cripple performance (#901951) --- kernel.spec | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel.spec b/kernel.spec index 5c37dc65a..a5fc8838a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -706,6 +706,11 @@ Patch1100: handle-efi-roms.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch Patch1825: drm-i915-dp-stfu.patch +# mustard patch to shut abrt up. please drop (and notify ajax) whenever it +# fails to apply +Patch1826: drm-i915-tv-detect-hush.patch +# d-i-n backport for https://bugzilla.redhat.com/show_bug.cgi?id=901951 +Patch1827: drm-i915-lvds-reclock-fix.patch # Quiet boot fixes # silence the ACPI blacklist code @@ -1460,6 +1465,8 @@ ApplyPatch handle-efi-roms.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-dp-stfu.patch +ApplyPatch drm-i915-tv-detect-hush.patch +ApplyPatch drm-i915-lvds-reclock-fix.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -2402,6 +2409,10 @@ fi # ||----w | # || || %changelog +* Thu Feb 14 2013 Adam Jackson +- i915: Hush asserts during TV detection, just useless noise +- i915: Fix LVDS downclock to not cripple performance (#901951) + * Thu Feb 14 2013 Josh Boyer - Add patch to fix corruption on newer M6116 SATA bridges (rhbz 909591) - CVE-2013-0228 xen: xen_iret() invalid %ds local DoS (rhbz 910848 906309) From 8686bf4a41a060880be6f1b12c833e1d9e51927e Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 14 Feb 2013 14:17:18 -0500 Subject: [PATCH 181/492] i915: Hush asserts during TV detection, just useless noise - i915: Fix LVDS downclock to not cripple performance (#901951) --- drm-i915-lvds-reclock-fix.patch | 72 +++++++++++++++++++++++++++++++++ drm-i915-tv-detect-hush.patch | 46 +++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 drm-i915-lvds-reclock-fix.patch create mode 100644 drm-i915-tv-detect-hush.patch diff --git a/drm-i915-lvds-reclock-fix.patch b/drm-i915-lvds-reclock-fix.patch new file mode 100644 index 000000000..28b7d6731 --- /dev/null +++ b/drm-i915-lvds-reclock-fix.patch @@ -0,0 +1,72 @@ +Origin: + +http://cgit.freedesktop.org/~danvet/drm-intel/commit/?h=drm-intel-next&id=725a5b54028916cd2511a251c5b5b13d1715addc + +Rediffed for 3.7.x, and any bugs introduced, by ajax + +diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c +--- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c.jx 2013-02-14 12:40:21.068832043 -0500 ++++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c 2013-02-14 12:41:16.645147300 -0500 +@@ -1919,9 +1919,6 @@ i915_gem_object_move_to_inactive(struct + BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS); + BUG_ON(!obj->active); + +- if (obj->pin_count) /* are we a framebuffer? */ +- intel_mark_fb_idle(obj); +- + list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); + + list_del_init(&obj->ring_list); +diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c +--- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx 2013-02-14 12:40:22.022854621 -0500 ++++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c 2013-02-14 12:41:16.648147371 -0500 +@@ -6094,11 +6094,6 @@ void intel_mark_busy(struct drm_device * + + void intel_mark_idle(struct drm_device *dev) + { +-} +- +-void intel_mark_fb_busy(struct drm_i915_gem_object *obj) +-{ +- struct drm_device *dev = obj->base.dev; + struct drm_crtc *crtc; + + if (!i915_powersave) +@@ -6108,12 +6103,11 @@ void intel_mark_fb_busy(struct drm_i915_ + if (!crtc->fb) + continue; + +- if (to_intel_framebuffer(crtc->fb)->obj == obj) +- intel_increase_pllclock(crtc); ++ intel_decrease_pllclock(crtc); + } + } + +-void intel_mark_fb_idle(struct drm_i915_gem_object *obj) ++void intel_mark_fb_busy(struct drm_i915_gem_object *obj) + { + struct drm_device *dev = obj->base.dev; + struct drm_crtc *crtc; +@@ -6126,7 +6120,7 @@ void intel_mark_fb_idle(struct drm_i915_ + continue; + + if (to_intel_framebuffer(crtc->fb)->obj == obj) +- intel_decrease_pllclock(crtc); ++ intel_increase_pllclock(crtc); + } + } + +diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h +--- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h.jx 2013-02-14 12:40:21.071832114 -0500 ++++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h 2013-02-14 12:41:16.648147371 -0500 +@@ -417,9 +417,8 @@ extern bool intel_sdvo_init(struct drm_d + extern void intel_dvo_init(struct drm_device *dev); + extern void intel_tv_init(struct drm_device *dev); + extern void intel_mark_busy(struct drm_device *dev); +-extern void intel_mark_idle(struct drm_device *dev); + extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj); +-extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj); ++extern void intel_mark_idle(struct drm_device *dev); + extern bool intel_lvds_init(struct drm_device *dev); + extern void intel_dp_init(struct drm_device *dev, int output_reg, + enum port port); diff --git a/drm-i915-tv-detect-hush.patch b/drm-i915-tv-detect-hush.patch new file mode 100644 index 000000000..e774db071 --- /dev/null +++ b/drm-i915-tv-detect-hush.patch @@ -0,0 +1,46 @@ +Obviously this is not upstreamable... + +diff -up linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c +--- linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx 2013-01-30 12:03:28.000000000 -0500 ++++ linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c 2013-01-30 12:40:53.177449368 -0500 +@@ -6925,6 +6925,11 @@ intel_modeset_check_state(struct drm_dev + struct intel_encoder *encoder; + struct intel_connector *connector; + ++ /* oh hush */ ++ extern int i915_in_tv_detect; ++ if (i915_in_tv_detect) ++ return; ++ + list_for_each_entry(connector, &dev->mode_config.connector_list, + base.head) { + /* This also checks the encoder/connector hw state with the +diff -up linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_tv.c.jx linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_tv.c +--- linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_tv.c.jx 2012-12-10 22:30:57.000000000 -0500 ++++ linux-3.7.5-202.fc18.x86_64/drivers/gpu/drm/i915/intel_tv.c 2013-01-30 12:39:34.318593585 -0500 +@@ -1296,6 +1296,8 @@ static void intel_tv_find_better_format( + connector->dev->mode_config.tv_mode_property, i); + } + ++int i915_in_tv_detect = 0; ++ + /** + * Detect the TV connection. + * +@@ -1314,11 +1316,15 @@ intel_tv_detect(struct drm_connector *co + if (force) { + struct intel_load_detect_pipe tmp; + ++ i915_in_tv_detect = 1; + if (intel_get_load_detect_pipe(connector, &mode, &tmp)) { + type = intel_tv_detect_type(intel_tv, connector); + intel_release_load_detect_pipe(connector, &tmp); +- } else ++ i915_in_tv_detect = 0; ++ } else { ++ i915_in_tv_detect = 0; + return connector_status_unknown; ++ } + } else + return connector->status; + From 158d3b65d58b98c5e03241ebbff712cb4402b8f1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 14 Feb 2013 15:31:34 -0600 Subject: [PATCH 182/492] Linux v3.7.8 --- kernel.spec | 23 +- net_37.mbox | 2939 --------------------------------------------------- sources | 2 +- 3 files changed, 6 insertions(+), 2958 deletions(-) delete mode 100644 net_37.mbox diff --git a/kernel.spec b/kernel.spec index a5fc8838a..12f40a835 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -781,16 +781,10 @@ Patch22233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 892428 Patch22238: brcmsmac-updates-rhbz892428.patch -#rhbz 863424 -Patch22239: Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch - #rhbz 799564 Patch22240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch -#rhbz 903881 -Patch22246: rtlwifi-Fix-scheduling-while-atomic-bug.patch - #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch @@ -801,8 +795,6 @@ Patch23000: silence-brcmsmac-warning.patch Patch23100: validate-pud-largepage.patch -Patch23200: net_37.mbox - #rhbz 909591 Patch21255: usb-cypress-supertop.patch @@ -1521,16 +1513,10 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 892428 ApplyPatch brcmsmac-updates-rhbz892428.patch -#rhbz 863424 -ApplyPatch Revert-iwlwifi-fix-the-reclaimed-packet-tracking-upon.patch - #rhbz 799564 ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch -#rhbz 903881 -ApplyPatch rtlwifi-Fix-scheduling-while-atomic-bug.patch - #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch @@ -1538,8 +1524,6 @@ ApplyPatch silence-brcmsmac-warning.patch ApplyPatch validate-pud-largepage.patch -ApplyPatch net_37.mbox - #rhbz 906309 910848 CVE-2013-0228 ApplyPatch xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch @@ -2409,6 +2393,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 14 2013 Justin M. Forbes - 3.7.8-201 +- Linux v3.7.8 + * Thu Feb 14 2013 Adam Jackson - i915: Hush asserts during TV detection, just useless noise - i915: Fix LVDS downclock to not cripple performance (#901951) diff --git a/net_37.mbox b/net_37.mbox deleted file mode 100644 index 742400e11..000000000 --- a/net_37.mbox +++ /dev/null @@ -1,2939 +0,0 @@ -From 3e79c606d6a4504e2608cf03b6d4dd0c6b6dc008 Mon Sep 17 00:00:00 2001 -From: Cong Wang -Date: Mon, 7 Jan 2013 21:17:00 +0000 -Subject: [PATCH 01/44] net: prevent setting ttl=0 via IP_TTL - -[ Upstream commit c9be4a5c49cf51cc70a993f004c5bb30067a65ce ] - -A regression is introduced by the following commit: - - commit 4d52cfbef6266092d535237ba5a4b981458ab171 - Author: Eric Dumazet - Date: Tue Jun 2 00:42:16 2009 -0700 - - net: ipv4/ip_sockglue.c cleanups - - Pure cleanups - -but it is not a pure cleanup... - - - if (val != -1 && (val < 1 || val>255)) - + if (val != -1 && (val < 0 || val > 255)) - -Since there is no reason provided to allow ttl=0, change it back. - -Reported-by: nitin padalia -Cc: nitin padalia -Cc: Eric Dumazet -Cc: David S. Miller -Signed-off-by: Cong Wang -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv4/ip_sockglue.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c -index 14bbfcf..e95d72b 100644 ---- a/net/ipv4/ip_sockglue.c -+++ b/net/ipv4/ip_sockglue.c -@@ -590,7 +590,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, - case IP_TTL: - if (optlen < 1) - goto e_inval; -- if (val != -1 && (val < 0 || val > 255)) -+ if (val != -1 && (val < 1 || val > 255)) - goto e_inval; - inet->uc_ttl = val; - break; --- -1.7.11.7 - - -From a91ced21d91a2b96ccd2b6e4524df45ff8c9201c Mon Sep 17 00:00:00 2001 -From: Romain Kuntz -Date: Wed, 9 Jan 2013 15:02:26 +0100 -Subject: [PATCH 02/44] ipv6: fix the noflags test in - addrconf_get_prefix_route - -[ Upstream commit 85da53bf1c336bb07ac038fb951403ab0478d2c5 ] - -The tests on the flags in addrconf_get_prefix_route() does no make -much sense: the 'noflags' parameter contains the set of flags that -must not match with the route flags, so the test must be done -against 'noflags', and not against 'flags'. - -Signed-off-by: Romain Kuntz -Acked-by: YOSHIFUJI Hideaki -Signed-off-by: David S. Miller ---- - net/ipv6/addrconf.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 0424e4e..a468a36 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -1723,7 +1723,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, - continue; - if ((rt->rt6i_flags & flags) != flags) - continue; -- if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) -+ if ((rt->rt6i_flags & noflags) != 0) - continue; - dst_hold(&rt->dst); - break; --- -1.7.11.7 - - -From 43a18605f87a654eb6673ffb8ff99df13420d544 Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Thu, 10 Jan 2013 23:19:10 +0000 -Subject: [PATCH 03/44] net, wireless: overwrite default_ethtool_ops - -[ Upstream commit d07d7507bfb4e23735c9b83e397c43e1e8a173e8 ] - -Since: - -commit 2c60db037034d27f8c636403355d52872da92f81 -Author: Eric Dumazet -Date: Sun Sep 16 09:17:26 2012 +0000 - - net: provide a default dev->ethtool_ops - -wireless core does not correctly assign ethtool_ops. - -After alloc_netdev*() call, some cfg80211 drivers provide they own -ethtool_ops, but some do not. For them, wireless core provide generic -cfg80211_ethtool_ops, which is assigned in NETDEV_REGISTER notify call: - - if (!dev->ethtool_ops) - dev->ethtool_ops = &cfg80211_ethtool_ops; - -But after Eric's commit, dev->ethtool_ops is no longer NULL (on cfg80211 -drivers without custom ethtool_ops), but points to &default_ethtool_ops. - -In order to fix the problem, provide function which will overwrite -default_ethtool_ops and use it by wireless core. - -Signed-off-by: Stanislaw Gruszka -Acked-by: Johannes Berg -Acked-by: Ben Hutchings -Signed-off-by: David S. Miller ---- - include/linux/netdevice.h | 3 +++ - net/core/dev.c | 8 ++++++++ - net/wireless/core.c | 3 +-- - 3 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index a848ffc..825fb7e 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -60,6 +60,9 @@ struct wireless_dev; - #define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) - -+extern void netdev_set_default_ethtool_ops(struct net_device *dev, -+ const struct ethtool_ops *ops); -+ - /* hardware address assignment types */ - #define NET_ADDR_PERM 0 /* address is permanent (default) */ - #define NET_ADDR_RANDOM 1 /* address is generated randomly */ -diff --git a/net/core/dev.c b/net/core/dev.c -index e5942bf..3470794 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -6012,6 +6012,14 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) - - static const struct ethtool_ops default_ethtool_ops; - -+void netdev_set_default_ethtool_ops(struct net_device *dev, -+ const struct ethtool_ops *ops) -+{ -+ if (dev->ethtool_ops == &default_ethtool_ops) -+ dev->ethtool_ops = ops; -+} -+EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); -+ - /** - * alloc_netdev_mqs - allocate network device - * @sizeof_priv: size of private data to allocate space for -diff --git a/net/wireless/core.c b/net/wireless/core.c -index 3f72530..d1531e5 100644 ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -856,8 +856,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, - /* allow mac80211 to determine the timeout */ - wdev->ps_timeout = -1; - -- if (!dev->ethtool_ops) -- dev->ethtool_ops = &cfg80211_ethtool_ops; -+ netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops); - - if ((wdev->iftype == NL80211_IFTYPE_STATION || - wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || --- -1.7.11.7 - - -From 10a209641c46d1b7fab2e45148ac83a2e3ec9bab Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sun, 13 Jan 2013 18:21:51 +0000 -Subject: [PATCH 04/44] tcp: fix a panic on UP machines in - reqsk_fastopen_remove - -[ Upstream commit cce894bb824429fd312706c7012acae43e725865 ] - -spin_is_locked() on a non !SMP build is kind of useless. - -BUG_ON(!spin_is_locked(xx)) is guaranteed to crash. - -Just remove this check in reqsk_fastopen_remove() as -the callers do hold the socket lock. - -Reported-by: Ketan Kulkarni -Signed-off-by: Eric Dumazet -Cc: Jerry Chu -Cc: Yuchung Cheng -Cc: Dave Taht -Acked-by: H.K. Jerry Chu -Signed-off-by: David S. Miller ---- - net/core/request_sock.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/net/core/request_sock.c b/net/core/request_sock.c -index c31d9e8..4425148 100644 ---- a/net/core/request_sock.c -+++ b/net/core/request_sock.c -@@ -186,8 +186,6 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, - struct fastopen_queue *fastopenq = - inet_csk(lsk)->icsk_accept_queue.fastopenq; - -- BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk)); -- - tcp_sk(sk)->fastopen_rsk = NULL; - spin_lock_bh(&fastopenq->lock); - fastopenq->qlen--; --- -1.7.11.7 - - -From d9c9e8ef86d318c97b88dc4efcf46530a0b46543 Mon Sep 17 00:00:00 2001 -From: Stephen Hemminger -Date: Wed, 16 Jan 2013 09:55:57 -0800 -Subject: [PATCH 05/44] MAINTAINERS: Stephen Hemminger email change - -[ Upstream commit adbbf69d1a54abf424e91875746a610dcc80017d ] - -I changed my email because the vyatta.com mail server is now -redirected to brocade.com; and the Brocade mail system -is not friendly to Linux desktop users. - -Signed-off-by: Stephen Hemminger -Signed-off-by: David S. Miller ---- - MAINTAINERS | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/MAINTAINERS b/MAINTAINERS -index 9386a63..4eb1deb 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2898,7 +2898,7 @@ S: Maintained - F: drivers/net/ethernet/i825xx/eexpress.* - - ETHERNET BRIDGE --M: Stephen Hemminger -+M: Stephen Hemminger - L: bridge@lists.linux-foundation.org - L: netdev@vger.kernel.org - W: http://www.linuxfoundation.org/en/Net:Bridge -@@ -4739,7 +4739,7 @@ S: Maintained - - MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) - M: Mirko Lindner --M: Stephen Hemminger -+M: Stephen Hemminger - L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/ethernet/marvell/sk* -@@ -4993,7 +4993,7 @@ S: Supported - F: drivers/infiniband/hw/nes/ - - NETEM NETWORK EMULATOR --M: Stephen Hemminger -+M: Stephen Hemminger - L: netem@lists.linux-foundation.org - S: Maintained - F: net/sched/sch_netem.c --- -1.7.11.7 - - -From bb1e86b0fd4ee8fa047dee973bad46363420a80a Mon Sep 17 00:00:00 2001 -From: Romain KUNTZ -Date: Wed, 16 Jan 2013 12:47:40 +0000 -Subject: [PATCH 06/44] ipv6: fix header length calculation in - ip6_append_data() - -[ Upstream commit 7efdba5bd9a2f3e2059beeb45c9fa55eefe1bced ] - -Commit 299b0767 (ipv6: Fix IPsec slowpath fragmentation problem) -has introduced a error in the header length calculation that -provokes corrupted packets when non-fragmentable extensions -headers (Destination Option or Routing Header Type 2) are used. - -rt->rt6i_nfheader_len is the length of the non-fragmentable -extension header, and it should be substracted to -rt->dst.header_len, and not to exthdrlen, as it was done before -commit 299b0767. - -This patch reverts to the original and correct behavior. It has -been successfully tested with and without IPsec on packets -that include non-fragmentable extensions headers. - -Signed-off-by: Romain Kuntz -Acked-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_output.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index aece3e7..8dea314 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1279,10 +1279,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, - if (dst_allfrag(rt->dst.path)) - cork->flags |= IPCORK_ALLFRAG; - cork->length = 0; -- exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; -+ exthdrlen = (opt ? opt->opt_flen : 0); - length += exthdrlen; - transhdrlen += exthdrlen; -- dst_exthdrlen = rt->dst.header_len; -+ dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; - } else { - rt = (struct rt6_info *)cork->dst; - fl6 = &inet->cork.fl.u.ip6; --- -1.7.11.7 - - -From f6296b4042c585592d4251b423f9d2bc6bfdf2cb Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Thu, 17 Jan 2013 13:30:49 -0800 -Subject: [PATCH 07/44] macvlan: fix macvlan_get_size() - -[ Upstream commit 01fe944f1024bd4e5c327ddbe8d657656b66af2f ] - -commit df8ef8f3aaa (macvlan: add FDB bridge ops and macvlan flags) -forgot to update macvlan_get_size() after the addition of -IFLA_MACVLAN_FLAGS - -Signed-off-by: Eric Dumazet -Cc: John Fastabend -Signed-off-by: David S. Miller ---- - drivers/net/macvlan.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c -index 68a43fe..d3fb97d 100644 ---- a/drivers/net/macvlan.c -+++ b/drivers/net/macvlan.c -@@ -822,7 +822,10 @@ static int macvlan_changelink(struct net_device *dev, - - static size_t macvlan_get_size(const struct net_device *dev) - { -- return nla_total_size(4); -+ return (0 -+ + nla_total_size(4) /* IFLA_MACVLAN_MODE */ -+ + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ -+ ); - } - - static int macvlan_fill_info(struct sk_buff *skb, --- -1.7.11.7 - - -From e8002481da092b921028dfb8c82873f5b8f378d3 Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Wed, 16 Jan 2013 13:36:37 +0000 -Subject: [PATCH 08/44] net: calxedaxgmac: throw away overrun frames - -[ Upstream commit d6fb3be544b46a7611a3373fcaa62b5b0be01888 ] - -The xgmac driver assumes 1 frame per descriptor. If a frame larger than -the descriptor's buffer size is received, the frame will spill over into -the next descriptor. So check for received frames that span more than one -descriptor and discard them. This prevents a crash if we receive erroneous -large packets. - -Signed-off-by: Rob Herring -Cc: netdev@vger.kernel.org -Cc: linux-kernel@vger.kernel.org -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/calxeda/xgmac.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c -index 16814b3..e29c1b6 100644 ---- a/drivers/net/ethernet/calxeda/xgmac.c -+++ b/drivers/net/ethernet/calxeda/xgmac.c -@@ -546,6 +546,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) - return -1; - } - -+ /* All frames should fit into a single buffer */ -+ if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) -+ return -1; -+ - /* Check if packet has checksum already */ - if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && - !(ext_status & RXDESC_IP_PAYLOAD_MASK)) --- -1.7.11.7 - - -From cea9757b2a648469443228917fb352b0d06d215d Mon Sep 17 00:00:00 2001 -From: Yan Burman -Date: Thu, 17 Jan 2013 05:30:42 +0000 -Subject: [PATCH 09/44] net/mlx4_en: Fix bridged vSwitch configuration for non - SRIOV mode - -[ Upstream commit 213815a1e6ae70b9648483b110bc5081795f99e8 ] - -Commit 5b4c4d36860e "mlx4_en: Allow communication between functions on -same host" introduced a regression under which a bridge acting as vSwitch -whose uplink is an mlx4 Ethernet device become non-operative in native -(non sriov) mode. This happens since broadcast ARP requests sent by VMs -were loopback-ed by the HW and hence the bridge learned VM source MACs -on both the VM and the uplink ports. - -The fix is to place the DMAC in the send WQE only under SRIOV/eSwitch -configuration or when the device is in selftest. - -Reviewed-by: Or Gerlitz -Signed-off-by: Yan Burman -Signed-off-by: Amir Vadai -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mellanox/mlx4/en_tx.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c -index b35094c..fc1ac65 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c -@@ -629,10 +629,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) - ring->tx_csum++; - } - -- /* Copy dst mac address to wqe */ -- ethh = (struct ethhdr *)skb->data; -- tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); -- tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); -+ if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { -+ /* Copy dst mac address to wqe. This allows loopback in eSwitch, -+ * so that VFs and PF can communicate with each other -+ */ -+ ethh = (struct ethhdr *)skb->data; -+ tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); -+ tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); -+ } -+ - /* Handle LSO (TSO) packets */ - if (lso_header_size) { - /* Mark opcode as LSO */ --- -1.7.11.7 - - -From 71558617a4904a27b7dd35dfb82c9029b87af357 Mon Sep 17 00:00:00 2001 -From: Or Gerlitz -Date: Thu, 17 Jan 2013 05:30:43 +0000 -Subject: [PATCH 10/44] net/mlx4_core: Set number of msix vectors under SRIOV - mode to firmware defaults - -[ Upstream commit ca4c7b35f75492de7fbf5ee95be07481c348caee ] - -The lines - - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - -which hard code the number of requested msi-x vectors under multi-function -mode to two can be removed completely, since the firmware sets num_eqs and -reserved_eqs appropriately Thus, the code line: - - nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, nreq); - -is by itself sufficient and correct for all cases. Currently, for mfunc -mode num_eqs = 32 and reserved_eqs = 28, hence four vectors will be enabled. - -This triples (one vector is used for the async events and commands EQ) the -horse power provided for processing of incoming packets on netdev RSS scheme, -IO initiators/targets commands processing flows, etc. - -Reviewed-by: Jack Morgenstein -Signed-off-by: Amir Vadai -Signed-off-by: Or Gerlitz -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mellanox/mlx4/main.c | 11 ++--------- - 1 file changed, 2 insertions(+), 9 deletions(-) - -diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c -index 2aa80af..d4b3935 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/main.c -+++ b/drivers/net/ethernet/mellanox/mlx4/main.c -@@ -1702,15 +1702,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) - int i; - - if (msi_x) { -- /* In multifunction mode each function gets 2 msi-X vectors -- * one for data path completions anf the other for asynch events -- * or command completions */ -- if (mlx4_is_mfunc(dev)) { -- nreq = 2; -- } else { -- nreq = min_t(int, dev->caps.num_eqs - -- dev->caps.reserved_eqs, nreq); -- } -+ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, -+ nreq); - - entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); - if (!entries) --- -1.7.11.7 - - -From 9e1626d8ecc01327036f8ad064a326a2ad31ae93 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sat, 19 Jan 2013 16:10:37 +0000 -Subject: [PATCH 11/44] tcp: fix incorrect LOCKDROPPEDICMPS counter -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit b74aa930ef49a3c0d8e4c1987f89decac768fb2c ] - -commit 563d34d057 (tcp: dont drop MTU reduction indications) -added an error leading to incorrect accounting of -LINUX_MIB_LOCKDROPPEDICMPS - -If socket is owned by the user, we want to increment -this SNMP counter, unless the message is a -(ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED) one. - -Reported-by: Maciej Å»enczykowski -Signed-off-by: Eric Dumazet -Cc: Neal Cardwell -Signed-off-by: Maciej Å»enczykowski -Acked-by: Neal Cardwell -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_ipv4.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c -index bc3cb46..e637770 100644 ---- a/net/ipv4/tcp_ipv4.c -+++ b/net/ipv4/tcp_ipv4.c -@@ -380,11 +380,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) - * We do take care of PMTU discovery (RFC1191) special case : - * we can receive locally generated ICMP messages while socket is held. - */ -- if (sock_owned_by_user(sk) && -- type != ICMP_DEST_UNREACH && -- code != ICMP_FRAG_NEEDED) -- NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); -- -+ if (sock_owned_by_user(sk)) { -+ if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)) -+ NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); -+ } - if (sk->sk_state == TCP_CLOSE) - goto out; - --- -1.7.11.7 - - -From 67ee774cb516f0fe5259760c59a807de18fd78d8 Mon Sep 17 00:00:00 2001 -From: Tilman Schmidt -Date: Mon, 21 Jan 2013 11:57:21 +0000 -Subject: [PATCH 12/44] isdn/gigaset: fix zero size border case in debug dump - -[ Upstream commit d721a1752ba544df8d7d36959038b26bc92bdf80 ] - -If subtracting 12 from l leaves zero we'd do a zero size allocation, -leading to an oops later when we try to set the NUL terminator. - -Reported-by: Dan Carpenter -Signed-off-by: Tilman Schmidt -Signed-off-by: David S. Miller ---- - drivers/isdn/gigaset/capi.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c -index 68452b7..03a0a01 100644 ---- a/drivers/isdn/gigaset/capi.c -+++ b/drivers/isdn/gigaset/capi.c -@@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, - CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, - CAPIMSG_CONTROL(data)); - l -= 12; -+ if (l <= 0) -+ return; - dbgline = kmalloc(3 * l, GFP_ATOMIC); - if (!dbgline) - return; --- -1.7.11.7 - - -From a7640c96407dd3f44a8f709f9ae880bc6211b04b Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Tue, 22 Jan 2013 06:33:05 +0000 -Subject: [PATCH 13/44] netxen: fix off by one bug in - netxen_release_tx_buffer() - -[ Upstream commit a05948f296ce103989b28a2606e47d2e287c3c89 ] - -Christoph Paasch found netxen could trigger a BUG in its dismantle -phase, in netxen_release_tx_buffer(), using full size TSO packets. - -cmd_buf->frag_count includes the skb->data part, so the loop must -start at index 1 instead of 0, or else we can make an out -of bound access to cmd_buff->frag_array[MAX_SKB_FRAGS + 2] - -Christoph provided the fixes in netxen_map_tx_skb() function. -In case of a dma mapping error, its better to clear the dma fields -so that we don't try to unmap them again in netxen_release_tx_buffer() - -Reported-by: Christoph Paasch -Signed-off-by: Eric Dumazet -Tested-by: Christoph Paasch -Cc: Sony Chacko -Cc: Rajesh Borundia -Signed-off-by: Christoph Paasch -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 2 +- - drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c -index bc165f4..695667d 100644 ---- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c -+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c -@@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) - buffrag->length, PCI_DMA_TODEVICE); - buffrag->dma = 0ULL; - } -- for (j = 0; j < cmd_buf->frag_count; j++) { -+ for (j = 1; j < cmd_buf->frag_count; j++) { - buffrag++; - if (buffrag->dma) { - pci_unmap_page(adapter->pdev, buffrag->dma, -diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c -index df45061..1b55ca1 100644 ---- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c -+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c -@@ -1963,10 +1963,12 @@ unwind: - while (--i >= 0) { - nf = &pbuf->frag_array[i+1]; - pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); -+ nf->dma = 0ULL; - } - - nf = &pbuf->frag_array[0]; - pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); -+ nf->dma = 0ULL; - - out_err: - return -ENOMEM; --- -1.7.11.7 - - -From 6aaa957c972243891f2edb3905765deffa37dbff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= -Date: Mon, 21 Jan 2013 22:30:35 +0000 -Subject: [PATCH 14/44] r8169: remove the obsolete and incorrect AMD - workaround -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 5d0feaff230c0abfe4a112e6f09f096ed99e0b2d ] - -This was introduced in commit 6dccd16 "r8169: merge with version -6.001.00 of Realtek's r8169 driver". I did not find the version -6.001.00 online, but in 6.002.00 or any later r8169 from Realtek -this hunk is no longer present. - -Also commit 05af214 "r8169: fix Ethernet Hangup for RTL8110SC -rev d" claims to have fixed this issue otherwise. - -The magic compare mask of 0xfffe000 is dubious as it masks -parts of the Reserved part, and parts of the VLAN tag. But this -does not make much sense as the VLAN tag parts are perfectly -valid there. In matter of fact this seems to be triggered with -any VLAN tagged packet as RxVlanTag bit is matched. I would -suspect 0xfffe0000 was intended to test reserved part only. - -Finally, this hunk is evil as it can cause more packets to be -handled than what was NAPI quota causing net/core/dev.c: -net_rx_action(): WARN_ON_ONCE(work > weight) to trigger, and -mess up the NAPI state causing device to hang. - -As result, any system using VLANs and having high receive -traffic (so that NAPI poll budget limits rtl_rx) would result -in device hang. - -Signed-off-by: Timo Teräs -Acked-by: Francois Romieu -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/r8169.c | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c -index 927aa33..6afe74e 100644 ---- a/drivers/net/ethernet/realtek/r8169.c -+++ b/drivers/net/ethernet/realtek/r8169.c -@@ -6064,13 +6064,6 @@ process_pkt: - tp->rx_stats.bytes += pkt_size; - u64_stats_update_end(&tp->rx_stats.syncp); - } -- -- /* Work around for AMD plateform. */ -- if ((desc->opts2 & cpu_to_le32(0xfffe000)) && -- (tp->mac_version == RTL_GIGA_MAC_VER_05)) { -- desc->opts2 = 0; -- cur_rx++; -- } - } - - count = cur_rx - tp->cur_rx; --- -1.7.11.7 - - -From 24d7fa8b3e9f8f9834e8af9f13a49647cbfda7a2 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Fri, 25 Jan 2013 07:44:41 +0000 -Subject: [PATCH 15/44] net: loopback: fix a dst refcounting issue - -[ Upstream commit 794ed393b707f01858f5ebe2ae5eabaf89d00022 ] - -Ben Greear reported crashes in ip_rcv_finish() on a stress -test involving many macvlans. - -We tracked the bug to a dst use after free. ip_rcv_finish() -was calling dst->input() and got garbage for dst->input value. - -It appears the bug is in loopback driver, lacking -a skb_dst_force() before calling netif_rx(). - -As a result, a non refcounted dst, normally protected by a -RCU read_lock section, was escaping this section and could -be freed before the packet being processed. - - [] loopback_xmit+0x64/0x83 - [] dev_hard_start_xmit+0x26c/0x35e - [] dev_queue_xmit+0x2c4/0x37c - [] ? dev_hard_start_xmit+0x35e/0x35e - [] ? eth_header+0x28/0xb6 - [] neigh_resolve_output+0x176/0x1a7 - [] ip_finish_output2+0x297/0x30d - [] ? ip_finish_output2+0x137/0x30d - [] ip_finish_output+0x63/0x68 - [] ip_output+0x61/0x67 - [] dst_output+0x17/0x1b - [] ip_local_out+0x1e/0x23 - [] ip_queue_xmit+0x315/0x353 - [] ? ip_send_unicast_reply+0x2cc/0x2cc - [] tcp_transmit_skb+0x7ca/0x80b - [] tcp_connect+0x53c/0x587 - [] ? getnstimeofday+0x44/0x7d - [] ? ktime_get_real+0x11/0x3e - [] tcp_v4_connect+0x3c2/0x431 - [] __inet_stream_connect+0x84/0x287 - [] ? inet_stream_connect+0x22/0x49 - [] ? _local_bh_enable_ip+0x84/0x9f - [] ? local_bh_enable+0xd/0x11 - [] ? lock_sock_nested+0x6e/0x79 - [] ? inet_stream_connect+0x22/0x49 - [] inet_stream_connect+0x33/0x49 - [] sys_connect+0x75/0x98 - -This bug was introduced in linux-2.6.35, in commit -7fee226ad2397b (net: add a noref bit on skb dst) - -skb_dst_force() is enforced in dev_queue_xmit() for devices having a -qdisc. - -Reported-by: Ben Greear -Signed-off-by: Eric Dumazet -Tested-by: Ben Greear -Signed-off-by: David S. Miller ---- - drivers/net/loopback.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c -index 81f8f9e..fcbf680 100644 ---- a/drivers/net/loopback.c -+++ b/drivers/net/loopback.c -@@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, - - skb_orphan(skb); - -+ /* Before queueing this packet to netif_rx(), -+ * make sure dst is refcounted. -+ */ -+ skb_dst_force(skb); -+ - skb->protocol = eth_type_trans(skb, dev); - - /* it's OK to use per_cpu_ptr() because BHs are off */ --- -1.7.11.7 - - -From f6d1707cdb200b651c019f693d636154cce43248 Mon Sep 17 00:00:00 2001 -From: Pravin B Shelar -Date: Wed, 23 Jan 2013 11:45:42 +0000 -Subject: [PATCH 16/44] IP_GRE: Fix kernel panic in IP_GRE with GRE csum. - -[ Upstream commit 5465740ace36f179de5bb0ccb5d46ddeb945e309 ] - -Due to IP_GRE GSO support, GRE can recieve non linear skb which -results in panic in case of GRE_CSUM. Following patch fixes it by -using correct csum API. - -Bug introduced in commit 6b78f16e4bdde3936b (gre: add GSO support) - -Signed-off-by: Pravin B Shelar -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv4/ip_gre.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c -index 7240f8e..07538a7 100644 ---- a/net/ipv4/ip_gre.c -+++ b/net/ipv4/ip_gre.c -@@ -972,8 +972,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev - ptr--; - } - if (tunnel->parms.o_flags&GRE_CSUM) { -+ int offset = skb_transport_offset(skb); -+ - *ptr = 0; -- *(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr)); -+ *(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset, -+ skb->len - offset, -+ 0)); - } - } - --- -1.7.11.7 - - -From 443811a0868d9d9815f4bbe1aabea6be7f25f906 Mon Sep 17 00:00:00 2001 -From: Cong Wang -Date: Sun, 27 Jan 2013 21:14:08 +0000 -Subject: [PATCH 17/44] pktgen: correctly handle failures when adding a device - -[ Upstream commit 604dfd6efc9b79bce432f2394791708d8e8f6efc ] - -The return value of pktgen_add_device() is not checked, so -even if we fail to add some device, for example, non-exist one, -we still see "OK:...". This patch fixes it. - -After this patch, I got: - - # echo "add_device non-exist" > /proc/net/pktgen/kpktgend_0 - -bash: echo: write error: No such device - # cat /proc/net/pktgen/kpktgend_0 - Running: - Stopped: - Result: ERROR: can not add device non-exist - # echo "add_device eth0" > /proc/net/pktgen/kpktgend_0 - # cat /proc/net/pktgen/kpktgend_0 - Running: - Stopped: eth0 - Result: OK: add_device=eth0 - -(Candidate for -stable) - -Cc: David S. Miller -Signed-off-by: Cong Wang -Signed-off-by: David S. Miller ---- - net/core/pktgen.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/net/core/pktgen.c b/net/core/pktgen.c -index d1dc14c..21350db 100644 ---- a/net/core/pktgen.c -+++ b/net/core/pktgen.c -@@ -1795,10 +1795,13 @@ static ssize_t pktgen_thread_write(struct file *file, - return -EFAULT; - i += len; - mutex_lock(&pktgen_thread_lock); -- pktgen_add_device(t, f); -+ ret = pktgen_add_device(t, f); - mutex_unlock(&pktgen_thread_lock); -- ret = count; -- sprintf(pg_result, "OK: add_device=%s", f); -+ if (!ret) { -+ ret = count; -+ sprintf(pg_result, "OK: add_device=%s", f); -+ } else -+ sprintf(pg_result, "ERROR: can not add device %s", f); - goto out; - } - --- -1.7.11.7 - - -From 9159b16b6d82f3051602f0ee51701458a6a58432 Mon Sep 17 00:00:00 2001 -From: Marcelo Ricardo Leitner -Date: Tue, 29 Jan 2013 22:26:08 +0000 -Subject: [PATCH 18/44] ipv6: do not create neighbor entries for local - delivery - -[ Upstream commit bd30e947207e2ea0ff2c08f5b4a03025ddce48d3 ] - -They will be created at output, if ever needed. This avoids creating -empty neighbor entries when TPROXYing/Forwarding packets for addresses -that are not even directly reachable. - -Note that IPv4 already handles it this way. No neighbor entries are -created for local input. - -Tested by myself and customer. - -Signed-off-by: Jiri Pirko -Signed-off-by: Marcelo Ricardo Leitner -Signed-off-by: David S. Miller ---- - net/ipv6/route.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index b1e6cf0..b140ef2 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -872,7 +872,7 @@ restart: - dst_hold(&rt->dst); - read_unlock_bh(&table->tb6_lock); - -- if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP)) -+ if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL))) - nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); - else if (!(rt->dst.flags & DST_HOST)) - nrt = rt6_alloc_clone(rt, &fl6->daddr); --- -1.7.11.7 - - -From aaf884494fda8734dcd8f42602e646e2238d01f6 Mon Sep 17 00:00:00 2001 -From: "David S. Miller" -Date: Tue, 29 Jan 2013 22:58:04 -0500 -Subject: [PATCH 19/44] via-rhine: Fix bugs in NAPI support. - -[ Upstream commit 559bcac35facfed49ab4f408e162971612dcfdf3 ] - -1) rhine_tx() should use dev_kfree_skb() not dev_kfree_skb_irq() - -2) rhine_slow_event_task's NAPI triggering logic is racey, it - should just hit the interrupt mask register. This is the - same as commit 7dbb491878a2c51d372a8890fa45a8ff80358af1 - ("r8169: avoid NAPI scheduling delay.") made to fix the same - problem in the r8169 driver. From Francois Romieu. - -Reported-by: Jamie Gloudon -Tested-by: Jamie Gloudon -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/via/via-rhine.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c -index 0459c09..046526e0 100644 ---- a/drivers/net/ethernet/via/via-rhine.c -+++ b/drivers/net/ethernet/via/via-rhine.c -@@ -1802,7 +1802,7 @@ static void rhine_tx(struct net_device *dev) - rp->tx_skbuff[entry]->len, - PCI_DMA_TODEVICE); - } -- dev_kfree_skb_irq(rp->tx_skbuff[entry]); -+ dev_kfree_skb(rp->tx_skbuff[entry]); - rp->tx_skbuff[entry] = NULL; - entry = (++rp->dirty_tx) % TX_RING_SIZE; - } -@@ -2011,11 +2011,7 @@ static void rhine_slow_event_task(struct work_struct *work) - if (intr_status & IntrPCIErr) - netif_warn(rp, hw, dev, "PCI error\n"); - -- napi_disable(&rp->napi); -- rhine_irq_disable(rp); -- /* Slow and safe. Consider __napi_schedule as a replacement ? */ -- napi_enable(&rp->napi); -- napi_schedule(&rp->napi); -+ iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable); - - out_unlock: - mutex_unlock(&rp->task_lock); --- -1.7.11.7 - - -From 4c26aa283f7673e08076645d776d1155ea24d01d Mon Sep 17 00:00:00 2001 -From: Phil Sutter -Date: Fri, 1 Feb 2013 07:21:41 +0000 -Subject: [PATCH 20/44] packet: fix leakage of tx_ring memory - -[ Upstream commit 9665d5d62487e8e7b1f546c00e11107155384b9a ] - -When releasing a packet socket, the routine packet_set_ring() is reused -to free rings instead of allocating them. But when calling it for the -first time, it fills req->tp_block_nr with the value of rb->pg_vec_len -which in the second invocation makes it bail out since req->tp_block_nr -is greater zero but req->tp_block_size is zero. - -This patch solves the problem by passing a zeroed auto-variable to -packet_set_ring() upon each invocation from packet_release(). - -As far as I can tell, this issue exists even since 69e3c75 (net: TX_RING -and packet mmap), i.e. the original inclusion of TX ring support into -af_packet, but applies only to sockets with both RX and TX ring -allocated, which is probably why this was unnoticed all the time. - -Signed-off-by: Phil Sutter -Cc: Johann Baudy -Cc: Daniel Borkmann -Acked-by: Daniel Borkmann -Signed-off-by: David S. Miller ---- - net/packet/af_packet.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 94060ed..5db6316 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -2335,13 +2335,15 @@ static int packet_release(struct socket *sock) - - packet_flush_mclist(sk); - -- memset(&req_u, 0, sizeof(req_u)); -- -- if (po->rx_ring.pg_vec) -+ if (po->rx_ring.pg_vec) { -+ memset(&req_u, 0, sizeof(req_u)); - packet_set_ring(sk, &req_u, 1, 0); -+ } - -- if (po->tx_ring.pg_vec) -+ if (po->tx_ring.pg_vec) { -+ memset(&req_u, 0, sizeof(req_u)); - packet_set_ring(sk, &req_u, 1, 1); -+ } - - fanout_release(sk); - --- -1.7.11.7 - - -From 7cc84ac7f54b5d6e70c62bf62cedd52047efb24b Mon Sep 17 00:00:00 2001 -From: Tommi Rantala -Date: Wed, 6 Feb 2013 03:24:02 +0000 -Subject: [PATCH 21/44] ipv6/ip6_gre: fix error case handling in - ip6gre_tunnel_xmit() - -[ Upstream commit 41ab3e31bd50b42c85ac0aa0469642866aee2a9a ] - -ip6gre_tunnel_xmit() is leaking the skb when we hit this error branch, -and the -1 return value from this function is bogus. Use the error -handling we already have in place in ip6gre_tunnel_xmit() for this error -case to fix this. - -Signed-off-by: Tommi Rantala -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_gre.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c -index d5cb3c4..a23350c 100644 ---- a/net/ipv6/ip6_gre.c -+++ b/net/ipv6/ip6_gre.c -@@ -976,7 +976,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb, - int ret; - - if (!ip6_tnl_xmit_ctl(t)) -- return -1; -+ goto tx_err; - - switch (skb->protocol) { - case htons(ETH_P_IP): --- -1.7.11.7 - - -From 09d6e93572bb278ea5a0cfaa63e18c01b25a9c7e Mon Sep 17 00:00:00 2001 -From: Heiko Carstens -Date: Fri, 8 Feb 2013 00:19:11 +0000 -Subject: [PATCH 22/44] atm/iphase: rename fregt_t -> ffreg_t - -[ Upstream commit ab54ee80aa7585f9666ff4dd665441d7ce41f1e8 ] - -We have conflicting type qualifiers for "freg_t" in s390's ptrace.h and the -iphase atm device driver, which causes the compile error below. -Unfortunately the s390 typedef can't be renamed, since it's a user visible api, -nor can I change the include order in s390 code to avoid the conflict. - -So simply rename the iphase typedef to a new name. Fixes this compile error: - -In file included from drivers/atm/iphase.c:66:0: -drivers/atm/iphase.h:639:25: error: conflicting type qualifiers for 'freg_t' -In file included from next/arch/s390/include/asm/ptrace.h:9:0, - from next/arch/s390/include/asm/lowcore.h:12, - from next/arch/s390/include/asm/thread_info.h:30, - from include/linux/thread_info.h:54, - from include/linux/preempt.h:9, - from include/linux/spinlock.h:50, - from include/linux/seqlock.h:29, - from include/linux/time.h:5, - from include/linux/stat.h:18, - from include/linux/module.h:10, - from drivers/atm/iphase.c:43: -next/arch/s390/include/uapi/asm/ptrace.h:197:3: note: previous declaration of 'freg_t' was here - -Signed-off-by: Heiko Carstens -Acked-by: chas williams - CONTRACTOR -Signed-off-by: David S. Miller ---- - drivers/atm/iphase.h | 146 +++++++++++++++++++++++++-------------------------- - 1 file changed, 73 insertions(+), 73 deletions(-) - -diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h -index 6a0955e..53ecac5 100644 ---- a/drivers/atm/iphase.h -+++ b/drivers/atm/iphase.h -@@ -636,82 +636,82 @@ struct rx_buf_desc { - #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE - #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE - --typedef volatile u_int freg_t; -+typedef volatile u_int ffreg_t; - typedef u_int rreg_t; - - typedef struct _ffredn_t { -- freg_t idlehead_high; /* Idle cell header (high) */ -- freg_t idlehead_low; /* Idle cell header (low) */ -- freg_t maxrate; /* Maximum rate */ -- freg_t stparms; /* Traffic Management Parameters */ -- freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ -- freg_t rm_type; /* */ -- u_int filler5[0x17 - 0x06]; -- freg_t cmd_reg; /* Command register */ -- u_int filler18[0x20 - 0x18]; -- freg_t cbr_base; /* CBR Pointer Base */ -- freg_t vbr_base; /* VBR Pointer Base */ -- freg_t abr_base; /* ABR Pointer Base */ -- freg_t ubr_base; /* UBR Pointer Base */ -- u_int filler24; -- freg_t vbrwq_base; /* VBR Wait Queue Base */ -- freg_t abrwq_base; /* ABR Wait Queue Base */ -- freg_t ubrwq_base; /* UBR Wait Queue Base */ -- freg_t vct_base; /* Main VC Table Base */ -- freg_t vcte_base; /* Extended Main VC Table Base */ -- u_int filler2a[0x2C - 0x2A]; -- freg_t cbr_tab_beg; /* CBR Table Begin */ -- freg_t cbr_tab_end; /* CBR Table End */ -- freg_t cbr_pointer; /* CBR Pointer */ -- u_int filler2f[0x30 - 0x2F]; -- freg_t prq_st_adr; /* Packet Ready Queue Start Address */ -- freg_t prq_ed_adr; /* Packet Ready Queue End Address */ -- freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ -- freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ -- freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ -- freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ -- freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ -- freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ -- u_int filler38[0x40 - 0x38]; -- freg_t queue_base; /* Base address for PRQ and TCQ */ -- freg_t desc_base; /* Base address of descriptor table */ -- u_int filler42[0x45 - 0x42]; -- freg_t mode_reg_0; /* Mode register 0 */ -- freg_t mode_reg_1; /* Mode register 1 */ -- freg_t intr_status_reg;/* Interrupt Status register */ -- freg_t mask_reg; /* Mask Register */ -- freg_t cell_ctr_high1; /* Total cell transfer count (high) */ -- freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ -- freg_t state_reg; /* Status register */ -- u_int filler4c[0x58 - 0x4c]; -- freg_t curr_desc_num; /* Contains the current descriptor num */ -- freg_t next_desc; /* Next descriptor */ -- freg_t next_vc; /* Next VC */ -- u_int filler5b[0x5d - 0x5b]; -- freg_t present_slot_cnt;/* Present slot count */ -- u_int filler5e[0x6a - 0x5e]; -- freg_t new_desc_num; /* New descriptor number */ -- freg_t new_vc; /* New VC */ -- freg_t sched_tbl_ptr; /* Schedule table pointer */ -- freg_t vbrwq_wptr; /* VBR wait queue write pointer */ -- freg_t vbrwq_rptr; /* VBR wait queue read pointer */ -- freg_t abrwq_wptr; /* ABR wait queue write pointer */ -- freg_t abrwq_rptr; /* ABR wait queue read pointer */ -- freg_t ubrwq_wptr; /* UBR wait queue write pointer */ -- freg_t ubrwq_rptr; /* UBR wait queue read pointer */ -- freg_t cbr_vc; /* CBR VC */ -- freg_t vbr_sb_vc; /* VBR SB VC */ -- freg_t abr_sb_vc; /* ABR SB VC */ -- freg_t ubr_sb_vc; /* UBR SB VC */ -- freg_t vbr_next_link; /* VBR next link */ -- freg_t abr_next_link; /* ABR next link */ -- freg_t ubr_next_link; /* UBR next link */ -- u_int filler7a[0x7c-0x7a]; -- freg_t out_rate_head; /* Out of rate head */ -- u_int filler7d[0xca-0x7d]; /* pad out to full address space */ -- freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ -- freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ -- u_int fillercc[0x100-0xcc]; /* pad out to full address space */ -+ ffreg_t idlehead_high; /* Idle cell header (high) */ -+ ffreg_t idlehead_low; /* Idle cell header (low) */ -+ ffreg_t maxrate; /* Maximum rate */ -+ ffreg_t stparms; /* Traffic Management Parameters */ -+ ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ -+ ffreg_t rm_type; /* */ -+ u_int filler5[0x17 - 0x06]; -+ ffreg_t cmd_reg; /* Command register */ -+ u_int filler18[0x20 - 0x18]; -+ ffreg_t cbr_base; /* CBR Pointer Base */ -+ ffreg_t vbr_base; /* VBR Pointer Base */ -+ ffreg_t abr_base; /* ABR Pointer Base */ -+ ffreg_t ubr_base; /* UBR Pointer Base */ -+ u_int filler24; -+ ffreg_t vbrwq_base; /* VBR Wait Queue Base */ -+ ffreg_t abrwq_base; /* ABR Wait Queue Base */ -+ ffreg_t ubrwq_base; /* UBR Wait Queue Base */ -+ ffreg_t vct_base; /* Main VC Table Base */ -+ ffreg_t vcte_base; /* Extended Main VC Table Base */ -+ u_int filler2a[0x2C - 0x2A]; -+ ffreg_t cbr_tab_beg; /* CBR Table Begin */ -+ ffreg_t cbr_tab_end; /* CBR Table End */ -+ ffreg_t cbr_pointer; /* CBR Pointer */ -+ u_int filler2f[0x30 - 0x2F]; -+ ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ -+ ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ -+ ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ -+ ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ -+ ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ -+ ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ -+ ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ -+ ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ -+ u_int filler38[0x40 - 0x38]; -+ ffreg_t queue_base; /* Base address for PRQ and TCQ */ -+ ffreg_t desc_base; /* Base address of descriptor table */ -+ u_int filler42[0x45 - 0x42]; -+ ffreg_t mode_reg_0; /* Mode register 0 */ -+ ffreg_t mode_reg_1; /* Mode register 1 */ -+ ffreg_t intr_status_reg;/* Interrupt Status register */ -+ ffreg_t mask_reg; /* Mask Register */ -+ ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ -+ ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ -+ ffreg_t state_reg; /* Status register */ -+ u_int filler4c[0x58 - 0x4c]; -+ ffreg_t curr_desc_num; /* Contains the current descriptor num */ -+ ffreg_t next_desc; /* Next descriptor */ -+ ffreg_t next_vc; /* Next VC */ -+ u_int filler5b[0x5d - 0x5b]; -+ ffreg_t present_slot_cnt;/* Present slot count */ -+ u_int filler5e[0x6a - 0x5e]; -+ ffreg_t new_desc_num; /* New descriptor number */ -+ ffreg_t new_vc; /* New VC */ -+ ffreg_t sched_tbl_ptr; /* Schedule table pointer */ -+ ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ -+ ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ -+ ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ -+ ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ -+ ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ -+ ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ -+ ffreg_t cbr_vc; /* CBR VC */ -+ ffreg_t vbr_sb_vc; /* VBR SB VC */ -+ ffreg_t abr_sb_vc; /* ABR SB VC */ -+ ffreg_t ubr_sb_vc; /* UBR SB VC */ -+ ffreg_t vbr_next_link; /* VBR next link */ -+ ffreg_t abr_next_link; /* ABR next link */ -+ ffreg_t ubr_next_link; /* UBR next link */ -+ u_int filler7a[0x7c-0x7a]; -+ ffreg_t out_rate_head; /* Out of rate head */ -+ u_int filler7d[0xca-0x7d]; /* pad out to full address space */ -+ ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ -+ ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ -+ u_int fillercc[0x100-0xcc]; /* pad out to full address space */ - } ffredn_t; - - typedef struct _rfredn_t { --- -1.7.11.7 - - -From 5ef9a447aa4e6a1da43a04b98befa5643c806c1b Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Wed, 6 Feb 2013 23:41:35 +0000 -Subject: [PATCH 23/44] xen/netback: shutdown the ring if it contains garbage. - -[ Upstream commit 48856286b64e4b66ec62b94e504d0b29c1ade664 ] - -A buggy or malicious frontend should not be able to confuse netback. -If we spot anything which is not as it should be then shutdown the -device and don't try to continue with the ring in a potentially -hostile state. Well behaved and non-hostile frontends will not be -penalised. - -As well as making the existing checks for such errors fatal also add a -new check that ensures that there isn't an insane number of requests -on the ring (i.e. more than would fit in the ring). If the ring -contains garbage then previously is was possible to loop over this -insane number, getting an error each time and therefore not generating -any more pending requests and therefore not exiting the loop in -xen_netbk_tx_build_gops for an externded period. - -Also turn various netdev_dbg calls which no precipitate a fatal error -into netdev_err, they are rate limited because the device is shutdown -afterwards. - -This fixes at least one known DoS/softlockup of the backend domain. - -Signed-off-by: Ian Campbell -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Jan Beulich -Signed-off-by: David S. Miller ---- - drivers/net/xen-netback/common.h | 3 ++ - drivers/net/xen-netback/interface.c | 23 ++++++++------ - drivers/net/xen-netback/netback.c | 62 +++++++++++++++++++++++++++---------- - 3 files changed, 62 insertions(+), 26 deletions(-) - -diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h -index 94b79c3..9d7f172 100644 ---- a/drivers/net/xen-netback/common.h -+++ b/drivers/net/xen-netback/common.h -@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); - /* Notify xenvif that ring now has space to send an skb to the frontend */ - void xenvif_notify_tx_completion(struct xenvif *vif); - -+/* Prevent the device from generating any further traffic. */ -+void xenvif_carrier_off(struct xenvif *vif); -+ - /* Returns number of ring slots required to send an skb to the frontend */ - unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); - -diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c -index b7d41f8..b8c5193 100644 ---- a/drivers/net/xen-netback/interface.c -+++ b/drivers/net/xen-netback/interface.c -@@ -343,17 +343,22 @@ err: - return err; - } - --void xenvif_disconnect(struct xenvif *vif) -+void xenvif_carrier_off(struct xenvif *vif) - { - struct net_device *dev = vif->dev; -- if (netif_carrier_ok(dev)) { -- rtnl_lock(); -- netif_carrier_off(dev); /* discard queued packets */ -- if (netif_running(dev)) -- xenvif_down(vif); -- rtnl_unlock(); -- xenvif_put(vif); -- } -+ -+ rtnl_lock(); -+ netif_carrier_off(dev); /* discard queued packets */ -+ if (netif_running(dev)) -+ xenvif_down(vif); -+ rtnl_unlock(); -+ xenvif_put(vif); -+} -+ -+void xenvif_disconnect(struct xenvif *vif) -+{ -+ if (netif_carrier_ok(vif->dev)) -+ xenvif_carrier_off(vif); - - atomic_dec(&vif->refcnt); - wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index f2d6b78..c2e3336 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -888,6 +888,13 @@ static void netbk_tx_err(struct xenvif *vif, - xenvif_put(vif); - } - -+static void netbk_fatal_tx_err(struct xenvif *vif) -+{ -+ netdev_err(vif->dev, "fatal error; disabling device\n"); -+ xenvif_carrier_off(vif); -+ xenvif_put(vif); -+} -+ - static int netbk_count_requests(struct xenvif *vif, - struct xen_netif_tx_request *first, - struct xen_netif_tx_request *txp, -@@ -901,19 +908,22 @@ static int netbk_count_requests(struct xenvif *vif, - - do { - if (frags >= work_to_do) { -- netdev_dbg(vif->dev, "Need more frags\n"); -+ netdev_err(vif->dev, "Need more frags\n"); -+ netbk_fatal_tx_err(vif); - return -frags; - } - - if (unlikely(frags >= MAX_SKB_FRAGS)) { -- netdev_dbg(vif->dev, "Too many frags\n"); -+ netdev_err(vif->dev, "Too many frags\n"); -+ netbk_fatal_tx_err(vif); - return -frags; - } - - memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), - sizeof(*txp)); - if (txp->size > first->size) { -- netdev_dbg(vif->dev, "Frags galore\n"); -+ netdev_err(vif->dev, "Frag is bigger than frame.\n"); -+ netbk_fatal_tx_err(vif); - return -frags; - } - -@@ -921,8 +931,9 @@ static int netbk_count_requests(struct xenvif *vif, - frags++; - - if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { -- netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", -+ netdev_err(vif->dev, "txp->offset: %x, size: %u\n", - txp->offset, txp->size); -+ netbk_fatal_tx_err(vif); - return -frags; - } - } while ((txp++)->flags & XEN_NETTXF_more_data); -@@ -1095,7 +1106,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, - - do { - if (unlikely(work_to_do-- <= 0)) { -- netdev_dbg(vif->dev, "Missing extra info\n"); -+ netdev_err(vif->dev, "Missing extra info\n"); -+ netbk_fatal_tx_err(vif); - return -EBADR; - } - -@@ -1104,8 +1116,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, - if (unlikely(!extra.type || - extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { - vif->tx.req_cons = ++cons; -- netdev_dbg(vif->dev, -+ netdev_err(vif->dev, - "Invalid extra type: %d\n", extra.type); -+ netbk_fatal_tx_err(vif); - return -EINVAL; - } - -@@ -1121,13 +1134,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, - struct xen_netif_extra_info *gso) - { - if (!gso->u.gso.size) { -- netdev_dbg(vif->dev, "GSO size must not be zero.\n"); -+ netdev_err(vif->dev, "GSO size must not be zero.\n"); -+ netbk_fatal_tx_err(vif); - return -EINVAL; - } - - /* Currently only TCPv4 S.O. is supported. */ - if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { -- netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); -+ netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); -+ netbk_fatal_tx_err(vif); - return -EINVAL; - } - -@@ -1264,9 +1279,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) - - /* Get a netif from the list with work to do. */ - vif = poll_net_schedule_list(netbk); -+ /* This can sometimes happen because the test of -+ * list_empty(net_schedule_list) at the top of the -+ * loop is unlocked. Just go back and have another -+ * look. -+ */ - if (!vif) - continue; - -+ if (vif->tx.sring->req_prod - vif->tx.req_cons > -+ XEN_NETIF_TX_RING_SIZE) { -+ netdev_err(vif->dev, -+ "Impossible number of requests. " -+ "req_prod %d, req_cons %d, size %ld\n", -+ vif->tx.sring->req_prod, vif->tx.req_cons, -+ XEN_NETIF_TX_RING_SIZE); -+ netbk_fatal_tx_err(vif); -+ continue; -+ } -+ - RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); - if (!work_to_do) { - xenvif_put(vif); -@@ -1294,17 +1325,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) - work_to_do = xen_netbk_get_extras(vif, extras, - work_to_do); - idx = vif->tx.req_cons; -- if (unlikely(work_to_do < 0)) { -- netbk_tx_err(vif, &txreq, idx); -+ if (unlikely(work_to_do < 0)) - continue; -- } - } - - ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); -- if (unlikely(ret < 0)) { -- netbk_tx_err(vif, &txreq, idx - ret); -+ if (unlikely(ret < 0)) - continue; -- } -+ - idx += ret; - - if (unlikely(txreq.size < ETH_HLEN)) { -@@ -1316,11 +1344,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) - - /* No crossing a page as the payload mustn't fragment. */ - if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { -- netdev_dbg(vif->dev, -+ netdev_err(vif->dev, - "txreq.offset: %x, size: %u, end: %lu\n", - txreq.offset, txreq.size, - (txreq.offset&~PAGE_MASK) + txreq.size); -- netbk_tx_err(vif, &txreq, idx); -+ netbk_fatal_tx_err(vif); - continue; - } - -@@ -1348,8 +1376,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) - gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; - - if (netbk_set_skb_gso(vif, skb, gso)) { -+ /* Failure in netbk_set_skb_gso is fatal. */ - kfree_skb(skb); -- netbk_tx_err(vif, &txreq, idx); - continue; - } - } --- -1.7.11.7 - - -From 10948f5aa9992de84e022e218b494586fe92d547 Mon Sep 17 00:00:00 2001 -From: Matthew Daley -Date: Wed, 6 Feb 2013 23:41:36 +0000 -Subject: [PATCH 24/44] xen/netback: don't leak pages on failure in - xen_netbk_tx_check_gop. - -[ Upstream commit 7d5145d8eb2b9791533ffe4dc003b129b9696c48 ] - -Signed-off-by: Matthew Daley -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ian Campbell -Acked-by: Jan Beulich -Signed-off-by: David S. Miller ---- - drivers/net/xen-netback/netback.c | 38 +++++++++++++------------------------- - 1 file changed, 13 insertions(+), 25 deletions(-) - -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index c2e3336..bf692df 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) - atomic_dec(&netbk->netfront_count); - } - --static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); -+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, -+ u8 status); - static void make_tx_response(struct xenvif *vif, - struct xen_netif_tx_request *txp, - s8 st); -@@ -1007,30 +1008,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, - { - struct gnttab_copy *gop = *gopp; - u16 pending_idx = *((u16 *)skb->data); -- struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; -- struct xenvif *vif = pending_tx_info[pending_idx].vif; -- struct xen_netif_tx_request *txp; - struct skb_shared_info *shinfo = skb_shinfo(skb); - int nr_frags = shinfo->nr_frags; - int i, err, start; - - /* Check status of header. */ - err = gop->status; -- if (unlikely(err)) { -- pending_ring_idx_t index; -- index = pending_index(netbk->pending_prod++); -- txp = &pending_tx_info[pending_idx].req; -- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -- netbk->pending_ring[index] = pending_idx; -- xenvif_put(vif); -- } -+ if (unlikely(err)) -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); - - /* Skip first skb fragment if it is on same page as header fragment. */ - start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); - - for (i = start; i < nr_frags; i++) { - int j, newerr; -- pending_ring_idx_t index; - - pending_idx = frag_get_pending_idx(&shinfo->frags[i]); - -@@ -1039,16 +1030,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, - if (likely(!newerr)) { - /* Had a previous error? Invalidate this fragment. */ - if (unlikely(err)) -- xen_netbk_idx_release(netbk, pending_idx); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); - continue; - } - - /* Error on this fragment: respond to client with an error. */ -- txp = &netbk->pending_tx_info[pending_idx].req; -- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -- index = pending_index(netbk->pending_prod++); -- netbk->pending_ring[index] = pending_idx; -- xenvif_put(vif); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); - - /* Not the first error? Preceding frags already invalidated. */ - if (err) -@@ -1056,10 +1043,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, - - /* First error: invalidate header and preceding fragments. */ - pending_idx = *((u16 *)skb->data); -- xen_netbk_idx_release(netbk, pending_idx); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); - for (j = start; j < i; j++) { - pending_idx = frag_get_pending_idx(&shinfo->frags[j]); -- xen_netbk_idx_release(netbk, pending_idx); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); - } - - /* Remember the error: invalidate all subsequent fragments. */ -@@ -1093,7 +1080,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) - - /* Take an extra reference to offset xen_netbk_idx_release */ - get_page(netbk->mmap_pages[pending_idx]); -- xen_netbk_idx_release(netbk, pending_idx); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); - } - } - -@@ -1476,7 +1463,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) - txp->size -= data_len; - } else { - /* Schedule a response immediately. */ -- xen_netbk_idx_release(netbk, pending_idx); -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); - } - - if (txp->flags & XEN_NETTXF_csum_blank) -@@ -1528,7 +1515,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) - xen_netbk_tx_submit(netbk); - } - --static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) -+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, -+ u8 status) - { - struct xenvif *vif; - struct pending_tx_info *pending_tx_info; -@@ -1542,7 +1530,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) - - vif = pending_tx_info->vif; - -- make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); -+ make_tx_response(vif, &pending_tx_info->req, status); - - index = pending_index(netbk->pending_prod++); - netbk->pending_ring[index] = pending_idx; --- -1.7.11.7 - - -From 2e0b7c1781a94640566dccf9d7441d500fa69e40 Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Wed, 6 Feb 2013 23:41:37 +0000 -Subject: [PATCH 25/44] xen/netback: free already allocated memory on failure - in xen_netbk_get_requests - -[ Upstream commit 4cc7c1cb7b11b6f3515bd9075527576a1eecc4aa ] - -Signed-off-by: Ian Campbell -Signed-off-by: David S. Miller ---- - drivers/net/xen-netback/netback.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index bf692df..dcb2d4d 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -978,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, - pending_idx = netbk->pending_ring[index]; - page = xen_netbk_alloc_page(netbk, skb, pending_idx); - if (!page) -- return NULL; -+ goto err; - - gop->source.u.ref = txp->gref; - gop->source.domid = vif->domid; -@@ -1000,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, - } - - return gop; -+err: -+ /* Unwind, freeing all pages and sending error responses. */ -+ while (i-- > start) { -+ xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), -+ XEN_NETIF_RSP_ERROR); -+ } -+ /* The head too, if necessary. */ -+ if (start) -+ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); -+ -+ return NULL; - } - - static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, --- -1.7.11.7 - - -From d5b2f3542a1f9c7b5092816b87db08e9f08f1551 Mon Sep 17 00:00:00 2001 -From: Ian Campbell -Date: Wed, 6 Feb 2013 23:41:38 +0000 -Subject: [PATCH 26/44] netback: correct netbk_tx_err to handle wrap around. - -[ Upstream commit b9149729ebdcfce63f853aa54a404c6a8f6ebbf3 ] - -Signed-off-by: Ian Campbell -Acked-by: Jan Beulich -Signed-off-by: David S. Miller ---- - drivers/net/xen-netback/netback.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index dcb2d4d..2b9520c 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -880,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif, - - do { - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); -- if (cons >= end) -+ if (cons == end) - break; - txp = RING_GET_REQUEST(&vif->tx, cons++); - } while (1); --- -1.7.11.7 - - -From 28ecceda6c2f58f14379e35a0caec5f9b57cc798 Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Wed, 16 Jan 2013 20:55:01 +0000 -Subject: [PATCH 27/44] ipv4: Remove output route check in ipv4_mtu -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 38d523e2948162776903349c89d65f7b9370dadb ] - -The output route check was introduced with git commit 261663b0 -(ipv4: Don't use the cached pmtu informations for input routes) -during times when we cached the pmtu informations on the -inetpeer. Now the pmtu informations are back in the routes, -so this check is obsolete. It also had some unwanted side effects, -as reported by Timo Teras and Lukas Tribus. - -Signed-off-by: Steffen Klassert -Acked-by: Timo Teräs -Signed-off-by: David S. Miller ---- - net/ipv4/route.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index df25142..11d28e3 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -1120,7 +1120,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) - if (!mtu || time_after_eq(jiffies, rt->dst.expires)) - mtu = dst_metric_raw(dst, RTAX_MTU); - -- if (mtu && rt_is_output_route(rt)) -+ if (mtu) - return mtu; - - mtu = dst->dev->mtu; --- -1.7.11.7 - - -From d282905a8f4d2f86ffca23f2bbee1697fdf832aa Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Wed, 16 Jan 2013 20:58:10 +0000 -Subject: [PATCH 28/44] ipv4: Don't update the pmtu on mtu locked routes - -[ Upstream commit fa1e492aa3cbafba9f8fc6d05e5b08a3091daf4a ] - -Routes with locked mtu should not use learned pmtu informations, -so do not update the pmtu on these routes. - -Reported-by: Julian Anastasov -Signed-off-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - net/ipv4/route.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 11d28e3..0660d6f 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -912,6 +912,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) - struct dst_entry *dst = &rt->dst; - struct fib_result res; - -+ if (dst_metric_locked(dst, RTAX_MTU)) -+ return; -+ - if (dst->dev->mtu < mtu) - return; - --- -1.7.11.7 - - -From 7e5337b6085429c382297b71d3099ec56b82829d Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Wed, 16 Jan 2013 22:09:49 +0000 -Subject: [PATCH 29/44] ipv6: Add an error handler for icmp6 - -[ Upstream commit 6f809da27c94425e07be4a64d5093e1df95188e9 ] - -pmtu and redirect events are now handled in the protocols error handler, -so add an error handler for icmp6 to do this. It is needed in the case -when we have no socket context. Based on a patch by Duan Jiong. - -Reported-by: Duan Jiong -Signed-off-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - net/ipv6/icmp.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c -index 24d69db..4d844d7 100644 ---- a/net/ipv6/icmp.c -+++ b/net/ipv6/icmp.c -@@ -81,10 +81,22 @@ static inline struct sock *icmpv6_sk(struct net *net) - return net->ipv6.icmp_sk[smp_processor_id()]; - } - -+static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, -+ u8 type, u8 code, int offset, __be32 info) -+{ -+ struct net *net = dev_net(skb->dev); -+ -+ if (type == ICMPV6_PKT_TOOBIG) -+ ip6_update_pmtu(skb, net, info, 0, 0); -+ else if (type == NDISC_REDIRECT) -+ ip6_redirect(skb, net, 0, 0); -+} -+ - static int icmpv6_rcv(struct sk_buff *skb); - - static const struct inet6_protocol icmpv6_protocol = { - .handler = icmpv6_rcv, -+ .err_handler = icmpv6_err, - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, - }; - --- -1.7.11.7 - - -From 5d7f31144c2e375a5a241bc76648ccd8a6d5e6c9 Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Mon, 21 Jan 2013 01:59:11 +0000 -Subject: [PATCH 30/44] ipv4: Invalidate the socket cached route on pmtu - events if possible - -[ Upstream commit 9cb3a50c5f63ed745702972f66eaee8767659acd ] - -The route lookup in ipv4_sk_update_pmtu() might return a route -different from the route we cached at the socket. This is because -standart routes are per cpu, so each cpu has it's own struct rtable. -This means that we do not invalidate the socket cached route if the -NET_RX_SOFTIRQ is not served by the same cpu that the sending socket -uses. As a result, the cached route reused until we disconnect. - -With this patch we invalidate the socket cached route if possible. -If the socket is owened by the user, we can't update the cached -route directly. A followup patch will implement socket release -callback functions for datagram sockets to handle this case. - -Reported-by: Yurij M. Plotnikov -Signed-off-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - net/ipv4/route.c | 42 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 41 insertions(+), 1 deletion(-) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 0660d6f..fc6a6b4 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -965,7 +965,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, - } - EXPORT_SYMBOL_GPL(ipv4_update_pmtu); - --void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) -+static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) - { - const struct iphdr *iph = (const struct iphdr *) skb->data; - struct flowi4 fl4; -@@ -978,6 +978,46 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) - ip_rt_put(rt); - } - } -+ -+void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) -+{ -+ const struct iphdr *iph = (const struct iphdr *) skb->data; -+ struct flowi4 fl4; -+ struct rtable *rt; -+ struct dst_entry *dst; -+ -+ bh_lock_sock(sk); -+ rt = (struct rtable *) __sk_dst_get(sk); -+ -+ if (sock_owned_by_user(sk) || !rt) { -+ __ipv4_sk_update_pmtu(skb, sk, mtu); -+ goto out; -+ } -+ -+ __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); -+ -+ if (!__sk_dst_check(sk, 0)) { -+ rt = ip_route_output_flow(sock_net(sk), &fl4, sk); -+ if (IS_ERR(rt)) -+ goto out; -+ } -+ -+ __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); -+ -+ dst = dst_check(&rt->dst, 0); -+ if (!dst) { -+ rt = ip_route_output_flow(sock_net(sk), &fl4, sk); -+ if (IS_ERR(rt)) -+ goto out; -+ -+ dst = &rt->dst; -+ } -+ -+ __sk_dst_set(sk, dst); -+ -+out: -+ bh_unlock_sock(sk); -+} - EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); - - void ipv4_redirect(struct sk_buff *skb, struct net *net, --- -1.7.11.7 - - -From 250a2bac5bcef490f775aa2680c3934915aeb51a Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Mon, 21 Jan 2013 02:00:03 +0000 -Subject: [PATCH 31/44] ipv4: Add a socket release callback for datagram - sockets - -[ Upstream commit 8141ed9fcedb278f4a3a78680591bef1e55f75fb ] - -This implements a socket release callback function to check -if the socket cached route got invalid during the time -we owned the socket. The function is used from udp, raw -and ping sockets. - -Signed-off-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - include/net/ip.h | 2 ++ - net/ipv4/datagram.c | 25 +++++++++++++++++++++++++ - net/ipv4/ping.c | 1 + - net/ipv4/raw.c | 1 + - net/ipv4/udp.c | 1 + - 5 files changed, 30 insertions(+) - -diff --git a/include/net/ip.h b/include/net/ip.h -index 0707fb9..a68f838 100644 ---- a/include/net/ip.h -+++ b/include/net/ip.h -@@ -143,6 +143,8 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) - extern int ip4_datagram_connect(struct sock *sk, - struct sockaddr *uaddr, int addr_len); - -+extern void ip4_datagram_release_cb(struct sock *sk); -+ - struct ip_reply_arg { - struct kvec iov[1]; - int flags; -diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c -index 424fafb..b28e863 100644 ---- a/net/ipv4/datagram.c -+++ b/net/ipv4/datagram.c -@@ -85,3 +85,28 @@ out: - return err; - } - EXPORT_SYMBOL(ip4_datagram_connect); -+ -+void ip4_datagram_release_cb(struct sock *sk) -+{ -+ const struct inet_sock *inet = inet_sk(sk); -+ const struct ip_options_rcu *inet_opt; -+ __be32 daddr = inet->inet_daddr; -+ struct flowi4 fl4; -+ struct rtable *rt; -+ -+ if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0)) -+ return; -+ -+ rcu_read_lock(); -+ inet_opt = rcu_dereference(inet->inet_opt); -+ if (inet_opt && inet_opt->opt.srr) -+ daddr = inet_opt->opt.faddr; -+ rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, -+ inet->inet_saddr, inet->inet_dport, -+ inet->inet_sport, sk->sk_protocol, -+ RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); -+ if (!IS_ERR(rt)) -+ __sk_dst_set(sk, &rt->dst); -+ rcu_read_unlock(); -+} -+EXPORT_SYMBOL_GPL(ip4_datagram_release_cb); -diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c -index 8f3d054..6f9c072 100644 ---- a/net/ipv4/ping.c -+++ b/net/ipv4/ping.c -@@ -738,6 +738,7 @@ struct proto ping_prot = { - .recvmsg = ping_recvmsg, - .bind = ping_bind, - .backlog_rcv = ping_queue_rcv_skb, -+ .release_cb = ip4_datagram_release_cb, - .hash = ping_v4_hash, - .unhash = ping_v4_unhash, - .get_port = ping_v4_get_port, -diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c -index 73d1e4d..6f08991 100644 ---- a/net/ipv4/raw.c -+++ b/net/ipv4/raw.c -@@ -894,6 +894,7 @@ struct proto raw_prot = { - .recvmsg = raw_recvmsg, - .bind = raw_bind, - .backlog_rcv = raw_rcv_skb, -+ .release_cb = ip4_datagram_release_cb, - .hash = raw_hash_sk, - .unhash = raw_unhash_sk, - .obj_size = sizeof(struct raw_sock), -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 79c8dbe..1f4d405 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -1952,6 +1952,7 @@ struct proto udp_prot = { - .recvmsg = udp_recvmsg, - .sendpage = udp_sendpage, - .backlog_rcv = __udp_queue_rcv_skb, -+ .release_cb = ip4_datagram_release_cb, - .hash = udp_lib_hash, - .unhash = udp_lib_unhash, - .rehash = udp_v4_rehash, --- -1.7.11.7 - - -From db28ad52a9a7c7fff4063d733e39169c663b2d2e Mon Sep 17 00:00:00 2001 -From: Steffen Klassert -Date: Tue, 22 Jan 2013 00:01:28 +0000 -Subject: [PATCH 32/44] ipv4: Fix route refcount on pmtu discovery - -[ Upstream commit b44108dbdbaa07c609bb5755e8dd6c2035236251 ] - -git commit 9cb3a50c (ipv4: Invalidate the socket cached route on -pmtu events if possible) introduced a refcount problem. We don't -get a refcount on the route if we get it from__sk_dst_get(), but -we need one if we want to reuse this route because __sk_dst_set() -releases the refcount of the old route. This patch adds proper -refcount handling for that case. We introduce a 'new' flag to -indicate that we are going to use a new route and we release the -old route only if we replace it by a new one. - -Reported-by: Julian Anastasov -Signed-off-by: Steffen Klassert -Signed-off-by: David S. Miller ---- - net/ipv4/route.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index fc6a6b4..0fdfe4c 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -985,6 +985,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) - struct flowi4 fl4; - struct rtable *rt; - struct dst_entry *dst; -+ bool new = false; - - bh_lock_sock(sk); - rt = (struct rtable *) __sk_dst_get(sk); -@@ -1000,20 +1001,26 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) - rt = ip_route_output_flow(sock_net(sk), &fl4, sk); - if (IS_ERR(rt)) - goto out; -+ -+ new = true; - } - - __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); - - dst = dst_check(&rt->dst, 0); - if (!dst) { -+ if (new) -+ dst_release(&rt->dst); -+ - rt = ip_route_output_flow(sock_net(sk), &fl4, sk); - if (IS_ERR(rt)) - goto out; - -- dst = &rt->dst; -+ new = true; - } - -- __sk_dst_set(sk, dst); -+ if (new) -+ __sk_dst_set(sk, &rt->dst); - - out: - bh_unlock_sock(sk); --- -1.7.11.7 - - -From 9fdbfac789ac6ee2eade40d045576f701b5ea3ee Mon Sep 17 00:00:00 2001 -From: Neil Horman -Date: Thu, 17 Jan 2013 11:15:08 +0000 -Subject: [PATCH 33/44] sctp: refactor sctp_outq_teardown to insure proper - re-initalization - -[ Upstream commit 2f94aabd9f6c925d77aecb3ff020f1cc12ed8f86 ] - -Jamie Parsons reported a problem recently, in which the re-initalization of an -association (The duplicate init case), resulted in a loss of receive window -space. He tracked down the root cause to sctp_outq_teardown, which discarded -all the data on an outq during a re-initalization of the corresponding -association, but never reset the outq->outstanding_data field to zero. I wrote, -and he tested this fix, which does a proper full re-initalization of the outq, -fixing this problem, and hopefully future proofing us from simmilar issues down -the road. - -Signed-off-by: Neil Horman -Reported-by: Jamie Parsons -Tested-by: Jamie Parsons -CC: Jamie Parsons -CC: Vlad Yasevich -CC: "David S. Miller" -CC: netdev@vger.kernel.org -Acked-by: Vlad Yasevich -Signed-off-by: David S. Miller ---- - net/sctp/outqueue.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c -index 1b4a7f8..bcaa4c8 100644 ---- a/net/sctp/outqueue.c -+++ b/net/sctp/outqueue.c -@@ -224,7 +224,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) - - /* Free the outqueue structure and any related pending chunks. - */ --void sctp_outq_teardown(struct sctp_outq *q) -+static void __sctp_outq_teardown(struct sctp_outq *q) - { - struct sctp_transport *transport; - struct list_head *lchunk, *temp; -@@ -277,8 +277,6 @@ void sctp_outq_teardown(struct sctp_outq *q) - sctp_chunk_free(chunk); - } - -- q->error = 0; -- - /* Throw away any leftover control chunks. */ - list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { - list_del_init(&chunk->list); -@@ -286,11 +284,17 @@ void sctp_outq_teardown(struct sctp_outq *q) - } - } - -+void sctp_outq_teardown(struct sctp_outq *q) -+{ -+ __sctp_outq_teardown(q); -+ sctp_outq_init(q->asoc, q); -+} -+ - /* Free the outqueue structure and any related pending chunks. */ - void sctp_outq_free(struct sctp_outq *q) - { - /* Throw away leftover chunks. */ -- sctp_outq_teardown(q); -+ __sctp_outq_teardown(q); - - /* If we were kmalloc()'d, free the memory. */ - if (q->malloced) --- -1.7.11.7 - - -From b6eafd305aecd134d3333b2ebff487e86bd39eae Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Fri, 8 Feb 2013 03:04:34 +0000 -Subject: [PATCH 34/44] net: sctp: sctp_setsockopt_auth_key: use kzfree - instead of kfree - -[ Upstream commit 6ba542a291a5e558603ac51cda9bded347ce7627 ] - -In sctp_setsockopt_auth_key, we create a temporary copy of the user -passed shared auth key for the endpoint or association and after -internal setup, we free it right away. Since it's sensitive data, we -should zero out the key before returning the memory back to the -allocator. Thus, use kzfree instead of kfree, just as we do in -sctp_auth_key_put(). - -Signed-off-by: Daniel Borkmann -Signed-off-by: David S. Miller ---- - net/sctp/socket.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 406d957..9261d9a 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -3388,7 +3388,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, - - ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); - out: -- kfree(authkey); -+ kzfree(authkey); - return ret; - } - --- -1.7.11.7 - - -From de6cbc343521cd56514d53fc249fbbd03532d04c Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Fri, 8 Feb 2013 03:04:35 +0000 -Subject: [PATCH 35/44] net: sctp: sctp_endpoint_free: zero out secret key - data - -[ Upstream commit b5c37fe6e24eec194bb29d22fdd55d73bcc709bf ] - -On sctp_endpoint_destroy, previously used sensitive keying material -should be zeroed out before the memory is returned, as we already do -with e.g. auth keys when released. - -Signed-off-by: Daniel Borkmann -Acked-by: Vlad Yasevich -Signed-off-by: David S. Miller ---- - net/sctp/endpointola.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c -index 1859e2b..80a7264 100644 ---- a/net/sctp/endpointola.c -+++ b/net/sctp/endpointola.c -@@ -249,6 +249,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) - /* Final destructor for endpoint. */ - static void sctp_endpoint_destroy(struct sctp_endpoint *ep) - { -+ int i; -+ - SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); - - /* Free up the HMAC transform. */ -@@ -271,6 +273,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) - sctp_inq_free(&ep->base.inqueue); - sctp_bind_addr_free(&ep->base.bind_addr); - -+ for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i) -+ memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE); -+ - /* Remove and free the port */ - if (sctp_sk(ep->base.sk)->bind_hash) - sctp_put_port(ep->base.sk); --- -1.7.11.7 - - -From a8963d813f812a9c13baed12ec4c06a1c3443e7c Mon Sep 17 00:00:00 2001 -From: Yuchung Cheng -Date: Thu, 31 Jan 2013 11:16:46 -0800 -Subject: [PATCH 36/44] tcp: detect SYN/data drop when F-RTO is disabled - -[ Upstream commit 66555e92fb7a619188c02cceae4bbc414f15f96d ] - -On receiving the SYN-ACK, Fast Open checks icsk_retransmit for SYN -retransmission to detect SYN/data drops. But if F-RTO is disabled, -icsk_retransmit is reset at step D of tcp_fastretrans_alert() ( -under tcp_ack()) before tcp_rcv_fastopen_synack(). The fix is to use -total_retrans instead which accounts for SYN retransmission regardless -the use of F-RTO. - -Signed-off-by: Yuchung Cheng -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_input.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 181fc82..765db33 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -5639,8 +5639,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, - * the remote receives only the retransmitted (regular) SYNs: either - * the original SYN-data or the corresponding SYN-ACK is lost. - */ -- syn_drop = (cookie->len <= 0 && data && -- inet_csk(sk)->icsk_retransmits); -+ syn_drop = (cookie->len <= 0 && data && tp->total_retrans); - - tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); - --- -1.7.11.7 - - -From 8bee456022dadde41b6fe3c551f7e46af777df10 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sat, 2 Feb 2013 05:23:16 +0000 -Subject: [PATCH 37/44] tcp: fix an infinite loop in tcp_slow_start() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 973ec449bb4f2b8c514bacbcb4d9506fc31c8ce3 ] - -Since commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()), -a nul snd_cwnd triggers an infinite loop in tcp_slow_start() - -Avoid this infinite loop and log a one time error for further -analysis. FRTO code is suspected to cause this bug. - -Reported-by: Pasi Kärkkäinen -Signed-off-by: Eric Dumazet -Cc: Neal Cardwell -Cc: Yuchung Cheng -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_cong.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c -index 1432cdb..fc582a7 100644 ---- a/net/ipv4/tcp_cong.c -+++ b/net/ipv4/tcp_cong.c -@@ -309,6 +309,12 @@ void tcp_slow_start(struct tcp_sock *tp) - { - int cnt; /* increase in packets */ - unsigned int delta = 0; -+ u32 snd_cwnd = tp->snd_cwnd; -+ -+ if (unlikely(!snd_cwnd)) { -+ pr_err_once("snd_cwnd is nul, please report this bug.\n"); -+ snd_cwnd = 1U; -+ } - - /* RFC3465: ABC Slow start - * Increase only after a full MSS of bytes is acked -@@ -323,7 +329,7 @@ void tcp_slow_start(struct tcp_sock *tp) - if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh) - cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */ - else -- cnt = tp->snd_cwnd; /* exponential increase */ -+ cnt = snd_cwnd; /* exponential increase */ - - /* RFC3465: ABC - * We MAY increase by 2 if discovered delayed ack -@@ -333,11 +339,11 @@ void tcp_slow_start(struct tcp_sock *tp) - tp->bytes_acked = 0; - - tp->snd_cwnd_cnt += cnt; -- while (tp->snd_cwnd_cnt >= tp->snd_cwnd) { -- tp->snd_cwnd_cnt -= tp->snd_cwnd; -+ while (tp->snd_cwnd_cnt >= snd_cwnd) { -+ tp->snd_cwnd_cnt -= snd_cwnd; - delta++; - } -- tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp); -+ tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp); - } - EXPORT_SYMBOL_GPL(tcp_slow_start); - --- -1.7.11.7 - - -From 704e9be40e69eed1a96363ce2a6707801f5ff174 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sun, 3 Feb 2013 09:13:05 +0000 -Subject: [PATCH 38/44] tcp: frto should not set snd_cwnd to 0 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 2e5f421211ff76c17130b4597bc06df4eeead24f ] - -Commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()) -uncovered a bug in FRTO code : -tcp_process_frto() is setting snd_cwnd to 0 if the number -of in flight packets is 0. - -As Neal pointed out, if no packet is in flight we lost our -chance to disambiguate whether a loss timeout was spurious. - -We should assume it was a proper loss. - -Reported-by: Pasi Kärkkäinen -Signed-off-by: Neal Cardwell -Signed-off-by: Eric Dumazet -Cc: Ilpo Järvinen -Cc: Yuchung Cheng -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_input.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 765db33..3a5f691 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -3484,7 +3484,8 @@ static bool tcp_process_frto(struct sock *sk, int flag) - ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) - tp->undo_marker = 0; - -- if (!before(tp->snd_una, tp->frto_highmark)) { -+ if (!before(tp->snd_una, tp->frto_highmark) || -+ !tcp_packets_in_flight(tp)) { - tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); - return true; - } --- -1.7.11.7 - - -From cd3789e7ba292f27f25e9076dd23b97cf30d89b4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= -Date: Mon, 4 Feb 2013 02:14:25 +0000 -Subject: [PATCH 39/44] tcp: fix for zero packets_in_flight was too broad -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 6731d2095bd4aef18027c72ef845ab1087c3ba63 ] - -There are transients during normal FRTO procedure during which -the packets_in_flight can go to zero between write_queue state -updates and firing the resulting segments out. As FRTO processing -occurs during that window the check must be more precise to -not match "spuriously" :-). More specificly, e.g., when -packets_in_flight is zero but FLAG_DATA_ACKED is true the problematic -branch that set cwnd into zero would not be taken and new segments -might be sent out later. - -Signed-off-by: Ilpo Järvinen -Tested-by: Eric Dumazet -Acked-by: Neal Cardwell -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_input.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 3a5f691..beabc80 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -3484,8 +3484,7 @@ static bool tcp_process_frto(struct sock *sk, int flag) - ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) - tp->undo_marker = 0; - -- if (!before(tp->snd_una, tp->frto_highmark) || -- !tcp_packets_in_flight(tp)) { -+ if (!before(tp->snd_una, tp->frto_highmark)) { - tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); - return true; - } -@@ -3505,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag) - } - } else { - if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { -+ if (!tcp_packets_in_flight(tp)) { -+ tcp_enter_frto_loss(sk, 2, flag); -+ return true; -+ } -+ - /* Prevent sending of new data. */ - tp->snd_cwnd = min(tp->snd_cwnd, - tcp_packets_in_flight(tp)); --- -1.7.11.7 - - -From a037491fdc5e5ca2b6f21366b1165555e285c71d Mon Sep 17 00:00:00 2001 -From: Willy Tarreau -Date: Sun, 2 Dec 2012 11:49:27 +0000 -Subject: [PATCH 40/44] tcp: don't abort splice() after small transfers - -[ Upstream commit 02275a2ee7c0ea475b6f4a6428f5df592bc9d30b ] - -TCP coalescing added a regression in splice(socket->pipe) performance, -for some workloads because of the way tcp_read_sock() is implemented. - -The reason for this is the break when (offset + 1 != skb->len). - -As we released the socket lock, this condition is possible if TCP stack -added a fragment to the skb, which can happen with TCP coalescing. - -So let's go back to the beginning of the loop when this happens, -to give a chance to splice more frags per system call. - -Doing so fixes the issue and makes GRO 10% faster than LRO -on CPU-bound splice() workloads instead of the opposite. - -Signed-off-by: Willy Tarreau -Signed-off-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv4/tcp.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index e457c7a..91de64d 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -1490,15 +1490,19 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, - copied += used; - offset += used; - } -- /* -- * If recv_actor drops the lock (e.g. TCP splice -+ /* If recv_actor drops the lock (e.g. TCP splice - * receive) the skb pointer might be invalid when - * getting here: tcp_collapse might have deleted it - * while aggregating skbs from the socket queue. - */ -- skb = tcp_recv_skb(sk, seq-1, &offset); -- if (!skb || (offset+1 != skb->len)) -+ skb = tcp_recv_skb(sk, seq - 1, &offset); -+ if (!skb) - break; -+ /* TCP coalescing might have appended data to the skb. -+ * Try to splice more frags -+ */ -+ if (offset + 1 != skb->len) -+ continue; - } - if (tcp_hdr(skb)->fin) { - sk_eat_skb(sk, skb, false); --- -1.7.11.7 - - -From 1f2037984ea99422150679b62f18e9d41f2e9b71 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Thu, 10 Jan 2013 07:06:10 +0000 -Subject: [PATCH 41/44] tcp: splice: fix an infinite loop in tcp_read_sock() - -[ Upstream commit ff905b1e4aad8ccbbb0d42f7137f19482742ff07 ] - -commit 02275a2ee7c0 (tcp: don't abort splice() after small transfers) -added a regression. - -[ 83.843570] INFO: rcu_sched self-detected stall on CPU -[ 83.844575] INFO: rcu_sched detected stalls on CPUs/tasks: { 6} (detected by 0, t=21002 jiffies, g=4457, c=4456, q=13132) -[ 83.844582] Task dump for CPU 6: -[ 83.844584] netperf R running task 0 8966 8952 0x0000000c -[ 83.844587] 0000000000000000 0000000000000006 0000000000006c6c 0000000000000000 -[ 83.844589] 000000000000006c 0000000000000096 ffffffff819ce2bc ffffffffffffff10 -[ 83.844592] ffffffff81088679 0000000000000010 0000000000000246 ffff880c4b9ddcd8 -[ 83.844594] Call Trace: -[ 83.844596] [] ? vprintk_emit+0x1c9/0x4c0 -[ 83.844601] [] ? schedule+0x29/0x70 -[ 83.844606] [] ? tcp_splice_data_recv+0x42/0x50 -[ 83.844610] [] ? tcp_read_sock+0xda/0x260 -[ 83.844613] [] ? tcp_prequeue_process+0xb0/0xb0 -[ 83.844615] [] ? tcp_splice_read+0xc0/0x250 -[ 83.844618] [] ? sock_splice_read+0x22/0x30 -[ 83.844622] [] ? do_splice_to+0x7b/0xa0 -[ 83.844627] [] ? sys_splice+0x59c/0x5d0 -[ 83.844630] [] ? putname+0x2b/0x40 -[ 83.844633] [] ? do_sys_open+0x174/0x1e0 -[ 83.844636] [] ? system_call_fastpath+0x16/0x1b - -if recv_actor() returns 0, we should stop immediately, -because looping wont give a chance to drain the pipe. - -Signed-off-by: Eric Dumazet -Cc: Willy Tarreau -Signed-off-by: David S. Miller ---- - net/ipv4/tcp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 91de64d..6e92233 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -1481,7 +1481,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, - break; - } - used = recv_actor(desc, skb, offset, len); -- if (used < 0) { -+ if (used <= 0) { - if (!copied) - copied = used; - break; --- -1.7.11.7 - - -From a2252d0dd0d7345a6266c6c1c5c3e7ff7025c207 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 9 Jan 2013 20:59:09 +0000 -Subject: [PATCH 42/44] tcp: fix splice() and tcp collapsing interaction - -[ Upstream commit f26845b43c75d3f32f98d194c1327b5b1e6b3fb0 ] - -Under unusual circumstances, TCP collapse can split a big GRO TCP packet -while its being used in a splice(socket->pipe) operation. - -skb_splice_bits() releases the socket lock before calling -splice_to_pipe(). - -[ 1081.353685] WARNING: at net/ipv4/tcp.c:1330 tcp_cleanup_rbuf+0x4d/0xfc() -[ 1081.371956] Hardware name: System x3690 X5 -[7148Z68]- -[ 1081.391820] cleanup rbuf bug: copied AD3BCF1 seq AD370AF rcvnxt AD3CF13 - -To fix this problem, we must eat skbs in tcp_recv_skb(). - -Remove the inline keyword from tcp_recv_skb() definition since -it has three call sites. - -Reported-by: Christian Becker -Cc: Willy Tarreau -Signed-off-by: Eric Dumazet -Tested-by: Willy Tarreau -Signed-off-by: David S. Miller ---- - net/ipv4/tcp.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 6e92233..667e8a0 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -1427,12 +1427,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) - } - #endif - --static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) -+static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) - { - struct sk_buff *skb; - u32 offset; - -- skb_queue_walk(&sk->sk_receive_queue, skb) { -+ while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { - offset = seq - TCP_SKB_CB(skb)->seq; - if (tcp_hdr(skb)->syn) - offset--; -@@ -1440,6 +1440,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) - *off = offset; - return skb; - } -+ /* This looks weird, but this can happen if TCP collapsing -+ * splitted a fat GRO packet, while we released socket lock -+ * in skb_splice_bits() -+ */ -+ sk_eat_skb(sk, skb, false); - } - return NULL; - } -@@ -1519,8 +1524,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, - tcp_rcv_space_adjust(sk); - - /* Clean up data we have read: This will do ACK frames. */ -- if (copied > 0) -+ if (copied > 0) { -+ tcp_recv_skb(sk, seq, &offset); - tcp_cleanup_rbuf(sk, copied); -+ } - return copied; - } - EXPORT_SYMBOL(tcp_read_sock); --- -1.7.11.7 - - -From 6d0823b619aa6fc4280d61438626b7c6c9bb31ee Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sat, 5 Jan 2013 21:31:18 +0000 -Subject: [PATCH 43/44] net: splice: avoid high order page splitting - -[ Upstream commit 82bda6195615891181115f579a480aa5001ce7e9 ] - -splice() can handle pages of any order, but network code tries hard to -split them in PAGE_SIZE units. Not quite successfully anyway, as -__splice_segment() assumed poff < PAGE_SIZE. This is true for -the skb->data part, not necessarily for the fragments. - -This patch removes this logic to give the pages as they are in the skb. - -Signed-off-by: Eric Dumazet -Cc: Willy Tarreau -Signed-off-by: David S. Miller ---- - net/core/skbuff.c | 38 +++++++++----------------------------- - 1 file changed, 9 insertions(+), 29 deletions(-) - -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index 3f0636c..5b1b915 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -1677,20 +1677,6 @@ static bool spd_fill_page(struct splice_pipe_desc *spd, - return false; - } - --static inline void __segment_seek(struct page **page, unsigned int *poff, -- unsigned int *plen, unsigned int off) --{ -- unsigned long n; -- -- *poff += off; -- n = *poff / PAGE_SIZE; -- if (n) -- *page = nth_page(*page, n); -- -- *poff = *poff % PAGE_SIZE; -- *plen -= off; --} -- - static bool __splice_segment(struct page *page, unsigned int poff, - unsigned int plen, unsigned int *off, - unsigned int *len, struct sk_buff *skb, -@@ -1698,6 +1684,8 @@ static bool __splice_segment(struct page *page, unsigned int poff, - struct sock *sk, - struct pipe_inode_info *pipe) - { -+ unsigned int flen; -+ - if (!*len) - return true; - -@@ -1708,24 +1696,16 @@ static bool __splice_segment(struct page *page, unsigned int poff, - } - - /* ignore any bits we already processed */ -- if (*off) { -- __segment_seek(&page, &poff, &plen, *off); -- *off = 0; -- } -- -- do { -- unsigned int flen = min(*len, plen); -+ poff += *off; -+ plen -= *off; -+ *off = 0; - -- /* the linear region may spread across several pages */ -- flen = min_t(unsigned int, flen, PAGE_SIZE - poff); -+ flen = min(*len, plen); - -- if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) -- return true; -- -- __segment_seek(&page, &poff, &plen, flen); -- *len -= flen; -+ if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) -+ return true; - -- } while (*len && plen); -+ *len -= flen; - - return false; - } --- -1.7.11.7 - - -From 6a1308f7cb927c58898aed1fa44a0df8bf1d8e4c Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Fri, 11 Jan 2013 14:46:37 +0000 -Subject: [PATCH 44/44] net: splice: fix __splice_segment() - -[ Upstream commit bc9540c637c3d8712ccbf9dcf28621f380ed5e64 ] - -commit 9ca1b22d6d2 (net: splice: avoid high order page splitting) -forgot that skb->head could need a copy into several page frags. - -This could be the case for loopback traffic mostly. - -Also remove now useless skb argument from linear_to_page() -and __splice_segment() prototypes. - -Signed-off-by: Eric Dumazet -Cc: Willy Tarreau -Signed-off-by: David S. Miller ---- - net/core/skbuff.c | 28 +++++++++++++++------------- - 1 file changed, 15 insertions(+), 13 deletions(-) - -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index 5b1b915..1899d83 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -1620,7 +1620,7 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) - - static struct page *linear_to_page(struct page *page, unsigned int *len, - unsigned int *offset, -- struct sk_buff *skb, struct sock *sk) -+ struct sock *sk) - { - struct page_frag *pfrag = sk_page_frag(sk); - -@@ -1653,14 +1653,14 @@ static bool spd_can_coalesce(const struct splice_pipe_desc *spd, - static bool spd_fill_page(struct splice_pipe_desc *spd, - struct pipe_inode_info *pipe, struct page *page, - unsigned int *len, unsigned int offset, -- struct sk_buff *skb, bool linear, -+ bool linear, - struct sock *sk) - { - if (unlikely(spd->nr_pages == MAX_SKB_FRAGS)) - return true; - - if (linear) { -- page = linear_to_page(page, len, &offset, skb, sk); -+ page = linear_to_page(page, len, &offset, sk); - if (!page) - return true; - } -@@ -1679,13 +1679,11 @@ static bool spd_fill_page(struct splice_pipe_desc *spd, - - static bool __splice_segment(struct page *page, unsigned int poff, - unsigned int plen, unsigned int *off, -- unsigned int *len, struct sk_buff *skb, -+ unsigned int *len, - struct splice_pipe_desc *spd, bool linear, - struct sock *sk, - struct pipe_inode_info *pipe) - { -- unsigned int flen; -- - if (!*len) - return true; - -@@ -1700,12 +1698,16 @@ static bool __splice_segment(struct page *page, unsigned int poff, - plen -= *off; - *off = 0; - -- flen = min(*len, plen); -- -- if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) -- return true; -+ do { -+ unsigned int flen = min(*len, plen); - -- *len -= flen; -+ if (spd_fill_page(spd, pipe, page, &flen, poff, -+ linear, sk)) -+ return true; -+ poff += flen; -+ plen -= flen; -+ *len -= flen; -+ } while (*len && plen); - - return false; - } -@@ -1728,7 +1730,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, - if (__splice_segment(virt_to_page(skb->data), - (unsigned long) skb->data & (PAGE_SIZE - 1), - skb_headlen(skb), -- offset, len, skb, spd, -+ offset, len, spd, - skb_head_is_locked(skb), - sk, pipe)) - return true; -@@ -1741,7 +1743,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, - - if (__splice_segment(skb_frag_page(f), - f->page_offset, skb_frag_size(f), -- offset, len, skb, spd, false, sk, pipe)) -+ offset, len, spd, false, sk, pipe)) - return true; - } - --- -1.7.11.7 - diff --git a/sources b/sources index c686ded5b..59ee680ce 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -e232d2535bbd36fe05c203bacc5b72ea patch-3.7.7.xz +bf62e0cbc13524bb802d2ed05c7e2e6a patch-3.7.8.xz From ba9cd286943322d7380b78730f8e5ac2be75cd59 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 15 Feb 2013 08:00:59 -0500 Subject: [PATCH 183/492] CVE-2013-0290 net: infinite loop in __skb_recv_datagram (rhbz 911479 911473) --- kernel.spec | 11 +++- ...infinite-loop-in-__skb_recv_datagram.patch | 53 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 net-fix-infinite-loop-in-__skb_recv_datagram.patch diff --git a/kernel.spec b/kernel.spec index 12f40a835..92321303d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -791,6 +791,9 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 906309 910848 CVE-2013-0228 Patch21248: xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch +#rhbz 911479 911473 CVE-2013-0290 +Patch22256: net-fix-infinite-loop-in-__skb_recv_datagram.patch + Patch23000: silence-brcmsmac-warning.patch Patch23100: validate-pud-largepage.patch @@ -1530,6 +1533,9 @@ ApplyPatch xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch #rhbz 909591 ApplyPatch usb-cypress-supertop.patch +#rhbz 911479 911473 CVE-2013-0290 +ApplyPatch net-fix-infinite-loop-in-__skb_recv_datagram.patch + # END OF PATCH APPLICATIONS %endif @@ -2393,6 +2399,9 @@ fi # ||----w | # || || %changelog +* Fri Feb 15 2013 Josh Boyer +- CVE-2013-0290 net: infinite loop in __skb_recv_datagram (rhbz 911479 911473) + * Thu Feb 14 2013 Justin M. Forbes - 3.7.8-201 - Linux v3.7.8 diff --git a/net-fix-infinite-loop-in-__skb_recv_datagram.patch b/net-fix-infinite-loop-in-__skb_recv_datagram.patch new file mode 100644 index 000000000..a049bb46a --- /dev/null +++ b/net-fix-infinite-loop-in-__skb_recv_datagram.patch @@ -0,0 +1,53 @@ +From 77c1090f94d1b0b5186fb13a1b71b47b1343f87f Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 12 Feb 2013 06:16:53 +0000 +Subject: [PATCH] net: fix infinite loop in __skb_recv_datagram() + +Tommi was fuzzing with trinity and reported the following problem : + +commit 3f518bf745 (datagram: Add offset argument to __skb_recv_datagram) +missed that a raw socket receive queue can contain skbs with no payload. + +We can loop in __skb_recv_datagram() with MSG_PEEK mode, because +wait_for_packet() is not prepared to skip these skbs. + +[ 83.541011] INFO: rcu_sched detected stalls on CPUs/tasks: {} +(detected by 0, t=26002 jiffies, g=27673, c=27672, q=75) +[ 83.541011] INFO: Stall ended before state dump start +[ 108.067010] BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child31:2847] +... +[ 108.067010] Call Trace: +[ 108.067010] [] __skb_recv_datagram+0x1a3/0x3b0 +[ 108.067010] [] skb_recv_datagram+0x2d/0x30 +[ 108.067010] [] rawv6_recvmsg+0xad/0x240 +[ 108.067010] [] sock_common_recvmsg+0x34/0x50 +[ 108.067010] [] sock_recvmsg+0xbc/0xf0 +[ 108.067010] [] sys_recvfrom+0xde/0x150 +[ 108.067010] [] system_call_fastpath+0x16/0x1b + +Reported-by: Tommi Rantala +Tested-by: Tommi Rantala +Signed-off-by: Eric Dumazet +Cc: Pavel Emelyanov +Acked-by: Pavel Emelyanov +Signed-off-by: David S. Miller +--- + net/core/datagram.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/datagram.c b/net/core/datagram.c +index 0337e2b..368f9c3 100644 +--- a/net/core/datagram.c ++++ b/net/core/datagram.c +@@ -187,7 +187,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, + skb_queue_walk(queue, skb) { + *peeked = skb->peeked; + if (flags & MSG_PEEK) { +- if (*off >= skb->len) { ++ if (*off >= skb->len && skb->len) { + *off -= skb->len; + continue; + } +-- +1.8.1.2 + From 65a226a1b6acedcefe1459ada382800d3117a07c Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 18 Feb 2013 13:45:40 -0500 Subject: [PATCH 184/492] i915: Fix a mismerge in 3.7.y that leads to divide-by-zero in i915_update_wm --- kernel.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel.spec b/kernel.spec index 92321303d..47bb3eb35 100644 --- a/kernel.spec +++ b/kernel.spec @@ -711,6 +711,8 @@ Patch1825: drm-i915-dp-stfu.patch Patch1826: drm-i915-tv-detect-hush.patch # d-i-n backport for https://bugzilla.redhat.com/show_bug.cgi?id=901951 Patch1827: drm-i915-lvds-reclock-fix.patch +# Fix a mismerge in 3.7.y +Patch1828: drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch # Quiet boot fixes # silence the ACPI blacklist code @@ -1462,6 +1464,7 @@ ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-tv-detect-hush.patch ApplyPatch drm-i915-lvds-reclock-fix.patch +ApplyPatch drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -2399,6 +2402,9 @@ fi # ||----w | # || || %changelog +* Mon Feb 18 2013 Adam Jackson - CVE-2013-0290 net: infinite loop in __skb_recv_datagram (rhbz 911479 911473) From f82ba77f4554fc9cc49538dde9832be5ca90eb02 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 18 Feb 2013 13:45:51 -0500 Subject: [PATCH 185/492] Add drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch --- ...Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch diff --git a/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch b/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch new file mode 100644 index 000000000..bd232a5ad --- /dev/null +++ b/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch @@ -0,0 +1,28 @@ +From 3566b9ac5b4004af0e2b1c62c5ded1116b39d490 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Mon, 18 Feb 2013 13:40:16 -0500 +Subject: [PATCH] drm/i915: Fix up mismerge of 3490ea5d in 3.7.y + +The 3.7.y version of this seems to have missed a hunk in i9xx_update_wm. + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/i915/intel_pm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 4e6a2b2..313088f 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -1474,7 +1474,7 @@ static void i9xx_update_wm(struct drm_device *dev) + + fifo_size = dev_priv->display.get_fifo_size(dev, 0); + crtc = intel_get_crtc_for_plane(dev, 0); +- if (crtc->enabled && crtc->fb) { ++ if (intel_crtc_active(crtc)) { + planea_wm = intel_calculate_wm(crtc->mode.clock, + wm_info, fifo_size, + crtc->fb->bits_per_pixel / 8, +-- +1.8.1.2 + From d338b6bb72c587e66d765471391c708acb5a0404 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 18 Feb 2013 13:39:18 -0600 Subject: [PATCH 186/492] Linux v3.7.9 --- kernel.spec | 17 +-- sources | 2 +- validate-pud-largepage.patch | 102 -------------- ...-usable-in-xen_iret-for-32-bit-PVOPS.patch | 131 ------------------ 4 files changed, 6 insertions(+), 246 deletions(-) delete mode 100644 validate-pud-largepage.patch delete mode 100644 xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch diff --git a/kernel.spec b/kernel.spec index 47bb3eb35..d06b71c0f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -790,16 +790,11 @@ Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch -#rhbz 906309 910848 CVE-2013-0228 -Patch21248: xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch - #rhbz 911479 911473 CVE-2013-0290 Patch22256: net-fix-infinite-loop-in-__skb_recv_datagram.patch Patch23000: silence-brcmsmac-warning.patch -Patch23100: validate-pud-largepage.patch - #rhbz 909591 Patch21255: usb-cypress-supertop.patch @@ -1528,11 +1523,6 @@ ApplyPatch ath9k_rx_dma_stop_check.patch ApplyPatch silence-brcmsmac-warning.patch -ApplyPatch validate-pud-largepage.patch - -#rhbz 906309 910848 CVE-2013-0228 -ApplyPatch xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch - #rhbz 909591 ApplyPatch usb-cypress-supertop.patch @@ -2402,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Mon Feb 18 2013 Justin M. Forbes - 3.7.9-201 +- Linux v3.7.9 + * Mon Feb 18 2013 Adam Jackson -To: Ingo Molnar , Andrew Morton -Cc: Mel Gorman , linux-kernel@vger.kernel.org, linux-mm@kvack.org -Subject: [PATCH] x86: mm: Check if PUD is large when validating a kernel address -Message-ID: <20130211145236.GX21389@suse.de> -MIME-Version: 1.0 - -A user reported the following oops when a backup process read -/proc/kcore. - - BUG: unable to handle kernel paging request at ffffbb00ff33b000 - IP: [] kern_addr_valid+0xbe/0x110 - PGD 0 - Oops: 0000 [#1] SMP - CPU 6 - Modules linked in: af_packet nfs lockd fscache auth_rpcgss nfs_acl sunrpc 8021q garp stp llc cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf microcode fuse nls_iso8859_1 nls_cp437 vfat fat loop dm_mod ioatdma ipv6 ipv6_lib igb dca i7core_edac edac_core i2c_i801 i2c_core cdc_ether usbnet bnx2 mii iTCO_wdt iTCO_vendor_support shpchp rtc_cmos pci_hotplug tpm_tis sg tpm pcspkr tpm_bios serio_raw button ext3 jbd mbcache uhci_hcd ehci_hcd usbcore sd_mod crc_t10dif usb_common processor thermal_sys hwmon scsi_dh_emc scsi_dh_rdac scsi_dh_alua scsi_dh_hp_sw scsi_dh ata_generic ata_piix libata megaraid_sas scsi_mod - - Pid: 16196, comm: Hibackp Not tainted 3.0.13-0.27-default #1 IBM System x3550 M3 -[7944 K3G]-/94Y7614 - RIP: 0010:[] [] kern_addr_valid+0xbe/0x110 - RSP: 0018:ffff88094165fe80 EFLAGS: 00010246 - RAX: 00003300ff33b000 RBX: ffff880100000000 RCX: 0000000000000000 - RDX: 0000000100000000 RSI: ffff880000000000 RDI: ff32b300ff33b400 - RBP: 0000000000001000 R08: 00003ffffffff000 R09: 0000000000000000 - R10: 22302e31223d6e6f R11: 0000000000000246 R12: 0000000000001000 - R13: 0000000000003000 R14: 0000000000571be0 R15: ffff88094165ff50 - FS: 00007ff152d33700(0000) GS:ffff88097f2c0000(0000) knlGS:0000000000000000 - CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b - CR2: ffffbb00ff33b000 CR3: 00000009405a3000 CR4: 00000000000006e0 - DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 - DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 - Process Hibackp (pid: 16196, threadinfo ffff88094165e000, task ffff8808eb9ba600) - Stack: - ffffffff811b8aaa 0000000000004000 ffff880943fea480 ffff8808ef2bae50 - ffff880943d32980 fffffffffffffffb ffff8808ef2bae40 ffff88094165ff50 - 0000000000004000 000000000056ebe0 ffffffff811ad847 000000000056ebe0 - Call Trace: - [] read_kcore+0x17a/0x370 - [] proc_reg_read+0x77/0xc0 - [] vfs_read+0xc7/0x130 - [] sys_read+0x53/0xa0 - [] system_call_fastpath+0x16/0x1b - -Investigation determined that the bug triggered when reading system RAM -at the 4G mark. On this system, that was the first address using 1G pages -for the virt->phys direct mapping so the PUD is pointing to a physical -address, not a PMD page. The problem is that the page table walker in -kern_addr_valid() is not checking pud_large() and treats the physical -address as if it was a PMD. If it happens to look like pmd_none then it'll -silently fail, probably returning zeros instead of real data. If the data -happens to look like a present PMD though, it will be walked resulting in -the oops above. This patch adds the necessary pud_large() check. - -Unfortunately the problem was not readily reproducible and now they are -running the backup program without accessing /proc/kcore so the patch has -not been validated but I think it makes sense. If reviewers agree then it -should also be included in -stable back as far as 3.0-stable. - -Cc: stable@vger.kernel.org -Signed-off-by: Mel Gorman ---- - arch/x86/include/asm/pgtable.h | 5 +++++ - arch/x86/mm/init_64.c | 3 +++ - 2 files changed, 8 insertions(+) - -diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h -index 5199db2..1c1a955 100644 ---- a/arch/x86/include/asm/pgtable.h -+++ b/arch/x86/include/asm/pgtable.h -@@ -142,6 +142,11 @@ static inline unsigned long pmd_pfn(pmd_t pmd) - return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; - } - -+static inline unsigned long pud_pfn(pud_t pud) -+{ -+ return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT; -+} -+ - #define pte_page(pte) pfn_to_page(pte_pfn(pte)) - - static inline int pmd_large(pmd_t pte) -diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c -index 2ead3c8..75c9a6a 100644 ---- a/arch/x86/mm/init_64.c -+++ b/arch/x86/mm/init_64.c -@@ -831,6 +831,9 @@ int kern_addr_valid(unsigned long addr) - if (pud_none(*pud)) - return 0; - -+ if (pud_large(*pud)) -+ return pfn_valid(pud_pfn(*pud)); -+ - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return 0; - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Don't email: email@kvack.org - diff --git a/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch b/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch deleted file mode 100644 index d3b2b5602..000000000 --- a/xen-dont-assume-ds-is-usable-in-xen_iret-for-32-bit-PVOPS.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 13d2b4d11d69a92574a55bfd985cfb0ca77aebdc Mon Sep 17 00:00:00 2001 -From: Jan Beulich -Date: Thu, 24 Jan 2013 13:11:10 +0000 -Subject: [PATCH] x86/xen: don't assume %ds is usable in xen_iret for 32-bit - PVOPS. - -This fixes CVE-2013-0228 / XSA-42 - -Drew Jones while working on CVE-2013-0190 found that that unprivileged guest user -in 32bit PV guest can use to crash the > guest with the panic like this: - -------------- -general protection fault: 0000 [#1] SMP -last sysfs file: /sys/devices/vbd-51712/block/xvda/dev -Modules linked in: sunrpc ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 -iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 -xt_state nf_conntrack ip6table_filter ip6_tables ipv6 xen_netfront ext4 -mbcache jbd2 xen_blkfront dm_mirror dm_region_hash dm_log dm_mod [last -unloaded: scsi_wait_scan] - -Pid: 1250, comm: r Not tainted 2.6.32-356.el6.i686 #1 -EIP: 0061:[] EFLAGS: 00010086 CPU: 0 -EIP is at xen_iret+0x12/0x2b -EAX: eb8d0000 EBX: 00000001 ECX: 08049860 EDX: 00000010 -ESI: 00000000 EDI: 003d0f00 EBP: b77f8388 ESP: eb8d1fe0 - DS: 0000 ES: 007b FS: 0000 GS: 00e0 SS: 0069 -Process r (pid: 1250, ti=eb8d0000 task=c2953550 task.ti=eb8d0000) -Stack: - 00000000 0027f416 00000073 00000206 b77f8364 0000007b 00000000 00000000 -Call Trace: -Code: c3 8b 44 24 18 81 4c 24 38 00 02 00 00 8d 64 24 30 e9 03 00 00 00 -8d 76 00 f7 44 24 08 00 00 02 80 75 33 50 b8 00 e0 ff ff 21 e0 <8b> 40 -10 8b 04 85 a0 f6 ab c0 8b 80 0c b0 b3 c0 f6 44 24 0d 02 -EIP: [] xen_iret+0x12/0x2b SS:ESP 0069:eb8d1fe0 -general protection fault: 0000 [#2] ----[ end trace ab0d29a492dcd330 ]--- -Kernel panic - not syncing: Fatal exception -Pid: 1250, comm: r Tainted: G D --------------- -2.6.32-356.el6.i686 #1 -Call Trace: - [] ? panic+0x6e/0x122 - [] ? oops_end+0xbc/0xd0 - [] ? do_general_protection+0x0/0x210 - [] ? error_code+0x73/ -------------- - -Petr says: " - I've analysed the bug and I think that xen_iret() cannot cope with - mangled DS, in this case zeroed out (null selector/descriptor) by either - xen_failsafe_callback() or RESTORE_REGS because the corresponding LDT - entry was invalidated by the reproducer. " - -Jan took a look at the preliminary patch and came up a fix that solves -this problem: - -"This code gets called after all registers other than those handled by -IRET got already restored, hence a null selector in %ds or a non-null -one that got loaded from a code or read-only data descriptor would -cause a kernel mode fault (with the potential of crashing the kernel -as a whole, if panic_on_oops is set)." - -The way to fix this is to realize that the we can only relay on the -registers that IRET restores. The two that are guaranteed are the -%cs and %ss as they are always fixed GDT selectors. Also they are -inaccessible from user mode - so they cannot be altered. This is -the approach taken in this patch. - -Another alternative option suggested by Jan would be to relay on -the subtle realization that using the %ebp or %esp relative references uses -the %ss segment. In which case we could switch from using %eax to %ebp and -would not need the %ss over-rides. That would also require one extra -instruction to compensate for the one place where the register is used -as scaled index. However Andrew pointed out that is too subtle and if -further work was to be done in this code-path it could escape folks attention -and lead to accidents. - -Reviewed-by: Petr Matousek -Reported-by: Petr Matousek -Reviewed-by: Andrew Cooper -Signed-off-by: Jan Beulich -Signed-off-by: Konrad Rzeszutek Wilk ---- - arch/x86/xen/xen-asm_32.S | 14 +++++++------- - 1 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S -index f9643fc..33ca6e4 100644 ---- a/arch/x86/xen/xen-asm_32.S -+++ b/arch/x86/xen/xen-asm_32.S -@@ -89,11 +89,11 @@ ENTRY(xen_iret) - */ - #ifdef CONFIG_SMP - GET_THREAD_INFO(%eax) -- movl TI_cpu(%eax), %eax -- movl __per_cpu_offset(,%eax,4), %eax -- mov xen_vcpu(%eax), %eax -+ movl %ss:TI_cpu(%eax), %eax -+ movl %ss:__per_cpu_offset(,%eax,4), %eax -+ mov %ss:xen_vcpu(%eax), %eax - #else -- movl xen_vcpu, %eax -+ movl %ss:xen_vcpu, %eax - #endif - - /* check IF state we're restoring */ -@@ -106,11 +106,11 @@ ENTRY(xen_iret) - * resuming the code, so we don't have to be worried about - * being preempted to another CPU. - */ -- setz XEN_vcpu_info_mask(%eax) -+ setz %ss:XEN_vcpu_info_mask(%eax) - xen_iret_start_crit: - - /* check for unmasked and pending */ -- cmpw $0x0001, XEN_vcpu_info_pending(%eax) -+ cmpw $0x0001, %ss:XEN_vcpu_info_pending(%eax) - - /* - * If there's something pending, mask events again so we can -@@ -118,7 +118,7 @@ xen_iret_start_crit: - * touch XEN_vcpu_info_mask. - */ - jne 1f -- movb $1, XEN_vcpu_info_mask(%eax) -+ movb $1, %ss:XEN_vcpu_info_mask(%eax) - - 1: popl %eax - --- -1.7.7.6 - From 011d7ca774c718bc4b0b0b0a83d869bda12d7cb5 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 19 Feb 2013 14:25:22 +0000 Subject: [PATCH 187/492] Fix OMAP thermal driver by building it in (seems it doesn't auto load when a module) --- config-arm-omap | 3 ++- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-arm-omap b/config-arm-omap index 68421b06e..9bf447708 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -143,6 +143,8 @@ CONFIG_PM_SLEEP_SMP=y CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y +# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES +CONFIG_OMAP_BANDGAP=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y @@ -312,7 +314,6 @@ CONFIG_IR_RX51=m # CONFIG_TIDSPBRIDGE_BACKTRACE is not set # CONFIG_OMAP_REMOTEPROC is not set -# CONFIG_OMAP_BANDGAP is not set # CONFIG_OMAP_IOVMM is not set CONFIG_CRYPTO_DEV_OMAP_SHAM=m diff --git a/kernel.spec b/kernel.spec index d06b71c0f..6f7895433 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2392,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 19 2013 Peter Robinson +- Fix OMAP thermal driver by building it in (seems it doesn't auto load when a module) + * Mon Feb 18 2013 Justin M. Forbes - 3.7.9-201 - Linux v3.7.9 From 3cecb56a14791c80003d3711dec5baada472cc12 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 19 Feb 2013 11:19:00 -0500 Subject: [PATCH 188/492] Backport support for newer ALPS touchpads (rhbz 812111) --- alps-v2-3.7.patch | 2494 +++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 2504 insertions(+), 1 deletion(-) create mode 100644 alps-v2-3.7.patch diff --git a/alps-v2-3.7.patch b/alps-v2-3.7.patch new file mode 100644 index 000000000..262cd0d92 --- /dev/null +++ b/alps-v2-3.7.patch @@ -0,0 +1,2494 @@ +From 2c5e103a6d0a2a0c74cd8b299d58c4ca07911aad Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:55:19 -0800 +Subject: [PATCH 01/15] Input: ALPS - document the alps.h data structures + +Add kernel-doc markup. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.h | 74 ++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 61 insertions(+), 13 deletions(-) + +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index ae1ac35..67be4e5 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -17,30 +17,78 @@ + #define ALPS_PROTO_V3 2 + #define ALPS_PROTO_V4 3 + ++/** ++ * struct alps_model_info - touchpad ID table ++ * @signature: E7 response string to match. ++ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response ++ * (aka command mode response) identifies the firmware minor version. This ++ * can be used to distinguish different hardware models which are not ++ * uniquely identifiable through their E7 responses. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * ++ * Many (but not all) ALPS touchpads can be identified by looking at the ++ * values returned in the "E7 report" and/or the "EC report." This table ++ * lists a number of such touchpads. ++ */ + struct alps_model_info { +- unsigned char signature[3]; +- unsigned char command_mode_resp; /* v3/v4 only */ ++ unsigned char signature[3]; ++ unsigned char command_mode_resp; + unsigned char proto_version; +- unsigned char byte0, mask0; +- unsigned char flags; ++ unsigned char byte0, mask0; ++ unsigned char flags; + }; + ++/** ++ * struct alps_nibble_commands - encodings for register accesses ++ * @command: PS/2 command used for the nibble ++ * @data: Data supplied as an argument to the PS/2 command, if applicable ++ * ++ * The ALPS protocol uses magic sequences to transmit binary data to the ++ * touchpad, as it is generally not OK to send arbitrary bytes out the ++ * PS/2 port. Each of the sequences in this table sends one nibble of the ++ * register address or (write) data. Different versions of the ALPS protocol ++ * use slightly different encodings. ++ */ + struct alps_nibble_commands { + int command; + unsigned char data; + }; + ++/** ++ * struct alps_data - private data structure for the ALPS driver ++ * @dev2: "Relative" device used to report trackstick or mouse activity. ++ * @phys: Physical path for the relative device. ++ * @i: Information on the detected touchpad model. ++ * @nibble_commands: Command mapping used for touchpad register accesses. ++ * @addr_command: Command used to tell the touchpad that a register address ++ * follows. ++ * @prev_fin: Finger bit from previous packet. ++ * @multi_packet: Multi-packet data in progress. ++ * @multi_data: Saved multi-packet data. ++ * @x1: First X coordinate from last MT report. ++ * @x2: Second X coordinate from last MT report. ++ * @y1: First Y coordinate from last MT report. ++ * @y2: Second Y coordinate from last MT report. ++ * @fingers: Number of fingers from last MT report. ++ * @quirks: Bitmap of ALPS_QUIRK_*. ++ * @timer: Timer for flushing out the final report packet in the stream. ++ */ + struct alps_data { +- struct input_dev *dev2; /* Relative device */ +- char phys[32]; /* Phys */ +- const struct alps_model_info *i;/* Info */ ++ struct input_dev *dev2; ++ char phys[32]; ++ const struct alps_model_info *i; + const struct alps_nibble_commands *nibble_commands; +- int addr_command; /* Command to set register address */ +- int prev_fin; /* Finger bit from previous packet */ +- int multi_packet; /* Multi-packet data in progress */ +- unsigned char multi_data[6]; /* Saved multi-packet data */ +- int x1, x2, y1, y2; /* Coordinates from last MT report */ +- int fingers; /* Number of fingers from MT report */ ++ int addr_command; ++ int prev_fin; ++ int multi_packet; ++ unsigned char multi_data[6]; ++ int x1, x2, y1, y2; ++ int fingers; + u8 quirks; + struct timer_list timer; + }; +-- +1.8.1.2 + + +From 80378616e681afdc14b236c99a77c1296f0b8031 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:56:33 -0800 +Subject: [PATCH 02/15] Input: ALPS - copy "model" info into alps_data struct + +Not every type of ALPS touchpad is well-suited to table-based detection. +Start moving the various alps_model_data attributes into the alps_data +struct so that we don't need a unique table entry for every possible +permutation of protocol version, flags, byte0/mask0, etc. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 63 +++++++++++++++++++++++----------------------- + drivers/input/mouse/alps.h | 14 +++++++++-- + 2 files changed, 43 insertions(+), 34 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index cf5af1f..9664e94 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -122,10 +122,10 @@ static const struct alps_model_info alps_model_data[] = { + + /* Packet formats are described in Documentation/input/alps.txt */ + +-static bool alps_is_valid_first_byte(const struct alps_model_info *model, ++static bool alps_is_valid_first_byte(struct alps_data *priv, + unsigned char data) + { +- return (data & model->mask0) == model->byte0; ++ return (data & priv->mask0) == priv->byte0; + } + + static void alps_report_buttons(struct psmouse *psmouse, +@@ -158,14 +158,13 @@ static void alps_report_buttons(struct psmouse *psmouse, + static void alps_process_packet_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + struct input_dev *dev2 = priv->dev2; + int x, y, z, ges, fin, left, right, middle; + int back = 0, forward = 0; + +- if (model->proto_version == ALPS_PROTO_V1) { ++ if (priv->proto_version == ALPS_PROTO_V1) { + left = packet[2] & 0x10; + right = packet[2] & 0x08; + middle = 0; +@@ -181,12 +180,12 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + z = packet[5]; + } + +- if (model->flags & ALPS_FW_BK_1) { ++ if (priv->flags & ALPS_FW_BK_1) { + back = packet[0] & 0x10; + forward = packet[2] & 4; + } + +- if (model->flags & ALPS_FW_BK_2) { ++ if (priv->flags & ALPS_FW_BK_2) { + back = packet[3] & 4; + forward = packet[2] & 4; + if ((middle = forward && back)) +@@ -196,7 +195,7 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + ges = packet[2] & 1; + fin = packet[2] & 2; + +- if ((model->flags & ALPS_DUALPOINT) && z == 127) { ++ if ((priv->flags & ALPS_DUALPOINT) && z == 127) { + input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); + input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); + +@@ -239,15 +238,15 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + input_report_abs(dev, ABS_PRESSURE, z); + input_report_key(dev, BTN_TOOL_FINGER, z > 0); + +- if (model->flags & ALPS_WHEEL) ++ if (priv->flags & ALPS_WHEEL) + input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); + +- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { ++ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + input_report_key(dev, BTN_FORWARD, forward); + input_report_key(dev, BTN_BACK, back); + } + +- if (model->flags & ALPS_FOUR_BUTTONS) { ++ if (priv->flags & ALPS_FOUR_BUTTONS) { + input_report_key(dev, BTN_0, packet[2] & 4); + input_report_key(dev, BTN_1, packet[0] & 0x10); + input_report_key(dev, BTN_2, packet[3] & 4); +@@ -699,9 +698,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + static void alps_process_packet(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + alps_process_packet_v1_v2(psmouse); +@@ -765,7 +763,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + if (((psmouse->packet[3] | + psmouse->packet[4] | + psmouse->packet[5]) & 0x80) || +- (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { ++ (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { + psmouse_dbg(psmouse, + "refusing packet %x %x %x %x (suspected interleaved ps/2)\n", + psmouse->packet[3], psmouse->packet[4], +@@ -846,7 +844,6 @@ static void alps_flush_packet(unsigned long data) + static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + + if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ + if (psmouse->pktcnt == 3) { +@@ -859,15 +856,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + + /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ + +- if ((model->flags & ALPS_PS2_INTERLEAVED) && ++ if ((priv->flags & ALPS_PS2_INTERLEAVED) && + psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { + return alps_handle_interleaved_ps2(psmouse); + } + +- if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { ++ if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) { + psmouse_dbg(psmouse, + "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", +- psmouse->packet[0], model->mask0, model->byte0); ++ psmouse->packet[0], priv->mask0, priv->byte0); + return PSMOUSE_BAD_DATA; + } + +@@ -1192,16 +1189,16 @@ static int alps_poll(struct psmouse *psmouse) + unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; + +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, true); + + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; + +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, false); + +- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) ++ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) + return -1; + + if ((psmouse->badbyte & 0xc8) == 0x08) { +@@ -1219,9 +1216,8 @@ static int alps_poll(struct psmouse *psmouse) + static int alps_hw_init_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } +@@ -1236,7 +1232,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) + return -1; + } + +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, false)) { + return -1; + } +@@ -1522,10 +1518,9 @@ error: + static int alps_hw_init(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + int ret = -1; + +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + ret = alps_hw_init_v1_v2(psmouse); +@@ -1587,7 +1582,10 @@ int alps_init(struct psmouse *psmouse) + if (!model) + goto init_fail; + +- priv->i = model; ++ priv->proto_version = model->proto_version; ++ priv->byte0 = model->byte0; ++ priv->mask0 = model->mask0; ++ priv->flags = model->flags; + + if (alps_hw_init(psmouse)) + goto init_fail; +@@ -1611,7 +1609,7 @@ int alps_init(struct psmouse *psmouse) + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); + +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +@@ -1635,17 +1633,17 @@ int alps_init(struct psmouse *psmouse) + + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + +- if (model->flags & ALPS_WHEEL) { ++ if (priv->flags & ALPS_WHEEL) { + dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); + dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); + } + +- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { ++ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); + dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); + } + +- if (model->flags & ALPS_FOUR_BUTTONS) { ++ if (priv->flags & ALPS_FOUR_BUTTONS) { + dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); + dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); + dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); +@@ -1656,7 +1654,8 @@ int alps_init(struct psmouse *psmouse) + + snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); + dev2->phys = priv->phys; +- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; ++ dev2->name = (priv->flags & ALPS_DUALPOINT) ? ++ "DualPoint Stick" : "PS/2 Mouse"; + dev2->id.bustype = BUS_I8042; + dev2->id.vendor = 0x0002; + dev2->id.product = PSMOUSE_ALPS; +@@ -1675,7 +1674,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; ++ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 67be4e5..efd0eea 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -63,10 +63,15 @@ struct alps_nibble_commands { + * struct alps_data - private data structure for the ALPS driver + * @dev2: "Relative" device used to report trackstick or mouse activity. + * @phys: Physical path for the relative device. +- * @i: Information on the detected touchpad model. + * @nibble_commands: Command mapping used for touchpad register accesses. + * @addr_command: Command used to tell the touchpad that a register address + * follows. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. + * @multi_data: Saved multi-packet data. +@@ -81,9 +86,14 @@ struct alps_nibble_commands { + struct alps_data { + struct input_dev *dev2; + char phys[32]; +- const struct alps_model_info *i; ++ ++ /* these are autodetected when the device is identified */ + const struct alps_nibble_commands *nibble_commands; + int addr_command; ++ unsigned char proto_version; ++ unsigned char byte0, mask0; ++ unsigned char flags; ++ + int prev_fin; + int multi_packet; + unsigned char multi_data[6]; +-- +1.8.1.2 + + +From 7b9d630645b501a484e498461259167858d331e6 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:57:04 -0800 +Subject: [PATCH 03/15] Input: ALPS - move alps_get_model() down below hw_init + code + +This will minimize the number of forward declarations needed when +alps_get_model() starts assigning function pointers. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 186 ++++++++++++++++++++++----------------------- + 1 file changed, 93 insertions(+), 93 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 9664e94..3c15fd3 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1000,99 +1000,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) + return 0; + } + +-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) +-{ +- struct ps2dev *ps2dev = &psmouse->ps2dev; +- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; +- unsigned char param[4]; +- const struct alps_model_info *model = NULL; +- int i; +- +- /* +- * First try "E6 report". +- * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. +- * The bits 0-2 of the first byte will be 1s if some buttons are +- * pressed. +- */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) +- return NULL; +- +- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- +- if ((param[0] & 0xf8) != 0 || param[1] != 0 || +- (param[2] != 10 && param[2] != 100)) +- return NULL; +- +- /* +- * Now try "E7 report". Allowed responses are in +- * alps_model_data[].signature +- */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) +- return NULL; +- +- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- +- if (version) { +- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) +- /* empty */; +- *version = (param[0] << 8) | (param[1] << 4) | i; +- } +- +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) { +- model = alps_model_data + i; +- break; +- } +- } +- +- if (model && model->proto_version > ALPS_PROTO_V2) { +- /* +- * Need to check command mode response to identify +- * model +- */ +- model = NULL; +- if (alps_enter_command_mode(psmouse, param)) { +- psmouse_warn(psmouse, +- "touchpad failed to enter command mode\n"); +- } else { +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && +- alps_model_data[i].command_mode_resp == param[0]) { +- model = alps_model_data + i; +- break; +- } +- } +- alps_exit_command_mode(psmouse); +- +- if (!model) +- psmouse_dbg(psmouse, +- "Unknown command mode response %2.2x\n", +- param[0]); +- } +- } +- +- return model; +-} +- + /* + * For DualPoint devices select the device that should respond to + * subsequent commands. It looks like glidepad is behind stickpointer, +@@ -1536,6 +1443,99 @@ static int alps_hw_init(struct psmouse *psmouse) + return ret; + } + ++static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; ++ unsigned char param[4]; ++ const struct alps_model_info *model = NULL; ++ int i; ++ ++ /* ++ * First try "E6 report". ++ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. ++ * The bits 0-2 of the first byte will be 1s if some buttons are ++ * pressed. ++ */ ++ param[0] = 0; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) ++ return NULL; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return NULL; ++ ++ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", ++ param[0], param[1], param[2]); ++ ++ if ((param[0] & 0xf8) != 0 || param[1] != 0 || ++ (param[2] != 10 && param[2] != 100)) ++ return NULL; ++ ++ /* ++ * Now try "E7 report". Allowed responses are in ++ * alps_model_data[].signature ++ */ ++ param[0] = 0; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) ++ return NULL; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return NULL; ++ ++ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", ++ param[0], param[1], param[2]); ++ ++ if (version) { ++ for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) ++ /* empty */; ++ *version = (param[0] << 8) | (param[1] << 4) | i; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (!memcmp(param, alps_model_data[i].signature, ++ sizeof(alps_model_data[i].signature))) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ ++ if (model && model->proto_version > ALPS_PROTO_V2) { ++ /* ++ * Need to check command mode response to identify ++ * model ++ */ ++ model = NULL; ++ if (alps_enter_command_mode(psmouse, param)) { ++ psmouse_warn(psmouse, ++ "touchpad failed to enter command mode\n"); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && ++ alps_model_data[i].command_mode_resp == param[0]) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ alps_exit_command_mode(psmouse); ++ ++ if (!model) ++ psmouse_dbg(psmouse, ++ "Unknown command mode response %2.2x\n", ++ param[0]); ++ } ++ } ++ ++ return model; ++} ++ + static int alps_reconnect(struct psmouse *psmouse) + { + const struct alps_model_info *model; +-- +1.8.1.2 + + +From 59f721fed5e707eeae2d084dff0963f0cb02901a Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:19:01 -0800 +Subject: [PATCH 04/15] Input: ALPS - introduce helper function for repeated + commands + +Several ALPS driver init sequences repeat a command three times, then +issue PSMOUSE_CMD_GETINFO to read the result. Move this into a helper +function to simplify the code. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 71 ++++++++++++++++++++-------------------------- + 1 file changed, 30 insertions(+), 41 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 3c15fd3..c03ce3f 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -966,24 +966,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, + return __alps_command_mode_write_reg(psmouse, value); + } + ++static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, ++ int repeated_command, unsigned char *param) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ param[0] = 0; ++ if (init_command && ps2_command(ps2dev, param, init_command)) ++ return -EIO; ++ ++ if (ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command)) ++ return -EIO; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -EIO; ++ ++ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", ++ repeated_command, param[0], param[1], param[2]); ++ return 0; ++} ++ + static int alps_enter_command_mode(struct psmouse *psmouse, + unsigned char *resp) + { + unsigned char param[4]; +- struct ps2dev *ps2dev = &psmouse->ps2dev; + +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { + psmouse_err(psmouse, "failed to enter command mode\n"); + return -1; + } + + if (param[0] != 0x88 && param[1] != 0x07) { + psmouse_dbg(psmouse, +- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", +- param[0], param[1], param[2]); ++ "unknown response while entering command mode\n"); + return -1; + } + +@@ -1043,18 +1061,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) + + static int alps_get_status(struct psmouse *psmouse, char *param) + { +- struct ps2dev *ps2dev = &psmouse->ps2dev; +- + /* Get status: 0xF5 0xF5 0xF5 0xE9 */ +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || +- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param)) + return -1; + +- psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- + return 0; + } + +@@ -1445,7 +1455,6 @@ static int alps_hw_init(struct psmouse *psmouse) + + static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) + { +- struct ps2dev *ps2dev = &psmouse->ps2dev; + static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; + unsigned char param[4]; + const struct alps_model_info *model = NULL; +@@ -1457,20 +1466,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * The bits 0-2 of the first byte will be 1s if some buttons are + * pressed. + */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, ++ param)) + return NULL; + +- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- + if ((param[0] & 0xf8) != 0 || param[1] != 0 || + (param[2] != 10 && param[2] != 100)) + return NULL; +@@ -1479,20 +1478,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * Now try "E7 report". Allowed responses are in + * alps_model_data[].signature + */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, ++ param)) + return NULL; + +- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- + if (version) { + for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) + /* empty */; +-- +1.8.1.2 + + +From b07564337687bf94d1872b0bb0d072e56434d821 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:19:59 -0800 +Subject: [PATCH 05/15] Input: ALPS - rework detection sequence + +If the E6 report test passes, get the E7 and EC reports right away and +then try to match an entry in the table. + +Pass in the alps_data struct, so that the detection code will be able to +set operating parameters based on information found during detection. + +Change the version (psmouse->model) to report the protocol version only, +in preparation for supporting models that do not show up in the ID table. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 124 +++++++++++++++++++-------------------------- + drivers/input/mouse/alps.h | 8 +-- + 2 files changed, 56 insertions(+), 76 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index c03ce3f..c11b47e 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1453,86 +1453,76 @@ static int alps_hw_init(struct psmouse *psmouse) + return ret; + } + +-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) ++static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, ++ unsigned char *e7, unsigned char *ec) + { +- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; +- unsigned char param[4]; +- const struct alps_model_info *model = NULL; ++ const struct alps_model_info *model; + int i; + ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ model = &alps_model_data[i]; ++ ++ if (!memcmp(e7, model->signature, sizeof(model->signature)) && ++ (!model->command_mode_resp || ++ model->command_mode_resp == ec[2])) { ++ ++ priv->proto_version = model->proto_version; ++ priv->flags = model->flags; ++ priv->byte0 = model->byte0; ++ priv->mask0 = model->mask0; ++ ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ++{ ++ unsigned char e6[4], e7[4], ec[4]; ++ + /* + * First try "E6 report". + * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. + * The bits 0-2 of the first byte will be 1s if some buttons are + * pressed. + */ +- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, +- param)) +- return NULL; ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE11, e6)) ++ return -EIO; + +- if ((param[0] & 0xf8) != 0 || param[1] != 0 || +- (param[2] != 10 && param[2] != 100)) +- return NULL; ++ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) ++ return -EINVAL; + + /* +- * Now try "E7 report". Allowed responses are in +- * alps_model_data[].signature ++ * Now get the "E7" and "EC" reports. These will uniquely identify ++ * most ALPS touchpads. + */ +- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, +- param)) +- return NULL; +- +- if (version) { +- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) +- /* empty */; +- *version = (param[0] << 8) | (param[1] << 4) | i; +- } +- +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) { +- model = alps_model_data + i; +- break; +- } +- } ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE21, e7) || ++ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_RESET_WRAP, ec) || ++ alps_exit_command_mode(psmouse)) ++ return -EIO; + +- if (model && model->proto_version > ALPS_PROTO_V2) { +- /* +- * Need to check command mode response to identify +- * model +- */ +- model = NULL; +- if (alps_enter_command_mode(psmouse, param)) { +- psmouse_warn(psmouse, +- "touchpad failed to enter command mode\n"); +- } else { +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && +- alps_model_data[i].command_mode_resp == param[0]) { +- model = alps_model_data + i; +- break; +- } +- } +- alps_exit_command_mode(psmouse); ++ if (alps_match_table(psmouse, priv, e7, ec) == 0) ++ return 0; + +- if (!model) +- psmouse_dbg(psmouse, +- "Unknown command mode response %2.2x\n", +- param[0]); +- } +- } ++ psmouse_info(psmouse, ++ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", ++ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); + +- return model; ++ return -EINVAL; + } + + static int alps_reconnect(struct psmouse *psmouse) + { +- const struct alps_model_info *model; ++ struct alps_data *priv = psmouse->private; + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, NULL); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) + return -1; + + return alps_hw_init(psmouse); +@@ -1551,9 +1541,7 @@ static void alps_disconnect(struct psmouse *psmouse) + int alps_init(struct psmouse *psmouse) + { + struct alps_data *priv; +- const struct alps_model_info *model; + struct input_dev *dev1 = psmouse->dev, *dev2; +- int version; + + priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + dev2 = input_allocate_device(); +@@ -1567,15 +1555,9 @@ int alps_init(struct psmouse *psmouse) + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) + goto init_fail; + +- priv->proto_version = model->proto_version; +- priv->byte0 = model->byte0; +- priv->mask0 = model->mask0; +- priv->flags = model->flags; +- + if (alps_hw_init(psmouse)) + goto init_fail; + +@@ -1680,18 +1662,16 @@ init_fail: + + int alps_detect(struct psmouse *psmouse, bool set_properties) + { +- int version; +- const struct alps_model_info *model; ++ struct alps_data dummy; + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, &dummy) < 0) + return -1; + + if (set_properties) { + psmouse->vendor = "ALPS"; +- psmouse->name = model->flags & ALPS_DUALPOINT ? ++ psmouse->name = dummy.flags & ALPS_DUALPOINT ? + "DualPoint TouchPad" : "GlidePoint"; +- psmouse->model = version; ++ psmouse->model = dummy.proto_version << 8; + } + return 0; + } +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index efd0eea..a81b318 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -12,10 +12,10 @@ + #ifndef _ALPS_H + #define _ALPS_H + +-#define ALPS_PROTO_V1 0 +-#define ALPS_PROTO_V2 1 +-#define ALPS_PROTO_V3 2 +-#define ALPS_PROTO_V4 3 ++#define ALPS_PROTO_V1 1 ++#define ALPS_PROTO_V2 2 ++#define ALPS_PROTO_V3 3 ++#define ALPS_PROTO_V4 4 + + /** + * struct alps_model_info - touchpad ID table +-- +1.8.1.2 + + +From 3291afbdc14314b4eb4b97efc9017a26f00bb143 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:22:08 -0800 +Subject: [PATCH 06/15] Input: ALPS - use function pointers for different + protocol handlers + +In anticipation of adding more ALPS protocols and more per-device quirks, +use function pointers instead of switch statements to call functions that +differ from one device to the next. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 101 +++++++++++++++++++++------------------------ + drivers/input/mouse/alps.h | 7 ++++ + 2 files changed, 54 insertions(+), 54 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index c11b47e..3cca3ef 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -114,6 +114,11 @@ static const struct alps_model_info alps_model_data[] = { + { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1); ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1); ++ + /* + * XXX - this entry is suspicious. First byte has zero lower nibble, + * which is what a normal mouse would report. Also, the value 0x0e +@@ -695,24 +700,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + input_sync(dev); + } + +-static void alps_process_packet(struct psmouse *psmouse) +-{ +- struct alps_data *priv = psmouse->private; +- +- switch (priv->proto_version) { +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- alps_process_packet_v1_v2(psmouse); +- break; +- case ALPS_PROTO_V3: +- alps_process_packet_v3(psmouse); +- break; +- case ALPS_PROTO_V4: +- alps_process_packet_v4(psmouse); +- break; +- } +-} +- + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -771,7 +758,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + + /* Continue with the next packet */ + psmouse->packet[0] = psmouse->packet[6]; +@@ -815,6 +802,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + static void alps_flush_packet(unsigned long data) + { + struct psmouse *psmouse = (struct psmouse *)data; ++ struct alps_data *priv = psmouse->private; + + serio_pause_rx(psmouse->ps2dev.serio); + +@@ -833,7 +821,7 @@ static void alps_flush_packet(unsigned long data) + psmouse->packet[3], psmouse->packet[4], + psmouse->packet[5]); + } else { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + } + psmouse->pktcnt = 0; + } +@@ -878,7 +866,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + if (psmouse->pktcnt == psmouse->pktsize) { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + return PSMOUSE_FULL_PACKET; + } + +@@ -1432,25 +1420,26 @@ error: + return -1; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static void alps_set_defaults(struct alps_data *priv) + { +- struct alps_data *priv = psmouse->private; +- int ret = -1; +- + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +- ret = alps_hw_init_v1_v2(psmouse); ++ priv->hw_init = alps_hw_init_v1_v2; ++ priv->process_packet = alps_process_packet_v1_v2; ++ priv->set_abs_params = alps_set_abs_params_st; + break; + case ALPS_PROTO_V3: +- ret = alps_hw_init_v3(psmouse); ++ priv->hw_init = alps_hw_init_v3; ++ priv->process_packet = alps_process_packet_v3; ++ priv->set_abs_params = alps_set_abs_params_mt; + break; + case ALPS_PROTO_V4: +- ret = alps_hw_init_v4(psmouse); ++ priv->hw_init = alps_hw_init_v4; ++ priv->process_packet = alps_process_packet_v4; ++ priv->set_abs_params = alps_set_abs_params_mt; + break; + } +- +- return ret; + } + + static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, +@@ -1467,6 +1456,8 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, + model->command_mode_resp == ec[2])) { + + priv->proto_version = model->proto_version; ++ alps_set_defaults(priv); ++ + priv->flags = model->flags; + priv->byte0 = model->byte0; + priv->mask0 = model->mask0; +@@ -1525,7 +1516,7 @@ static int alps_reconnect(struct psmouse *psmouse) + if (alps_identify(psmouse, priv) < 0) + return -1; + +- return alps_hw_init(psmouse); ++ return priv->hw_init(psmouse); + } + + static void alps_disconnect(struct psmouse *psmouse) +@@ -1538,6 +1529,29 @@ static void alps_disconnect(struct psmouse *psmouse) + kfree(priv); + } + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++} ++ ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ ++ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++} ++ + int alps_init(struct psmouse *psmouse) + { + struct alps_data *priv; +@@ -1558,7 +1572,7 @@ int alps_init(struct psmouse *psmouse) + if (alps_identify(psmouse, priv) < 0) + goto init_fail; + +- if (alps_hw_init(psmouse)) ++ if (priv->hw_init(psmouse)) + goto init_fail; + + /* +@@ -1580,28 +1594,7 @@ int alps_init(struct psmouse *psmouse) + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); + +- switch (priv->proto_version) { +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); +- break; +- case ALPS_PROTO_V3: +- case ALPS_PROTO_V4: +- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); +- input_mt_init_slots(dev1, 2, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- +- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); +- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); +- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); +- +- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- break; +- } +- ++ priv->set_abs_params(priv, dev1); + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + + if (priv->flags & ALPS_WHEEL) { +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index a81b318..0934f8b 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -72,6 +72,9 @@ struct alps_nibble_commands { + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * @hw_init: Protocol-specific hardware init function. ++ * @process_packet: Protocol-specific function to process a report packet. ++ * @set_abs_params: Protocol-specific function to configure the input_dev. + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. + * @multi_data: Saved multi-packet data. +@@ -94,6 +97,10 @@ struct alps_data { + unsigned char byte0, mask0; + unsigned char flags; + ++ int (*hw_init)(struct psmouse *psmouse); ++ void (*process_packet)(struct psmouse *psmouse); ++ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); ++ + int prev_fin; + int multi_packet; + unsigned char multi_data[6]; +-- +1.8.1.2 + + +From 9984c4d8611c9ecb4942349f1058b4ad1fcfb7c8 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:23:04 -0800 +Subject: [PATCH 07/15] Input: ALPS - move {addr,nibble}_command settings into + alps_set_defaults() + +This allows alps_identify() to override these settings based on the +device characteristics, if it is ever necessary. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 3cca3ef..22f5ef1 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1192,14 +1192,10 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) + + static int alps_hw_init_v3(struct psmouse *psmouse) + { +- struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val; + unsigned char param[4]; + +- priv->nibble_commands = alps_v3_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; +- + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +@@ -1345,13 +1341,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) + + static int alps_hw_init_v4(struct psmouse *psmouse) + { +- struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + +- priv->nibble_commands = alps_v4_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_DISABLE; +- + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +@@ -1433,11 +1425,15 @@ static void alps_set_defaults(struct alps_data *priv) + priv->hw_init = alps_hw_init_v3; + priv->process_packet = alps_process_packet_v3; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + break; + case ALPS_PROTO_V4: + priv->hw_init = alps_hw_init_v4; + priv->process_packet = alps_process_packet_v4; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; + break; + } + } +-- +1.8.1.2 + + +From a8e2c2b0cc44c0ec2cb59a79c1a341f5608248cc Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:23:34 -0800 +Subject: [PATCH 08/15] Input: ALPS - rework detection of Pinnacle AGx + touchpads + +The official ALPS driver uses the EC report, not the E7 report, to detect +these devices. Also, they check for a range of values; the original +table-based code only checked for two specific ones. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 22f5ef1..f70a930 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -109,8 +109,6 @@ static const struct alps_model_info alps_model_data[] = { + { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ +- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, +- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, + { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + +@@ -1414,6 +1412,10 @@ error: + + static void alps_set_defaults(struct alps_data *priv) + { ++ priv->byte0 = 0x8f; ++ priv->mask0 = 0x8f; ++ priv->flags = ALPS_DUALPOINT; ++ + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +@@ -1493,8 +1495,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + alps_exit_command_mode(psmouse)) + return -EIO; + +- if (alps_match_table(psmouse, priv, e7, ec) == 0) ++ if (alps_match_table(psmouse, priv, e7, ec) == 0) { ++ return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x07 && ++ ec[2] >= 0x90 && ec[2] <= 0x9d) { ++ priv->proto_version = ALPS_PROTO_V3; ++ alps_set_defaults(priv); ++ + return 0; ++ } + + psmouse_info(psmouse, + "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", +-- +1.8.1.2 + + +From a5f89d7393f5582efeb3e83bd4bc3eb146528371 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:24:22 -0800 +Subject: [PATCH 09/15] Input: ALPS - fix command mode check + +Pinnacle class devices should return "88 07 xx" or "88 08 xx" when +entering command mode. If either the first byte or the second byte is +invalid, return an error. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index f70a930..15c1eb5 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -985,7 +985,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + return -1; + } + +- if (param[0] != 0x88 && param[1] != 0x07) { ++ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { + psmouse_dbg(psmouse, + "unknown response while entering command mode\n"); + return -1; +-- +1.8.1.2 + + +From 8b9993ec92c4ba02b2c155da6d5f5aa3502aa672 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:24:55 -0800 +Subject: [PATCH 10/15] Input: ALPS - move pixel and bitmap info into alps_data + struct + +Newer touchpads use different constants, so make them runtime- +configurable. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 47 ++++++++++++++++++++++++---------------------- + drivers/input/mouse/alps.h | 8 ++++++++ + 2 files changed, 33 insertions(+), 22 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 15c1eb5..9199d2d 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -27,12 +27,6 @@ + /* + * Definitions for ALPS version 3 and 4 command mode protocol + */ +-#define ALPS_V3_X_MAX 2000 +-#define ALPS_V3_Y_MAX 1400 +- +-#define ALPS_BITMAP_X_BITS 15 +-#define ALPS_BITMAP_Y_BITS 11 +- + #define ALPS_CMD_NIBBLE_10 0x01f2 + + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { +@@ -269,7 +263,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + * These points are returned in x1, y1, x2, and y2 when the return value + * is greater than 0. + */ +-static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++static int alps_process_bitmap(struct alps_data *priv, ++ unsigned int x_map, unsigned int y_map, + int *x1, int *y1, int *x2, int *y2) + { + struct alps_bitmap_point { +@@ -311,7 +306,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + * y bitmap is reversed for what we need (lower positions are in + * higher bits), so we process from the top end. + */ +- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); + prev_bit = 0; + point = &y_low; + for (i = 0; y_map != 0; i++, y_map <<= 1) { +@@ -357,16 +352,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + } + } + +- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + + if (fingers > 1) { +- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x2 = (priv->x_max * ++ (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y2 = (priv->y_max * ++ (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + } + + return fingers; +@@ -484,7 +481,8 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + ((packet[2] & 0x7f) << 1) | + (packet[4] & 0x01); + +- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ bmap_fingers = alps_process_bitmap(priv, ++ x_bitmap, y_bitmap, + &x1, &y1, &x2, &y2); + + /* +@@ -641,7 +639,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + ((priv->multi_data[3] & 0x1f) << 5) | + (priv->multi_data[1] & 0x1f); + +- fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, + &x1, &y1, &x2, &y2); + + /* Store MT data.*/ +@@ -1416,6 +1414,11 @@ static void alps_set_defaults(struct alps_data *priv) + priv->mask0 = 0x8f; + priv->flags = ALPS_DUALPOINT; + ++ priv->x_max = 2000; ++ priv->y_max = 1400; ++ priv->x_bits = 15; ++ priv->y_bits = 11; ++ + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +@@ -1546,15 +1549,15 @@ static void alps_set_abs_params_mt(struct alps_data *priv, + { + set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); + input_mt_init_slots(dev1, 2, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); + + set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); + set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); + set_bit(BTN_TOOL_QUADTAP, dev1->keybit); + +- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); + } + + int alps_init(struct psmouse *psmouse) +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 0934f8b..5e638be 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -72,6 +72,10 @@ struct alps_nibble_commands { + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * @x_max: Largest possible X position value. ++ * @y_max: Largest possible Y position value. ++ * @x_bits: Number of X bits in the MT bitmap. ++ * @y_bits: Number of Y bits in the MT bitmap. + * @hw_init: Protocol-specific hardware init function. + * @process_packet: Protocol-specific function to process a report packet. + * @set_abs_params: Protocol-specific function to configure the input_dev. +@@ -96,6 +100,10 @@ struct alps_data { + unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; ++ int x_max; ++ int y_max; ++ int x_bits; ++ int y_bits; + + int (*hw_init)(struct psmouse *psmouse); + void (*process_packet)(struct psmouse *psmouse); +-- +1.8.1.2 + + +From 3e8674cc18aece18d3a9cdd484f157d44a5682b8 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:26:11 -0800 +Subject: [PATCH 11/15] Input: ALPS - make the V3 packet field decoder + "pluggable" + +A number of different ALPS touchpad protocols can reuse +alps_process_touchpad_packet_v3() with small tweaks to the bitfield +decoding. Create a new priv->decode_fields() callback that handles the +per-model differences. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 101 +++++++++++++++++++++++++-------------------- + drivers/input/mouse/alps.h | 38 +++++++++++++++++ + 2 files changed, 95 insertions(+), 44 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 9199d2d..7f0855e 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -447,17 +447,49 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + return; + } + ++static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) ++{ ++ f->left = !!(p[3] & 0x01); ++ f->right = !!(p[3] & 0x02); ++ f->middle = !!(p[3] & 0x04); ++ ++ f->ts_left = !!(p[3] & 0x10); ++ f->ts_right = !!(p[3] & 0x20); ++ f->ts_middle = !!(p[3] & 0x40); ++} ++ ++static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) ++{ ++ f->first_mp = !!(p[4] & 0x40); ++ f->is_mp = !!(p[0] & 0x40); ++ ++ f->fingers = (p[5] & 0x3) + 1; ++ f->x_map = ((p[4] & 0x7e) << 8) | ++ ((p[1] & 0x7f) << 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y_map = ((p[3] & 0x70) << 4) | ++ ((p[2] & 0x7f) << 1) | ++ (p[4] & 0x01); ++ ++ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); ++ f->z = p[5] & 0x7f; ++ ++ alps_decode_buttons_v3(f, p); ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + struct input_dev *dev2 = priv->dev2; +- int x, y, z; +- int left, right, middle; + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + int fingers = 0, bmap_fingers; +- unsigned int x_bitmap, y_bitmap; ++ struct alps_fields f; ++ ++ priv->decode_fields(&f, packet); + + /* + * There's no single feature of touchpad position and bitmap packets +@@ -472,17 +504,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * packet. Check for this, and when it happens process the + * position packet as usual. + */ +- if (packet[0] & 0x40) { +- fingers = (packet[5] & 0x3) + 1; +- x_bitmap = ((packet[4] & 0x7e) << 8) | +- ((packet[1] & 0x7f) << 2) | +- ((packet[0] & 0x30) >> 4); +- y_bitmap = ((packet[3] & 0x70) << 4) | +- ((packet[2] & 0x7f) << 1) | +- (packet[4] & 0x01); +- ++ if (f.is_mp) { ++ fingers = f.fingers; + bmap_fingers = alps_process_bitmap(priv, +- x_bitmap, y_bitmap, ++ f.x_map, f.y_map, + &x1, &y1, &x2, &y2); + + /* +@@ -493,7 +518,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + fingers = bmap_fingers; + + /* Now process position packet */ +- packet = priv->multi_data; ++ priv->decode_fields(&f, priv->multi_data); + } else { + priv->multi_packet = 0; + } +@@ -507,10 +532,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * out misidentified bitmap packets, we reject anything with this + * bit set. + */ +- if (packet[0] & 0x40) ++ if (f.is_mp) + return; + +- if (!priv->multi_packet && (packet[4] & 0x40)) { ++ if (!priv->multi_packet && f.first_mp) { + priv->multi_packet = 1; + memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); + return; +@@ -518,22 +543,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + priv->multi_packet = 0; + +- left = packet[3] & 0x01; +- right = packet[3] & 0x02; +- middle = packet[3] & 0x04; +- +- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | +- ((packet[0] & 0x30) >> 4); +- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); +- z = packet[5] & 0x7f; +- + /* + * Sometimes the hardware sends a single packet with z = 0 + * in the middle of a stream. Real releases generate packets + * with x, y, and z all zero, so these seem to be flukes. + * Ignore them. + */ +- if (x && y && !z) ++ if (f.x && f.y && !f.z) + return; + + /* +@@ -541,12 +557,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * to rely on ST data. + */ + if (!fingers) { +- x1 = x; +- y1 = y; +- fingers = z > 0 ? 1 : 0; ++ x1 = f.x; ++ y1 = f.y; ++ fingers = f.z > 0 ? 1 : 0; + } + +- if (z >= 64) ++ if (f.z >= 64) + input_report_key(dev, BTN_TOUCH, 1); + else + input_report_key(dev, BTN_TOUCH, 0); +@@ -555,26 +571,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + input_mt_report_finger_count(dev, fingers); + +- input_report_key(dev, BTN_LEFT, left); +- input_report_key(dev, BTN_RIGHT, right); +- input_report_key(dev, BTN_MIDDLE, middle); ++ input_report_key(dev, BTN_LEFT, f.left); ++ input_report_key(dev, BTN_RIGHT, f.right); ++ input_report_key(dev, BTN_MIDDLE, f.middle); + +- if (z > 0) { +- input_report_abs(dev, ABS_X, x); +- input_report_abs(dev, ABS_Y, y); ++ if (f.z > 0) { ++ input_report_abs(dev, ABS_X, f.x); ++ input_report_abs(dev, ABS_Y, f.y); + } +- input_report_abs(dev, ABS_PRESSURE, z); ++ input_report_abs(dev, ABS_PRESSURE, f.z); + + input_sync(dev); + + if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { +- left = packet[3] & 0x10; +- right = packet[3] & 0x20; +- middle = packet[3] & 0x40; +- +- input_report_key(dev2, BTN_LEFT, left); +- input_report_key(dev2, BTN_RIGHT, right); +- input_report_key(dev2, BTN_MIDDLE, middle); ++ input_report_key(dev2, BTN_LEFT, f.ts_left); ++ input_report_key(dev2, BTN_RIGHT, f.ts_right); ++ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); + input_sync(dev2); + } + } +@@ -1430,6 +1442,7 @@ static void alps_set_defaults(struct alps_data *priv) + priv->hw_init = alps_hw_init_v3; + priv->process_packet = alps_process_packet_v3; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->decode_fields = alps_decode_pinnacle; + priv->nibble_commands = alps_v3_nibble_commands; + priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + break; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 5e638be..9704805 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -60,6 +60,42 @@ struct alps_nibble_commands { + }; + + /** ++ * struct alps_fields - decoded version of the report packet ++ * @x_map: Bitmap of active X positions for MT. ++ * @y_map: Bitmap of active Y positions for MT. ++ * @fingers: Number of fingers for MT. ++ * @x: X position for ST. ++ * @y: Y position for ST. ++ * @z: Z position for ST. ++ * @first_mp: Packet is the first of a multi-packet report. ++ * @is_mp: Packet is part of a multi-packet report. ++ * @left: Left touchpad button is active. ++ * @right: Right touchpad button is active. ++ * @middle: Middle touchpad button is active. ++ * @ts_left: Left trackstick button is active. ++ * @ts_right: Right trackstick button is active. ++ * @ts_middle: Middle trackstick button is active. ++ */ ++struct alps_fields { ++ unsigned int x_map; ++ unsigned int y_map; ++ unsigned int fingers; ++ unsigned int x; ++ unsigned int y; ++ unsigned int z; ++ unsigned int first_mp:1; ++ unsigned int is_mp:1; ++ ++ unsigned int left:1; ++ unsigned int right:1; ++ unsigned int middle:1; ++ ++ unsigned int ts_left:1; ++ unsigned int ts_right:1; ++ unsigned int ts_middle:1; ++}; ++ ++/** + * struct alps_data - private data structure for the ALPS driver + * @dev2: "Relative" device used to report trackstick or mouse activity. + * @phys: Physical path for the relative device. +@@ -78,6 +114,7 @@ struct alps_nibble_commands { + * @y_bits: Number of Y bits in the MT bitmap. + * @hw_init: Protocol-specific hardware init function. + * @process_packet: Protocol-specific function to process a report packet. ++ * @decode_fields: Protocol-specific function to read packet bitfields. + * @set_abs_params: Protocol-specific function to configure the input_dev. + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. +@@ -107,6 +144,7 @@ struct alps_data { + + int (*hw_init)(struct psmouse *psmouse); + void (*process_packet)(struct psmouse *psmouse); ++ void (*decode_fields)(struct alps_fields *f, unsigned char *p); + void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); + + int prev_fin; +-- +1.8.1.2 + + +From 8852c5c13a191156db0f4d4428165f0dee9ce29e Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:27:08 -0800 +Subject: [PATCH 12/15] Input: ALPS - add support for "Rushmore" touchpads + +Rushmore touchpads are found on Dell E6230/E6430/E6530. They use the V3 +protocol with slightly tweaked init sequences and report formats. + +The E7 report is 73 03 0a, and the EC report is 88 08 1d + +Credits: Emmanuel Thome reported the MT bitmap changes. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 7f0855e..956c523 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -479,6 +479,14 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) + alps_decode_buttons_v3(f, p); + } + ++static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) ++{ ++ alps_decode_pinnacle(f, p); ++ ++ f->x_map |= (p[5] & 0x10) << 11; ++ f->y_map |= (p[5] & 0x20) << 6; ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -1331,6 +1339,40 @@ error: + return -1; + } + ++static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val, ret = -1; ++ ++ if (alps_enter_command_mode(psmouse, NULL) || ++ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || ++ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) ++ goto error; ++ ++ /* enter absolute mode */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); ++ ++error: ++ alps_exit_command_mode(psmouse); ++ return ret; ++} ++ + /* Must be in command mode when calling this function */ + static int alps_absolute_mode_v4(struct psmouse *psmouse) + { +@@ -1513,6 +1555,16 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + + if (alps_match_table(psmouse, priv, e7, ec) == 0) { + return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x08) { ++ priv->proto_version = ALPS_PROTO_V3; ++ alps_set_defaults(priv); ++ ++ priv->hw_init = alps_hw_init_rushmore_v3; ++ priv->decode_fields = alps_decode_rushmore; ++ priv->x_bits = 16; ++ priv->y_bits = 12; ++ ++ return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x07 && + ec[2] >= 0x90 && ec[2] <= 0x9d) { + priv->proto_version = ALPS_PROTO_V3; +-- +1.8.1.2 + + +From dd22ae0f4aad37dc8371fe265e43a8426a3d4b1d Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:28:07 -0800 +Subject: [PATCH 13/15] Input: ALPS - enable trackstick on Rushmore touchpads + +Separate out the common trackstick probe/setup sequences, then call them +from each of the v3 init functions. + +Credits: Emmanual Thome furnished the information on the trackstick init +and how it affected the report format. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 185 ++++++++++++++++++++++++++++----------------- + 1 file changed, 115 insertions(+), 70 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 956c523..618ae44 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -29,6 +29,9 @@ + */ + #define ALPS_CMD_NIBBLE_10 0x01f2 + ++#define ALPS_REG_BASE_RUSHMORE 0xc2c0 ++#define ALPS_REG_BASE_PINNACLE 0x0000 ++ + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { + { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ + { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ +@@ -1168,26 +1171,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) + } + + /* +- * Enable or disable passthrough mode to the trackstick. Must be in +- * command mode when calling this function. ++ * Enable or disable passthrough mode to the trackstick. + */ +-static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) ++static int alps_passthrough_mode_v3(struct psmouse *psmouse, ++ int reg_base, bool enable) + { +- int reg_val; ++ int reg_val, ret = -1; + +- reg_val = alps_command_mode_read_reg(psmouse, 0x0008); +- if (reg_val == -1) ++ if (alps_enter_command_mode(psmouse, NULL)) + return -1; + ++ reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); ++ if (reg_val == -1) ++ goto error; ++ + if (enable) + reg_val |= 0x01; + else + reg_val &= ~0x01; + +- if (__alps_command_mode_write_reg(psmouse, reg_val)) +- return -1; ++ ret = __alps_command_mode_write_reg(psmouse, reg_val); + +- return 0; ++error: ++ if (alps_exit_command_mode(psmouse)) ++ ret = -1; ++ return ret; + } + + /* Must be in command mode when calling this function */ +@@ -1206,69 +1214,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) + return 0; + } + +-static int alps_hw_init_v3(struct psmouse *psmouse) ++static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) + { +- struct ps2dev *ps2dev = &psmouse->ps2dev; +- int reg_val; +- unsigned char param[4]; ++ int ret = -EIO, reg_val; + + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +- /* Check for trackstick */ +- reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); + if (reg_val == -1) + goto error; +- if (reg_val & 0x80) { +- if (alps_passthrough_mode_v3(psmouse, true)) +- goto error; +- if (alps_exit_command_mode(psmouse)) +- goto error; ++ ++ /* bit 7: trackstick is present */ ++ ret = reg_val & 0x80 ? 0 : -ENODEV; ++ ++error: ++ alps_exit_command_mode(psmouse); ++ return ret; ++} ++ ++static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int ret = 0; ++ unsigned char param[4]; ++ ++ if (alps_passthrough_mode_v3(psmouse, reg_base, true)) ++ return -EIO; ++ ++ /* ++ * E7 report for the trackstick ++ * ++ * There have been reports of failures to seem to trace back ++ * to the above trackstick check failing. When these occur ++ * this E7 report fails, so when that happens we continue ++ * with the assumption that there isn't a trackstick after ++ * all. ++ */ ++ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { ++ psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ ret = -ENODEV; ++ } else { ++ psmouse_dbg(psmouse, ++ "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); + + /* +- * E7 report for the trackstick +- * +- * There have been reports of failures to seem to trace back +- * to the above trackstick check failing. When these occur +- * this E7 report fails, so when that happens we continue +- * with the assumption that there isn't a trackstick after +- * all. ++ * Not sure what this does, but it is absolutely ++ * essential. Without it, the touchpad does not ++ * work at all and the trackstick just emits normal ++ * PS/2 packets. + */ +- param[0] = 0x64; +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { +- psmouse_warn(psmouse, "trackstick E7 report failed\n"); +- } else { +- psmouse_dbg(psmouse, +- "trackstick E7 report: %2.2x %2.2x %2.2x\n", +- param[0], param[1], param[2]); +- +- /* +- * Not sure what this does, but it is absolutely +- * essential. Without it, the touchpad does not +- * work at all and the trackstick just emits normal +- * PS/2 packets. +- */ +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- alps_command_mode_send_nibble(psmouse, 0x9) || +- alps_command_mode_send_nibble(psmouse, 0x4)) { +- psmouse_err(psmouse, +- "Error sending magic E6 sequence\n"); +- goto error_passthrough; +- } ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ alps_command_mode_send_nibble(psmouse, 0x9) || ++ alps_command_mode_send_nibble(psmouse, 0x4)) { ++ psmouse_err(psmouse, ++ "Error sending magic E6 sequence\n"); ++ ret = -EIO; ++ goto error; + } + +- if (alps_enter_command_mode(psmouse, NULL)) +- goto error_passthrough; +- if (alps_passthrough_mode_v3(psmouse, false)) +- goto error; ++ /* ++ * This ensures the trackstick packets are in the format ++ * supported by this driver. If bit 1 isn't set the packet ++ * format is different. ++ */ ++ if (alps_enter_command_mode(psmouse, NULL) || ++ alps_command_mode_write_reg(psmouse, ++ reg_base + 0x08, 0x82) || ++ alps_exit_command_mode(psmouse)) ++ ret = -EIO; + } + +- if (alps_absolute_mode_v3(psmouse)) { ++error: ++ if (alps_passthrough_mode_v3(psmouse, reg_base, false)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static int alps_hw_init_v3(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val; ++ unsigned char param[4]; ++ ++ reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); ++ if (reg_val == -EIO) ++ goto error; ++ if (reg_val == 0 && ++ alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) ++ goto error; ++ ++ if (alps_enter_command_mode(psmouse, NULL) || ++ alps_absolute_mode_v3(psmouse)) { + psmouse_err(psmouse, "Failed to enter absolute mode\n"); + goto error; + } +@@ -1305,14 +1346,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) + goto error; + +- /* +- * This ensures the trackstick packets are in the format +- * supported by this driver. If bit 1 isn't set the packet +- * format is different. +- */ +- if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) +- goto error; +- + alps_exit_command_mode(psmouse); + + /* Set rate and enable data reporting */ +@@ -1325,10 +1358,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + + return 0; + +-error_passthrough: +- /* Something failed while in passthrough mode, so try to get out */ +- if (!alps_enter_command_mode(psmouse, NULL)) +- alps_passthrough_mode_v3(psmouse, false); + error: + /* + * Leaving the touchpad in command mode will essentially render +@@ -1341,9 +1370,19 @@ error: + + static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) + { ++ struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val, ret = -1; + ++ if (priv->flags & ALPS_DUALPOINT) { ++ reg_val = alps_setup_trackstick_v3(psmouse, ++ ALPS_REG_BASE_RUSHMORE); ++ if (reg_val == -EIO) ++ goto error; ++ if (reg_val == -ENODEV) ++ priv->flags &= ~ALPS_DUALPOINT; ++ } ++ + if (alps_enter_command_mode(psmouse, NULL) || + alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || + alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) +@@ -1564,6 +1603,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + priv->x_bits = 16; + priv->y_bits = 12; + ++ /* hack to make addr_command, nibble_command available */ ++ psmouse->private = priv; ++ ++ if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) ++ priv->flags &= ~ALPS_DUALPOINT; ++ + return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x07 && + ec[2] >= 0x90 && ec[2] <= 0x9d) { +-- +1.8.1.2 + + +From 1c89f1435ea5344dc2dbb5c59f56b2d12d852fdc Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Sat, 16 Feb 2013 22:40:03 -0800 +Subject: [PATCH 14/15] Input: ALPS - Remove unused argument to + alps_enter_command_mode() + +Now that alps_identify() explicitly issues an EC report using +alps_rpt_cmd(), we no longer need to look at the magic numbers returned +by alps_enter_command_mode(). + +Signed-off-by: Kevin Cernekee +--- + drivers/input/mouse/alps.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 618ae44..8e01c31 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -996,8 +996,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, + return 0; + } + +-static int alps_enter_command_mode(struct psmouse *psmouse, +- unsigned char *resp) ++static int alps_enter_command_mode(struct psmouse *psmouse) + { + unsigned char param[4]; + +@@ -1011,9 +1010,6 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + "unknown response while entering command mode\n"); + return -1; + } +- +- if (resp) +- *resp = param[2]; + return 0; + } + +@@ -1178,7 +1174,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, + { + int reg_val, ret = -1; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + return -1; + + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); +@@ -1218,7 +1214,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) + { + int ret = -EIO, reg_val; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + goto error; + + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); +@@ -1281,7 +1277,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) + * supported by this driver. If bit 1 isn't set the packet + * format is different. + */ +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_command_mode_write_reg(psmouse, + reg_base + 0x08, 0x82) || + alps_exit_command_mode(psmouse)) +@@ -1308,7 +1304,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) + goto error; + +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_absolute_mode_v3(psmouse)) { + psmouse_err(psmouse, "Failed to enter absolute mode\n"); + goto error; +@@ -1383,7 +1379,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) + priv->flags &= ~ALPS_DUALPOINT; + } + +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || + alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) + goto error; +@@ -1433,7 +1429,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + goto error; + + if (alps_absolute_mode_v4(psmouse)) { +-- +1.8.1.2 + + +From 35458ea14080b1d529ecee4c01dabc91e8ff9f25 Mon Sep 17 00:00:00 2001 +From: Dave Turvene +Date: Sat, 16 Feb 2013 22:40:04 -0800 +Subject: [PATCH 15/15] Input: ALPS - Add "Dolphin V1" touchpad support + +These touchpads use a different protocol; they have been seen on Dell +N5110, Dell 17R SE, and others. + +The official ALPS driver identifies them by looking for an exact match +on the E7 report: 73 03 50. Dolphin V1 returns an EC report of +73 01 xx (02 and 0d have been seen); Dolphin V2 returns an EC report of +73 02 xx (02 has been seen). + +Dolphin V2 probably needs a different initialization sequence and/or +report parser, so it is left for a future commit. + +Signed-off-by: Dave Turvene +Signed-off-by: Kevin Cernekee +--- + drivers/input/mouse/alps.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.h | 1 + + 2 files changed, 66 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 8e01c31..b7abd40 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) + f->y_map |= (p[5] & 0x20) << 6; + } + ++static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) ++{ ++ f->first_mp = !!(p[0] & 0x02); ++ f->is_mp = !!(p[0] & 0x20); ++ ++ f->fingers = ((p[0] & 0x6) >> 1 | ++ (p[0] & 0x10) >> 2); ++ f->x_map = ((p[2] & 0x60) >> 5) | ++ ((p[4] & 0x7f) << 2) | ++ ((p[5] & 0x7f) << 9) | ++ ((p[3] & 0x07) << 16) | ++ ((p[3] & 0x70) << 15) | ++ ((p[0] & 0x01) << 22); ++ f->y_map = (p[1] & 0x7f) | ++ ((p[2] & 0x1f) << 7); ++ ++ f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); ++ f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); ++ f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; ++ ++ alps_decode_buttons_v3(f, p); ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -876,7 +899,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + /* Bytes 2 - pktsize should have 0 in the highest bit */ +- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && ++ if (priv->proto_version != ALPS_PROTO_V5 && ++ psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, +@@ -1005,7 +1029,8 @@ static int alps_enter_command_mode(struct psmouse *psmouse) + return -1; + } + +- if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { ++ if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && ++ param[0] != 0x73) { + psmouse_dbg(psmouse, + "unknown response while entering command mode\n"); + return -1; +@@ -1497,6 +1522,23 @@ error: + return -1; + } + ++static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[2]; ++ ++ /* This is dolphin "v1" as empirically defined by florin9doi */ ++ param[0] = 0x64; ++ param[1] = 0x28; ++ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || ++ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) ++ return -1; ++ ++ return 0; ++} ++ + static void alps_set_defaults(struct alps_data *priv) + { + priv->byte0 = 0x8f; +@@ -1530,6 +1572,21 @@ static void alps_set_defaults(struct alps_data *priv) + priv->nibble_commands = alps_v4_nibble_commands; + priv->addr_command = PSMOUSE_CMD_DISABLE; + break; ++ case ALPS_PROTO_V5: ++ priv->hw_init = alps_hw_init_dolphin_v1; ++ priv->process_packet = alps_process_packet_v3; ++ priv->decode_fields = alps_decode_dolphin; ++ priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; ++ priv->byte0 = 0xc8; ++ priv->mask0 = 0xc8; ++ priv->flags = 0; ++ priv->x_max = 1360; ++ priv->y_max = 660; ++ priv->x_bits = 23; ++ priv->y_bits = 12; ++ break; + } + } + +@@ -1590,6 +1647,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + + if (alps_match_table(psmouse, priv, e7, ec) == 0) { + return 0; ++ } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && ++ ec[0] == 0x73 && ec[1] == 0x01) { ++ priv->proto_version = ALPS_PROTO_V5; ++ alps_set_defaults(priv); ++ ++ return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x08) { + priv->proto_version = ALPS_PROTO_V3; + alps_set_defaults(priv); +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 9704805..eee5985 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -16,6 +16,7 @@ + #define ALPS_PROTO_V2 2 + #define ALPS_PROTO_V3 3 + #define ALPS_PROTO_V4 4 ++#define ALPS_PROTO_V5 5 + + /** + * struct alps_model_info - touchpad ID table +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 6f7895433..37ef3ac35 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -798,6 +798,9 @@ Patch23000: silence-brcmsmac-warning.patch #rhbz 909591 Patch21255: usb-cypress-supertop.patch +#rhbz 812111 +Patch24000: alps-v2-3.7.patch + # END OF PATCH DEFINITIONS %endif @@ -1529,6 +1532,9 @@ ApplyPatch usb-cypress-supertop.patch #rhbz 911479 911473 CVE-2013-0290 ApplyPatch net-fix-infinite-loop-in-__skb_recv_datagram.patch +#rhbz 812111 +ApplyPatch alps-v2-3.7.patch + # END OF PATCH APPLICATIONS %endif @@ -2392,6 +2398,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 19 2013 Josh Boyer +- Backport support for newer ALPS touchpads (rhbz 812111) + * Tue Feb 19 2013 Peter Robinson - Fix OMAP thermal driver by building it in (seems it doesn't auto load when a module) From 7509bfeeae14115dd4be3babaab001c6d522f0f6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 19 Feb 2013 11:56:05 -0500 Subject: [PATCH 189/492] Add support for Atheros 04ca:3004 bluetooth devices (rhbz 844750) --- ...pport-for-atheros-04ca-3004-device-t.patch | 47 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 54 insertions(+) create mode 100644 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch diff --git a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch new file mode 100644 index 000000000..cfa1710de --- /dev/null +++ b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch @@ -0,0 +1,47 @@ +From 95e9fe367b98a8f4f3c7538fc40a4f94d7f5e35f Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 18 Feb 2013 10:32:13 -0500 +Subject: [PATCH] bluetooth: Add support for atheros 04ca:3004 device to ath3k + +Yet another version of the atheros bluetooth chipset + +Reported-by: niktr@mail.ru +Signed-off-by: Josh Boyer +--- + drivers/bluetooth/ath3k.c | 2 ++ + drivers/bluetooth/btusb.c | 1 + + 2 files changed, 3 insertions(+) + + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index b00000e..284658c 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0x3004) }, + { USB_DEVICE(0x0CF3, 0x311D) }, + { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x04CA, 0x3004) }, + { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x13d3, 0x3362) }, + { USB_DEVICE(0x0CF3, 0xE004) }, +@@ -103,6 +104,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a1d4ede..fa59179 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, diff --git a/kernel.spec b/kernel.spec index 37ef3ac35..0019353ca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -793,6 +793,9 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 911479 911473 CVE-2013-0290 Patch22256: net-fix-infinite-loop-in-__skb_recv_datagram.patch +#rhbz 844750 +Patch22257: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 909591 @@ -1532,6 +1535,9 @@ ApplyPatch usb-cypress-supertop.patch #rhbz 911479 911473 CVE-2013-0290 ApplyPatch net-fix-infinite-loop-in-__skb_recv_datagram.patch +#rhbz 844750 +ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + #rhbz 812111 ApplyPatch alps-v2-3.7.patch @@ -2399,6 +2405,7 @@ fi # || || %changelog * Tue Feb 19 2013 Josh Boyer +- Add support for Atheros 04ca:3004 bluetooth devices (rhbz 844750) - Backport support for newer ALPS touchpads (rhbz 812111) * Tue Feb 19 2013 Peter Robinson From a593134d04fc802331659f2662f07fbebdf6adc1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Feb 2013 08:32:08 -0500 Subject: [PATCH 190/492] Fix oops from acpi_rsdp setup in secure-boot patchset (rhbz 906225) --- kernel.spec | 9 +- ...04.patch => secure-boot-3.7-20130219.patch | 187 +++++++----------- 2 files changed, 77 insertions(+), 119 deletions(-) rename secure-boot-3.7-20130204.patch => secure-boot-3.7-20130219.patch (88%) diff --git a/kernel.spec b/kernel.spec index 0019353ca..b410b19ab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -690,7 +690,7 @@ Patch800: linux-2.6-crash-driver.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-3.7-20130204.patch +Patch1000: secure-boot-3.7-20130219.patch Patch1001: efivarfs-3.7.patch # Improve PCI support on UEFI @@ -1447,7 +1447,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.7.patch -ApplyPatch secure-boot-3.7-20130204.patch +ApplyPatch secure-boot-3.7-20130219.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -2404,6 +2404,9 @@ fi # ||----w | # || || %changelog +* Wed Feb 20 2013 Josh Boyer +- Fix oops from acpi_rsdp setup in secure-boot patchset (rhbz 906225) + * Tue Feb 19 2013 Josh Boyer - Add support for Atheros 04ca:3004 bluetooth devices (rhbz 844750) - Backport support for newer ALPS touchpads (rhbz 812111) diff --git a/secure-boot-3.7-20130204.patch b/secure-boot-3.7-20130219.patch similarity index 88% rename from secure-boot-3.7-20130204.patch rename to secure-boot-3.7-20130219.patch index 621be74be..48ef2e7fe 100644 --- a/secure-boot-3.7-20130204.patch +++ b/secure-boot-3.7-20130219.patch @@ -1,7 +1,7 @@ -From 428db98d65770561ec5b8e9fc1931acf2210c5dd Mon Sep 17 00:00:00 2001 +From 33ecf899ae618a163e553c24674a48bd0cb4dd17 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/17] Secure boot: Add new capability +Subject: [PATCH 01/19] Secure boot: Add new capability Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. @@ -32,13 +32,13 @@ index ba478fa..7109e65 100644 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) -- -1.8.1 +1.8.1.2 -From 57902a5335b6f1f0aad56c669c874b45e9dd4ee8 Mon Sep 17 00:00:00 2001 +From 0867a7288326c109ac3f1a52a342f577e1f77618 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 02/17] SELinux: define mapping for new Secure Boot capability +Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability Add the name of the new Secure Boot capability. This allows SELinux policies to properly map CAP_COMPROMISE_KERNEL to the appropriate @@ -65,13 +65,13 @@ index df2de54..70e2834 100644 { "tun_socket", { COMMON_SOCK_PERMS, NULL } }, -- -1.8.1 +1.8.1.2 -From 7e2d1d442399258426c0724e7fd6adc6fd8a8590 Mon Sep 17 00:00:00 2001 +From 23873817d2cec32d4af90fc7038b53c949e3f5a6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 03/17] Secure boot: Add a dummy kernel parameter that will +Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset @@ -131,13 +131,13 @@ index 48cea3d..3f5be65 100644 * prepare_kernel_cred - Prepare a set of credentials for a kernel service * @daemon: A userspace daemon to be used as a reference -- -1.8.1 +1.8.1.2 -From 6be9cea6bf2cf06898efa300644ea9e6ad9c5a18 Mon Sep 17 00:00:00 2001 +From 6e786fc19b3dc3aa53e6f556af2baf261573321f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 04/17] efi: Enable secure boot lockdown automatically when +Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when enabled in firmware The firmware has a set of flags that indicate whether secure boot is enabled @@ -275,13 +275,13 @@ index b424f64..fef4ca6 100644 #ifdef CONFIG_EFI # ifdef CONFIG_X86 -- -1.8.1 +1.8.1.2 -From 2d03e24bded4e30a14656795eb8e052bbaa5ee27 Mon Sep 17 00:00:00 2001 +From 7f17830b2d2e02a1d8614ed06d2eaf37f4a2b9d1 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 05/17] Add EFI signature data types +Subject: [PATCH 05/19] Add EFI signature data types Add the data types that are used for containing hashes, keys and certificates for cryptographic verification. @@ -330,13 +330,13 @@ index fef4ca6..a5dab3c 100644 * All runtime access to EFI goes through this structure: */ -- -1.8.1 +1.8.1.2 -From 2152dae45a6f98592ed5a6da8416a4a799bda3dd Mon Sep 17 00:00:00 2001 +From f6e6bcac73c2c4dd0295a528f80d3c6660e9e279 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 06/17] Add an EFI signature blob parser and key loader. +Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader. X.509 certificates are loaded into the specified keyring as asymmetric type keys. @@ -509,13 +509,13 @@ index a5dab3c..7bfc4f2 100644 * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- -1.8.1 +1.8.1.2 -From bb1024f03b0a4cb05bac6503b933279a905bc5fb Mon Sep 17 00:00:00 2001 +From 26e3eaf96f1433fbb5f0d617b80b5d00e16aeb2c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 07/17] MODSIGN: Add module certificate blacklist keyring +Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring This adds an additional keyring that is used to store certificates that are blacklisted. This keyring is searched first when loading signed modules @@ -621,13 +621,13 @@ index f2970bd..5423195 100644 &key_type_asymmetric, id); if (IS_ERR(key)) -- -1.8.1 +1.8.1.2 -From 10f89ba8724e88046cd05aef20e80a935d3968f6 Mon Sep 17 00:00:00 2001 +From ec7d8de0b4b29fa052dd9408fab20ce46857b486 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH 08/17] MODSIGN: Import certificates from UEFI Secure Boot +Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot Secure Boot stores a list of allowed certificates in the 'db' variable. This imports those certificates into the module signing keyring. This @@ -806,13 +806,13 @@ index 0000000..b9237d7 +} +late_initcall(load_uefi_certs); -- -1.8.1 +1.8.1.2 -From db76f49f8ded0df6aaff8ae2531ff1aaeff04440 Mon Sep 17 00:00:00 2001 +From ff5f0af5e29e73ba00c04bc67978086d5ed811bd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 09/17] PCI: Lock down BAR access in secure boot environments +Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments Any hardware that can potentially generate DMA has to be locked down from userspace in order to avoid it being possible for an attacker to cause @@ -907,13 +907,13 @@ index e1c1ec5..97e785f 100644 dev = pci_get_bus_and_slot(bus, dfn); -- -1.8.1 +1.8.1.2 -From 0d71d1586db8d8f6f2f362953fc747528f0dbb2a Mon Sep 17 00:00:00 2001 +From f6a7b0b3c9ca8b0814d03daed9f98fb009a57cc7 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 10/17] x86: Lock down IO port access in secure boot +Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot environments IO port access would permit users to gain access to PCI configuration @@ -964,13 +964,13 @@ index 0537903..47501fc 100644 return -EFAULT; while (count-- > 0 && i < 65536) { -- -1.8.1 +1.8.1.2 -From cbe40e9c220c6c49774e04d6e4df437a2f450aba Mon Sep 17 00:00:00 2001 +From 014664ed0733041ae2e6ddacd21f8eb8ed94d6e9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 11/17] ACPI: Limit access to custom_method +Subject: [PATCH 11/19] ACPI: Limit access to custom_method It must be impossible for even root to get code executed in kernel context under a secure boot environment. custom_method effectively allows arbitrary @@ -996,13 +996,13 @@ index 5d42c24..247d58b 100644 /* parse the table header to get the table length */ if (count <= sizeof(struct acpi_table_header)) -- -1.8.1 +1.8.1.2 -From 48da61f5b2a04df0a7df6d9e443a6705e2bc6ef9 Mon Sep 17 00:00:00 2001 +From f1262b9e78f41307e0be23aa6c54f79dfc5c8d39 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 12/17] asus-wmi: Restrict debugfs interface +Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface We have no way of validating what all of the Asus WMI methods do on a given machine, and there's a risk that some will allow hardware state to @@ -1049,13 +1049,13 @@ index c0e9ff4..3c10167 100644 1, asus->debug.method_id, &input, &output); -- -1.8.1 +1.8.1.2 -From 293d2f88602d7d951c23e379c66d0adc440de47c Mon Sep 17 00:00:00 2001 +From f31dc86516ee8088177a5a82869a3633a6e555b1 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 13/17] Restrict /dev/mem and /dev/kmem in secure boot setups +Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups Allowing users to write to address space makes it possible for the kernel to be subverted. Restrict this when we need to protect the kernel. @@ -1090,18 +1090,21 @@ index 47501fc..8817cdc 100644 unsigned long to_write = min_t(unsigned long, count, (unsigned long)high_memory - p); -- -1.8.1 +1.8.1.2 -From ca1c6f1c294f4ca76599603b801e84945d6f0277 Mon Sep 17 00:00:00 2001 +From e5724ed32b15d5dec9a239036598d9273b105506 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 14/17] acpi: Ignore acpi_rsdp kernel parameter in a secure +Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment This option allows userspace to pass the RSDP address to the kernel. This could potentially be used to circumvent the secure boot trust model. -We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. +This is setup through the setup_arch function, which is called before the +security_init function sets up the security_ops, so we cannot use a +capable call here. We ignore the setting if we are booted in Secure Boot +mode. Signed-off-by: Josh Boyer --- @@ -1109,7 +1112,7 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 251435a..b67cf29 100644 +index 251435a..eef0b89 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); @@ -1117,18 +1120,18 @@ index 251435a..b67cf29 100644 { #ifdef CONFIG_KEXEC - if (acpi_rsdp) -+ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) ++ if (acpi_rsdp && !efi_enabled(EFI_SECURE_BOOT)) return acpi_rsdp; #endif -- -1.8.1 +1.8.1.2 -From 1e5b3f2c3ea547cd281bf5754fbc7717431db5fe Mon Sep 17 00:00:00 2001 +From 1bc68fa7cb2ea5983ab1de20fd881eed74e214cb Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 15/17] kexec: Disable in a secure boot environment +Subject: [PATCH 15/19] kexec: Disable in a secure boot environment kexec could be used as a vector for a malicious user to use a signed kernel to circumvent the secure boot trust model. In the long run we'll want to @@ -1154,13 +1157,13 @@ index 5e4bd78..dd464e0 100644 /* -- -1.8.1 +1.8.1.2 -From c399cdb725681eba45239b3ae9218f0fc813e678 Mon Sep 17 00:00:00 2001 +From b6ec4b0890d4cb00c17b4a1dee6da84bb5fff597 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH 16/17] MODSIGN: Always enforce module signing in a Secure Boot +Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot environment If a machine is booted into a Secure Boot environment, we need to @@ -1216,13 +1219,13 @@ index 3e544f4..7a9a802 100644 static int param_set_bool_enable_only(const char *val, const struct kernel_param *kp) -- -1.8.1 +1.8.1.2 -From 8e236de2ec08dceb9ce1e8ab07926e85440deb6b Mon Sep 17 00:00:00 2001 +From 19d340a563439ab3892159510bb3ba7730bf9ea9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH 17/17] hibernate: Disable in a Secure Boot environment +Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment There is currently no way to verify the resume image when returning from hibernate. This might compromise the secure boot trust model, @@ -1330,12 +1333,13 @@ index 4ed81e7..b11a0f4 100644 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -- -1.8.1 +1.8.1.2 -From 04a46ceeb9eb2dca0364ce836614de722e988c81 Mon Sep 17 00:00:00 2001 + +From a0f61de745510aade63ef7694cecf11cb98559cf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Feb 2013 19:25:05 -0500 -Subject: [PATCH] efi: Disable secure boot if shim is in insecure mode +Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode A user can manually tell the shim boot loader to disable validation of images it loads. When a user does this, it creates a UEFI variable called @@ -1349,10 +1353,10 @@ Signed-off-by: Josh Boyer 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 96bd86b..6e1331c 100644 +index 4983e43..eea615a 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -851,8 +851,9 @@ fail: +@@ -733,8 +733,9 @@ fail: static int get_secure_boot(efi_system_table_t *_table) { @@ -1363,7 +1367,7 @@ index 96bd86b..6e1331c 100644 efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_status_t status; -@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table) +@@ -758,6 +759,23 @@ static int get_secure_boot(efi_system_table_t *_table) if (setup == 1) return 0; @@ -1388,61 +1392,20 @@ index 96bd86b..6e1331c 100644 } -- -1.8.1 +1.8.1.2 - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.99.210 with SMTP id es18csp140114oab; - Fri, 8 Feb 2013 11:12:52 -0800 (PST) -X-Received: by 10.66.86.71 with SMTP id n7mr19917975paz.77.1360350771724; - Fri, 08 Feb 2013 11:12:51 -0800 (PST) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id e5si41603022pax.261.2013.02.08.11.12.50; - Fri, 08 Feb 2013 11:12:51 -0800 (PST) -Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-efi-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1760288Ab3BHTM0 (ORCPT - + 14 others); Fri, 8 Feb 2013 14:12:26 -0500 -Received: from smtp.outflux.net ([198.145.64.163]:49396 "EHLO smtp.outflux.net" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1760349Ab3BHTMY (ORCPT ); - Fri, 8 Feb 2013 14:12:24 -0500 -Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) - by vinyl.outflux.net (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id r18JCEtT006197; - Fri, 8 Feb 2013 11:12:14 -0800 -Date: Fri, 8 Feb 2013 11:12:13 -0800 -From: Kees Cook -To: linux-kernel@vger.kernel.org -Cc: Matthew Garrett , - "H. Peter Anvin" , - Thomas Gleixner , - Ingo Molnar , x86@kernel.org, - linux-efi@vger.kernel.org, linux-security-module@vger.kernel.org -Subject: [PATCH] x86: Lock down MSR writing in secure boot -Message-ID: <20130208191213.GA25081@www.outflux.net> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -X-MIMEDefang-Filter: outflux$Revision: 1.316 $ -X-HELO: www.outflux.net -X-Scanned-By: MIMEDefang 2.71 on 10.2.0.1 -Sender: linux-efi-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-efi@vger.kernel.org + +From 5467b18cc9b3475658328a38ad6922d6b32c87ca Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 8 Feb 2013 11:12:13 -0800 +Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is set since it could lead to execution of arbitrary code in kernel mode. Signed-off-by: Kees Cook --- -This would be used on top of Matthew Garrett's existing "Secure boot -policy support" patch series. ---- - arch/x86/kernel/msr.c | 7 +++++++ + arch/x86/kernel/msr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c @@ -1471,13 +1434,5 @@ index 4929502..adaab3d 100644 err = -EFAULT; break; -- -1.7.9.5 +1.8.1.2 - --- -Kees Cook -Chrome OS Security --- -To unsubscribe from this list: send the line "unsubscribe linux-efi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html From 6b1ca21dd3c883617964ff95958a41c4f3dc7fcf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Feb 2013 12:21:26 -0500 Subject: [PATCH 191/492] Fix perf report field separator issue (rhbz 906055) --- kernel.spec | 13 +++-- ...period-symbol_conf.field_sep-display.patch | 48 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 perf-hists-Fix-period-symbol_conf.field_sep-display.patch diff --git a/kernel.spec b/kernel.spec index b410b19ab..fedd8fbb4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -793,13 +793,16 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 911479 911473 CVE-2013-0290 Patch22256: net-fix-infinite-loop-in-__skb_recv_datagram.patch +#rhbz 909591 +Patch22255: usb-cypress-supertop.patch + #rhbz 844750 Patch22257: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch -Patch23000: silence-brcmsmac-warning.patch +#rhbz 906055 +Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch -#rhbz 909591 -Patch21255: usb-cypress-supertop.patch +Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 Patch24000: alps-v2-3.7.patch @@ -1538,6 +1541,9 @@ ApplyPatch net-fix-infinite-loop-in-__skb_recv_datagram.patch #rhbz 844750 ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#rhbz 906055 +ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch + #rhbz 812111 ApplyPatch alps-v2-3.7.patch @@ -2405,6 +2411,7 @@ fi # || || %changelog * Wed Feb 20 2013 Josh Boyer +- Fix perf report field separator issue (rhbz 906055) - Fix oops from acpi_rsdp setup in secure-boot patchset (rhbz 906225) * Tue Feb 19 2013 Josh Boyer diff --git a/perf-hists-Fix-period-symbol_conf.field_sep-display.patch b/perf-hists-Fix-period-symbol_conf.field_sep-display.patch new file mode 100644 index 000000000..f81755cdf --- /dev/null +++ b/perf-hists-Fix-period-symbol_conf.field_sep-display.patch @@ -0,0 +1,48 @@ +From 755b5f5715c117f4723ec04a81a46da85c9179a3 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sat, 20 Oct 2012 22:14:10 +0200 +Subject: [PATCH] perf hists: Fix period symbol_conf.field_sep display + +Upstream commit c0d246b85fc7d42688d7a5d999ea671777caf65b + +Currently we don't properly display hist data with symbol_conf.field_sep +separator. We need to display either space or separator. + +Signed-off-by: Jiri Olsa +Cc: Arnaldo Carvalho de Melo +Cc: Peter Zijlstra +Cc: Ingo Molnar +Cc: Paul Mackerras +Cc: Corey Ashford +Cc: Frederic Weisbecker +Cc: Namhyung Kim +Link: http://lkml.kernel.org/n/tip-cyggwys0bz5kqdowwvfd8h72@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +--- + tools/perf/ui/hist.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c +index f5a1e4f..947e20a 100644 +--- a/tools/perf/ui/hist.c ++++ b/tools/perf/ui/hist.c +@@ -363,11 +363,15 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, + if (!perf_hpp__format[i].cond) + continue; + ++ /* ++ * If there's no field_sep, we still need ++ * to display initial ' '. ++ */ + if (!sep || !first) { + ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); + advance_hpp(hpp, ret); ++ } else + first = false; +- } + + if (color && perf_hpp__format[i].color) + ret = perf_hpp__format[i].color(hpp, he); +-- +1.8.1.2 + From 445e22c3178315e287ccde10b164a93fc67890b5 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 21 Feb 2013 10:26:52 -0500 Subject: [PATCH 192/492] Resolves: rhbz 892060 Backport of upstream commit ecd9883724b78cc72ed92c98bcb1a46c764fff21 --- ipv6-dst-from-ptr-race.patch | 134 +++++++++++++++++++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 143 insertions(+) create mode 100644 ipv6-dst-from-ptr-race.patch diff --git a/ipv6-dst-from-ptr-race.patch b/ipv6-dst-from-ptr-race.patch new file mode 100644 index 000000000..d1cab3230 --- /dev/null +++ b/ipv6-dst-from-ptr-race.patch @@ -0,0 +1,134 @@ +diff -up ./include/net/dst.h.orig ./include/net/dst.h +--- ./include/net/dst.h.orig 2012-12-10 22:30:57.000000000 -0500 ++++ ./include/net/dst.h 2013-02-20 09:42:49.541777989 -0500 +@@ -36,13 +36,9 @@ struct dst_entry { + struct net_device *dev; + struct dst_ops *ops; + unsigned long _metrics; +- union { +- unsigned long expires; +- /* point to where the dst_entry copied from */ +- struct dst_entry *from; +- }; ++ unsigned long expires; + struct dst_entry *path; +- void *__pad0; ++ struct dst_entry *from; + #ifdef CONFIG_XFRM + struct xfrm_state *xfrm; + #else +diff -up ./include/net/ip6_fib.h.orig ./include/net/ip6_fib.h +--- ./include/net/ip6_fib.h.orig 2012-12-10 22:30:57.000000000 -0500 ++++ ./include/net/ip6_fib.h 2013-02-20 09:42:49.597779552 -0500 +@@ -157,50 +157,35 @@ static inline struct inet6_dev *ip6_dst_ + + static inline void rt6_clean_expires(struct rt6_info *rt) + { +- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) +- dst_release(rt->dst.from); +- + rt->rt6i_flags &= ~RTF_EXPIRES; +- rt->dst.from = NULL; + } + + static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) + { +- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) +- dst_release(rt->dst.from); +- +- rt->rt6i_flags |= RTF_EXPIRES; + rt->dst.expires = expires; ++ rt->rt6i_flags |= RTF_EXPIRES; + } + +-static inline void rt6_update_expires(struct rt6_info *rt, int timeout) ++static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) + { +- if (!(rt->rt6i_flags & RTF_EXPIRES)) { +- if (rt->dst.from) +- dst_release(rt->dst.from); +- /* dst_set_expires relies on expires == 0 +- * if it has not been set previously. +- */ +- rt->dst.expires = 0; +- } ++ struct rt6_info *rt; + +- dst_set_expires(&rt->dst, timeout); +- rt->rt6i_flags |= RTF_EXPIRES; ++ for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); ++ rt = (struct rt6_info *)rt->dst.from); ++ if (rt && rt != rt0) ++ rt0->dst.expires = rt->dst.expires; ++ ++ dst_set_expires(&rt0->dst, timeout); ++ rt0->rt6i_flags |= RTF_EXPIRES; + } + + static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) + { + struct dst_entry *new = (struct dst_entry *) from; + +- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) { +- if (new == rt->dst.from) +- return; +- dst_release(rt->dst.from); +- } +- + rt->rt6i_flags &= ~RTF_EXPIRES; +- rt->dst.from = new; + dst_hold(new); ++ rt->dst.from = new; + } + + struct fib6_walker_t { +diff -up ./net/core/dst.c.orig ./net/core/dst.c +--- ./net/core/dst.c.orig 2012-12-10 22:30:57.000000000 -0500 ++++ ./net/core/dst.c 2013-02-20 09:42:49.984790357 -0500 +@@ -179,6 +179,7 @@ void *dst_alloc(struct dst_ops *ops, str + dst_init_metrics(dst, dst_default_metrics, true); + dst->expires = 0UL; + dst->path = dst; ++ dst->from = NULL; + #ifdef CONFIG_XFRM + dst->xfrm = NULL; + #endif +diff -up ./net/ipv6/route.c.orig ./net/ipv6/route.c +--- ./net/ipv6/route.c.orig 2012-12-10 22:30:57.000000000 -0500 ++++ ./net/ipv6/route.c 2013-02-20 09:42:50.238797449 -0500 +@@ -297,6 +297,7 @@ static void ip6_dst_destroy(struct dst_e + { + struct rt6_info *rt = (struct rt6_info *)dst; + struct inet6_dev *idev = rt->rt6i_idev; ++ struct dst_entry *from = dst->from; + + if (rt->n) + neigh_release(rt->n); +@@ -309,8 +310,8 @@ static void ip6_dst_destroy(struct dst_e + in6_dev_put(idev); + } + +- if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) +- dst_release(dst->from); ++ dst->from = NULL; ++ dst_release(from); + + if (rt6_has_peer(rt)) { + struct inet_peer *peer = rt6_peer_ptr(rt); +@@ -998,7 +999,6 @@ struct dst_entry *ip6_blackhole_route(st + + rt->rt6i_gateway = ort->rt6i_gateway; + rt->rt6i_flags = ort->rt6i_flags; +- rt6_clean_expires(rt); + rt->rt6i_metric = 0; + + memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); +@@ -1814,8 +1814,6 @@ static struct rt6_info *ip6_rt_copy(stru + if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == + (RTF_DEFAULT | RTF_ADDRCONF)) + rt6_set_from(rt, ort); +- else +- rt6_clean_expires(rt); + rt->rt6i_metric = 0; + + #ifdef CONFIG_IPV6_SUBTREES diff --git a/kernel.spec b/kernel.spec index fedd8fbb4..13722b913 100644 --- a/kernel.spec +++ b/kernel.spec @@ -807,6 +807,9 @@ Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 Patch24000: alps-v2-3.7.patch +#rhbz 892060 +Patch24001: ipv6-dst-from-ptr-race.patch + # END OF PATCH DEFINITIONS %endif @@ -1547,6 +1550,9 @@ ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch #rhbz 812111 ApplyPatch alps-v2-3.7.patch +#rhbz 892060 +ApplyPatch ipv6-dst-from-ptr-race.patch + # END OF PATCH APPLICATIONS %endif @@ -2410,6 +2416,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 21 2013 Neil Horman +- Fix crash from race in ipv6 dst entries (rhbz 892060) + * Wed Feb 20 2013 Josh Boyer - Fix perf report field separator issue (rhbz 906055) - Fix oops from acpi_rsdp setup in secure-boot patchset (rhbz 906225) From e7cbab64b1864c04cb58cd967fc8b7ad14dd6b34 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 22 Feb 2013 08:53:39 -0500 Subject: [PATCH 193/492] Add support for bluetooth in Acer Aspire S7 (rhbz 879408) --- ...upport-for-Foxconn-Hon-Hai-0489-e056.patch | 56 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch diff --git a/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch b/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch new file mode 100644 index 000000000..322a3c262 --- /dev/null +++ b/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch @@ -0,0 +1,56 @@ +From a5b6b6d3574e57559ec44865f48022cd116dd669 Mon Sep 17 00:00:00 2001 +From: AceLan Kao +Date: Thu, 3 Jan 2013 12:25:00 +0800 +Subject: [PATCH] Bluetooth: Add support for Foxconn / Hon Hai [0489:e056] + +Add support for the AR9462 chip + +T: Bus=01 Lev=02 Prnt=02 Port=05 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0489 ProdID=e056 Rev=00.01 +C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb + +Signed-off-by: AceLan Kao +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/ath3k.c | 2 ++ + drivers/bluetooth/btusb.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index b00000e..b86ea45 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -81,6 +81,7 @@ static struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0xE004) }, + { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0489, 0xe057) }, ++ { USB_DEVICE(0x0489, 0xe056) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, +@@ -108,6 +109,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a1d4ede..c76030e 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -139,6 +139,7 @@ static struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 13722b913..6f4b9a07e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -802,6 +802,9 @@ Patch22257: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #rhbz 906055 Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch +#rhbz 879408 +Patch22259: Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 @@ -1553,6 +1556,9 @@ ApplyPatch alps-v2-3.7.patch #rhbz 892060 ApplyPatch ipv6-dst-from-ptr-race.patch +#rhbz 879408 +ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch + # END OF PATCH APPLICATIONS %endif @@ -2416,6 +2422,9 @@ fi # ||----w | # || || %changelog +* Fri Feb 22 2013 Josh Boyer +- Add support for bluetooth in Acer Aspire S7 (rhbz 879408) + * Thu Feb 21 2013 Neil Horman - Fix crash from race in ipv6 dst entries (rhbz 892060) From 950189b40da0af5930efd5223b71186e2ff5863a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 24 Feb 2013 13:58:12 -0500 Subject: [PATCH 194/492] CVE-2013-1763 sock_diag: out-of-bounds access to sock_diag_handlers (rhbz 915052,915057) --- kernel.spec | 11 ++- ...-bounds-access-to-sock_diag_handlers.patch | 86 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch diff --git a/kernel.spec b/kernel.spec index 6f4b9a07e..a44a59cb6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 205 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -805,6 +805,9 @@ Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch #rhbz 879408 Patch22259: Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch +#CVE-2013-1763 rhbz 915052,915057 +Patch22260: sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 @@ -1559,6 +1562,9 @@ ApplyPatch ipv6-dst-from-ptr-race.patch #rhbz 879408 ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch +#CVE-2013-1763 rhbz 915052,915057 +ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch + # END OF PATCH APPLICATIONS %endif @@ -2422,6 +2428,9 @@ fi # ||----w | # || || %changelog +* Sun Feb 24 2013 Josh Boyer - 3.7.9-205 +- CVE-2013-1763 sock_diag: out-of-bounds access to sock_diag_handlers (rhbz 915052,915057) + * Fri Feb 22 2013 Josh Boyer - Add support for bluetooth in Acer Aspire S7 (rhbz 879408) diff --git a/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch b/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch new file mode 100644 index 000000000..7508a7676 --- /dev/null +++ b/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch @@ -0,0 +1,86 @@ +Path: news.gmane.org!not-for-mail +From: Mathias Krause +Newsgroups: gmane.linux.network +Subject: [PATCH 1/2] sock_diag: Fix out-of-bounds access to sock_diag_handlers[] +Date: Sat, 23 Feb 2013 12:13:47 +0100 +Lines: 28 +Approved: news@gmane.org +Message-ID: <1361618028-9024-2-git-send-email-minipli@googlemail.com> +References: <1361618028-9024-1-git-send-email-minipli@googlemail.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: ger.gmane.org 1361618069 2156 80.91.229.3 (23 Feb 2013 11:14:29 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Sat, 23 Feb 2013 11:14:29 +0000 (UTC) +Cc: netdev@vger.kernel.org, Mathias Krause +To: "David S. Miller" +Original-X-From: netdev-owner@vger.kernel.org Sat Feb 23 12:14:49 2013 +Return-path: +Envelope-to: linux-netdev-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1U9D3z-0003H8-6Z + for linux-netdev-2@plane.gmane.org; Sat, 23 Feb 2013 12:14:43 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757811Ab3BWLOQ (ORCPT ); + Sat, 23 Feb 2013 06:14:16 -0500 +Original-Received: from mail-bk0-f53.google.com ([209.85.214.53]:46309 "EHLO + mail-bk0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1757044Ab3BWLOM (ORCPT + ); Sat, 23 Feb 2013 06:14:12 -0500 +Original-Received: by mail-bk0-f53.google.com with SMTP id j10so635828bkw.40 + for ; Sat, 23 Feb 2013 03:14:11 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=googlemail.com; s=20120113; + h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to + :references; + bh=NM4oEi0qkLdUhxSK1IKpg60DjwOeNtHa0EKsIVngex0=; + b=xdMKHhwMk8BGqDXVGVKf/KcWjSwJajtfpzPDCVugS7vLJh2HtrJnhKiBOUta3XNtTK + ibjB4FQuAenC9ZjXfuEPdo4ct1CIQC2xN2sW/VmeqhYip/xDJ/csVRnX/BxNYWDTFkHo + Uva0peiyrsvR1W0oTeqNLQ1fYIm4f1UwYHzhouschB9mlYHfrCDQFuI7TDfOTUNN1lmY + D5T4vV1aWKsxHx1OYFSRS3aUo3l0Tyzx0zeSPJH+aL3mrhoBDc84RtjsmRafY7RiEXi8 + ropiUO1Q9ATcLZd1/2+L/ausYzkP7NiU16SdbkQWuZkP1J8nBK7n5pahlYnDcktklyGM + od5Q== +X-Received: by 10.204.149.196 with SMTP id u4mr2435753bkv.23.1361618051168; + Sat, 23 Feb 2013 03:14:11 -0800 (PST) +Original-Received: from jig.fritz.box (pD9EB2658.dip.t-dialin.net. [217.235.38.88]) + by mx.google.com with ESMTPS id gy3sm1474145bkc.16.2013.02.23.03.14.09 + (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); + Sat, 23 Feb 2013 03:14:10 -0800 (PST) +X-Mailer: git-send-email 1.7.10.4 +In-Reply-To: <1361618028-9024-1-git-send-email-minipli@googlemail.com> +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:260061 +Archived-At: + +Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY +with a family greater or equal then AF_MAX -- the array size of +sock_diag_handlers[]. The current code does not test for this +condition therefore is vulnerable to an out-of-bound access opening +doors for a privilege escalation. + +Signed-off-by: Mathias Krause +--- + net/core/sock_diag.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c +index 602cd63..750f44f 100644 +--- a/net/core/sock_diag.c ++++ b/net/core/sock_diag.c +@@ -121,6 +121,9 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + if (nlmsg_len(nlh) < sizeof(*req)) + return -EINVAL; + ++ if (req->sdiag_family >= AF_MAX) ++ return -EINVAL; ++ + hndl = sock_diag_lock_handler(req->sdiag_family); + if (hndl == NULL) + err = -ENOENT; +-- +1.7.10.4 + From fa8ce41f27e65dfd7c9b9a326cedd259b36df152 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Feb 2013 10:00:31 -0500 Subject: [PATCH 195/492] Honor dmesg_restrict for /dev/kmsg (rhbz 903192) --- ...or-dmesg_restrict-sysctl-on-dev-kmsg.patch | 46 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch diff --git a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch new file mode 100644 index 000000000..acaf5f881 --- /dev/null +++ b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch @@ -0,0 +1,46 @@ +From feaf4959c30d0640093a607c577940d3e9351076 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 22 Feb 2013 11:47:37 -0500 +Subject: [PATCH] kmsg: Honor dmesg_restrict sysctl on /dev/kmsg + +Originally, the addition of the dmesg_restrict covered both the syslog +method of accessing dmesg, as well as /dev/kmsg itself. This was done +indirectly by security_syslog calling cap_syslog before doing any LSM +checks. + +However, commit 12b3052c3ee (capabilities/syslog: open code cap_syslog +logic to fix build failure) moved the code around and pushed the checks +into the caller itself. That seems to have inadvertently dropped the +checks for dmesg_restrict on /dev/kmsg. Most people haven't noticed +because util-linux dmesg(1) defaults to using the syslog method for +access in older versions. With util-linux 2.22 and a kernel newer than +3.5, dmesg(1) defaults to reading directly from /dev/kmsg. + +Fix this by making an explicit check in the devkmsg_open function. + +This fixes https://bugzilla.redhat.com/show_bug.cgi?id=903192 + +Reported-by: Christian Kujau +CC: stable@vger.kernel.org +Signed-off-by: Josh Boyer +--- + kernel/printk.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/printk.c b/kernel/printk.c +index f24633a..398ef9a 100644 +--- a/kernel/printk.c ++++ b/kernel/printk.c +@@ -615,6 +615,9 @@ static int devkmsg_open(struct inode *inode, struct file *file) + struct devkmsg_user *user; + int err; + ++ if (dmesg_restrict && !capable(CAP_SYSLOG)) ++ return -EACCES; ++ + /* write-only does not need any file context */ + if ((file->f_flags & O_ACCMODE) == O_WRONLY) + return 0; +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index a44a59cb6..22713dfc5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 205 +%global baserelease 206 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -808,6 +808,9 @@ Patch22259: Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch #CVE-2013-1763 rhbz 915052,915057 Patch22260: sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch +#rhbz 903192 +Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 @@ -1565,6 +1568,9 @@ ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch #CVE-2013-1763 rhbz 915052,915057 ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch +#rhbz 903192 +ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2428,6 +2434,9 @@ fi # ||----w | # || || %changelog +* Mon Feb 25 2013 Josh Boyer +- Honor dmesg_restrict for /dev/kmsg (rhbz 903192) + * Sun Feb 24 2013 Josh Boyer - 3.7.9-205 - CVE-2013-1763 sock_diag: out-of-bounds access to sock_diag_handlers (rhbz 915052,915057) From a46911c9f818ef20f51de572ab1f75957e8732b3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Feb 2013 08:14:54 -0500 Subject: [PATCH 196/492] Fix vmalloc_fault oops during lazy MMU (rhbz 914737) --- kernel.spec | 9 ++++ ...c_fault-oops-during-lazy-MMU-updates.patch | 48 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch diff --git a/kernel.spec b/kernel.spec index 22713dfc5..4410b1ee4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -811,6 +811,9 @@ Patch22260: sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch #rhbz 903192 Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch +#rhbz 914737 +Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 @@ -1571,6 +1574,9 @@ ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch #rhbz 903192 ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch +#rhbz 914737 +ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch + # END OF PATCH APPLICATIONS %endif @@ -2434,6 +2440,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 26 2013 Josh Boyer +- Fix vmalloc_fault oops during lazy MMU (rhbz 914737) + * Mon Feb 25 2013 Josh Boyer - Honor dmesg_restrict for /dev/kmsg (rhbz 903192) diff --git a/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch b/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch new file mode 100644 index 000000000..31b0de8fb --- /dev/null +++ b/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch @@ -0,0 +1,48 @@ +From: Samu Kallio <> +Subject: [PATCH] x86: mm: Fix vmalloc_fault oops during lazy MMU updates. +Date: Sun, 17 Feb 2013 04:35:52 +0200 + +In paravirtualized x86_64 kernels, vmalloc_fault may cause an oops +when lazy MMU updates are enabled, because set_pgd effects are being +deferred. + +One instance of this problem is during process mm cleanup with memory +cgroups enabled. The chain of events is as follows: + +- zap_pte_range enables lazy MMU updates +- zap_pte_range eventually calls mem_cgroup_charge_statistics, + which accesses the vmalloc'd mem_cgroup per-cpu stat area +- vmalloc_fault is triggered which tries to sync the corresponding + PGD entry with set_pgd, but the update is deferred +- vmalloc_fault oopses due to a mismatch in the PUD entries + +Calling arch_flush_lazy_mmu_mode immediately after set_pgd makes the +changes visible to the consistency checks. + +Signed-off-by: Samu Kallio +--- + arch/x86/mm/fault.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) +diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c +index 8e13ecb..0a45298 100644 +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -378,10 +378,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) + if (pgd_none(*pgd_ref)) + return -1; + +- if (pgd_none(*pgd)) ++ if (pgd_none(*pgd)) { + set_pgd(pgd, *pgd_ref); +- else ++ arch_flush_lazy_mmu_mode(); ++ } else { + BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); ++ } + + /* + * Below here mismatches are bugs because these lower tables +-- +1.8.1.3 + + From f23e92fc888d1346c2714febe3b92dfdcd862973 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Feb 2013 09:08:13 -0500 Subject: [PATCH 197/492] CVE-2013-1767 tmpfs: fix use-after-free of mempolicy obj (rhbz 915592,915716) --- kernel.spec | 7 ++ ...x-use-after-free-of-mempolicy-object.patch | 107 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 tmpfs-fix-use-after-free-of-mempolicy-object.patch diff --git a/kernel.spec b/kernel.spec index 4410b1ee4..a85160bdf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -814,6 +814,9 @@ Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +#CVE-2013-1767 rhbz 915592,915716 +Patch22263: tmpfs-fix-use-after-free-of-mempolicy-object.patch + Patch23000: silence-brcmsmac-warning.patch #rhbz 812111 @@ -1577,6 +1580,9 @@ ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +#CVE-2013-1767 rhbz 915592,915716 +ApplyPatch tmpfs-fix-use-after-free-of-mempolicy-object.patch + # END OF PATCH APPLICATIONS %endif @@ -2441,6 +2447,7 @@ fi # || || %changelog * Tue Feb 26 2013 Josh Boyer +- CVE-2013-1767 tmpfs: fix use-after-free of mempolicy obj (rhbz 915592,915716) - Fix vmalloc_fault oops during lazy MMU (rhbz 914737) * Mon Feb 25 2013 Josh Boyer diff --git a/tmpfs-fix-use-after-free-of-mempolicy-object.patch b/tmpfs-fix-use-after-free-of-mempolicy-object.patch new file mode 100644 index 000000000..56dbf8e80 --- /dev/null +++ b/tmpfs-fix-use-after-free-of-mempolicy-object.patch @@ -0,0 +1,107 @@ +From 5f00110f7273f9ff04ac69a5f85bb535a4fd0987 Mon Sep 17 00:00:00 2001 +From: Greg Thelen +Date: Fri, 22 Feb 2013 16:36:01 -0800 +Subject: [PATCH] tmpfs: fix use-after-free of mempolicy object + +The tmpfs remount logic preserves filesystem mempolicy if the mpol=M +option is not specified in the remount request. A new policy can be +specified if mpol=M is given. + +Before this patch remounting an mpol bound tmpfs without specifying +mpol= mount option in the remount request would set the filesystem's +mempolicy object to a freed mempolicy object. + +To reproduce the problem boot a DEBUG_PAGEALLOC kernel and run: + # mkdir /tmp/x + + # mount -t tmpfs -o size=100M,mpol=interleave nodev /tmp/x + + # grep /tmp/x /proc/mounts + nodev /tmp/x tmpfs rw,relatime,size=102400k,mpol=interleave:0-3 0 0 + + # mount -o remount,size=200M nodev /tmp/x + + # grep /tmp/x /proc/mounts + nodev /tmp/x tmpfs rw,relatime,size=204800k,mpol=??? 0 0 + # note ? garbage in mpol=... output above + + # dd if=/dev/zero of=/tmp/x/f count=1 + # panic here + +Panic: + BUG: unable to handle kernel NULL pointer dereference at (null) + IP: [< (null)>] (null) + [...] + Oops: 0010 [#1] SMP DEBUG_PAGEALLOC + Call Trace: + mpol_shared_policy_init+0xa5/0x160 + shmem_get_inode+0x209/0x270 + shmem_mknod+0x3e/0xf0 + shmem_create+0x18/0x20 + vfs_create+0xb5/0x130 + do_last+0x9a1/0xea0 + path_openat+0xb3/0x4d0 + do_filp_open+0x42/0xa0 + do_sys_open+0xfe/0x1e0 + compat_sys_open+0x1b/0x20 + cstar_dispatch+0x7/0x1f + +Non-debug kernels will not crash immediately because referencing the +dangling mpol will not cause a fault. Instead the filesystem will +reference a freed mempolicy object, which will cause unpredictable +behavior. + +The problem boils down to a dropped mpol reference below if +shmem_parse_options() does not allocate a new mpol: + + config = *sbinfo + shmem_parse_options(data, &config, true) + mpol_put(sbinfo->mpol) + sbinfo->mpol = config.mpol /* BUG: saves unreferenced mpol */ + +This patch avoids the crash by not releasing the mempolicy if +shmem_parse_options() doesn't create a new mpol. + +How far back does this issue go? I see it in both 2.6.36 and 3.3. I did +not look back further. + +Signed-off-by: Greg Thelen +Acked-by: Hugh Dickins +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + mm/shmem.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/mm/shmem.c b/mm/shmem.c +index 7162c58..5e2ff59 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -2486,6 +2486,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) + unsigned long inodes; + int error = -EINVAL; + ++ config.mpol = NULL; + if (shmem_parse_options(data, &config, true)) + return error; + +@@ -2510,8 +2511,13 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) + sbinfo->max_inodes = config.max_inodes; + sbinfo->free_inodes = config.max_inodes - inodes; + +- mpol_put(sbinfo->mpol); +- sbinfo->mpol = config.mpol; /* transfers initial ref */ ++ /* ++ * Preserve previous mempolicy unless mpol remount option was specified. ++ */ ++ if (config.mpol) { ++ mpol_put(sbinfo->mpol); ++ sbinfo->mpol = config.mpol; /* transfers initial ref */ ++ } + out: + spin_unlock(&sbinfo->stat_lock); + return error; +-- +1.8.1.2 + From c546daa7be3058e621b8c32883fd690ab84efcfa Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 26 Feb 2013 17:02:44 -0600 Subject: [PATCH 198/492] Avoid recursion in put_user_ns, potential overflow --- kernel.spec | 9 +- userns-avoid-recursion-in-put_user_ns.patch | 108 ++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 userns-avoid-recursion-in-put_user_ns.patch diff --git a/kernel.spec b/kernel.spec index a85160bdf..fdfa562c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 206 +%global baserelease 207 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -825,6 +825,8 @@ Patch24000: alps-v2-3.7.patch #rhbz 892060 Patch24001: ipv6-dst-from-ptr-race.patch +Patch24100: userns-avoid-recursion-in-put_user_ns.patch + # END OF PATCH DEFINITIONS %endif @@ -1583,6 +1585,8 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #CVE-2013-1767 rhbz 915592,915716 ApplyPatch tmpfs-fix-use-after-free-of-mempolicy-object.patch +ApplyPatch userns-avoid-recursion-in-put_user_ns.patch + # END OF PATCH APPLICATIONS %endif @@ -2446,6 +2450,9 @@ fi # ||----w | # || || %changelog +* Tue Feb 26 2013 Justin M. Forbes +- Avoid recursion in put_user_ns, potential overflow + * Tue Feb 26 2013 Josh Boyer - CVE-2013-1767 tmpfs: fix use-after-free of mempolicy obj (rhbz 915592,915716) - Fix vmalloc_fault oops during lazy MMU (rhbz 914737) diff --git a/userns-avoid-recursion-in-put_user_ns.patch b/userns-avoid-recursion-in-put_user_ns.patch new file mode 100644 index 000000000..d364e79f5 --- /dev/null +++ b/userns-avoid-recursion-in-put_user_ns.patch @@ -0,0 +1,108 @@ +commit c61a2810a2161986353705b44d9503e6bb079f4f +Author: Eric W. Biederman +Date: Fri Dec 28 18:58:39 2012 -0800 + + userns: Avoid recursion in put_user_ns + + When freeing a deeply nested user namespace free_user_ns calls + put_user_ns on it's parent which may in turn call free_user_ns again. + When -fno-optimize-sibling-calls is passed to gcc one stack frame per + user namespace is left on the stack, potentially overflowing the + kernel stack. CONFIG_FRAME_POINTER forces -fno-optimize-sibling-calls + so we can't count on gcc to optimize this code. + + Remove struct kref and use a plain atomic_t. Making the code more + flexible and easier to comprehend. Make the loop in free_user_ns + explict to guarantee that the stack does not overflow with + CONFIG_FRAME_POINTER enabled. + + I have tested this fix with a simple program that uses unshare to + create a deeply nested user namespace structure and then calls exit. + With 1000 nesteuser namespaces before this change running my test + program causes the kernel to die a horrible death. With 10,000,000 + nested user namespaces after this change my test program runs to + completion and causes no harm. + + Acked-by: Serge Hallyn + Pointed-out-by: Vasily Kulikov + Signed-off-by: "Eric W. Biederman" + +--- linux-3.7.9-105.fc17.noarch/include/linux/user_namespace.h 2013-02-14 11:29:49.757652513 -0600 ++++ linux-3.7.9-105.fc17.user_ns/include/linux/user_namespace.h 2013-02-26 15:19:40.696782035 -0600 +@@ -21,7 +21,7 @@ struct user_namespace { + struct uid_gid_map uid_map; + struct uid_gid_map gid_map; + struct uid_gid_map projid_map; +- struct kref kref; ++ atomic_t count; + struct user_namespace *parent; + kuid_t owner; + kgid_t group; +@@ -34,17 +34,17 @@ extern struct user_namespace init_user_n + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) + { + if (ns) +- kref_get(&ns->kref); ++ atomic_inc(&ns->count); + return ns; + } + + extern int create_user_ns(struct cred *new); +-extern void free_user_ns(struct kref *kref); ++extern void free_user_ns(struct user_namespace *ns); + + static inline void put_user_ns(struct user_namespace *ns) + { +- if (ns) +- kref_put(&ns->kref, free_user_ns); ++ if (ns && atomic_dec_and_test(&ns->count)) ++ free_user_ns(ns); + } + + struct seq_operations; +--- linux-3.7.9-105.fc17.noarch/kernel/user.c 2013-02-14 11:29:46.675652732 -0600 ++++ linux-3.7.9-105.fc17.user_ns/kernel/user.c 2013-02-26 15:16:12.347796824 -0600 +@@ -46,9 +46,7 @@ struct user_namespace init_user_ns = { + .count = 4294967295U, + }, + }, +- .kref = { +- .refcount = ATOMIC_INIT(3), +- }, ++ .count = ATOMIC_INIT(3), + .owner = GLOBAL_ROOT_UID, + .group = GLOBAL_ROOT_GID, + }; +--- linux-3.7.9-105.fc17.noarch/kernel/user_namespace.c 2013-02-14 11:29:46.690652731 -0600 ++++ linux-3.7.9-105.fc17.user_ns/kernel/user_namespace.c 2013-02-26 15:24:47.984760224 -0600 +@@ -52,7 +52,7 @@ int create_user_ns(struct cred *new) + if (!ns) + return -ENOMEM; + +- kref_init(&ns->kref); ++ atomic_set(&ns->count, 1); + ns->parent = parent_ns; + ns->owner = owner; + ns->group = group; +@@ -78,14 +78,15 @@ int create_user_ns(struct cred *new) + return 0; + } + +-void free_user_ns(struct kref *kref) ++void free_user_ns(struct user_namespace *ns) + { +- struct user_namespace *parent, *ns = +- container_of(kref, struct user_namespace, kref); ++ struct user_namespace *parent; + +- parent = ns->parent; +- kmem_cache_free(user_ns_cachep, ns); +- put_user_ns(parent); ++ do { ++ parent = ns->parent; ++ kmem_cache_free(user_ns_cachep, ns); ++ ns = parent; ++ } while (atomic_dec_and_test(&parent->count)); + } + EXPORT_SYMBOL(free_user_ns); + From 1c0d824c486d3425286b5cc255cf4bad9e27297f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Feb 2013 13:14:18 -0500 Subject: [PATCH 199/492] Rebase to 3.8.0 Still work to do (See changelog) --- ...e-enable-interrupts-after-tx-timeout.patch | 29 - ...ing-address-before-enabling-receiver.patch | 64 - ...t-ring-address-after-enabling-C-mode.patch | 100 - USB-report-submission-of-active-URBs.patch | 46 - ...-set_debug-on-pl310-r3p0-and-earlier.patch | 31 - brcmsmac-updates-rhbz892428.patch | 28 - config-arm-generic | 14 + config-arm-kirkwood | 12 +- config-arm-omap | 62 +- config-arm-tegra | 20 +- config-armv7 | 84 +- config-generic | 72 +- config-powerpc-generic | 7 +- config-s390x | 21 +- config-x86-32-generic | 8 + config-x86-generic | 3 + config-x86_64-generic | 4 + ...Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch | 28 - efivarfs-3.7.patch | 1654 ----------------- exec-use-eloop-for-max-recursion-depth.patch | 144 -- handle-efi-roms.patch | 388 ---- kernel.spec | 116 +- modsign-post-KS-jwb.patch | 78 - ...infinite-loop-in-__skb_recv_datagram.patch | 53 - power-x86-destdir.patch | 35 - ...130219.patch => secure-boot-20130219.patch | 0 silence-brcmsmac-warning.patch | 14 - sources | 1 - 28 files changed, 309 insertions(+), 2807 deletions(-) delete mode 100644 8139cp-re-enable-interrupts-after-tx-timeout.patch delete mode 100644 8139cp-revert-set-ring-address-before-enabling-receiver.patch delete mode 100644 8139cp-set-ring-address-after-enabling-C-mode.patch delete mode 100644 USB-report-submission-of-active-URBs.patch delete mode 100644 arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch delete mode 100644 brcmsmac-updates-rhbz892428.patch delete mode 100644 drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch delete mode 100644 efivarfs-3.7.patch delete mode 100644 exec-use-eloop-for-max-recursion-depth.patch delete mode 100644 handle-efi-roms.patch delete mode 100644 modsign-post-KS-jwb.patch delete mode 100644 net-fix-infinite-loop-in-__skb_recv_datagram.patch delete mode 100644 power-x86-destdir.patch rename secure-boot-3.7-20130219.patch => secure-boot-20130219.patch (100%) delete mode 100644 silence-brcmsmac-warning.patch diff --git a/8139cp-re-enable-interrupts-after-tx-timeout.patch b/8139cp-re-enable-interrupts-after-tx-timeout.patch deleted file mode 100644 index c0196188e..000000000 --- a/8139cp-re-enable-interrupts-after-tx-timeout.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 01ffc0a7f1c1801a2354719dedbc32aff45b987d Mon Sep 17 00:00:00 2001 -From: David Woodhouse -Date: Sat, 24 Nov 2012 12:11:21 +0000 -Subject: [PATCH] 8139cp: re-enable interrupts after tx timeout - -Recovery doesn't work too well if we leave interrupts disabled... - -Signed-off-by: David Woodhouse -Acked-by: Francois Romieu -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/8139cp.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c -index 3de318d..6cb96b4 100644 ---- a/drivers/net/ethernet/realtek/8139cp.c -+++ b/drivers/net/ethernet/realtek/8139cp.c -@@ -1219,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev) - cp_clean_rings(cp); - rc = cp_init_rings(cp); - cp_start_hw(cp); -+ cp_enable_irq(cp); - - netif_wake_queue(dev); - --- -1.7.6.5 - diff --git a/8139cp-revert-set-ring-address-before-enabling-receiver.patch b/8139cp-revert-set-ring-address-before-enabling-receiver.patch deleted file mode 100644 index 07ae2c28d..000000000 --- a/8139cp-revert-set-ring-address-before-enabling-receiver.patch +++ /dev/null @@ -1,64 +0,0 @@ -From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 -From: Francois Romieu -Date: Wed, 21 Nov 2012 10:07:29 +0000 -Subject: 8139cp: revert "set ring address before enabling receiver" - -From: Francois Romieu - -commit b26623dab7eeb1e9f5898c7a49458789dd492f20 upstream. - -This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. - -The original patch was tested with emulated hardware. Real -hardware chokes. - -Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 - -Signed-off-by: Francois Romieu -Acked-by: Jeff Garzik -Signed-off-by: David S. Miller -Signed-off-by: CAI Qian -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/realtek/8139cp.c -+++ b/drivers/net/ethernet/realtek/8139cp.c -@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_privat - cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - -- cpw32_f(HiTxRingAddr, 0); -- cpw32_f(HiTxRingAddr + 4, 0); -- -- ring_dma = cp->ring_dma; -- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -- -- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -- - cp_start_hw(cp); - cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ - -@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_privat - - cpw8(Config5, cpr8(Config5) & PMEStatus); - -+ cpw32_f(HiTxRingAddr, 0); -+ cpw32_f(HiTxRingAddr + 4, 0); -+ -+ ring_dma = cp->ring_dma; -+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -+ -+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -+ - cpw16(MultiIntr, 0); - - cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/8139cp-set-ring-address-after-enabling-C-mode.patch b/8139cp-set-ring-address-after-enabling-C-mode.patch deleted file mode 100644 index 33bd340e9..000000000 --- a/8139cp-set-ring-address-after-enabling-C-mode.patch +++ /dev/null @@ -1,100 +0,0 @@ -From a9dbe40fc10cea2efe6e1ff9e03c62dd7579c5ba Mon Sep 17 00:00:00 2001 -From: David Woodhouse -Date: Wed, 21 Nov 2012 10:27:19 +0000 -Subject: [PATCH] 8139cp: set ring address after enabling C+ mode - -This fixes (for me) a regression introduced by commit b01af457 ("8139cp: -set ring address before enabling receiver"). That commit configured the -descriptor ring addresses earlier in the initialisation sequence, in -order to avoid the possibility of triggering stray DMA before the -correct address had been set up. - -Unfortunately, it seems that the hardware will scribble garbage into the -TxRingAddr registers when we enable "plus mode" Tx in the CpCmd -register. Observed on a Traverse Geos router board. - -To deal with this, while not reintroducing the problem which led to the -original commit, we augment cp_start_hw() to write to the CpCmd register -*first*, then set the descriptor ring addresses, and then finally to -enable Rx and Tx in the original 8139 Cmd register. The datasheet -actually indicates that we should enable Tx/Rx in the Cmd register -*before* configuring the descriptor addresses, but that would appear to -re-introduce the problem that the offending commit b01af457 was trying -to solve. And this variant appears to work fine on real hardware. - -Signed-off-by: David Woodhouse -Cc: stable@kernel.org [3.5+] -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/8139cp.c | 40 +++++++++++++++++++++++---------- - 1 files changed, 28 insertions(+), 12 deletions(-) - -diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c -index 1c81825..5166d94 100644 ---- a/drivers/net/ethernet/realtek/8139cp.c -+++ b/drivers/net/ethernet/realtek/8139cp.c -@@ -957,7 +957,35 @@ static void cp_reset_hw (struct cp_private *cp) - - static inline void cp_start_hw (struct cp_private *cp) - { -+ dma_addr_t ring_dma; -+ - cpw16(CpCmd, cp->cpcmd); -+ -+ /* -+ * These (at least TxRingAddr) need to be configured after the -+ * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33 -+ * (C+ Command Register) recommends that these and more be configured -+ * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware -+ * it's been observed that the TxRingAddr is actually reset to garbage -+ * when C+ mode Tx is enabled in CpCmd. -+ */ -+ cpw32_f(HiTxRingAddr, 0); -+ cpw32_f(HiTxRingAddr + 4, 0); -+ -+ ring_dma = cp->ring_dma; -+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -+ -+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -+ -+ /* -+ * Strictly speaking, the datasheet says this should be enabled -+ * *before* setting the descriptor addresses. But what, then, would -+ * prevent it from doing DMA to random unconfigured addresses? -+ * This variant appears to work fine. -+ */ - cpw8(Cmd, RxOn | TxOn); - } - -@@ -969,7 +997,6 @@ static void cp_enable_irq(struct cp_private *cp) - static void cp_init_hw (struct cp_private *cp) - { - struct net_device *dev = cp->dev; -- dma_addr_t ring_dma; - - cp_reset_hw(cp); - -@@ -979,17 +1006,6 @@ static void cp_init_hw (struct cp_private *cp) - cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - -- cpw32_f(HiTxRingAddr, 0); -- cpw32_f(HiTxRingAddr + 4, 0); -- -- ring_dma = cp->ring_dma; -- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -- -- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -- - cp_start_hw(cp); - cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ - --- -1.7.6.5 - diff --git a/USB-report-submission-of-active-URBs.patch b/USB-report-submission-of-active-URBs.patch deleted file mode 100644 index 4496c913a..000000000 --- a/USB-report-submission-of-active-URBs.patch +++ /dev/null @@ -1,46 +0,0 @@ -commit 2f02bc8af3abb846823811af65ec6cc46a4d525d -Author: Alan Stern -Date: Wed Nov 7 16:35:00 2012 -0500 - - USB: report submission of active URBs - - This patch (as1633) changes slightly the way usbcore handled - submissions of URBs that are already active. It will now return - -EBUSY rather than -EINVAL, and it will call WARN_ONCE to draw - people's attention to the bug. - - Signed-off-by: Alan Stern - Signed-off-by: Greg Kroah-Hartman - -diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt -index 8d1e2a9..9c3eb84 100644 ---- a/Documentation/usb/error-codes.txt -+++ b/Documentation/usb/error-codes.txt -@@ -21,6 +21,8 @@ Non-USB-specific: - - USB-specific: - -+-EBUSY The URB is already active. -+ - -ENODEV specified USB-device or bus doesn't exist - - -ENOENT specified interface or endpoint does not exist or -diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c -index 3662287..e0d9d94 100644 ---- a/drivers/usb/core/urb.c -+++ b/drivers/usb/core/urb.c -@@ -321,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) - struct usb_host_endpoint *ep; - int is_out; - -- if (!urb || urb->hcpriv || !urb->complete) -+ if (!urb || !urb->complete) - return -EINVAL; -+ if (urb->hcpriv) { -+ WARN_ONCE(1, "URB %p submitted while active\n", urb); -+ return -EBUSY; -+ } -+ - dev = urb->dev; - if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) - return -ENODEV; diff --git a/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch b/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch deleted file mode 100644 index 662ebe666..000000000 --- a/arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Rob Herring - -PL310 errata work-arounds using .set_debug function are only needed on -r3p0 and earlier, so check the rev and only set .set_debug on older revs. - -Avoiding debug register accesses fixes aborts on non-secure platforms -like highbank. It is assumed that non-secure platforms needing these -work-arounds have already implemented .set_debug with secure monitor -calls. - -Signed-off-by: Rob Herring ---- - arch/arm/mm/cache-l2x0.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c -index 8a97e64..6cf2fd1 100644 ---- a/arch/arm/mm/cache-l2x0.c -+++ b/arch/arm/mm/cache-l2x0.c -@@ -334,7 +334,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) - /* Unmapped register. */ - sync_reg_offset = L2X0_DUMMY_REG; - #endif -- outer_cache.set_debug = pl310_set_debug; -+ if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0) -+ outer_cache.set_debug = pl310_set_debug; - break; - case L2X0_CACHE_ID_PART_L210: - ways = (aux >> 13) & 0xf; --- -1.7.10.4 diff --git a/brcmsmac-updates-rhbz892428.patch b/brcmsmac-updates-rhbz892428.patch deleted file mode 100644 index 8b5e08f04..000000000 --- a/brcmsmac-updates-rhbz892428.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c -index 426b9a9..d7ce1ac 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c -@@ -361,7 +361,7 @@ static uint prevtxd(struct dma_info *di, uint i) - - static uint nextrxd(struct dma_info *di, uint i) - { -- return txd(di, i + 1); -+ return rxd(di, i + 1); - } - - static uint ntxdactive(struct dma_info *di, uint h, uint t) -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c -index 5710dc0..25c5410 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/main.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c -@@ -232,8 +232,8 @@ - - #define MAX_DMA_SEGS 4 - --/* Max # of entries in Tx FIFO based on 4kb page size */ --#define NTXD 256 -+/* # of entries in Tx FIFO */ -+#define NTXD 64 - /* Max # of entries in Rx FIFO based on 4kb page size */ - #define NRXD 256 - diff --git a/config-arm-generic b/config-arm-generic index 79e37a716..f1306225b 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -63,6 +63,7 @@ CONFIG_SCHED_SMT=y CONFIG_RCU_FANOUT=32 CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y @@ -109,6 +110,7 @@ CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_GENERIC_PLATFORM=m CONFIG_PINCTRL_SINGLE=m +CONFIG_POWER_RESET_GPIO=y CONFIG_USB_ULPI=y @@ -133,7 +135,9 @@ CONFIG_SERIO_AMBAKMI=m CONFIG_I2C_NOMADIK=m CONFIG_ARM_SP805_WATCHDOG=m CONFIG_FB_ARMCLCD=m +CONFIG_FB_SSD1307=m CONFIG_MPCORE_WATCHDOG=m +CONFIG_BACKLIGHT_PWM=m CONFIG_MMC_ARMMMCI=m CONFIG_MMC_SDHCI_PLTFM=m @@ -249,6 +253,7 @@ CONFIG_HW_RANDOM_ATMEL=m CONFIG_HW_RANDOM_EXYNOS=m # Device tree +CONFIG_DTC=y CONFIG_OF=y CONFIG_USE_OF=y CONFIG_OF_DEVICE=y @@ -290,25 +295,32 @@ CONFIG_GPIO_MCP23S08=m CONFIG_GPIO_ADNP=m CONFIG_PL310_ERRATA_753970=y +CONFIG_MFD_CORE=m CONFIG_MFD_88PM800=m CONFIG_MFD_88PM805=m CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TPS80031 is not set +# CONFIG_MFD_AS3711 is not set # CONFIG_MFD_SMSC is not set # CONFIG_MFD_DA9055 is not set # CONFIG_MFD_MAX8907 is not set CONFIG_REGULATOR_VIRTUAL_CONSUMER=m CONFIG_REGULATOR_USERSPACE_CONSUMER=m +# CONFIG_REGULATOR_DUMMY is not set CONFIG_REGULATOR_GPIO=m CONFIG_REGULATOR_AD5398=m CONFIG_REGULATOR_ANATOP=m CONFIG_REGULATOR_FAN53555=m CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_LP3972=m CONFIG_REGULATOR_MAX1586=m CONFIG_REGULATOR_MAX8649=m CONFIG_REGULATOR_MAX8660=m CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8973=m CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_TPS51632=m CONFIG_REGULATOR_TPS62360=m CONFIG_REGULATOR_TPS65023=m CONFIG_REGULATOR_TPS6507X=m @@ -317,6 +329,7 @@ CONFIG_EXTCON_GPIO=m # CONFIG_ARM_VIRT_EXT is not set # CONFIG_PINCTRL_EXYNOS4 is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set # CONFIG_AUTO_ZRELADDR is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set @@ -387,3 +400,4 @@ CONFIG_EXTCON_GPIO=m # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_CS89x0 is not set # CONFIG_DVB_USB_PCTV452E is not set +# CONFIG_PINCTRL_EXYNOS is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index ff1dad7df..f4fea2955 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -15,20 +15,29 @@ CONFIG_MACH_GURUPLUG=y CONFIG_MACH_ICONNECT_DT=y CONFIG_MACH_IB62X0_DT=y CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_INETSPACE_V2_DT=y CONFIG_MACH_IOMEGA_IX2_200_DT=y CONFIG_MACH_KM_KIRKWOOD_DT=y CONFIG_MACH_LSXL_DT=y +CONFIG_MACH_MPLCEC4_DT=y CONFIG_MACH_MV88F6281GTW_GE=y -CONFIG_MACH_NETSPACE_V2=y +CONFIG_MACH_NETSPACE_LITE_V2_DT=y CONFIG_MACH_NETSPACE_MAX_V2=y +CONFIG_MACH_NETSPACE_MAX_V2_DT=y +CONFIG_MACH_NETSPACE_MINI_V2_DT=y +CONFIG_MACH_NETSPACE_V2=y +CONFIG_MACH_NETSPACE_V2_DT=y CONFIG_MACH_NET2BIG_V2=y CONFIG_MACH_NET5BIG_V2=y +CONFIG_MACH_NSA310_DT=y +CONFIG_MACH_OPENBLOCKS_A6_DT=y CONFIG_MACH_OPENRD_BASE=y CONFIG_MACH_OPENRD_CLIENT=y CONFIG_MACH_OPENRD_ULTIMATE=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_TOPKICK_DT=y CONFIG_MACH_TS219=y CONFIG_MACH_TS219_DT=y CONFIG_MACH_TS41X=y @@ -51,6 +60,7 @@ CONFIG_LEDS_NETXBIG=m CONFIG_RTC_DRV_MV=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m +# CONFIG_PINCTRL_EXYNOS is not set CONFIG_PINCTRL_MVEBU=y CONFIG_PINCTRL_KIRKWOOD=y diff --git a/config-arm-omap b/config-arm-omap index 9bf447708..a53983357 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -41,7 +41,7 @@ CONFIG_SOC_OMAP3430=y CONFIG_SOC_TI81XX=y CONFIG_SOC_AM33XX=y CONFIG_SOC_OMAPTI816X=y -CONFIG_SOC_OMAP5=y +# CONFIG_SOC_OMAP5 is not set CONFIG_OMAP_PACKAGE_CBB=y CONFIG_OMAP_PACKAGE_CBL=y CONFIG_OMAP_PACKAGE_CBS=y @@ -143,8 +143,6 @@ CONFIG_PM_SLEEP_SMP=y CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y -# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES -CONFIG_OMAP_BANDGAP=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y @@ -172,6 +170,7 @@ CONFIG_TOUCHSCREEN_TI_TSCADC=m CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_OMAP_WATCHDOG=y +CONFIG_CLK_TWL6040=m CONFIG_TWL4030_CORE=y CONFIG_TWL4030_MADC=m CONFIG_TWL4030_POWER=y @@ -183,6 +182,7 @@ CONFIG_CHARGER_TWL4030=m CONFIG_TWL6030_PWM=m CONFIG_TWL6040_CORE=y CONFIG_SENSORS_TWL4030_MADC=m +CONFIG_SENSORS_LIS3_I2C=m CONFIG_TI_DAVINCI_EMAC=m CONFIG_TI_DAVINCI_MDIO=m CONFIG_TI_DAVINCI_CPDMA=m @@ -192,12 +192,16 @@ CONFIG_LEDS_LP8788=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_HDQ_MASTER_OMAP=m CONFIG_I2C_OMAP=m -CONFIG_SPI_OMAP24XX=y +CONFIG_SPI_OMAP24XX=m CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m CONFIG_MFD_LP8788=y +CONFIG_MFD_TPS65910=y +CONFIG_GPIO_TPS65910=y CONFIG_REGULATOR_TWL4030=y CONFIG_REGULATOR_LP8788=y +CONFIG_REGULATOR_TPS65217=y +CONFIG_REGULATOR_TPS65910=y # Enable V4L2 drivers for OMAP2+ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y @@ -234,20 +238,25 @@ CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y +CONFIG_FB_DA8XX=m +CONFIG_FB_DA8XX_CONSISTENT_DMA_SIZE=5 + +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_PANEL_GENERIC_DPI=m CONFIG_PANEL_TFP410=m CONFIG_PANEL_TAAL=m CONFIG_PANEL_PICODLP=m +CONFIG_PANEL_SHARP_LS037V7DW01=m +CONFIG_PANEL_NEC_NL8048HL11_01B=m +CONFIG_PANEL_TPO_TD043MTEA1=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_PWM=m CONFIG_BACKLIGHT_PANDORA=m -# -# OMAP2/3 Display Device Drivers -# -CONFIG_PANEL_GENERIC_DPI=y -CONFIG_PANEL_SHARP_LS037V7DW01=y -CONFIG_PANEL_NEC_NL8048HL11_01B=y -CONFIG_PANEL_TPO_TD043MTEA1=y CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_DMIC=m CONFIG_SND_OMAP_SOC_MCBSP=m CONFIG_SND_OMAP_SOC_MCPDM=m CONFIG_SND_OMAP_SOC_OVERO=m @@ -258,20 +267,18 @@ CONFIG_SND_OMAP_SOC_SDP4430=m CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=m CONFIG_SND_OMAP_SOC_ZOOM2=m -CONFIG_SND_OMAP_SOC_IGEP0020=y -CONFIG_SND_OMAP_SOC_OMAP_HDMI=y -# Because alsa is modular http://www.spinics.net/lists/linux-omap/msg67307.html -# CONFIG_SND_OMAP_SOC_OMAP4_HDMI is not set +CONFIG_SND_OMAP_SOC_IGEP0020=m +CONFIG_SND_OMAP_SOC_OMAP_HDMI=m CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_OMAP_SOC_RX51 is not set # CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_TLV320AIC23=y -CONFIG_SND_SOC_TLV320AIC3X=y -CONFIG_SND_SOC_TWL4030=y -CONFIG_SND_SOC_TWL6040=y -CONFIG_RADIO_WL128X +CONFIG_SND_SOC_TLV320AIC23=m +CONFIG_SND_SOC_TLV320AIC3X=m +CONFIG_SND_SOC_TWL4030=m +CONFIG_SND_SOC_TWL6040=m +CONFIG_RADIO_WL128X=m CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD_OMAP=y @@ -299,9 +306,17 @@ CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_TWL4030_USB=y CONFIG_TWL6030_USB=y +CONFIG_RTC_DRV_OMAP=m CONFIG_RTC_DRV_TWL4030=y +CONFIG_RTC_DRV_TPS65910=m -CONFIG_IR_RX51=m +CONFIG_PWM_TIECAP=m +CONFIG_PWM_TIEHRPWM=m +CONFIG_PWM_TWL=m +CONFIG_PWM_TWL_LED=m + +# CONFIG_IR_RX51 is not set +# CONFIG_BATTERY_RX51 is not set # CONFIG_TIDSPBRIDGE is not set # CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 @@ -314,6 +329,7 @@ CONFIG_IR_RX51=m # CONFIG_TIDSPBRIDGE_BACKTRACE is not set # CONFIG_OMAP_REMOTEPROC is not set +# CONFIG_OMAP_BANDGAP is not set # CONFIG_OMAP_IOVMM is not set CONFIG_CRYPTO_DEV_OMAP_SHAM=m @@ -321,7 +337,6 @@ CONFIG_CRYPTO_DEV_OMAP_AES=m # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_MTD_NAND_OMAP_BCH is not set -# CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set @@ -334,7 +349,8 @@ CONFIG_CRYPTO_DEV_OMAP_AES=m # CONFIG_MFD_AAT2870_CORE is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_PALMAS is not set -# CONFIG_REGULATOR_DUMMY is not set # CONFIG_REGULATOR_LP3972 is not set # CONFIG_REGULATOR_LP872X is not set +# CONFIG_OMAP2_DSS_DEBUG is not set +# CONFIG_OMAP2_DSS_DEBUGFS is not set diff --git a/config-arm-tegra b/config-arm-tegra index 894b5dbef..869b1728a 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -3,7 +3,6 @@ CONFIG_ARCH_TEGRA=y CONFIG_ARCH_TEGRA_2x_SOC=y # CONFIG_ARCH_TEGRA_3x_SOC is not set # CONFIG_ARM_LPAE is not set -CONFIG_TEGRA_PCI=y CONFIG_VFP=y CONFIG_VFPv3=y @@ -20,6 +19,7 @@ CONFIG_MACH_VENTANA=y CONFIG_TEGRA_DEBUG_UARTD=y CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_TEGRA_PCI=y CONFIG_TEGRA_IOMMU_GART=y CONFIG_TEGRA_IOMMU_SMMU=y @@ -72,15 +72,25 @@ CONFIG_SND_SOC_TEGRA_ALC5632=m CONFIG_SND_SOC_TEGRA_WM8753=m CONFIG_SND_SOC_TEGRA_WM8903=m CONFIG_SND_SOC_TEGRA_TRIMSLICE=m -# CONFIG_SND_SOC_TEGRA30_AHUB is not set -# CONFIG_SND_SOC_TEGRA30_I2S is not set +CONFIG_SND_SOC_TEGRA30_AHUB=m +CONFIG_SND_SOC_TEGRA30_I2S=m -CONFIG_MFD_NVEC=y +# AC100 (PAZ00) +# CONFIG_MFD_NVEC is not set +CONFIG_MFD_TPS80031=y CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y CONFIG_POWER_SUPPLY=y CONFIG_NVEC_LEDS=y +CONFIG_NVEC_PAZ00=y + +# CONFIG_MFD_TPS6586X is not set +# CONFIG_RTC_DRV_TPS6586X is not set + +CONFIG_PWM_TEGRA=m + +CONFIG_DRM_TEGRA=m CONFIG_CPU_PM=y CONFIG_ARM_CPU_SUSPEND=y @@ -95,3 +105,5 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_OF_GPIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y + +# CONFIG_DRM_TEGRA_DEBUG is not set diff --git a/config-armv7 b/config-armv7 index c865cb15f..c3af272a1 100644 --- a/config-armv7 +++ b/config-armv7 @@ -5,12 +5,18 @@ CONFIG_CPU_V7=y # CONFIG_ARCH_MULTI_V6 is not set CONFIG_ARCH_MULTI_V6_V7=y CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_MVEBU=y +# This is V6 so we'll eventually support it in v5 unified kernels +# CONFIG_ARCH_BCM is not set CONFIG_ARCH_HIGHBANK=y +CONFIG_ARCH_MVEBU=y +# CONFIG_ARCH_MXC is not set CONFIG_ARCH_PICOXCELL=y CONFIG_ARCH_SOCFPGA=y +CONFIG_ARCH_SUNXI=y CONFIG_ARCH_VEXPRESS_CA9X4=y CONFIG_ARCH_VEXPRESS_DT=y +# not enabling first round +# CONFIG_ARCH_ZYNQ is not set CONFIG_MACH_ARMADA_370_XP=y CONFIG_MACH_ARMADA_370=y @@ -49,6 +55,7 @@ CONFIG_HIGHPTE=y # CONFIG_THUMB2_KERNEL is not set # CONFIG_XEN is not set # CONFIG_HVC_DCC is not set +# CONFIG_VIRTIO_CONSOLE is not set # CONFIG_ARM_VIRT_EXT is not set @@ -89,6 +96,7 @@ CONFIG_RCU_FANOUT_LEAF=16 CONFIG_CPU_IDLE=y # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_LSM_MMAP_MIN_ADDR=32768 @@ -144,9 +152,6 @@ CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -# disable VIRTIO console on because not doing real virt and it breaks vexpress on qemu -# CONFIG_VIRTIO_CONSOLE is not set - CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y @@ -155,6 +160,8 @@ CONFIG_AMBA_PL08X=y CONFIG_ARM_SP805_WATCHDOG=m # highbank +CONFIG_CPU_IDLE_CALXEDA=y + CONFIG_EDAC_HIGHBANK_MC=m CONFIG_EDAC_HIGHBANK_L2=m @@ -173,6 +180,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_I2C_VERSATILE=m CONFIG_OC_ETM=y CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y +CONFIG_SENSORS_VEXPRESS=m # unknown and needs review CONFIG_ARM_AMBA=y @@ -184,9 +192,67 @@ CONFIG_CRYPTO_DEV_MV_CESA=m CONFIG_MV643XX_ETH=m CONFIG_I2C_MV64XXX=m CONFIG_PINCTRL_MVEBU=y +CONFIG_PINCTRL_ARMADA_370=y +CONFIG_PINCTRL_ARMADA_XP=y +CONFIG_PINCTRL_DOVE=y +CONFIG_EDAC_MV64X60=m +CONFIG_MVNETA=m +CONFIG_SATA_MV=m +CONFIG_MARVELL_PHY=m +CONFIG_RTC_DRV_S35390A=y +CONFIG_USB_EHCI_MV=m + +# Allwinner a1x +# CONFIG_SUNXI_RFKILL=y +# CONFIG_SUNXI_NAND=y +# CONFIG_SUNXI_DBGREG=m +# CONFIG_WEMAC_SUN4I=y +# CONFIG_KEYBOARD_SUN4IKEYPAD=m +# CONFIG_KEYBOARD_SUN4I_KEYBOARD=m +# CONFIG_IR_SUN4I=m +# CONFIG_TOUCHSCREEN_SUN4I_TS=m +# CONFIG_SUN4I_G2D=y +# CONFIG_I2C_SUN4I=y +# CONFIG_DRM_MALI=m +# CONFIG_MALI=m +# CONFIG_FB_SUNXI=m +# CONFIG_FB_SUNXI_UMP=y +# CONFIG_FB_SUNXI_LCD=m +# CONFIG_FB_SUNXI_HDMI=m +# CONFIG_SOUND_SUN4I=y +# CONFIG_SND_SUN4I_SOC_CODEC=y +# CONFIG_SND_SUN4I_SOC_HDMIAUDIO=y +# CONFIG_SND_SUN4I_SOC_SPDIF=m +# CONFIG_SND_SUN4I_SOC_I2S_INTERFACE=m +# CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_USB_SW_SUN4I_HCD=y +# CONFIG_USB_SW_SUN4I_HCD0=y +# CONFIG_USB_SW_SUN4I_HCI=y +# CONFIG_USB_SW_SUN4I_EHCI0=y +# CONFIG_USB_SW_SUN4I_EHCI1=y +# CONFIG_USB_SW_SUN4I_OHCI0=y +# CONFIG_USB_SW_SUN4I_OHCI1=y +# CONFIG_USB_SW_SUN4I_USB=y +# CONFIG_USB_SW_SUN4I_USB_MANAGER=y +# CONFIG_MMC_SUNXI_POWER_CONTROL=y +# CONFIG_MMC_SUNXI=y +# CONFIG_RTC_DRV_SUN4I=y + +# imx +CONFIG_BACKLIGHT_PWM=m +# CONFIG_DRM_IMX is not set +# CONFIG_DRM_IMX_FB_HELPER=m +# CONFIG_DRM_IMX_PARALLEL_DISPLAY=m +# CONFIG_DRM_IMX_IPUV3_CORE=m +# CONFIG_DRM_IMX_IPUV3=m +# CONFIG_VIDEO_CODA is not set + +CONFIG_INPUT_PWM_BEEPER=m # exynos # CONFIG_DRM_EXYNOS is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set +# CONFIG_PINCTRL_EXYNOS is not set # picoxcell CONFIG_CRYPTO_DEV_PICOXCELL=m @@ -194,8 +260,12 @@ CONFIG_CRYPTO_DEV_PICOXCELL=m # ST Ericsson # CONFIG_I2C_NOMADIK is not set +# OMAP +# CONFIG_SENSORS_LIS3_I2C is not set + # General ARM drivers # Device tree +CONFIG_DTC=y CONFIG_OF=y CONFIG_USE_OF=y CONFIG_OF_DEVICE=y @@ -263,6 +333,7 @@ CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_MPCORE_WATCHDOG=m # Multi function devices +CONFIG_MFD_CORE=m CONFIG_MFD_T7L66XB=y CONFIG_MFD_TC6387XB=y CONFIG_MFD_SYSCON=y @@ -285,6 +356,7 @@ CONFIG_GPIO_GENERIC_PLATFORM=m CONFIG_GPIO_EM=m CONFIG_GPIO_ADNP=m CONFIG_GPIO_MCP23S08=m +CONFIG_POWER_RESET_GPIO=y CONFIG_RFKILL_GPIO=m CONFIG_SERIAL_8250_EM=m CONFIG_INPUT_GP2A=m @@ -295,6 +367,9 @@ CONFIG_MDIO_BUS_MUX_MMIOREG=m CONFIG_MTD_OF_PARTS=y # CONFIG_MG_DISK is not set +# Framebuffers +CONFIG_FB_SSD1307=m + # Regulator drivers CONFIG_REGULATOR_FAN53555=m # Needs work/investigation @@ -340,6 +415,7 @@ CONFIG_PERF_EVENTS=y # CONFIG_VIDEO_DM6446_CCDC is not set # CONFIG_PANEL_TAAL is not set # CONFIG_IR_RX51 is not set +# CONFIG_DRM_OMAP is not set # CONFIG_GENERIC_CPUFREQ_CPU0 is not set # CONFIG_GPIO_TWL6040 is not set diff --git a/config-generic b/config-generic index 069aaf111..d7424a451 100644 --- a/config-generic +++ b/config-generic @@ -4,6 +4,8 @@ CONFIG_MMU=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set +# CONFIG_DEBUG_HOTPLUG_CPU0 is not set CONFIG_LOCALVERSION="" CONFIG_CROSS_COMPILE="" CONFIG_DEFAULT_HOSTNAME="(none)" @@ -52,6 +54,8 @@ CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_DEFAULT_CFQ=y +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y CONFIG_PID_NS=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y @@ -124,6 +128,7 @@ CONFIG_MMC_BLOCK_MINORS=8 CONFIG_MMC_BLOCK_BOUNCE=y CONFIG_MMC_SDHCI=m CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_SDHCI_ACPI=m CONFIG_MMC_SDRICOH_CS=m CONFIG_MMC_TIFM_SD=m CONFIG_MMC_WBSD=m @@ -132,6 +137,7 @@ CONFIG_MMC_SDHCI_PLTFM=m CONFIG_MMC_CB710=m CONFIG_MMC_RICOH_MMC=y CONFIG_MMC_USHC=m +CONFIG_MMC_REALTEK_PCI=m CONFIG_MMC_VUB300=m CONFIG_CB710_CORE=m @@ -340,6 +346,7 @@ CONFIG_SCSI_SRP=m CONFIG_SCSI_SRP_ATTRS=m CONFIG_SCSI_TGT=m CONFIG_SCSI_ISCI=m +CONFIG_SCSI_CHELSIO_FCOE=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=m @@ -416,6 +423,9 @@ CONFIG_SCSI_MVSAS_TASKLET=y CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y +CONFIG_SCSI_MPT3SAS=m +CONFIG_SCSI_MPT3SAS_MAX_SGE=128 +CONFIG_SCSI_MPT3SAS_LOGGING=y CONFIG_SCSI_UFSHCD=m @@ -607,6 +617,7 @@ CONFIG_FIREWIRE_SBP2=m CONFIG_FIREWIRE_NET=m CONFIG_FIREWIRE_OHCI_DEBUG=y CONFIG_FIREWIRE_NOSY=m +CONFIG_FIREWIRE_SERIAL=m # CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set # @@ -977,9 +988,11 @@ CONFIG_IP_SCTP=m CONFIG_NET_SCTPPROBE=m # CONFIG_SCTP_DBG_MSG is not set # CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -CONFIG_SCTP_HMAC_SHA1=y -# CONFIG_SCTP_HMAC_MD5 is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +CONFIG_SCTP_COOKIE_HMAC_SHA1=y CONFIG_ATM=m CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y @@ -1077,6 +1090,7 @@ CONFIG_DCB=y CONFIG_DNS_RESOLVER=m CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_BLA=y +CONFIG_BATMAN_ADV_DAT=y # CONFIG_BATMAN_ADV_DEBUG is not set CONFIG_OPENVSWITCH=m CONFIG_NETPRIO_CGROUP=m @@ -1187,6 +1201,9 @@ CONFIG_ATL2=m CONFIG_ATL1=m CONFIG_ATL1C=m CONFIG_ATL1E=m +CONFIG_NET_CADENCE=y +CONFIG_ARM_AT91_ETHER=m +CONFIG_MACB=m CONFIG_NET_VENDOR_BROCADE=y CONFIG_BNA=m @@ -1257,6 +1274,7 @@ CONFIG_IXGBE_PTP=y # CONFIG_NET_VENDOR_I825XX is not set CONFIG_NET_VENDOR_MARVELL=y +CONFIG_MVMDIO=m CONFIG_SKGE=m # CONFIG_SKGE_DEBUG is not set CONFIG_SKGE_GENESIS=y @@ -1483,6 +1501,7 @@ CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 # CONFIG_ADM8211 is not set CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m CONFIG_ATH5K=m CONFIG_ATH5K_DEBUG=y # CONFIG_ATH5K_TRACER is not set @@ -1490,6 +1509,7 @@ CONFIG_ATH6KL=m CONFIG_ATH6KL_DEBUG=y CONFIG_ATH6KL_SDIO=m CONFIG_ATH6KL_USB=m +CONFIG_AR5523=m CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y CONFIG_ATH9K_AHB=y @@ -1500,6 +1520,8 @@ CONFIG_ATH9K_HTC=m CONFIG_ATH9K_BTCOEX_SUPPORT=y # CONFIG_ATH9K_HTC_DEBUGFS is not set CONFIG_ATH9K_RATE_CONTROL=y +CONFIG_WIL6210=m +CONFIG_WIL6210_ISR_COR=y CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y # CONFIG_CARL9170_HWRNG is not set @@ -1530,6 +1552,7 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y CONFIG_BRCMFMAC_SDIO_OOB=y CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCM_TRACING is not set # CONFIG_BRCMISCAN is not set # CONFIG_BRCMDBG is not set CONFIG_HERMES=m @@ -1622,6 +1645,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -1932,6 +1956,7 @@ CONFIG_SERIO_SERPORT=y CONFIG_SERIO_RAW=m CONFIG_SERIO_ALTERA_PS2=m # CONFIG_SERIO_PS2MULT is not set +CONFIG_SERIO_ARC_PS2=m # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set @@ -2043,9 +2068,12 @@ CONFIG_TOUCHSCREEN_W90X900=m CONFIG_TOUCHSCREEN_ST1232=m CONFIG_TOUCHSCREEN_ATMEL_MXT=m # CONFIG_TOUCHSCREEN_MAX11801 is not set +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m CONFIG_INPUT_MISC=y CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_RETU_PWRBUTTON=m CONFIG_INPUT_UINPUT=m CONFIG_INPUT_WISTRON_BTNS=m CONFIG_INPUT_ATLAS_BTNS=m @@ -2169,6 +2197,8 @@ CONFIG_I2C_ALGOPCA=m # CONFIG_I2C_NFORCE2_S4985 is not set # CONFIG_I2C_INTEL_MID is not set # CONFIG_I2C_EG20T is not set +# CONFIG_I2C_CBUS_GPIO is not set +CONFIG_I2C_VIPERBOARD=m CONFIG_EEPROM_AT24=m CONFIG_EEPROM_LEGACY=m @@ -2339,6 +2369,8 @@ CONFIG_SENSORS_MAX197=m # CONFIG_PCH_PHUB is not set # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set +CONFIG_SERIAL_ARC=m +CONFIG_SERIAL_ARC_NR_PORTS=1 CONFIG_W1=m CONFIG_W1_CON=y @@ -2451,6 +2483,7 @@ CONFIG_RTC_DRV_RS5C372=m # CONFIG_RTC_DRV_SA1100 is not set # CONFIG_RTC_DRV_TEST is not set CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF8523=m CONFIG_RTC_DRV_V3020=m CONFIG_RTC_DRV_DS2404=m CONFIG_RTC_DRV_STK17TA8=m @@ -2671,6 +2704,7 @@ CONFIG_DVB_BT8XX=m CONFIG_DVB_BUDGET_CORE=m CONFIG_DVB_PLUTO2=m CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_SMS_USB_DRV=m CONFIG_SMS_SDIO_DRV=m @@ -3044,6 +3078,7 @@ CONFIG_SND_USB_6FIRE=m CONFIG_SND_FIREWIRE=y CONFIG_SND_FIREWIRE_SPEAKERS=m CONFIG_SND_ISIGHT=m +CONFIG_SND_SCS1X=m # # Open Sound System @@ -3131,6 +3166,7 @@ CONFIG_USB_HID=y CONFIG_HID_SUPPORT=y CONFIG_HID=y +CONFIG_I2C_HID=m CONFIG_HID_BATTERY_STRENGTH=y # debugging default is y upstream now CONFIG_HIDRAW=y @@ -3161,6 +3197,7 @@ CONFIG_HID_PS3REMOTE=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m CONFIG_HID_TWINHAN=m CONFIG_HID_ORTEK=m CONFIG_HID_PANTHERLORD=m @@ -3292,6 +3329,7 @@ CONFIG_USB_NET_RNDIS_HOST=m CONFIG_USB_NET_CDC_SUBSET=m CONFIG_USB_NET_CDC_EEM=m CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m CONFIG_USB_NET_ZAURUS=m CONFIG_USB_NET_CX82310_ETH=m CONFIG_USB_NET_INT51X1=m @@ -3411,6 +3449,7 @@ CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m # CONFIG_OMAP_USB2 is not set +CONFIG_USB_RCAR_PHY=m CONFIG_USB_ATM=m CONFIG_USB_CXACRU=m # CONFIG_USB_C67X00_HCD is not set @@ -3471,6 +3510,7 @@ CONFIG_SSB_PCMCIAHOST=y # CONFIG_SSB_SILENT is not set # CONFIG_SSB_DEBUG is not set CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_GPIO=y # Multifunction USB devices # CONFIG_MFD_PCF50633 is not set @@ -3487,6 +3527,10 @@ CONFIG_MFD_SUPPORT=y CONFIG_MFD_VX855=m CONFIG_MFD_SM501=m CONFIG_MFD_SM501_GPIO=y +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_TI_AM335X_TSCADC is not set +CONFIG_MFD_VIPERBOARD=m +# CONFIG_MFD_RETU is not set # CONFIG_MFD_TC6393XB is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set @@ -3648,6 +3692,7 @@ CONFIG_9P_FS_POSIX_ACL=y CONFIG_FUSE_FS=m # CONFIG_OMFS_FS is not set CONFIG_CUSE=m +# CONFIG_F2FS_FS is not set # # Network File Systems @@ -3687,6 +3732,7 @@ CONFIG_CIFS_POSIX=y CONFIG_CIFS_FSCACHE=y CONFIG_CIFS_ACL=y CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_DEBUG=y # CONFIG_CIFS_DEBUG2 is not set CONFIG_CIFS_DFS_UPCALL=y CONFIG_CIFS_NFSD_EXPORT=y @@ -4069,6 +4115,11 @@ CONFIG_KEXEC=y CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set CONFIG_THERMAL_HWMON=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_FAIR_SHARE=y +CONFIG_STEP_WISE=y +# CONFIG_USER_SPACE is not set # CONFIG_CPU_THERMAL is not set CONFIG_INOTIFY=y @@ -4145,6 +4196,7 @@ CONFIG_SND_INDIGOIOX=m CONFIG_SND_INDIGODJX=m # CONFIG_SND_SOC is not set +CONFIG_BALLOON_COMPACTION=y CONFIG_COMPACTION=y CONFIG_MIGRATION=y CONFIG_NEW_LEDS=y @@ -4256,6 +4308,8 @@ CONFIG_APM_POWER=m # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_PCF50633 is not set +# CONFIG_CHARGER_BQ2415X is not set +CONFIG_POWER_RESET=y # CONFIG_PDA_POWER is not set @@ -4265,6 +4319,7 @@ CONFIG_UIO=m CONFIG_UIO_CIF=m # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set CONFIG_UIO_AEC=m CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m @@ -4299,6 +4354,8 @@ CONFIG_NOZOMI=m # CONFIG_TPS65010 is not set CONFIG_INPUT_APANEL=m +CONFIG_INPUT_GP2A=m +# CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_INTEL_MENLOW is not set CONFIG_ENCLOSURE_SERVICES=m @@ -4312,6 +4369,7 @@ CONFIG_MSPRO_BLOCK=m CONFIG_MEMSTICK_TIFM_MS=m CONFIG_MEMSTICK_JMICRON_38X=m CONFIG_MEMSTICK_R592=m +CONFIG_MEMSTICK_REALTEK_PCI=m CONFIG_ACCESSIBILITY=y CONFIG_A11Y_BRAILLE_CONSOLE=y @@ -4432,6 +4490,7 @@ CONFIG_ALTERA_STAPL=m # CONFIG_BPCTL is not set # CONFIG_CED1401 is not set # CONFIG_DGRP is not set +# CONFIG_SB105X is not set # END OF STAGING # @@ -4459,8 +4518,9 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set -# FIXME: Revisit FAST_NO_HZ after 3.5 +# FIXME: Revisit FAST_NO_HZ after it's fixed # CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_RCU_NOCB_CPU is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TRACE is not set @@ -4517,6 +4577,9 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_CS5535 is not set # CONFIG_GPIO_ADP5588 is not set # CONFIG_GPIO_IT8761E is not set +# CONFIG SB105x is not set +# CONFIG_GPIO_TS5500 is not set +CONFIG_GPIO_VIPERBOARD=m # CONFIG_GPIO_MAX7300 is not set # CONFIG_UCB1400_CORE is not set # CONFIG_TPS6105X is not set @@ -4568,6 +4631,7 @@ CONFIG_BCMA_BLOCKIO=y CONFIG_BCMA_HOST_PCI_POSSIBLE=y CONFIG_BCMA_HOST_PCI=y CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y # CONFIG_BCMA_DEBUG is not set # CONFIG_GOOGLE_FIRMWARE is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index a6ef1c4df..902dccdee 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -313,7 +313,7 @@ CONFIG_SPARSE_IRQ=y # CONFIG_PPC_MPC5200_LPBFIFO is not set # CONFIG_CAN_MSCAN is not set # CONFIG_CAN_MPC5XXX is not set -CONFIG_PATA_MACIO=m +CONFIG_PATA_MACIO=y CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_88PM8607 is not set @@ -380,3 +380,8 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RTC_DRV_SNVS is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +CONFIG_POWER_RESET_GPIO=y +CONFIG_FB_SSD1307=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_BACKLIGHT_PWM=m +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=n diff --git a/config-s390x b/config-s390x index 41e41c53c..c0ae0aa0a 100644 --- a/config-s390x +++ b/config-s390x @@ -244,9 +244,22 @@ CONFIG_ETHERNET=y CONFIG_BPF_JIT=y # CONFIG_TRANSPARENT_HUGEPAGE is not set -# CONFIG_SCM_BUS is not set -# CONFIG_EADM_SCH is not set -# CONFIG_SCM_BLOCK is not set -# CONFIG_SCM_BLOCK_CLUSTER_WRITE is not set +CONFIG_SCM_BUS=y +CONFIG_EADM_SCH=m +CONFIG_SCM_BLOCK=m +CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_S390_PTDUMP is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +CONFIG_PCI_NR_FUNCTIONS=64 +CONFIG_HOTPLUG_PCI=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set +CONFIG_HOTPLUG_PCI_S390=m +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MCP23S08 is not set + +# CONFIG_PCI is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_PTP_1588_CLOCK_PCH is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index 3273fd151..0e9b3f4be 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -53,6 +53,8 @@ CONFIG_FB_GEODE_LX=y CONFIG_FB_GEODE_GX=y # CONFIG_FB_GEODE_GX1 is not set +CONFIG_FB_SSD1307=m + # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GODIRECT is not set # CONFIG_PCI_GOMMCONFIG is not set @@ -181,6 +183,9 @@ CONFIG_XO1_RFKILL=m CONFIG_X86_32_IRIS=m +CONFIG_POWER_RESET_GPIO=y + + CONFIG_MTD_OF_PARTS=y CONFIG_MTD_PHYSMAP_OF=m @@ -204,6 +209,9 @@ CONFIG_I2O_EXT_ADAPTEC=y CONFIG_I2O_CONFIG_OLD_IOCTL=y CONFIG_I2O_BUS=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_BACKLIGHT_PWM=m + # CONFIG_EDAC_SBRIDGE is not set # CONFIG_X86_WANT_INTEL_MID is not set diff --git a/config-x86-generic b/config-x86-generic index 15c0e4695..e8335a2f0 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -78,6 +78,7 @@ CONFIG_ACPI_SLEEP=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y # FIXME: Next two are deprecated. Remove them when they disappear upstream # CONFIG_ACPI_PROCFS_POWER is not set # CONFIG_ACPI_PROC_EVENT is not set @@ -282,6 +283,7 @@ CONFIG_MTD_CK804XROM=m CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set # CONFIG_CPU_IDLE_GOV_LADDER is not set CONFIG_CPU_IDLE_GOV_MENU=y @@ -409,6 +411,7 @@ CONFIG_HYPERV_UTILS=m CONFIG_HID_HYPERV_MOUSE=m CONFIG_HYPERV_NET=m CONFIG_HYPERV_STORAGE=m +CONFIG_HYPERV_BALLOON=m # Depends on HOTPLUG_PCI_PCIE CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m diff --git a/config-x86_64-generic b/config-x86_64-generic index 2e4195d5b..bcea67e2a 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -13,6 +13,8 @@ CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set # CONFIG_X86_NUMACHIP is not set +CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +CONFIG_NUMA_BALANCING=y CONFIG_NR_CPUS=128 CONFIG_PHYSICAL_START=0x1000000 @@ -52,6 +54,7 @@ CONFIG_CRYPTO_CAST5_AVX_X86_64=m CONFIG_CRYPTO_CAST6_AVX_X86_64=m CONFIG_CRYPTO_SERPENT_AVX_X86_64=m CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set @@ -71,6 +74,7 @@ CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP=y +# CONFIG_MOVABLE_NODE is not set # CONFIG_MEMORY_HOTPLUG is not set # CONFIG_MEMORY_HOTREMOVE is not set diff --git a/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch b/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch deleted file mode 100644 index bd232a5ad..000000000 --- a/drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 3566b9ac5b4004af0e2b1c62c5ded1116b39d490 Mon Sep 17 00:00:00 2001 -From: Adam Jackson -Date: Mon, 18 Feb 2013 13:40:16 -0500 -Subject: [PATCH] drm/i915: Fix up mismerge of 3490ea5d in 3.7.y - -The 3.7.y version of this seems to have missed a hunk in i9xx_update_wm. - -Signed-off-by: Adam Jackson ---- - drivers/gpu/drm/i915/intel_pm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c -index 4e6a2b2..313088f 100644 ---- a/drivers/gpu/drm/i915/intel_pm.c -+++ b/drivers/gpu/drm/i915/intel_pm.c -@@ -1474,7 +1474,7 @@ static void i9xx_update_wm(struct drm_device *dev) - - fifo_size = dev_priv->display.get_fifo_size(dev, 0); - crtc = intel_get_crtc_for_plane(dev, 0); -- if (crtc->enabled && crtc->fb) { -+ if (intel_crtc_active(crtc)) { - planea_wm = intel_calculate_wm(crtc->mode.clock, - wm_info, fifo_size, - crtc->fb->bits_per_pixel / 8, --- -1.8.1.2 - diff --git a/efivarfs-3.7.patch b/efivarfs-3.7.patch deleted file mode 100644 index 662406405..000000000 --- a/efivarfs-3.7.patch +++ /dev/null @@ -1,1654 +0,0 @@ -From cb6f23ee9601297c3c70d0cfe3d77dfde9bd119d Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Fri, 5 Oct 2012 13:54:56 +0800 -Subject: [PATCH 01/17] efi: Add support for a UEFI variable filesystem - -The existing EFI variables code only supports variables of up to 1024 -bytes. This limitation existed in version 0.99 of the EFI specification, -but was removed before any full releases. Since variables can now be -larger than a single page, sysfs isn't the best interface for this. So, -instead, let's add a filesystem. Variables can be read, written and -created, with the first 4 bytes of each variable representing its UEFI -attributes. The create() method doesn't actually commit to flash since -zero-length variables can't exist per-spec. - -Updates from Jeremy Kerr . - -Signed-off-by: Matthew Garrett -Signed-off-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 384 ++++++++++++++++++++++++++++++++++++++++++++- - include/linux/efi.h | 5 + - 2 files changed, 383 insertions(+), 6 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index d10c987..b605c48 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -80,6 +80,10 @@ - #include - #include - -+#include -+#include -+#include -+ - #include - - #define EFIVARS_VERSION "0.08" -@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL"); - MODULE_VERSION(EFIVARS_VERSION); - - #define DUMP_NAME_LEN 52 -+#define GUID_LEN 37 - - /* - * The maximum size of VariableName + Data = 1024 -@@ -108,7 +113,6 @@ struct efi_variable { - __u32 Attributes; - } __attribute__((packed)); - -- - struct efivar_entry { - struct efivars *efivars; - struct efi_variable var; -@@ -122,6 +126,9 @@ struct efivar_attribute { - ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); - }; - -+static struct efivars __efivars; -+static struct efivar_operations ops; -+ - #define PSTORE_EFI_ATTRIBUTES \ - (EFI_VARIABLE_NON_VOLATILE | \ - EFI_VARIABLE_BOOTSERVICE_ACCESS | \ -@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = { - .default_attrs = def_attrs, - }; - --static struct pstore_info efi_pstore_info; -- - static inline void - efivar_unregister(struct efivar_entry *var) - { - kobject_put(&var->kobj); - } - -+static int efivarfs_file_open(struct inode *inode, struct file *file) -+{ -+ file->private_data = inode->i_private; -+ return 0; -+} -+ -+static ssize_t efivarfs_file_write(struct file *file, -+ const char __user *userbuf, size_t count, loff_t *ppos) -+{ -+ struct efivar_entry *var = file->private_data; -+ struct efivars *efivars; -+ efi_status_t status; -+ void *data; -+ u32 attributes; -+ struct inode *inode = file->f_mapping->host; -+ int datasize = count - sizeof(attributes); -+ -+ if (count < sizeof(attributes)) -+ return -EINVAL; -+ -+ data = kmalloc(datasize, GFP_KERNEL); -+ -+ if (!data) -+ return -ENOMEM; -+ -+ efivars = var->efivars; -+ -+ if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { -+ count = -EFAULT; -+ goto out; -+ } -+ -+ if (attributes & ~(EFI_VARIABLE_MASK)) { -+ count = -EINVAL; -+ goto out; -+ } -+ -+ if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { -+ count = -EFAULT; -+ goto out; -+ } -+ -+ if (validate_var(&var->var, data, datasize) == false) { -+ count = -EINVAL; -+ goto out; -+ } -+ -+ status = efivars->ops->set_variable(var->var.VariableName, -+ &var->var.VendorGuid, -+ attributes, datasize, -+ data); -+ -+ switch (status) { -+ case EFI_SUCCESS: -+ mutex_lock(&inode->i_mutex); -+ i_size_write(inode, count); -+ mutex_unlock(&inode->i_mutex); -+ break; -+ case EFI_INVALID_PARAMETER: -+ count = -EINVAL; -+ break; -+ case EFI_OUT_OF_RESOURCES: -+ count = -ENOSPC; -+ break; -+ case EFI_DEVICE_ERROR: -+ count = -EIO; -+ break; -+ case EFI_WRITE_PROTECTED: -+ count = -EROFS; -+ break; -+ case EFI_SECURITY_VIOLATION: -+ count = -EACCES; -+ break; -+ case EFI_NOT_FOUND: -+ count = -ENOENT; -+ break; -+ default: -+ count = -EINVAL; -+ break; -+ } -+out: -+ kfree(data); -+ -+ return count; -+} -+ -+static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, -+ size_t count, loff_t *ppos) -+{ -+ struct efivar_entry *var = file->private_data; -+ struct efivars *efivars = var->efivars; -+ efi_status_t status; -+ unsigned long datasize = 0; -+ u32 attributes; -+ void *data; -+ ssize_t size; -+ -+ status = efivars->ops->get_variable(var->var.VariableName, -+ &var->var.VendorGuid, -+ &attributes, &datasize, NULL); -+ -+ if (status != EFI_BUFFER_TOO_SMALL) -+ return 0; -+ -+ data = kmalloc(datasize + 4, GFP_KERNEL); -+ -+ if (!data) -+ return 0; -+ -+ status = efivars->ops->get_variable(var->var.VariableName, -+ &var->var.VendorGuid, -+ &attributes, &datasize, -+ (data + 4)); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ memcpy(data, &attributes, 4); -+ size = simple_read_from_buffer(userbuf, count, ppos, -+ data, datasize + 4); -+ kfree(data); -+ -+ return size; -+} -+ -+static void efivarfs_evict_inode(struct inode *inode) -+{ -+ clear_inode(inode); -+} -+ -+static const struct super_operations efivarfs_ops = { -+ .statfs = simple_statfs, -+ .drop_inode = generic_delete_inode, -+ .evict_inode = efivarfs_evict_inode, -+ .show_options = generic_show_options, -+}; -+ -+static struct super_block *efivarfs_sb; -+ -+static const struct inode_operations efivarfs_dir_inode_operations; -+ -+static const struct file_operations efivarfs_file_operations = { -+ .open = efivarfs_file_open, -+ .read = efivarfs_file_read, -+ .write = efivarfs_file_write, -+ .llseek = no_llseek, -+}; -+ -+static struct inode *efivarfs_get_inode(struct super_block *sb, -+ const struct inode *dir, int mode, dev_t dev) -+{ -+ struct inode *inode = new_inode(sb); -+ -+ if (inode) { -+ inode->i_ino = get_next_ino(); -+ inode->i_uid = inode->i_gid = 0; -+ inode->i_mode = mode; -+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ inode->i_fop = &efivarfs_file_operations; -+ break; -+ case S_IFDIR: -+ inode->i_op = &efivarfs_dir_inode_operations; -+ inode->i_fop = &simple_dir_operations; -+ inc_nlink(inode); -+ break; -+ } -+ } -+ return inode; -+} -+ -+static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) -+{ -+ guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); -+ guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]); -+ guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]); -+ guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]); -+ guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]); -+ guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]); -+ guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]); -+ guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]); -+ guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]); -+ guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]); -+ guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]); -+ guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]); -+ guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]); -+ guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]); -+ guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]); -+ guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]); -+} -+ -+static int efivarfs_create(struct inode *dir, struct dentry *dentry, -+ umode_t mode, bool excl) -+{ -+ struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); -+ struct efivars *efivars = &__efivars; -+ struct efivar_entry *var; -+ int namelen, i = 0, err = 0; -+ -+ if (dentry->d_name.len < 38) -+ return -EINVAL; -+ -+ if (!inode) -+ return -ENOSPC; -+ -+ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); -+ -+ if (!var) -+ return -ENOMEM; -+ -+ namelen = dentry->d_name.len - GUID_LEN; -+ -+ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, -+ &var->var.VendorGuid); -+ -+ for (i = 0; i < namelen; i++) -+ var->var.VariableName[i] = dentry->d_name.name[i]; -+ -+ var->var.VariableName[i] = '\0'; -+ -+ inode->i_private = var; -+ var->efivars = efivars; -+ var->kobj.kset = efivars->kset; -+ -+ err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", -+ dentry->d_name.name); -+ if (err) -+ goto out; -+ -+ kobject_uevent(&var->kobj, KOBJ_ADD); -+ spin_lock(&efivars->lock); -+ list_add(&var->list, &efivars->list); -+ spin_unlock(&efivars->lock); -+ d_instantiate(dentry, inode); -+ dget(dentry); -+out: -+ if (err) -+ kfree(var); -+ return err; -+} -+ -+static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ struct efivar_entry *var = dentry->d_inode->i_private; -+ struct efivars *efivars = var->efivars; -+ efi_status_t status; -+ -+ spin_lock(&efivars->lock); -+ -+ status = efivars->ops->set_variable(var->var.VariableName, -+ &var->var.VendorGuid, -+ 0, 0, NULL); -+ -+ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { -+ list_del(&var->list); -+ spin_unlock(&efivars->lock); -+ efivar_unregister(var); -+ drop_nlink(dir); -+ dput(dentry); -+ return 0; -+ } -+ -+ spin_unlock(&efivars->lock); -+ return -EINVAL; -+}; -+ -+int efivarfs_fill_super(struct super_block *sb, void *data, int silent) -+{ -+ struct inode *inode = NULL; -+ struct dentry *root; -+ struct efivar_entry *entry, *n; -+ struct efivars *efivars = &__efivars; -+ int err; -+ -+ efivarfs_sb = sb; -+ -+ sb->s_maxbytes = MAX_LFS_FILESIZE; -+ sb->s_blocksize = PAGE_CACHE_SIZE; -+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -+ sb->s_magic = PSTOREFS_MAGIC; -+ sb->s_op = &efivarfs_ops; -+ sb->s_time_gran = 1; -+ -+ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); -+ if (!inode) { -+ err = -ENOMEM; -+ goto fail; -+ } -+ inode->i_op = &efivarfs_dir_inode_operations; -+ -+ root = d_make_root(inode); -+ sb->s_root = root; -+ if (!root) { -+ err = -ENOMEM; -+ goto fail; -+ } -+ -+ list_for_each_entry_safe(entry, n, &efivars->list, list) { -+ struct inode *inode; -+ struct dentry *dentry, *root = efivarfs_sb->s_root; -+ char *name; -+ unsigned long size = 0; -+ int len, i; -+ -+ len = utf16_strlen(entry->var.VariableName); -+ -+ /* GUID plus trailing NULL */ -+ name = kmalloc(len + 38, GFP_ATOMIC); -+ -+ for (i = 0; i < len; i++) -+ name[i] = entry->var.VariableName[i] & 0xFF; -+ -+ name[len] = '-'; -+ -+ efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); -+ -+ name[len+GUID_LEN] = '\0'; -+ -+ inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, -+ S_IFREG | 0644, 0); -+ dentry = d_alloc_name(root, name); -+ -+ efivars->ops->get_variable(entry->var.VariableName, -+ &entry->var.VendorGuid, -+ &entry->var.Attributes, -+ &size, -+ NULL); -+ -+ mutex_lock(&inode->i_mutex); -+ inode->i_private = entry; -+ i_size_write(inode, size+4); -+ mutex_unlock(&inode->i_mutex); -+ d_add(dentry, inode); -+ } -+ -+ return 0; -+fail: -+ iput(inode); -+ return err; -+} -+ -+static struct dentry *efivarfs_mount(struct file_system_type *fs_type, -+ int flags, const char *dev_name, void *data) -+{ -+ return mount_single(fs_type, flags, data, efivarfs_fill_super); -+} -+ -+static void efivarfs_kill_sb(struct super_block *sb) -+{ -+ kill_litter_super(sb); -+ efivarfs_sb = NULL; -+} -+ -+static struct file_system_type efivarfs_type = { -+ .name = "efivarfs", -+ .mount = efivarfs_mount, -+ .kill_sb = efivarfs_kill_sb, -+}; -+ -+static const struct inode_operations efivarfs_dir_inode_operations = { -+ .lookup = simple_lookup, -+ .unlink = efivarfs_unlink, -+ .create = efivarfs_create, -+}; -+ -+static struct pstore_info efi_pstore_info; -+ - #ifdef CONFIG_PSTORE - - static int efi_pstore_open(struct pstore_info *psi) -@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars, - pstore_register(&efivars->efi_pstore_info); - } - -+ register_filesystem(&efivarfs_type); -+ - out: - kfree(variable_name); - -@@ -1205,9 +1580,6 @@ out: - } - EXPORT_SYMBOL_GPL(register_efivars); - --static struct efivars __efivars; --static struct efivar_operations ops; -- - /* - * For now we register the efi subsystem with the firmware subsystem - * and the vars subsystem with the efi subsystem. In the future, it -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 8670eb1..b2af157 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -29,7 +29,12 @@ - #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) - #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) - #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) -+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) -+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) -+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) -+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) - #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) -+#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) - - typedef unsigned long efi_status_t; - typedef u8 efi_bool_t; --- -1.7.12.1 - - -From 2fc1dc88e97665c70f203f0132232ea55e8dd7eb Mon Sep 17 00:00:00 2001 -From: Jeremy Kerr -Date: Fri, 5 Oct 2012 13:54:56 +0800 -Subject: [PATCH 02/17] efi: Handle deletions and size changes in - efivarfs_write_file - -A write to an efivarfs file will not always result in a variable of -'count' size after the EFI SetVariable() call. We may have appended to -the existing data (ie, with the EFI_VARIABLE_APPEND_WRITE attribute), or -even have deleted the variable (with an authenticated variable update, -with a zero datasize). - -This change re-reads the updated variable from firmware, to check for -size changes and deletions. In the latter case, we need to drop the -dentry. - -Signed-off-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 49 ++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 39 insertions(+), 10 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index b605c48..d7658b4 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file, - u32 attributes; - struct inode *inode = file->f_mapping->host; - int datasize = count - sizeof(attributes); -+ unsigned long newdatasize; - - if (count < sizeof(attributes)) - return -EINVAL; -@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file, - - switch (status) { - case EFI_SUCCESS: -- mutex_lock(&inode->i_mutex); -- i_size_write(inode, count); -- mutex_unlock(&inode->i_mutex); - break; - case EFI_INVALID_PARAMETER: - count = -EINVAL; -- break; -+ goto out; - case EFI_OUT_OF_RESOURCES: - count = -ENOSPC; -- break; -+ goto out; - case EFI_DEVICE_ERROR: - count = -EIO; -- break; -+ goto out; - case EFI_WRITE_PROTECTED: - count = -EROFS; -- break; -+ goto out; - case EFI_SECURITY_VIOLATION: - count = -EACCES; -- break; -+ goto out; - case EFI_NOT_FOUND: - count = -ENOENT; -- break; -+ goto out; - default: - count = -EINVAL; -- break; -+ goto out; - } -+ -+ /* -+ * Writing to the variable may have caused a change in size (which -+ * could either be an append or an overwrite), or the variable to be -+ * deleted. Perform a GetVariable() so we can tell what actually -+ * happened. -+ */ -+ newdatasize = 0; -+ status = efivars->ops->get_variable(var->var.VariableName, -+ &var->var.VendorGuid, -+ NULL, &newdatasize, -+ NULL); -+ -+ if (status == EFI_BUFFER_TOO_SMALL) { -+ mutex_lock(&inode->i_mutex); -+ i_size_write(inode, newdatasize + sizeof(attributes)); -+ mutex_unlock(&inode->i_mutex); -+ -+ } else if (status == EFI_NOT_FOUND) { -+ spin_lock(&efivars->lock); -+ list_del(&var->list); -+ spin_unlock(&efivars->lock); -+ efivar_unregister(var); -+ drop_nlink(inode); -+ dput(file->f_dentry); -+ -+ } else { -+ pr_warn("efivarfs: inconsistent EFI variable implementation? " -+ "status = %lx\n", status); -+ } -+ - out: - kfree(data); - --- -1.7.12.1 - - -From c98611fc95672862950c9bc4d6a3a4c4453a3c3e Mon Sep 17 00:00:00 2001 -From: "Lee, Chun-Yi" -Date: Fri, 5 Oct 2012 13:54:56 +0800 -Subject: [PATCH 03/17] efi: add efivars kobject to efi sysfs folder - -UEFI variable filesystem need a new mount point, so this patch add -efivars kobject to efi_kobj for create a /sys/firmware/efi/efivars -folder. - -Cc: Matthew Garrett -Cc: H. Peter Anvin -Signed-off-by: Lee, Chun-Yi -Signed-off-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 9 +++++++++ - include/linux/efi.h | 1 + - 2 files changed, 10 insertions(+) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index d7658b4..6793965 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -1527,6 +1527,7 @@ void unregister_efivars(struct efivars *efivars) - sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); - kfree(efivars->new_var); - kfree(efivars->del_var); -+ kobject_put(efivars->kobject); - kset_unregister(efivars->kset); - } - EXPORT_SYMBOL_GPL(unregister_efivars); -@@ -1558,6 +1559,14 @@ int register_efivars(struct efivars *efivars, - goto out; - } - -+ efivars->kobject = kobject_create_and_add("efivars", parent_kobj); -+ if (!efivars->kobject) { -+ pr_err("efivars: Subsystem registration failed.\n"); -+ error = -ENOMEM; -+ kset_unregister(efivars->kset); -+ goto out; -+ } -+ - /* - * Per EFI spec, the maximum storage allocated for both - * the variable name and variable data is 1024 bytes. -diff --git a/include/linux/efi.h b/include/linux/efi.h -index b2af157..337aefb 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -662,6 +662,7 @@ struct efivars { - spinlock_t lock; - struct list_head list; - struct kset *kset; -+ struct kobject *kobject; - struct bin_attribute *new_var, *del_var; - const struct efivar_operations *ops; - struct efivar_entry *walk_entry; --- -1.7.12.1 - - -From 8ef5f49da57087022f2031820ceb3b1c6101d76c Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Thu, 4 Oct 2012 09:57:31 +0100 -Subject: [PATCH 04/17] efivarfs: Add documentation for the EFI variable - filesystem - -Signed-off-by: Matt Fleming ---- - Documentation/filesystems/00-INDEX | 2 ++ - Documentation/filesystems/efivarfs.txt | 16 ++++++++++++++++ - 2 files changed, 18 insertions(+) - create mode 100644 Documentation/filesystems/efivarfs.txt - -diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX -index 8c624a1..7b52ba7 100644 ---- a/Documentation/filesystems/00-INDEX -+++ b/Documentation/filesystems/00-INDEX -@@ -38,6 +38,8 @@ dnotify_test.c - - example program for dnotify - ecryptfs.txt - - docs on eCryptfs: stacked cryptographic filesystem for Linux. -+efivarfs.txt -+ - info for the efivarfs filesystem. - exofs.txt - - info, usage, mount options, design about EXOFS. - ext2.txt -diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt -new file mode 100644 -index 0000000..c477af0 ---- /dev/null -+++ b/Documentation/filesystems/efivarfs.txt -@@ -0,0 +1,16 @@ -+ -+efivarfs - a (U)EFI variable filesystem -+ -+The efivarfs filesystem was created to address the shortcomings of -+using entries in sysfs to maintain EFI variables. The old sysfs EFI -+variables code only supported variables of up to 1024 bytes. This -+limitation existed in version 0.99 of the EFI specification, but was -+removed before any full releases. Since variables can now be larger -+than a single page, sysfs isn't the best interface for this. -+ -+Variables can be created, deleted and modified with the efivarfs -+filesystem. -+ -+efivarfs is typically mounted like this, -+ -+ mount -t efivarfs none /sys/firmware/efi/efivars --- -1.7.12.1 - - -From f69c39248e2f1eebf24f5ee55139602c56d15aec Mon Sep 17 00:00:00 2001 -From: Andy Whitcroft -Date: Thu, 11 Oct 2012 11:32:17 +0100 -Subject: [PATCH 05/17] efivarfs: efivarfs_file_read ensure we free data in - error paths - -Signed-off-by: Andy Whitcroft -Acked-by: Matthew Garrett -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 6793965..b7c9a32 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -766,7 +766,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - unsigned long datasize = 0; - u32 attributes; - void *data; -- ssize_t size; -+ ssize_t size = 0; - - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, -@@ -784,13 +784,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - &var->var.VendorGuid, - &attributes, &datasize, - (data + 4)); -- - if (status != EFI_SUCCESS) -- return 0; -+ goto out_free; - - memcpy(data, &attributes, 4); - size = simple_read_from_buffer(userbuf, count, ppos, - data, datasize + 4); -+out_free: - kfree(data); - - return size; --- -1.7.12.1 - - -From 429136e16c7c43bbebb8b8030203161a2d3fc3ce Mon Sep 17 00:00:00 2001 -From: Andy Whitcroft -Date: Thu, 11 Oct 2012 11:32:18 +0100 -Subject: [PATCH 06/17] efivarfs: efivarfs_create() ensure we drop our - reference on inode on error - -Signed-off-by: Andy Whitcroft -Acked-by: Matthew Garrett -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index b7c9a32..6e5f367 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -866,7 +866,7 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) - static int efivarfs_create(struct inode *dir, struct dentry *dentry, - umode_t mode, bool excl) - { -- struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); -+ struct inode *inode; - struct efivars *efivars = &__efivars; - struct efivar_entry *var; - int namelen, i = 0, err = 0; -@@ -874,13 +874,15 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - if (dentry->d_name.len < 38) - return -EINVAL; - -+ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); - if (!inode) - return -ENOSPC; - - var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); -- -- if (!var) -- return -ENOMEM; -+ if (!var) { -+ err = -ENOMEM; -+ goto out; -+ } - - namelen = dentry->d_name.len - GUID_LEN; - -@@ -908,8 +910,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - d_instantiate(dentry, inode); - dget(dentry); - out: -- if (err) -+ if (err) { - kfree(var); -+ iput(inode); -+ } - return err; - } - --- -1.7.12.1 - - -From 1a19268e8a4bae43c1feb3f71ee468c6bc70aca6 Mon Sep 17 00:00:00 2001 -From: Andy Whitcroft -Date: Thu, 11 Oct 2012 11:32:19 +0100 -Subject: [PATCH 07/17] efivarfs: efivarfs_fill_super() fix inode reference - counts - -When d_make_root() fails it will automatically drop the reference -on the root inode. We should not be doing so as well. - -Signed-off-by: Andy Whitcroft -Acked-by: Matthew Garrett -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 16 ++++------------ - 1 file changed, 4 insertions(+), 12 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 6e5f367..adfc486 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -948,7 +948,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - struct dentry *root; - struct efivar_entry *entry, *n; - struct efivars *efivars = &__efivars; -- int err; - - efivarfs_sb = sb; - -@@ -960,18 +959,14 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - sb->s_time_gran = 1; - - inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); -- if (!inode) { -- err = -ENOMEM; -- goto fail; -- } -+ if (!inode) -+ return -ENOMEM; - inode->i_op = &efivarfs_dir_inode_operations; - - root = d_make_root(inode); - sb->s_root = root; -- if (!root) { -- err = -ENOMEM; -- goto fail; -- } -+ if (!root) -+ return -ENOMEM; - - list_for_each_entry_safe(entry, n, &efivars->list, list) { - struct inode *inode; -@@ -1012,9 +1007,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - } - - return 0; --fail: -- iput(inode); -- return err; - } - - static struct dentry *efivarfs_mount(struct file_system_type *fs_type, --- -1.7.12.1 - - -From f0d90a4024493aed6fc77ce5cd3b93f278fed9c0 Mon Sep 17 00:00:00 2001 -From: Andy Whitcroft -Date: Thu, 11 Oct 2012 11:32:20 +0100 -Subject: [PATCH 08/17] efivarfs: efivarfs_fill_super() ensure we free our - temporary name - -d_alloc_name() copies the passed name to new storage, once complete we -no longer need our name. - -Signed-off-by: Andy Whitcroft -Acked-by: Matthew Garrett -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index adfc486..36b3dd6 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -992,6 +992,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, - S_IFREG | 0644, 0); - dentry = d_alloc_name(root, name); -+ /* copied by the above to local storage in the dentry. */ -+ kfree(name); - - efivars->ops->get_variable(entry->var.VariableName, - &entry->var.VendorGuid, --- -1.7.12.1 - - -From c4cf244c318218153200d0011d8ef0ebcf3146ea Mon Sep 17 00:00:00 2001 -From: Andy Whitcroft -Date: Thu, 11 Oct 2012 11:32:21 +0100 -Subject: [PATCH 09/17] efivarfs: efivarfs_fill_super() ensure we clean up - correctly on error - -Ensure we free both the name and inode on error when building the -individual variables. - -Signed-off-by: Andy Whitcroft -Acked-by: Matthew Garrett -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 36b3dd6..216086d 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - struct dentry *root; - struct efivar_entry *entry, *n; - struct efivars *efivars = &__efivars; -+ char *name; - - efivarfs_sb = sb; - -@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - return -ENOMEM; - - list_for_each_entry_safe(entry, n, &efivars->list, list) { -- struct inode *inode; - struct dentry *dentry, *root = efivarfs_sb->s_root; -- char *name; - unsigned long size = 0; - int len, i; - -+ inode = NULL; -+ - len = utf16_strlen(entry->var.VariableName); - - /* GUID plus trailing NULL */ - name = kmalloc(len + 38, GFP_ATOMIC); -+ if (!name) -+ goto fail; - - for (i = 0; i < len; i++) - name[i] = entry->var.VariableName[i] & 0xFF; -@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - - inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, - S_IFREG | 0644, 0); -+ if (!inode) -+ goto fail_name; -+ - dentry = d_alloc_name(root, name); -+ if (!dentry) -+ goto fail_inode; -+ - /* copied by the above to local storage in the dentry. */ - kfree(name); - -@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - } - - return 0; -+ -+fail_inode: -+ iput(inode); -+fail_name: -+ kfree(name); -+fail: -+ return -ENOMEM; - } - - static struct dentry *efivarfs_mount(struct file_system_type *fs_type, --- -1.7.12.1 - - -From d3b7165568bcb50e4526c3dadda59e43f6681bc0 Mon Sep 17 00:00:00 2001 -From: Jeremy Kerr -Date: Thu, 11 Oct 2012 21:19:11 +0800 -Subject: [PATCH 10/17] efivarfs: Implement exclusive access for - {get,set}_variable - -Currently, efivarfs does not enforce exclusion over the get_variable and -set_variable operations. Section 7.1 of UEFI requires us to only allow a -single processor to enter {get,set}_variable services at once. - -This change acquires the efivars->lock over calls to these operations -from the efivarfs paths. - -Signed-off-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 68 +++++++++++++++++++++++++++++----------------- - 1 file changed, 43 insertions(+), 25 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 216086d..d478c56 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -690,35 +690,45 @@ static ssize_t efivarfs_file_write(struct file *file, - goto out; - } - -+ /* -+ * The lock here protects the get_variable call, the conditional -+ * set_variable call, and removal of the variable from the efivars -+ * list (in the case of an authenticated delete). -+ */ -+ spin_lock(&efivars->lock); -+ - status = efivars->ops->set_variable(var->var.VariableName, - &var->var.VendorGuid, - attributes, datasize, - data); - -- switch (status) { -- case EFI_SUCCESS: -- break; -- case EFI_INVALID_PARAMETER: -- count = -EINVAL; -- goto out; -- case EFI_OUT_OF_RESOURCES: -- count = -ENOSPC; -- goto out; -- case EFI_DEVICE_ERROR: -- count = -EIO; -- goto out; -- case EFI_WRITE_PROTECTED: -- count = -EROFS; -- goto out; -- case EFI_SECURITY_VIOLATION: -- count = -EACCES; -- goto out; -- case EFI_NOT_FOUND: -- count = -ENOENT; -- goto out; -- default: -- count = -EINVAL; -- goto out; -+ if (status != EFI_SUCCESS) { -+ spin_unlock(&efivars->lock); -+ kfree(data); -+ -+ switch (status) { -+ case EFI_INVALID_PARAMETER: -+ count = -EINVAL; -+ break; -+ case EFI_OUT_OF_RESOURCES: -+ count = -ENOSPC; -+ break; -+ case EFI_DEVICE_ERROR: -+ count = -EIO; -+ break; -+ case EFI_WRITE_PROTECTED: -+ count = -EROFS; -+ break; -+ case EFI_SECURITY_VIOLATION: -+ count = -EACCES; -+ break; -+ case EFI_NOT_FOUND: -+ count = -ENOENT; -+ break; -+ default: -+ count = -EINVAL; -+ } -+ return count; - } - - /* -@@ -734,12 +744,12 @@ static ssize_t efivarfs_file_write(struct file *file, - NULL); - - if (status == EFI_BUFFER_TOO_SMALL) { -+ spin_unlock(&efivars->lock); - mutex_lock(&inode->i_mutex); - i_size_write(inode, newdatasize + sizeof(attributes)); - mutex_unlock(&inode->i_mutex); - - } else if (status == EFI_NOT_FOUND) { -- spin_lock(&efivars->lock); - list_del(&var->list); - spin_unlock(&efivars->lock); - efivar_unregister(var); -@@ -747,6 +757,7 @@ static ssize_t efivarfs_file_write(struct file *file, - dput(file->f_dentry); - - } else { -+ spin_unlock(&efivars->lock); - pr_warn("efivarfs: inconsistent EFI variable implementation? " - "status = %lx\n", status); - } -@@ -768,9 +779,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - void *data; - ssize_t size = 0; - -+ spin_lock(&efivars->lock); - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, - &attributes, &datasize, NULL); -+ spin_unlock(&efivars->lock); - - if (status != EFI_BUFFER_TOO_SMALL) - return 0; -@@ -780,10 +793,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - if (!data) - return 0; - -+ spin_lock(&efivars->lock); - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, - &attributes, &datasize, - (data + 4)); -+ spin_unlock(&efivars->lock); -+ - if (status != EFI_SUCCESS) - goto out_free; - -@@ -1004,11 +1020,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - /* copied by the above to local storage in the dentry. */ - kfree(name); - -+ spin_lock(&efivars->lock); - efivars->ops->get_variable(entry->var.VariableName, - &entry->var.VendorGuid, - &entry->var.Attributes, - &size, - NULL); -+ spin_unlock(&efivars->lock); - - mutex_lock(&inode->i_mutex); - inode->i_private = entry; --- -1.7.12.1 - - -From 90a462e9cf439a1987e0f9434d1f615addcc1970 Mon Sep 17 00:00:00 2001 -From: Jeremy Kerr -Date: Fri, 19 Oct 2012 15:16:45 +0800 -Subject: [PATCH 11/17] efi: Clarify GUID length calculations - -At present, the handling of GUIDs in efivar file names isn't consistent. -We use GUID_LEN in some places, and 38 in others (GUID_LEN plus -separator), and implicitly use the presence of the trailing NUL. - -This change removes the trailing NUL from GUID_LEN, so that we're -explicitly adding it when required. We also replace magic numbers -with GUID_LEN, and clarify the comments where appropriate. - -We also fix the allocation size in efivar_create_sysfs_entry, where -we're allocating one byte too much, due to counting the trailing NUL -twice - once when calculating short_name_size, and once in the kzalloc. - -Signed-off-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 33 +++++++++++++++++++++++++-------- - 1 file changed, 25 insertions(+), 8 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index d478c56..a93e401 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -95,7 +95,12 @@ MODULE_LICENSE("GPL"); - MODULE_VERSION(EFIVARS_VERSION); - - #define DUMP_NAME_LEN 52 --#define GUID_LEN 37 -+ -+/* -+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) -+ * not including trailing NUL -+ */ -+#define GUID_LEN 36 - - /* - * The maximum size of VariableName + Data = 1024 -@@ -887,7 +892,11 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - struct efivar_entry *var; - int namelen, i = 0, err = 0; - -- if (dentry->d_name.len < 38) -+ /* -+ * We need a GUID, plus at least one letter for the variable name, -+ * plus the '-' separator -+ */ -+ if (dentry->d_name.len < GUID_LEN + 2) - return -EINVAL; - - inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); -@@ -900,7 +909,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - goto out; - } - -- namelen = dentry->d_name.len - GUID_LEN; -+ /* length of the variable name itself: remove GUID and separator */ -+ namelen = dentry->d_name.len - GUID_LEN - 1; - - efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, - &var->var.VendorGuid); -@@ -994,8 +1004,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - - len = utf16_strlen(entry->var.VariableName); - -- /* GUID plus trailing NULL */ -- name = kmalloc(len + 38, GFP_ATOMIC); -+ /* name, plus '-', plus GUID, plus NUL*/ -+ name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); - if (!name) - goto fail; - -@@ -1006,7 +1016,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - - efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); - -- name[len+GUID_LEN] = '\0'; -+ name[len+GUID_LEN+1] = '\0'; - - inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, - S_IFREG | 0644, 0); -@@ -1435,11 +1445,18 @@ efivar_create_sysfs_entry(struct efivars *efivars, - efi_char16_t *variable_name, - efi_guid_t *vendor_guid) - { -- int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; -+ int i, short_name_size; - char *short_name; - struct efivar_entry *new_efivar; - -- short_name = kzalloc(short_name_size + 1, GFP_KERNEL); -+ /* -+ * Length of the variable bytes in ASCII, plus the '-' separator, -+ * plus the GUID, plus trailing NUL -+ */ -+ short_name_size = variable_name_size / sizeof(efi_char16_t) -+ + 1 + GUID_LEN + 1; -+ -+ short_name = kzalloc(short_name_size, GFP_KERNEL); - new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); - - if (!short_name || !new_efivar) { --- -1.7.12.1 - - -From ecbf90823d85ebb41e68e6be01f476862d184825 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Tue, 16 Oct 2012 15:58:07 +0100 -Subject: [PATCH 12/17] efivarfs: Return an error if we fail to read a - variable - -Instead of always returning 0 in efivarfs_file_read(), even when we -fail to successfully read the variable, convert the EFI status to -something meaningful and return that to the caller. This way the user -will have some hint as to why the read failed. - -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 62 +++++++++++++++++++++++++++------------------- - 1 file changed, 36 insertions(+), 26 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index a93e401..277e426 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -653,6 +653,36 @@ static int efivarfs_file_open(struct inode *inode, struct file *file) - return 0; - } - -+static int efi_status_to_err(efi_status_t status) -+{ -+ int err; -+ -+ switch (status) { -+ case EFI_INVALID_PARAMETER: -+ err = -EINVAL; -+ break; -+ case EFI_OUT_OF_RESOURCES: -+ err = -ENOSPC; -+ break; -+ case EFI_DEVICE_ERROR: -+ err = -EIO; -+ break; -+ case EFI_WRITE_PROTECTED: -+ err = -EROFS; -+ break; -+ case EFI_SECURITY_VIOLATION: -+ err = -EACCES; -+ break; -+ case EFI_NOT_FOUND: -+ err = -ENOENT; -+ break; -+ default: -+ err = -EINVAL; -+ } -+ -+ return err; -+} -+ - static ssize_t efivarfs_file_write(struct file *file, - const char __user *userbuf, size_t count, loff_t *ppos) - { -@@ -711,29 +741,7 @@ static ssize_t efivarfs_file_write(struct file *file, - spin_unlock(&efivars->lock); - kfree(data); - -- switch (status) { -- case EFI_INVALID_PARAMETER: -- count = -EINVAL; -- break; -- case EFI_OUT_OF_RESOURCES: -- count = -ENOSPC; -- break; -- case EFI_DEVICE_ERROR: -- count = -EIO; -- break; -- case EFI_WRITE_PROTECTED: -- count = -EROFS; -- break; -- case EFI_SECURITY_VIOLATION: -- count = -EACCES; -- break; -- case EFI_NOT_FOUND: -- count = -ENOENT; -- break; -- default: -- count = -EINVAL; -- } -- return count; -+ return efi_status_to_err(status); - } - - /* -@@ -791,12 +799,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - spin_unlock(&efivars->lock); - - if (status != EFI_BUFFER_TOO_SMALL) -- return 0; -+ return efi_status_to_err(status); - - data = kmalloc(datasize + 4, GFP_KERNEL); - - if (!data) -- return 0; -+ return -ENOMEM; - - spin_lock(&efivars->lock); - status = efivars->ops->get_variable(var->var.VariableName, -@@ -805,8 +813,10 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - (data + 4)); - spin_unlock(&efivars->lock); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ size = efi_status_to_err(status); - goto out_free; -+ } - - memcpy(data, &attributes, 4); - size = simple_read_from_buffer(userbuf, count, ppos, --- -1.7.12.1 - - -From 39210330739b943856ff21b29b4a0804f4e8349f Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Mon, 22 Oct 2012 15:23:29 +0100 -Subject: [PATCH 13/17] efivarfs: Replace magic number with sizeof(attributes) - -Seeing "+ 4" littered throughout the functions gets a bit -confusing. Use "sizeof(attributes)" which clearly explains what -quantity we're adding. - -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 277e426..2c04434 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -801,7 +801,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - if (status != EFI_BUFFER_TOO_SMALL) - return efi_status_to_err(status); - -- data = kmalloc(datasize + 4, GFP_KERNEL); -+ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); - - if (!data) - return -ENOMEM; -@@ -810,7 +810,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, - &attributes, &datasize, -- (data + 4)); -+ (data + sizeof(attributes))); - spin_unlock(&efivars->lock); - - if (status != EFI_SUCCESS) { -@@ -818,9 +818,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - goto out_free; - } - -- memcpy(data, &attributes, 4); -+ memcpy(data, &attributes, sizeof(attributes)); - size = simple_read_from_buffer(userbuf, count, ppos, -- data, datasize + 4); -+ data, datasize + sizeof(attributes)); - out_free: - kfree(data); - --- -1.7.12.1 - - -From 5555f0af6294b3675a95a06da23101150644936d Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Mon, 22 Oct 2012 15:51:45 +0100 -Subject: [PATCH 14/17] efivarfs: Add unique magic number - -Using pstore's superblock magic number is no doubt going to cause -problems in the future. Give efivarfs its own magic number. - -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 2 +- - include/uapi/linux/magic.h | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 2c04434..3b0cf9a 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -991,7 +991,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -- sb->s_magic = PSTOREFS_MAGIC; -+ sb->s_magic = EFIVARFS_MAGIC; - sb->s_op = &efivarfs_ops; - sb->s_time_gran = 1; - -diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h -index e15192c..12f68c7 100644 ---- a/include/uapi/linux/magic.h -+++ b/include/uapi/linux/magic.h -@@ -27,6 +27,7 @@ - #define ISOFS_SUPER_MAGIC 0x9660 - #define JFFS2_SUPER_MAGIC 0x72b6 - #define PSTOREFS_MAGIC 0x6165676C -+#define EFIVARFS_MAGIC 0xde5e81e4 - - #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ - #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ --- -1.7.12.1 - - -From a42845c67f2386b164d0c5d8220838d7faf5a409 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Tue, 23 Oct 2012 12:35:43 +0100 -Subject: [PATCH 15/17] efivarfs: Make 'datasize' unsigned long - -There's no reason to declare 'datasize' as an int, since the majority -of the functions it's passed to expect an unsigned long anyway. Plus, -this way we avoid any sign problems during arithmetic. - -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 3b0cf9a..6a858d1 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -692,7 +692,7 @@ static ssize_t efivarfs_file_write(struct file *file, - void *data; - u32 attributes; - struct inode *inode = file->f_mapping->host; -- int datasize = count - sizeof(attributes); -+ unsigned long datasize = count - sizeof(attributes); - unsigned long newdatasize; - - if (count < sizeof(attributes)) --- -1.7.12.1 - - -From a268bdf6d7ce623ea4bdfcf39aa52ed3fbfdfd65 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Tue, 23 Oct 2012 12:41:03 +0100 -Subject: [PATCH 16/17] efivarfs: Return a consistent error when - efivarfs_get_inode() fails - -Instead of returning -ENOSPC if efivarfs_get_inode() fails we should -be returning -ENOMEM, since running out of memory is the only reason -it can fail. Furthermore, that's the error value used everywhere else -in this file. It's also less likely to confuse users that hit this -error case. - -Acked-by: Jeremy Kerr -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 6a858d1..58cec62 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -911,7 +911,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - - inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); - if (!inode) -- return -ENOSPC; -+ return -ENOMEM; - - var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); - if (!var) { --- -1.7.12.1 - - -From 9c3136c987175b179c0aa725d76cda156894f918 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Fri, 26 Oct 2012 12:18:53 +0100 -Subject: [PATCH 17/17] efivarfs: Fix return value of efivarfs_file_write() - -We're stuffing a variable of type size_t (unsigned) into a ssize_t -(signed) which, even though both types should be the same number of -bits, it's just asking for sign issues to be introduced. - -Cc: Jeremy Kerr -Reported-by: Alan Cox -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 58cec62..9ac9340 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -694,6 +694,7 @@ static ssize_t efivarfs_file_write(struct file *file, - struct inode *inode = file->f_mapping->host; - unsigned long datasize = count - sizeof(attributes); - unsigned long newdatasize; -+ ssize_t bytes = 0; - - if (count < sizeof(attributes)) - return -EINVAL; -@@ -706,22 +707,22 @@ static ssize_t efivarfs_file_write(struct file *file, - efivars = var->efivars; - - if (copy_from_user(&attributes, userbuf, sizeof(attributes))) { -- count = -EFAULT; -+ bytes = -EFAULT; - goto out; - } - - if (attributes & ~(EFI_VARIABLE_MASK)) { -- count = -EINVAL; -+ bytes = -EINVAL; - goto out; - } - - if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { -- count = -EFAULT; -+ bytes = -EFAULT; - goto out; - } - - if (validate_var(&var->var, data, datasize) == false) { -- count = -EINVAL; -+ bytes = -EINVAL; - goto out; - } - -@@ -744,6 +745,8 @@ static ssize_t efivarfs_file_write(struct file *file, - return efi_status_to_err(status); - } - -+ bytes = count; -+ - /* - * Writing to the variable may have caused a change in size (which - * could either be an append or an overwrite), or the variable to be -@@ -778,7 +781,7 @@ static ssize_t efivarfs_file_write(struct file *file, - out: - kfree(data); - -- return count; -+ return bytes; - } - - static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, --- -1.7.12.1 - -efivarfs_unlink() should drop the file's link count, not the directory's. - -Tested-by: Lee, Chun-Yi -Signed-off-by: Lingzhu Xiang ---- - drivers/firmware/efivars.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index d6b8d2f..60f5324 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -995,7 +995,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) - list_del(&var->list); - spin_unlock(&efivars->lock); - efivar_unregister(var); -- drop_nlink(dir); -+ drop_nlink(dentry->d_inode); - dput(dentry); - return 0; - } --- -1.7.7.6 - diff --git a/exec-use-eloop-for-max-recursion-depth.patch b/exec-use-eloop-for-max-recursion-depth.patch deleted file mode 100644 index a3c48884f..000000000 --- a/exec-use-eloop-for-max-recursion-depth.patch +++ /dev/null @@ -1,144 +0,0 @@ -From ba1b23d05259e31d30a78017cdfbc010dcb08aa6 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Mon, 26 Nov 2012 09:02:11 -0500 -Subject: [PATCH 2/2] exec: use -ELOOP for max recursion depth - -To avoid an explosion of request_module calls on a chain of abusive -scripts, fail maximum recursion with -ELOOP instead of -ENOEXEC. As soon -as maximum recursion depth is hit, the error will fail all the way back -up the chain, aborting immediately. - -This also has the side-effect of stopping the user's shell from attempting -to reexecute the top-level file as a shell script. As seen in the -dash source: - - if (cmd != path_bshell && errno == ENOEXEC) { - *argv-- = cmd; - *argv = cmd = path_bshell; - goto repeat; - } - -The above logic was designed for running scripts automatically that lacked -the "#!" header, not to re-try failed recursion. On a legitimate -ENOEXEC, -things continue to behave as the shell expects. - -Additionally, when tracking recursion, the binfmt handlers should not be -involved. The recursion being tracked is the depth of calls through -search_binary_handler(), so that function should be exclusively responsible -for tracking the depth. - -Signed-off-by: Kees Cook -Cc: halfdog -Cc: P J P -Cc: Alexander Viro -Signed-off-by: Andrew Morton ---- - fs/binfmt_em86.c | 1 - - fs/binfmt_misc.c | 6 ------ - fs/binfmt_script.c | 4 +--- - fs/exec.c | 10 +++++----- - include/linux/binfmts.h | 2 -- - 5 files changed, 6 insertions(+), 17 deletions(-) - -diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c -index 2790c7e..575796a 100644 ---- a/fs/binfmt_em86.c -+++ b/fs/binfmt_em86.c -@@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) - return -ENOEXEC; - } - -- bprm->recursion_depth++; /* Well, the bang-shell is implicit... */ - allow_write_access(bprm->file); - fput(bprm->file); - bprm->file = NULL; -diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c -index 772428d..f0f1a06 100644 ---- a/fs/binfmt_misc.c -+++ b/fs/binfmt_misc.c -@@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) - if (!enabled) - goto _ret; - -- retval = -ENOEXEC; -- if (bprm->recursion_depth > BINPRM_MAX_RECURSION) -- goto _ret; -- - /* to keep locking time low, we copy the interpreter string */ - read_lock(&entries_lock); - fmt = check_file(bprm); -@@ -200,8 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) - if (retval < 0) - goto _error; - -- bprm->recursion_depth++; -- - retval = search_binary_handler (bprm, regs); - if (retval < 0) - goto _error; -diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c -index df49d48..8ae4be1 100644 ---- a/fs/binfmt_script.c -+++ b/fs/binfmt_script.c -@@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) - char interp[BINPRM_BUF_SIZE]; - int retval; - -- if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || -- (bprm->recursion_depth > BINPRM_MAX_RECURSION)) -+ if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) - return -ENOEXEC; - /* - * This section does the #! interpretation. - * Sorta complicated, but hopefully it will work. -TYT - */ - -- bprm->recursion_depth++; - allow_write_access(bprm->file); - fput(bprm->file); - bprm->file = NULL; -diff --git a/fs/exec.c b/fs/exec.c -index c6e6de4..85c1f9e 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1371,6 +1371,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) - struct linux_binfmt *fmt; - pid_t old_pid, old_vpid; - -+ /* This allows 4 levels of binfmt rewrites before failing hard. */ -+ if (depth > 5) -+ return -ELOOP; -+ - retval = security_bprm_check(bprm); - if (retval) - return retval; -@@ -1395,12 +1399,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) - if (!try_module_get(fmt->module)) - continue; - read_unlock(&binfmt_lock); -+ bprm->recursion_depth = depth + 1; - retval = fn(bprm, regs); -- /* -- * Restore the depth counter to its starting value -- * in this call, so we don't have to rely on every -- * load_binary function to restore it on return. -- */ - bprm->recursion_depth = depth; - if (retval >= 0) { - if (depth == 0) { -diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h -index de0628e..54135f6 100644 ---- a/include/linux/binfmts.h -+++ b/include/linux/binfmts.h -@@ -54,8 +54,6 @@ struct linux_binprm { - #define BINPRM_FLAGS_EXECFD_BIT 1 - #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) - --#define BINPRM_MAX_RECURSION 4 -- - /* Function parameter for binfmt->coredump */ - struct coredump_params { - siginfo_t *siginfo; --- -1.8.0 - diff --git a/handle-efi-roms.patch b/handle-efi-roms.patch deleted file mode 100644 index bc080542b..000000000 --- a/handle-efi-roms.patch +++ /dev/null @@ -1,388 +0,0 @@ -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c 2012-08-22 15:26:32.485522068 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c 2012-08-22 15:25:40.529244868 -0400 -@@ -8,6 +8,7 @@ - * ----------------------------------------------------------------------- */ - - #include -+#include - #include - #include - #include -@@ -243,6 +244,121 @@ - *size = len; - } - -+static efi_status_t setup_efi_pci(struct boot_params *params) -+{ -+ efi_pci_io_protocol *pci; -+ efi_status_t status; -+ void **pci_handle; -+ efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; -+ unsigned long nr_pci, size = 0; -+ int i; -+ struct setup_data *data; -+ -+ data = (struct setup_data *)params->hdr.setup_data; -+ -+ while (data && data->next) -+ data = (struct setup_data *)data->next; -+ -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, &pci_proto, -+ NULL, &size, pci_handle); -+ -+ if (status == EFI_BUFFER_TOO_SMALL) { -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, size, &pci_handle); -+ -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = efi_call_phys5(sys_table->boottime->locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, &pci_proto, -+ NULL, &size, pci_handle); -+ } -+ -+ if (status != EFI_SUCCESS) -+ goto free_handle; -+ -+ nr_pci = size / sizeof(void *); -+ for (i = 0; i < nr_pci; i++) { -+ void *h = pci_handle[i]; -+ uint64_t attributes; -+ struct pci_setup_rom *rom; -+ -+ status = efi_call_phys3(sys_table->boottime->handle_protocol, -+ h, &pci_proto, &pci); -+ -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ if (!pci) -+ continue; -+ -+ status = efi_call_phys4(pci->attributes, pci, -+ EfiPciIoAttributeOperationGet, 0, -+ &attributes); -+ -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) -+ continue; -+ -+ if (!pci->romimage || !pci->romsize) -+ continue; -+ -+ size = pci->romsize + sizeof(*rom); -+ -+ status = efi_call_phys3(sys_table->boottime->allocate_pool, -+ EFI_LOADER_DATA, size, &rom); -+ -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ rom->data.type = SETUP_PCI; -+ rom->data.len = size - sizeof(struct setup_data); -+ rom->data.next = NULL; -+ rom->pcilen = pci->romsize; -+ -+ status = efi_call_phys5(pci->pci.read, pci, -+ EfiPciIoWidthUint16, PCI_VENDOR_ID, -+ 1, &(rom->vendor)); -+ -+ if (status != EFI_SUCCESS) -+ goto free_struct; -+ -+ status = efi_call_phys5(pci->pci.read, pci, -+ EfiPciIoWidthUint16, PCI_DEVICE_ID, -+ 1, &(rom->devid)); -+ -+ if (status != EFI_SUCCESS) -+ goto free_struct; -+ -+ status = efi_call_phys5(pci->get_location, pci, -+ &(rom->segment), &(rom->bus), -+ &(rom->device), &(rom->function)); -+ -+ if (status != EFI_SUCCESS) -+ goto free_struct; -+ -+ memcpy(rom->romdata, pci->romimage, pci->romsize); -+ -+ if (data) -+ data->next = (uint64_t)rom; -+ else -+ params->hdr.setup_data = (uint64_t)rom; -+ -+ data = (struct setup_data *)rom; -+ -+ continue; -+ free_struct: -+ efi_call_phys1(sys_table->boottime->free_pool, rom); -+ } -+ -+free_handle: -+ efi_call_phys1(sys_table->boottime->free_pool, pci_handle); -+ return status; -+} -+ - /* - * See if we have Graphics Output Protocol - */ -@@ -1052,6 +1171,8 @@ - - setup_graphics(boot_params); - -+ setup_efi_pci(boot_params); -+ - status = efi_call_phys3(sys_table->boottime->allocate_pool, - EFI_LOADER_DATA, sizeof(*gdt), - (void **)&gdt); -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:26:32.485522068 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h 2012-08-22 15:25:40.530244882 -0400 -@@ -13,6 +13,7 @@ - #define SETUP_NONE 0 - #define SETUP_E820_EXT 1 - #define SETUP_DTB 2 -+#define SETUP_PCI 3 - - /* extensible setup data list node */ - struct setup_data { -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h 2012-07-21 16:58:29.000000000 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h 2012-08-22 15:25:40.530244882 -0400 -@@ -171,4 +171,16 @@ - } - #endif - -+struct pci_setup_rom { -+ struct setup_data data; -+ uint16_t vendor; -+ uint16_t devid; -+ uint64_t pcilen; -+ unsigned long segment; -+ unsigned long bus; -+ unsigned long device; -+ unsigned long function; -+ uint8_t romdata[0]; -+}; -+ - #endif /* _ASM_X86_PCI_H */ -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c 2012-08-22 15:24:45.477951182 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c 2012-08-22 15:25:40.530244882 -0400 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | - PCI_PROBE_MMCONF; -@@ -608,6 +609,38 @@ - return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; - } - -+int pcibios_add_device(struct pci_dev *dev) -+{ -+ struct setup_data *data; -+ struct pci_setup_rom *rom; -+ u64 pa_data; -+ -+ if (boot_params.hdr.version < 0x0209) -+ return 0; -+ -+ pa_data = boot_params.hdr.setup_data; -+ while (pa_data) { -+ data = phys_to_virt(pa_data); -+ -+ if (data->type == SETUP_PCI) { -+ rom = (struct pci_setup_rom *)data; -+ -+ if ((pci_domain_nr(dev->bus) == rom->segment) && -+ (dev->bus->number == rom->bus) && -+ (PCI_SLOT(dev->devfn) == rom->device) && -+ (PCI_FUNC(dev->devfn) == rom->function) && -+ (dev->vendor == rom->vendor) && -+ (dev->device == rom->devid)) { -+ dev->rom = (void *)(pa_data + -+ offsetof(struct pci_setup_rom, romdata)); -+ dev->romlen = rom->pcilen; -+ } -+ } -+ pa_data = data->next; -+ } -+ return 0; -+} -+ - int pcibios_enable_device(struct pci_dev *dev, int mask) - { - int err; -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c 2012-08-22 15:24:47.425961575 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c 2012-08-22 15:26:20.147456241 -0400 -@@ -166,6 +166,11 @@ - int retval; - - pci_fixup_device(pci_fixup_final, dev); -+ -+ retval = pcibios_add_device(dev); -+ if (retval) -+ return retval; -+ - retval = device_add(&dev->dev); - if (retval) - return retval; -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c 2012-08-22 15:24:47.432961612 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c 2012-08-22 15:25:40.531244893 -0400 -@@ -1385,6 +1385,19 @@ - dr->pinned = 1; - } - -+/* -+ * pcibios_add_device - provide arch specific hooks when adding device dev -+ * @dev: the PCI device being added -+ * -+ * Permits the platform to provide architecture specific functionality when -+ * devices are added. This is the default implementation. Architecture -+ * implementations can override this. -+ */ -+int __attribute__ ((weak)) pcibios_add_device (struct pci_dev *dev) -+{ -+ return 0; -+} -+ - /** - * pcibios_disable_device - disable arch specific PCI resources for device dev - * @dev: the PCI device to disable -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-07-21 16:58:29.000000000 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c 2012-08-22 15:25:40.531244893 -0400 -@@ -126,6 +126,12 @@ - /* primary video rom always starts here */ - start = (loff_t)0xC0000; - *size = 0x20000; /* cover C000:0 through E000:0 */ -+ /* -+ * Some devices may provide ROMs via a source other than the BAR -+ */ -+ } else if (pdev->rom && pdev->romlen) { -+ *size = pdev->romlen; -+ return phys_to_virt(pdev->rom); - } else { - if (res->flags & - (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { -@@ -219,7 +225,8 @@ - if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) - return; - -- iounmap(rom); -+ if (!pdev->rom || !pdev->romlen) -+ iounmap(rom); - - /* Disable again before continuing, leave enabled if pci=rom */ - if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h 2012-08-22 15:24:49.550972911 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h 2012-08-22 15:25:40.533244906 -0400 -@@ -196,6 +196,77 @@ - void *create_event_ex; - } efi_boot_services_t; - -+typedef enum { -+ EfiPciIoWidthUint8, -+ EfiPciIoWidthUint16, -+ EfiPciIoWidthUint32, -+ EfiPciIoWidthUint64, -+ EfiPciIoWidthFifoUint8, -+ EfiPciIoWidthFifoUint16, -+ EfiPciIoWidthFifoUint32, -+ EfiPciIoWidthFifoUint64, -+ EfiPciIoWidthFillUint8, -+ EfiPciIoWidthFillUint16, -+ EfiPciIoWidthFillUint32, -+ EfiPciIoWidthFillUint64, -+ EfiPciIoWidthMaximum -+} EFI_PCI_IO_PROTOCOL_WIDTH; -+ -+typedef enum { -+ EfiPciIoAttributeOperationGet, -+ EfiPciIoAttributeOperationSet, -+ EfiPciIoAttributeOperationEnable, -+ EfiPciIoAttributeOperationDisable, -+ EfiPciIoAttributeOperationSupported, -+ EfiPciIoAttributeOperationMaximum -+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; -+ -+ -+typedef struct { -+ void *read; -+ void *write; -+} efi_pci_io_protocol_access_t; -+ -+typedef struct { -+ void *poll_mem; -+ void *poll_io; -+ efi_pci_io_protocol_access_t mem; -+ efi_pci_io_protocol_access_t io; -+ efi_pci_io_protocol_access_t pci; -+ void *copy_mem; -+ void *map; -+ void *unmap; -+ void *allocate_buffer; -+ void *free_buffer; -+ void *flush; -+ void *get_location; -+ void *attributes; -+ void *get_bar_attributes; -+ void *set_bar_attributes; -+ uint64_t romsize; -+ void *romimage; -+} efi_pci_io_protocol; -+ -+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 -+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 -+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 -+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 -+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 -+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 -+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 -+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 -+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 -+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 -+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 -+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 -+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 -+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 -+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 -+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 -+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 -+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 -+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 -+ - /* - * Types and defines for EFI ResetSystem - */ -diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h ---- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h 2012-08-22 15:24:48.703968392 -0400 -+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h 2012-08-22 15:25:40.534244910 -0400 -@@ -355,6 +355,8 @@ - }; - struct pci_ats *ats; /* Address Translation Service */ - #endif -+ void *rom; /* Physical pointer to ROM if it's not from the BAR */ -+ size_t romlen; /* Length of ROM if it's not from the BAR */ - }; - - static inline struct pci_dev *pci_physfn(struct pci_dev *dev) -@@ -1582,6 +1584,7 @@ - void pcibios_set_master(struct pci_dev *dev); - int pcibios_set_pcie_reset_state(struct pci_dev *dev, - enum pcie_reset_state state); -+int pcibios_add_device(struct pci_dev *dev); - - #ifdef CONFIG_PCI_MMCONFIG - extern void __init pci_mmcfg_early_init(void); diff --git a/kernel.spec b/kernel.spec index fdfa562c6..49039c5cf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,19 +62,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 207 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 7 +%define base_sublevel 8 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -650,8 +650,6 @@ Patch04: linux-2.6-compile-fixes.patch # build tweak for build ID magic, even for -vanilla Patch05: linux-2.6-makefile-after_link.patch -Patch06: power-x86-destdir.patch - %if !%{nopatches} @@ -686,15 +684,8 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch -# crypto/ -Patch901: modsign-post-KS-jwb.patch - # secure boot -Patch1000: secure-boot-3.7-20130219.patch -Patch1001: efivarfs-3.7.patch - -# Improve PCI support on UEFI -Patch1100: handle-efi-roms.patch +Patch1000: secure-boot-20130219.patch # virt + ksm patches @@ -711,8 +702,6 @@ Patch1825: drm-i915-dp-stfu.patch Patch1826: drm-i915-tv-detect-hush.patch # d-i-n backport for https://bugzilla.redhat.com/show_bug.cgi?id=901951 Patch1827: drm-i915-lvds-reclock-fix.patch -# Fix a mismerge in 3.7.y -Patch1828: drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch # Quiet boot fixes # silence the ACPI blacklist code @@ -747,7 +736,6 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-read_current_timer.patch # http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/137164.html -Patch21001: arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch Patch21002: arm-alignment-faults.patch # OMAP @@ -766,23 +754,9 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 871078 -Patch22112: USB-report-submission-of-active-URBs.patch - #rhbz 859485 Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz CVE-2012-4530 868285 880147 -Patch22229: exec-use-eloop-for-max-recursion-depth.patch - -#rhbz 851278 -Patch22231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch -Patch22232: 8139cp-set-ring-address-after-enabling-C-mode.patch -Patch22233: 8139cp-re-enable-interrupts-after-tx-timeout.patch - -#rhbz 892428 -Patch22238: brcmsmac-updates-rhbz892428.patch - #rhbz 799564 Patch22240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch @@ -790,9 +764,6 @@ Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch -#rhbz 911479 911473 CVE-2013-0290 -Patch22256: net-fix-infinite-loop-in-__skb_recv_datagram.patch - #rhbz 909591 Patch22255: usb-cypress-supertop.patch @@ -817,8 +788,6 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #CVE-2013-1767 rhbz 915592,915716 Patch22263: tmpfs-fix-use-after-free-of-mempolicy-object.patch -Patch23000: silence-brcmsmac-warning.patch - #rhbz 812111 Patch24000: alps-v2-3.7.patch @@ -827,6 +796,7 @@ Patch24001: ipv6-dst-from-ptr-race.patch Patch24100: userns-avoid-recursion-in-put_user_ns.patch + # END OF PATCH DEFINITIONS %endif @@ -1370,8 +1340,6 @@ ApplyPatch linux-2.6-makefile-after_link.patch # ApplyOptionalPatch linux-2.6-compile-fixes.patch -ApplyPatch power-x86-destdir.patch - %if !%{nopatches} # revert patches from upstream that conflict or that we get via other means @@ -1391,10 +1359,9 @@ ApplyPatch vmbugon-warnon.patch #ApplyPatch arm-read_current_timer.patch #ApplyPatch arm-fix-omapdrm.patch -ApplyPatch arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch -ApplyPatch arm-tegra-nvec-kconfig.patch +#ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch -ApplyPatch arm-tegra-sdhci-module-fix.patch +#ApplyPatch arm-tegra-sdhci-module-fix.patch ApplyPatch arm-alignment-faults.patch # @@ -1465,15 +1432,8 @@ ApplyPatch linux-2.6-crash-driver.patch # Hack e1000e to work on Montevina SDV ApplyPatch linux-2.6-e1000-ich9-montevina.patch -# crypto/ -ApplyPatch modsign-post-KS-jwb.patch - # secure boot -ApplyPatch efivarfs-3.7.patch -ApplyPatch secure-boot-3.7-20130219.patch - -# Improved PCI support for UEFI -ApplyPatch handle-efi-roms.patch +#ApplyPatch secure-boot-20130219.patch # Assorted Virt Fixes @@ -1488,7 +1448,6 @@ ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-tv-detect-hush.patch ApplyPatch drm-i915-lvds-reclock-fix.patch -ApplyPatch drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -1526,23 +1485,9 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 871078 -ApplyPatch USB-report-submission-of-active-URBs.patch - #rhbz 859485 ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz CVE-2012-4530 868285 880147 -ApplyPatch exec-use-eloop-for-max-recursion-depth.patch - -#rhbz 851278 -ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R -ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch -ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch - -#rhbz 892428 -ApplyPatch brcmsmac-updates-rhbz892428.patch - #rhbz 799564 ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch @@ -1550,28 +1495,23 @@ ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch -ApplyPatch silence-brcmsmac-warning.patch - #rhbz 909591 -ApplyPatch usb-cypress-supertop.patch - -#rhbz 911479 911473 CVE-2013-0290 -ApplyPatch net-fix-infinite-loop-in-__skb_recv_datagram.patch +#ApplyPatch usb-cypress-supertop.patch #rhbz 844750 -ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #rhbz 906055 ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch #rhbz 812111 -ApplyPatch alps-v2-3.7.patch +#ApplyPatch alps-v2-3.7.patch #rhbz 892060 ApplyPatch ipv6-dst-from-ptr-race.patch #rhbz 879408 -ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch +#ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch #CVE-2013-1763 rhbz 915052,915057 ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch @@ -1585,7 +1525,9 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #CVE-2013-1767 rhbz 915592,915716 ApplyPatch tmpfs-fix-use-after-free-of-mempolicy-object.patch -ApplyPatch userns-avoid-recursion-in-put_user_ns.patch +#ApplyPatch userns-avoid-recursion-in-put_user_ns.patch + + # END OF PATCH APPLICATIONS @@ -2450,6 +2392,34 @@ fi # ||----w | # || || %changelog +* Wed Feb 27 2013 Dave Jones +- 3.8.0 + Dropped (merged in 3.8) + - arm-l2x0-only-set-set_debug-on-pl310-r3p0-and-earlier.patch + - power-x86-destdir.patch + - modsign-post-KS-jwb.patch + - efivarfs-3.7.patch + - handle-efi-roms.patch + - drm-i915-Fix-up-mismerge-of-3490ea5d-in-3.7.y.patch + - USB-report-submission-of-active-URBs.patch + - exec-use-eloop-for-max-recursion-depth.patch + - 8139cp-revert-set-ring-address-before-enabling-receiver.patch + - 8139cp-set-ring-address-after-enabling-C-mode.patch + - 8139cp-re-enable-interrupts-after-tx-timeout.patch + - brcmsmac-updates-rhbz892428.patch + - silence-brcmsmac-warning.patch + - net-fix-infinite-loop-in-__skb_recv_datagram.patch + Needs checking: + - arm-tegra-nvec-kconfig.patch + - arm-tegra-sdhci-module-fix.patch + Needs reworking: + - secure-boot + - alps-v2-3.7.patch + - usb-cypress-supertop.patch + - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch + - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + - userns-avoid-recursion-in-put_user_ns.patch + * Tue Feb 26 2013 Justin M. Forbes - Avoid recursion in put_user_ns, potential overflow diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch deleted file mode 100644 index 1bafd22f5..000000000 --- a/modsign-post-KS-jwb.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 56713a28675b966e027a824a0130b80dffab209f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 5 Nov 2012 09:09:24 +1030 -Subject: [PATCH] MODSIGN: Add modules_sign make target - -If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this -patch will cause the modules to get a signature appended. The make target -is intended to be run after 'make modules_install', and will modify the -modules in-place in the installed location. It can be used to produce -signed modules after they have been processed by distribution build -scripts. - -Signed-off-by: Josh Boyer -Signed-off-by: Rusty Russell (minor typo fix) ---- - Makefile | 6 ++++++ - scripts/Makefile.modsign | 32 ++++++++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+), 0 deletions(-) - create mode 100644 scripts/Makefile.modsign - -diff --git a/Makefile b/Makefile -index 42d0e56..253aa1b 100644 ---- a/Makefile -+++ b/Makefile -@@ -981,6 +981,12 @@ _modinst_post: _modinst_ - $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst - $(call cmd,depmod) - -+ifeq ($(CONFIG_MODULE_SIG), y) -+PHONY += modules_sign -+modules_sign: -+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign -+endif -+ - else # CONFIG_MODULES - - # Modules not configured -diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign -new file mode 100644 -index 0000000..abfda62 ---- /dev/null -+++ b/scripts/Makefile.modsign -@@ -0,0 +1,32 @@ -+# ========================================================================== -+# Signing modules -+# ========================================================================== -+ -+PHONY := __modsign -+__modsign: -+ -+include scripts/Kbuild.include -+ -+__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) -+modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) -+ -+PHONY += $(modules) -+__modsign: $(modules) -+ @: -+ -+quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) -+ cmd_sign_ko = $(mod_sign_cmd) $(2)/$(notdir $@) -+ -+# Modules built outside the kernel source tree go into extra by default -+INSTALL_MOD_DIR ?= extra -+ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) -+ -+modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) -+ -+$(modules): -+ $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) -+ -+# Declare the contents of the .PHONY variable as phony. We keep that -+# information in a variable se we can use it in if_changed and friends. -+ -+.PHONY: $(PHONY) --- -1.7.7.6 - diff --git a/net-fix-infinite-loop-in-__skb_recv_datagram.patch b/net-fix-infinite-loop-in-__skb_recv_datagram.patch deleted file mode 100644 index a049bb46a..000000000 --- a/net-fix-infinite-loop-in-__skb_recv_datagram.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 77c1090f94d1b0b5186fb13a1b71b47b1343f87f Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Tue, 12 Feb 2013 06:16:53 +0000 -Subject: [PATCH] net: fix infinite loop in __skb_recv_datagram() - -Tommi was fuzzing with trinity and reported the following problem : - -commit 3f518bf745 (datagram: Add offset argument to __skb_recv_datagram) -missed that a raw socket receive queue can contain skbs with no payload. - -We can loop in __skb_recv_datagram() with MSG_PEEK mode, because -wait_for_packet() is not prepared to skip these skbs. - -[ 83.541011] INFO: rcu_sched detected stalls on CPUs/tasks: {} -(detected by 0, t=26002 jiffies, g=27673, c=27672, q=75) -[ 83.541011] INFO: Stall ended before state dump start -[ 108.067010] BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child31:2847] -... -[ 108.067010] Call Trace: -[ 108.067010] [] __skb_recv_datagram+0x1a3/0x3b0 -[ 108.067010] [] skb_recv_datagram+0x2d/0x30 -[ 108.067010] [] rawv6_recvmsg+0xad/0x240 -[ 108.067010] [] sock_common_recvmsg+0x34/0x50 -[ 108.067010] [] sock_recvmsg+0xbc/0xf0 -[ 108.067010] [] sys_recvfrom+0xde/0x150 -[ 108.067010] [] system_call_fastpath+0x16/0x1b - -Reported-by: Tommi Rantala -Tested-by: Tommi Rantala -Signed-off-by: Eric Dumazet -Cc: Pavel Emelyanov -Acked-by: Pavel Emelyanov -Signed-off-by: David S. Miller ---- - net/core/datagram.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/core/datagram.c b/net/core/datagram.c -index 0337e2b..368f9c3 100644 ---- a/net/core/datagram.c -+++ b/net/core/datagram.c -@@ -187,7 +187,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, - skb_queue_walk(queue, skb) { - *peeked = skb->peeked; - if (flags & MSG_PEEK) { -- if (*off >= skb->len) { -+ if (*off >= skb->len && skb->len) { - *off -= skb->len; - continue; - } --- -1.8.1.2 - diff --git a/power-x86-destdir.patch b/power-x86-destdir.patch deleted file mode 100644 index 97665314f..000000000 --- a/power-x86-destdir.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile -index f856495..984cc00 100644 ---- a/tools/power/x86/turbostat/Makefile -+++ b/tools/power/x86/turbostat/Makefile -@@ -1,3 +1,5 @@ -+DESTDIR ?= -+ - turbostat : turbostat.c - CFLAGS += -Wall - -@@ -5,5 +7,5 @@ clean : - rm -f turbostat - - install : -- install turbostat /usr/bin/turbostat -- install turbostat.8 /usr/share/man/man8 -+ install turbostat ${DESTDIR}/usr/bin/turbostat -+ install turbostat.8 ${DESTDIR}/usr/share/man/man8 -diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile -index f458237..f9824f0 100644 ---- a/tools/power/x86/x86_energy_perf_policy/Makefile -+++ b/tools/power/x86/x86_energy_perf_policy/Makefile -@@ -1,8 +1,10 @@ -+DESTDIR ?= -+ - x86_energy_perf_policy : x86_energy_perf_policy.c - - clean : - rm -f x86_energy_perf_policy - - install : -- install x86_energy_perf_policy /usr/bin/ -- install x86_energy_perf_policy.8 /usr/share/man/man8/ -+ install x86_energy_perf_policy ${DESTDIR}/usr/bin/ -+ install x86_energy_perf_policy.8 ${DESTDIR}/usr/share/man/man8/ diff --git a/secure-boot-3.7-20130219.patch b/secure-boot-20130219.patch similarity index 100% rename from secure-boot-3.7-20130219.patch rename to secure-boot-20130219.patch diff --git a/silence-brcmsmac-warning.patch b/silence-brcmsmac-warning.patch deleted file mode 100644 index b1915e9f1..000000000 --- a/silence-brcmsmac-warning.patch +++ /dev/null @@ -1,14 +0,0 @@ -This is fixed in 3.8, but is too much to backport for now. -As there's no point in abrt telling us this is broken, we'll just silence it. - ---- linux-3.7.7-201.fc18.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c~ 2013-02-12 11:36:18.787973130 -0500 -+++ linux-3.7.7-201.fc18.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c 2013-02-12 11:37:02.950969879 -0500 -@@ -7993,8 +7993,6 @@ void brcms_c_wait_for_tx_completion(stru - if (--timeout == 0) - break; - } -- -- WARN_ON_ONCE(timeout == 0); - } - - void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) diff --git a/sources b/sources index c375bc5d0..580ae0bbf 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -375fa67b3daba9e6040f13a0a29bf543 patch-3.7.9.xz From d3a4ba3dbfb0c4b5db0d2669b15373f06d842cef Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Feb 2013 14:08:29 -0500 Subject: [PATCH 200/492] update secure boot patchset --- kernel.spec | 5 +- ...130219.patch => secure-boot-20130218.patch | 198 +++++++++--------- 2 files changed, 99 insertions(+), 104 deletions(-) rename secure-boot-20130219.patch => secure-boot-20130218.patch (89%) diff --git a/kernel.spec b/kernel.spec index 49039c5cf..98a9edbf4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -685,7 +685,7 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # secure boot -Patch1000: secure-boot-20130219.patch +Patch1000: secure-boot-20130218.patch # virt + ksm patches @@ -1433,7 +1433,7 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # secure boot -#ApplyPatch secure-boot-20130219.patch +ApplyPatch secure-boot-20130218.patch # Assorted Virt Fixes @@ -2413,7 +2413,6 @@ fi - arm-tegra-nvec-kconfig.patch - arm-tegra-sdhci-module-fix.patch Needs reworking: - - secure-boot - alps-v2-3.7.patch - usb-cypress-supertop.patch - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch diff --git a/secure-boot-20130219.patch b/secure-boot-20130218.patch similarity index 89% rename from secure-boot-20130219.patch rename to secure-boot-20130218.patch index 48ef2e7fe..29ac46cd9 100644 --- a/secure-boot-20130219.patch +++ b/secure-boot-20130218.patch @@ -1,4 +1,4 @@ -From 33ecf899ae618a163e553c24674a48bd0cb4dd17 Mon Sep 17 00:00:00 2001 +From 0c5837031a4e996877930fd023a5877dd1d615ba Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 Subject: [PATCH 01/19] Secure boot: Add new capability @@ -35,7 +35,7 @@ index ba478fa..7109e65 100644 1.8.1.2 -From 0867a7288326c109ac3f1a52a342f577e1f77618 Mon Sep 17 00:00:00 2001 +From 87c8fddbcb3042fc4174b53763adbf66045a12be Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability @@ -50,7 +50,7 @@ Signed-off-by: Josh Boyer 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index df2de54..70e2834 100644 +index 14d04e6..ed99a2d 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { @@ -63,12 +63,12 @@ index df2de54..70e2834 100644 + "block_suspend", "compromise_kernel", NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", - { COMMON_SOCK_PERMS, NULL } }, + { COMMON_SOCK_PERMS, "attach_queue", NULL } }, -- 1.8.1.2 -From 23873817d2cec32d4af90fc7038b53c949e3f5a6 Mon Sep 17 00:00:00 2001 +From df14b5319bf3ed2110839e233ac61e6136745be8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will @@ -85,10 +85,10 @@ Signed-off-by: Josh Boyer 2 files changed, 24 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 9776f06..0d6c28d 100644 +index 6c72381..7dffdd5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -2654,6 +2654,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Note: increases power consumption, thus should only be enabled if running jitter sensitive (HPC/RT) workloads. @@ -103,10 +103,10 @@ index 9776f06..0d6c28d 100644 If this boot parameter is not specified, only the first security module asking for security registration will be diff --git a/kernel/cred.c b/kernel/cred.c -index 48cea3d..3f5be65 100644 +index e0573a4..c3f4e3e 100644 --- a/kernel/cred.c +++ b/kernel/cred.c -@@ -623,6 +623,23 @@ void __init cred_init(void) +@@ -565,6 +565,23 @@ void __init cred_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); } @@ -134,7 +134,7 @@ index 48cea3d..3f5be65 100644 1.8.1.2 -From 6e786fc19b3dc3aa53e6f556af2baf261573321f Mon Sep 17 00:00:00 2001 +From 49c76a665e8a09da48cbe271ea40266ca1a226c0 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when @@ -148,32 +148,32 @@ EFI_SECURE_BOOT bit for use with efi_enabled. Signed-off-by: Matthew Garrett Signed-off-by: Josh Boyer --- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ - arch/x86/include/asm/bootparam.h | 3 ++- - arch/x86/kernel/setup.c | 5 +++++ - include/linux/cred.h | 2 ++ - include/linux/efi.h | 1 + - 6 files changed, 44 insertions(+), 1 deletion(-) + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ + arch/x86/include/uapi/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 7 +++++++ + include/linux/cred.h | 2 ++ + include/linux/efi.h | 1 + + 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt -index cf5437d..7f9ed48 100644 +index 199f453..ff651d3 100644 --- a/Documentation/x86/zero-page.txt +++ b/Documentation/x86/zero-page.txt -@@ -27,6 +27,8 @@ Offset Proto Name Meaning +@@ -30,6 +30,8 @@ Offset Proto Name Meaning 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer (below) +1EB/001 ALL kbd_status Numlock is enabled +1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns + 1EF/001 ALL sentinel Used to detect broken bootloaders 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures 2D0/A00 ALL e820_map E820 memory map table - (array of struct e820entry) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index ccae7e2..4983e43 100644 +index f8fa411..96bd86b 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -731,6 +731,36 @@ fail: +@@ -849,6 +849,36 @@ fail: return status; } @@ -210,7 +210,7 @@ index ccae7e2..4983e43 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1025,6 +1055,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1143,6 +1173,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -218,31 +218,33 @@ index ccae7e2..4983e43 100644 + setup_graphics(boot_params); - status = efi_call_phys3(sys_table->boottime->allocate_pool, -diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h -index 2ad874c..c7338e0 100644 ---- a/arch/x86/include/asm/bootparam.h -+++ b/arch/x86/include/asm/bootparam.h -@@ -114,7 +114,8 @@ struct boot_params { + setup_efi_pci(boot_params); +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index c15ddaf..85d7685 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -131,7 +131,8 @@ struct boot_params { __u8 eddbuf_entries; /* 0x1e9 */ __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ __u8 kbd_status; /* 0x1eb */ -- __u8 _pad6[5]; /* 0x1ec */ +- __u8 _pad5[3]; /* 0x1ec */ + __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad6[4]; /* 0x1ed */ - struct setup_header hdr; /* setup header */ /* 0x1f1 */ - __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; - __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ ++ __u8 _pad5[2]; /* 0x1ed */ + /* + * The sentinel is set to a nonzero value (0xff) in header.S. + * diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index aeacb0e..a196a7e 100644 +index 8b24289..d74b441 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -1042,6 +1042,11 @@ void __init setup_arch(char **cmdline_p) +@@ -1042,6 +1042,13 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); + if (boot_params.secure_boot) { ++#ifdef CONFIG_EFI + set_bit(EFI_SECURE_BOOT, &x86_efi_facility); ++#endif + secureboot_enable(); + } + @@ -250,10 +252,10 @@ index aeacb0e..a196a7e 100644 * Parse the ACPI tables for possible boot-time SMP configuration. */ diff --git a/include/linux/cred.h b/include/linux/cred.h -index ebbed2c..a24faf1 100644 +index 04421e8..9e69542 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h -@@ -170,6 +170,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); +@@ -156,6 +156,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); extern int set_create_files_as(struct cred *, struct inode *); extern void __init cred_init(void); @@ -263,10 +265,10 @@ index ebbed2c..a24faf1 100644 * check for validity of credentials */ diff --git a/include/linux/efi.h b/include/linux/efi.h -index b424f64..fef4ca6 100644 +index 7a9498a..1ae16b6 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -551,6 +551,7 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -627,6 +627,7 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ #define EFI_64BIT 5 /* Is the firmware 64-bit? */ @@ -278,7 +280,7 @@ index b424f64..fef4ca6 100644 1.8.1.2 -From 7f17830b2d2e02a1d8614ed06d2eaf37f4a2b9d1 Mon Sep 17 00:00:00 2001 +From d4d1b3ad3e1a553c807b4ecafcbde4bf816e4db2 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 Subject: [PATCH 05/19] Add EFI signature data types @@ -292,10 +294,10 @@ Signed-off-by: David Howells 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index fef4ca6..a5dab3c 100644 +index 1ae16b6..de7021d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -388,6 +388,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, #define EFI_FILE_SYSTEM_GUID \ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) @@ -308,7 +310,7 @@ index fef4ca6..a5dab3c 100644 typedef struct { efi_guid_t guid; u64 table; -@@ -447,6 +453,20 @@ typedef struct { +@@ -523,6 +529,20 @@ typedef struct { #define EFI_INVALID_TABLE_ADDR (~0UL) @@ -333,7 +335,7 @@ index fef4ca6..a5dab3c 100644 1.8.1.2 -From f6e6bcac73c2c4dd0295a528f80d3c6660e9e279 Mon Sep 17 00:00:00 2001 +From 3cffca89eadf7e0f0a266c370f8034f33723831a Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader. @@ -494,10 +496,10 @@ index 0000000..636feb1 + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index a5dab3c..7bfc4f2 100644 +index de7021d..64b3e55 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -536,6 +536,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -612,6 +612,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -512,7 +514,7 @@ index a5dab3c..7bfc4f2 100644 1.8.1.2 -From 26e3eaf96f1433fbb5f0d617b80b5d00e16aeb2c Mon Sep 17 00:00:00 2001 +From 89ea7424726ae4f7265ab84e703cf2da77acda57 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring @@ -525,16 +527,16 @@ useful in cases where third party certificates are used for module signing. Signed-off-by: Josh Boyer --- init/Kconfig | 8 ++++++++ - kernel/modsign_pubkey.c | 17 +++++++++++++++++ + kernel/modsign_pubkey.c | 14 ++++++++++++++ kernel/module-internal.h | 3 +++ kernel/module_signing.c | 12 ++++++++++++ - 4 files changed, 40 insertions(+) + 4 files changed, 37 insertions(+) diff --git a/init/Kconfig b/init/Kconfig -index 6fdd6e3..7a9bf00 100644 +index be8b7f5..d972b77 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE +@@ -1665,6 +1665,14 @@ config MODULE_SIG_FORCE Reject unsigned modules or signed modules for which we don't have a key. Without this, such modules will simply taint the kernel. @@ -550,7 +552,7 @@ index 6fdd6e3..7a9bf00 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 767e559..d99cd51 100644 +index 2b6e699..4cd408d 100644 --- a/kernel/modsign_pubkey.c +++ b/kernel/modsign_pubkey.c @@ -17,6 +17,9 @@ @@ -563,22 +565,19 @@ index 767e559..d99cd51 100644 extern __initdata const u8 modsign_certificate_list[]; extern __initdata const u8 modsign_certificate_list_end[]; -@@ -52,6 +55,20 @@ static __init int module_verify_init(void) - if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) - panic("Can't instantiate module signing keyring\n"); +@@ -43,6 +46,17 @@ static __init int module_verify_init(void) + if (IS_ERR(modsign_keyring)) + panic("Can't allocate module signing keyring\n"); +#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", ++ modsign_blacklist = keyring_alloc(".modsign_blacklist", + KUIDT_INIT(0), KGIDT_INIT(0), + current_cred(), + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); ++ KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (IS_ERR(modsign_blacklist)) + panic("Can't allocate module signing blacklist keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module blacklist keyring\n"); +#endif + return 0; @@ -624,7 +623,7 @@ index f2970bd..5423195 100644 1.8.1.2 -From ec7d8de0b4b29fa052dd9408fab20ce46857b486 Mon Sep 17 00:00:00 2001 +From 733a5c25b896d8d5fa0051825a671911b50cb47d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot @@ -652,10 +651,10 @@ Signed-off-by: Josh Boyer create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index 7bfc4f2..014a013 100644 +index 64b3e55..76fe526 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -318,6 +318,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -394,6 +394,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, #define EFI_CERT_X509_GUID \ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) @@ -669,10 +668,10 @@ index 7bfc4f2..014a013 100644 efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index 7a9bf00..51aa170 100644 +index d972b77..27e3a82 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST +@@ -1673,6 +1673,15 @@ config MODULE_SIG_BLACKLIST should not pass module signature verification. If a module is signed with something in this keyring, the load will be rejected. @@ -689,18 +688,18 @@ index 7a9bf00..51aa170 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/Makefile b/kernel/Makefile -index 86e3285..12e17ab 100644 +index 6c072b6..8848829 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o + obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o +obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o -@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o +@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o $(obj)/configs.o: $(obj)/config_data.h @@ -809,7 +808,7 @@ index 0000000..b9237d7 1.8.1.2 -From ff5f0af5e29e73ba00c04bc67978086d5ed811bd Mon Sep 17 00:00:00 2001 +From 16027d676baed34a9de804dac68d48096a688b39 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments @@ -827,10 +826,10 @@ Signed-off-by: Matthew Garrett 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index f39378d..1db1e74 100644 +index 9c6e9bb..b966089 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c -@@ -546,6 +546,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, +@@ -622,6 +622,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, loff_t init_off = off; u8 *data = (u8*) buf; @@ -840,7 +839,7 @@ index f39378d..1db1e74 100644 if (off > dev->cfg_size) return 0; if (off + count > dev->cfg_size) { -@@ -852,6 +855,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +@@ -928,6 +931,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, resource_size_t start, end; int i; @@ -850,7 +849,7 @@ index f39378d..1db1e74 100644 for (i = 0; i < PCI_ROM_RESOURCE; i++) if (res == &pdev->resource[i]) break; -@@ -959,6 +965,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, +@@ -1035,6 +1041,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { @@ -910,7 +909,7 @@ index e1c1ec5..97e785f 100644 1.8.1.2 -From f6a7b0b3c9ca8b0814d03daed9f98fb009a57cc7 Mon Sep 17 00:00:00 2001 +From 9ff1537bbe8c22bbf7f992027da43d4fe8da0860 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot @@ -950,7 +949,7 @@ index 8c96897..a2578c4 100644 } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 0537903..47501fc 100644 +index c6fa3bc..fc28099 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, @@ -967,7 +966,7 @@ index 0537903..47501fc 100644 1.8.1.2 -From 014664ed0733041ae2e6ddacd21f8eb8ed94d6e9 Mon Sep 17 00:00:00 2001 +From 3b27408b1ced1ec83a3ce27f9d51161dbf7cea9a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 Subject: [PATCH 11/19] ACPI: Limit access to custom_method @@ -999,7 +998,7 @@ index 5d42c24..247d58b 100644 1.8.1.2 -From f1262b9e78f41307e0be23aa6c54f79dfc5c8d39 Mon Sep 17 00:00:00 2001 +From fb618a04089d454b7ade68c00a2b9c7dbac013f9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface @@ -1015,7 +1014,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c0e9ff4..3c10167 100644 +index f80ae4d..059195f 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data) @@ -1052,7 +1051,7 @@ index c0e9ff4..3c10167 100644 1.8.1.2 -From f31dc86516ee8088177a5a82869a3633a6e555b1 Mon Sep 17 00:00:00 2001 +From e515bbd5410d00835390fd8981aa9029e7b22b73 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups @@ -1066,7 +1065,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 6 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 47501fc..8817cdc 100644 +index fc28099..b5df7a8 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, @@ -1093,7 +1092,7 @@ index 47501fc..8817cdc 100644 1.8.1.2 -From e5724ed32b15d5dec9a239036598d9273b105506 Mon Sep 17 00:00:00 2001 +From fe27dd192ef250abcbaba973a14d43b21d7be497 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -1101,10 +1100,7 @@ Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure This option allows userspace to pass the RSDP address to the kernel. This could potentially be used to circumvent the secure boot trust model. -This is setup through the setup_arch function, which is called before the -security_init function sets up the security_ops, so we cannot use a -capable call here. We ignore the setting if we are booted in Secure Boot -mode. +We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. Signed-off-by: Josh Boyer --- @@ -1112,7 +1108,7 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 251435a..eef0b89 100644 +index bd22f86..88251d2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); @@ -1120,7 +1116,7 @@ index 251435a..eef0b89 100644 { #ifdef CONFIG_KEXEC - if (acpi_rsdp) -+ if (acpi_rsdp && !efi_enabled(EFI_SECURE_BOOT)) ++ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) return acpi_rsdp; #endif @@ -1128,7 +1124,7 @@ index 251435a..eef0b89 100644 1.8.1.2 -From 1bc68fa7cb2ea5983ab1de20fd881eed74e214cb Mon Sep 17 00:00:00 2001 +From c937b2c8e179bfdadb6617c0028f558e4d701e46 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 15/19] kexec: Disable in a secure boot environment @@ -1160,7 +1156,7 @@ index 5e4bd78..dd464e0 100644 1.8.1.2 -From b6ec4b0890d4cb00c17b4a1dee6da84bb5fff597 Mon Sep 17 00:00:00 2001 +From f08e390045266d53543a55afa16ca4be5a1c6316 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot @@ -1179,10 +1175,10 @@ Signed-off-by: Josh Boyer 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/cred.c b/kernel/cred.c -index 3f5be65..a381e27 100644 +index c3f4e3e..c5554e0 100644 --- a/kernel/cred.c +++ b/kernel/cred.c -@@ -623,11 +623,19 @@ void __init cred_init(void) +@@ -565,11 +565,19 @@ void __init cred_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); } @@ -1203,10 +1199,10 @@ index 3f5be65..a381e27 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index 3e544f4..7a9a802 100644 +index eab0827..93a16dc 100644 --- a/kernel/module.c +++ b/kernel/module.c -@@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ +@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ #ifdef CONFIG_MODULE_SIG #ifdef CONFIG_MODULE_SIG_FORCE @@ -1222,7 +1218,7 @@ index 3e544f4..7a9a802 100644 1.8.1.2 -From 19d340a563439ab3892159510bb3ba7730bf9ea9 Mon Sep 17 00:00:00 2001 +From 54ba1eec5847d964b1d458a240b50271b9a356a4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment @@ -1294,7 +1290,7 @@ index b26f5f1..7f63cb4 100644 len = p ? p - buf : n; diff --git a/kernel/power/main.c b/kernel/power/main.c -index f458238..734bc26 100644 +index 1c16f91..4f915fc 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,6 +15,7 @@ @@ -1336,7 +1332,7 @@ index 4ed81e7..b11a0f4 100644 1.8.1.2 -From a0f61de745510aade63ef7694cecf11cb98559cf Mon Sep 17 00:00:00 2001 +From 686090054f6c3784218b318c7adcc3c1f0ca5069 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Feb 2013 19:25:05 -0500 Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode @@ -1353,10 +1349,10 @@ Signed-off-by: Josh Boyer 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 4983e43..eea615a 100644 +index 96bd86b..6e1331c 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -733,8 +733,9 @@ fail: +@@ -851,8 +851,9 @@ fail: static int get_secure_boot(efi_system_table_t *_table) { @@ -1367,7 +1363,7 @@ index 4983e43..eea615a 100644 efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_status_t status; -@@ -758,6 +759,23 @@ static int get_secure_boot(efi_system_table_t *_table) +@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table) if (setup == 1) return 0; @@ -1395,7 +1391,7 @@ index 4983e43..eea615a 100644 1.8.1.2 -From 5467b18cc9b3475658328a38ad6922d6b32c87ca Mon Sep 17 00:00:00 2001 +From df607d2d5061b04f8a686cd74edd72c1f2836d8c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 8 Feb 2013 11:12:13 -0800 Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot From 48ab4b0ce8b39862472b3eafec833b0856b5aaef Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 27 Feb 2013 13:09:57 -0600 Subject: [PATCH 201/492] fix sources for 3.8 --- sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources b/sources index 580ae0bbf..bf83e961e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz +1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz From 7fa684400e4bfcacb8f122eb1477273bf0c8f9bc Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 27 Feb 2013 13:10:49 -0600 Subject: [PATCH 202/492] fix userns-avoid-recursion-in-put_user_ns.patch for f18 --- kernel.spec | 2 +- userns-avoid-recursion-in-put_user_ns.patch | 53 ++++++++++++--------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/kernel.spec b/kernel.spec index 98a9edbf4..2147b9ce3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1525,7 +1525,7 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #CVE-2013-1767 rhbz 915592,915716 ApplyPatch tmpfs-fix-use-after-free-of-mempolicy-object.patch -#ApplyPatch userns-avoid-recursion-in-put_user_ns.patch +ApplyPatch userns-avoid-recursion-in-put_user_ns.patch diff --git a/userns-avoid-recursion-in-put_user_ns.patch b/userns-avoid-recursion-in-put_user_ns.patch index d364e79f5..c3bb60444 100644 --- a/userns-avoid-recursion-in-put_user_ns.patch +++ b/userns-avoid-recursion-in-put_user_ns.patch @@ -27,8 +27,10 @@ Date: Fri Dec 28 18:58:39 2012 -0800 Pointed-out-by: Vasily Kulikov Signed-off-by: "Eric W. Biederman" ---- linux-3.7.9-105.fc17.noarch/include/linux/user_namespace.h 2013-02-14 11:29:49.757652513 -0600 -+++ linux-3.7.9-105.fc17.user_ns/include/linux/user_namespace.h 2013-02-26 15:19:40.696782035 -0600 +diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h +index b9bd2e6..4ce0093 100644 +--- a/include/linux/user_namespace.h ++++ b/include/linux/user_namespace.h @@ -21,7 +21,7 @@ struct user_namespace { struct uid_gid_map uid_map; struct uid_gid_map gid_map; @@ -38,7 +40,7 @@ Date: Fri Dec 28 18:58:39 2012 -0800 struct user_namespace *parent; kuid_t owner; kgid_t group; -@@ -34,17 +34,17 @@ extern struct user_namespace init_user_n +@@ -35,18 +35,18 @@ extern struct user_namespace init_user_ns; static inline struct user_namespace *get_user_ns(struct user_namespace *ns) { if (ns) @@ -46,11 +48,12 @@ Date: Fri Dec 28 18:58:39 2012 -0800 + atomic_inc(&ns->count); return ns; } - + extern int create_user_ns(struct cred *new); + extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred); -extern void free_user_ns(struct kref *kref); +extern void free_user_ns(struct user_namespace *ns); - + static inline void put_user_ns(struct user_namespace *ns) { - if (ns) @@ -58,11 +61,13 @@ Date: Fri Dec 28 18:58:39 2012 -0800 + if (ns && atomic_dec_and_test(&ns->count)) + free_user_ns(ns); } - + struct seq_operations; ---- linux-3.7.9-105.fc17.noarch/kernel/user.c 2013-02-14 11:29:46.675652732 -0600 -+++ linux-3.7.9-105.fc17.user_ns/kernel/user.c 2013-02-26 15:16:12.347796824 -0600 -@@ -46,9 +46,7 @@ struct user_namespace init_user_ns = { +diff --git a/kernel/user.c b/kernel/user.c +index 33acb5e..57ebfd4 100644 +--- a/kernel/user.c ++++ b/kernel/user.c +@@ -47,9 +47,7 @@ struct user_namespace init_user_ns = { .count = 4294967295U, }, }, @@ -72,37 +77,41 @@ Date: Fri Dec 28 18:58:39 2012 -0800 + .count = ATOMIC_INIT(3), .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, - }; ---- linux-3.7.9-105.fc17.noarch/kernel/user_namespace.c 2013-02-14 11:29:46.690652731 -0600 -+++ linux-3.7.9-105.fc17.user_ns/kernel/user_namespace.c 2013-02-26 15:24:47.984760224 -0600 -@@ -52,7 +52,7 @@ int create_user_ns(struct cred *new) - if (!ns) - return -ENOMEM; - + .proc_inum = PROC_USER_INIT_INO, +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 2b042c4..24f8ec3 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -78,7 +78,7 @@ int create_user_ns(struct cred *new) + return ret; + } + - kref_init(&ns->kref); + atomic_set(&ns->count, 1); + /* Leave the new->user_ns reference with the new user namespace. */ ns->parent = parent_ns; ns->owner = owner; - ns->group = group; -@@ -78,14 +78,15 @@ int create_user_ns(struct cred *new) - return 0; +@@ -104,15 +104,16 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) + return create_user_ns(cred); } - + -void free_user_ns(struct kref *kref) +void free_user_ns(struct user_namespace *ns) { - struct user_namespace *parent, *ns = - container_of(kref, struct user_namespace, kref); + struct user_namespace *parent; - + - parent = ns->parent; +- proc_free_inum(ns->proc_inum); - kmem_cache_free(user_ns_cachep, ns); - put_user_ns(parent); + do { + parent = ns->parent; ++ proc_free_inum(ns->proc_inum); + kmem_cache_free(user_ns_cachep, ns); + ns = parent; + } while (atomic_dec_and_test(&parent->count)); } EXPORT_SYMBOL(free_user_ns); - + From f847da58cdecf68eee5ec4f0e942109f45ee1e80 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Feb 2013 14:41:36 -0500 Subject: [PATCH 203/492] Update ALPS patch --- alps-v2-3.7.patch => alps.patch | 2925 ++++++++++--------------------- kernel.spec | 9 +- 2 files changed, 923 insertions(+), 2011 deletions(-) rename alps-v2-3.7.patch => alps.patch (51%) diff --git a/alps-v2-3.7.patch b/alps.patch similarity index 51% rename from alps-v2-3.7.patch rename to alps.patch index 262cd0d92..83d3cfe0a 100644 --- a/alps-v2-3.7.patch +++ b/alps.patch @@ -1,139 +1,42 @@ -From 2c5e103a6d0a2a0c74cd8b299d58c4ca07911aad Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:55:19 -0800 -Subject: [PATCH 01/15] Input: ALPS - document the alps.h data structures - -Add kernel-doc markup. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.h | 74 ++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 61 insertions(+), 13 deletions(-) - -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index ae1ac35..67be4e5 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -17,30 +17,78 @@ - #define ALPS_PROTO_V3 2 - #define ALPS_PROTO_V4 3 - -+/** -+ * struct alps_model_info - touchpad ID table -+ * @signature: E7 response string to match. -+ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response -+ * (aka command mode response) identifies the firmware minor version. This -+ * can be used to distinguish different hardware models which are not -+ * uniquely identifiable through their E7 responses. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * -+ * Many (but not all) ALPS touchpads can be identified by looking at the -+ * values returned in the "E7 report" and/or the "EC report." This table -+ * lists a number of such touchpads. -+ */ - struct alps_model_info { -- unsigned char signature[3]; -- unsigned char command_mode_resp; /* v3/v4 only */ -+ unsigned char signature[3]; -+ unsigned char command_mode_resp; - unsigned char proto_version; -- unsigned char byte0, mask0; -- unsigned char flags; -+ unsigned char byte0, mask0; -+ unsigned char flags; - }; - -+/** -+ * struct alps_nibble_commands - encodings for register accesses -+ * @command: PS/2 command used for the nibble -+ * @data: Data supplied as an argument to the PS/2 command, if applicable -+ * -+ * The ALPS protocol uses magic sequences to transmit binary data to the -+ * touchpad, as it is generally not OK to send arbitrary bytes out the -+ * PS/2 port. Each of the sequences in this table sends one nibble of the -+ * register address or (write) data. Different versions of the ALPS protocol -+ * use slightly different encodings. -+ */ - struct alps_nibble_commands { - int command; - unsigned char data; - }; - -+/** -+ * struct alps_data - private data structure for the ALPS driver -+ * @dev2: "Relative" device used to report trackstick or mouse activity. -+ * @phys: Physical path for the relative device. -+ * @i: Information on the detected touchpad model. -+ * @nibble_commands: Command mapping used for touchpad register accesses. -+ * @addr_command: Command used to tell the touchpad that a register address -+ * follows. -+ * @prev_fin: Finger bit from previous packet. -+ * @multi_packet: Multi-packet data in progress. -+ * @multi_data: Saved multi-packet data. -+ * @x1: First X coordinate from last MT report. -+ * @x2: Second X coordinate from last MT report. -+ * @y1: First Y coordinate from last MT report. -+ * @y2: Second Y coordinate from last MT report. -+ * @fingers: Number of fingers from last MT report. -+ * @quirks: Bitmap of ALPS_QUIRK_*. -+ * @timer: Timer for flushing out the final report packet in the stream. -+ */ - struct alps_data { -- struct input_dev *dev2; /* Relative device */ -- char phys[32]; /* Phys */ -- const struct alps_model_info *i;/* Info */ -+ struct input_dev *dev2; -+ char phys[32]; -+ const struct alps_model_info *i; - const struct alps_nibble_commands *nibble_commands; -- int addr_command; /* Command to set register address */ -- int prev_fin; /* Finger bit from previous packet */ -- int multi_packet; /* Multi-packet data in progress */ -- unsigned char multi_data[6]; /* Saved multi-packet data */ -- int x1, x2, y1, y2; /* Coordinates from last MT report */ -- int fingers; /* Number of fingers from MT report */ -+ int addr_command; -+ int prev_fin; -+ int multi_packet; -+ unsigned char multi_data[6]; -+ int x1, x2, y1, y2; -+ int fingers; - u8 quirks; - struct timer_list timer; - }; --- -1.8.1.2 - - -From 80378616e681afdc14b236c99a77c1296f0b8031 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:56:33 -0800 -Subject: [PATCH 02/15] Input: ALPS - copy "model" info into alps_data struct - -Not every type of ALPS touchpad is well-suited to table-based detection. -Start moving the various alps_model_data attributes into the alps_data -struct so that we don't need a unique table entry for every possible -permutation of protocol version, flags, byte0/mask0, etc. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 63 +++++++++++++++++++++++----------------------- - drivers/input/mouse/alps.h | 14 +++++++++-- - 2 files changed, 43 insertions(+), 34 deletions(-) - diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index cf5af1f..9664e94 100644 +index e229fa3..7b99fc7 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c +@@ -27,14 +27,11 @@ + /* + * Definitions for ALPS version 3 and 4 command mode protocol + */ +-#define ALPS_V3_X_MAX 2000 +-#define ALPS_V3_Y_MAX 1400 +- +-#define ALPS_BITMAP_X_BITS 15 +-#define ALPS_BITMAP_Y_BITS 11 +- + #define ALPS_CMD_NIBBLE_10 0x01f2 + ++#define ALPS_REG_BASE_RUSHMORE 0xc2c0 ++#define ALPS_REG_BASE_PINNACLE 0x0000 ++ + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { + { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ + { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ +@@ -109,11 +106,14 @@ static const struct alps_model_info alps_model_data[] = { + { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ +- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, +- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, + { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1); ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1); ++ + /* + * XXX - this entry is suspicious. First byte has zero lower nibble, + * which is what a normal mouse would report. Also, the value 0x0e @@ -122,10 +122,10 @@ static const struct alps_model_info alps_model_data[] = { /* Packet formats are described in Documentation/input/alps.txt */ @@ -206,27 +109,304 @@ index cf5af1f..9664e94 100644 input_report_key(dev, BTN_0, packet[2] & 4); input_report_key(dev, BTN_1, packet[0] & 0x10); input_report_key(dev, BTN_2, packet[3] & 4); -@@ -699,9 +698,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - static void alps_process_packet(struct psmouse *psmouse) +@@ -267,7 +266,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + * These points are returned in x1, y1, x2, and y2 when the return value + * is greater than 0. + */ +-static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++static int alps_process_bitmap(struct alps_data *priv, ++ unsigned int x_map, unsigned int y_map, + int *x1, int *y1, int *x2, int *y2) + { + struct alps_bitmap_point { +@@ -309,7 +309,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + * y bitmap is reversed for what we need (lower positions are in + * higher bits), so we process from the top end. + */ +- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); + prev_bit = 0; + point = &y_low; + for (i = 0; y_map != 0; i++, y_map <<= 1) { +@@ -355,16 +355,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + } + } + +- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + + if (fingers > 1) { +- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x2 = (priv->x_max * ++ (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y2 = (priv->y_max * ++ (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + } + + return fingers; +@@ -448,17 +450,57 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + return; + } + ++static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) ++{ ++ f->left = !!(p[3] & 0x01); ++ f->right = !!(p[3] & 0x02); ++ f->middle = !!(p[3] & 0x04); ++ ++ f->ts_left = !!(p[3] & 0x10); ++ f->ts_right = !!(p[3] & 0x20); ++ f->ts_middle = !!(p[3] & 0x40); ++} ++ ++static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) ++{ ++ f->first_mp = !!(p[4] & 0x40); ++ f->is_mp = !!(p[0] & 0x40); ++ ++ f->fingers = (p[5] & 0x3) + 1; ++ f->x_map = ((p[4] & 0x7e) << 8) | ++ ((p[1] & 0x7f) << 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y_map = ((p[3] & 0x70) << 4) | ++ ((p[2] & 0x7f) << 1) | ++ (p[4] & 0x01); ++ ++ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); ++ f->z = p[5] & 0x7f; ++ ++ alps_decode_buttons_v3(f, p); ++} ++ ++static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) ++{ ++ alps_decode_pinnacle(f, p); ++ ++ f->x_map |= (p[5] & 0x10) << 11; ++ f->y_map |= (p[5] & 0x20) << 6; ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + struct input_dev *dev2 = priv->dev2; +- int x, y, z; +- int left, right, middle; + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + int fingers = 0, bmap_fingers; +- unsigned int x_bitmap, y_bitmap; ++ struct alps_fields f; ++ ++ priv->decode_fields(&f, packet); + /* + * There's no single feature of touchpad position and bitmap packets +@@ -473,16 +515,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * packet. Check for this, and when it happens process the + * position packet as usual. + */ +- if (packet[0] & 0x40) { +- fingers = (packet[5] & 0x3) + 1; +- x_bitmap = ((packet[4] & 0x7e) << 8) | +- ((packet[1] & 0x7f) << 2) | +- ((packet[0] & 0x30) >> 4); +- y_bitmap = ((packet[3] & 0x70) << 4) | +- ((packet[2] & 0x7f) << 1) | +- (packet[4] & 0x01); +- +- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ if (f.is_mp) { ++ fingers = f.fingers; ++ bmap_fingers = alps_process_bitmap(priv, ++ f.x_map, f.y_map, + &x1, &y1, &x2, &y2); + + /* +@@ -493,7 +529,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + fingers = bmap_fingers; + + /* Now process position packet */ +- packet = priv->multi_data; ++ priv->decode_fields(&f, priv->multi_data); + } else { + priv->multi_packet = 0; + } +@@ -507,10 +543,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * out misidentified bitmap packets, we reject anything with this + * bit set. + */ +- if (packet[0] & 0x40) ++ if (f.is_mp) + return; + +- if (!priv->multi_packet && (packet[4] & 0x40)) { ++ if (!priv->multi_packet && f.first_mp) { + priv->multi_packet = 1; + memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); + return; +@@ -518,22 +554,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + priv->multi_packet = 0; + +- left = packet[3] & 0x01; +- right = packet[3] & 0x02; +- middle = packet[3] & 0x04; +- +- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | +- ((packet[0] & 0x30) >> 4); +- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); +- z = packet[5] & 0x7f; +- + /* + * Sometimes the hardware sends a single packet with z = 0 + * in the middle of a stream. Real releases generate packets + * with x, y, and z all zero, so these seem to be flukes. + * Ignore them. + */ +- if (x && y && !z) ++ if (f.x && f.y && !f.z) + return; + + /* +@@ -541,12 +568,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * to rely on ST data. + */ + if (!fingers) { +- x1 = x; +- y1 = y; +- fingers = z > 0 ? 1 : 0; ++ x1 = f.x; ++ y1 = f.y; ++ fingers = f.z > 0 ? 1 : 0; + } + +- if (z >= 64) ++ if (f.z >= 64) + input_report_key(dev, BTN_TOUCH, 1); + else + input_report_key(dev, BTN_TOUCH, 0); +@@ -555,26 +582,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + input_mt_report_finger_count(dev, fingers); + +- input_report_key(dev, BTN_LEFT, left); +- input_report_key(dev, BTN_RIGHT, right); +- input_report_key(dev, BTN_MIDDLE, middle); ++ input_report_key(dev, BTN_LEFT, f.left); ++ input_report_key(dev, BTN_RIGHT, f.right); ++ input_report_key(dev, BTN_MIDDLE, f.middle); + +- if (z > 0) { +- input_report_abs(dev, ABS_X, x); +- input_report_abs(dev, ABS_Y, y); ++ if (f.z > 0) { ++ input_report_abs(dev, ABS_X, f.x); ++ input_report_abs(dev, ABS_Y, f.y); + } +- input_report_abs(dev, ABS_PRESSURE, z); ++ input_report_abs(dev, ABS_PRESSURE, f.z); + + input_sync(dev); + + if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { +- left = packet[3] & 0x10; +- right = packet[3] & 0x20; +- middle = packet[3] & 0x40; +- +- input_report_key(dev2, BTN_LEFT, left); +- input_report_key(dev2, BTN_RIGHT, right); +- input_report_key(dev2, BTN_MIDDLE, middle); ++ input_report_key(dev2, BTN_LEFT, f.ts_left); ++ input_report_key(dev2, BTN_RIGHT, f.ts_right); ++ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); + input_sync(dev2); + } + } +@@ -639,7 +662,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + ((priv->multi_data[3] & 0x1f) << 5) | + (priv->multi_data[1] & 0x1f); + +- fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, + &x1, &y1, &x2, &y2); + + /* Store MT data.*/ +@@ -696,25 +719,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + input_sync(dev); + } + +-static void alps_process_packet(struct psmouse *psmouse) +-{ +- struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; +- - switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - alps_process_packet_v1_v2(psmouse); -@@ -765,7 +763,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- alps_process_packet_v1_v2(psmouse); +- break; +- case ALPS_PROTO_V3: +- alps_process_packet_v3(psmouse); +- break; +- case ALPS_PROTO_V4: +- alps_process_packet_v4(psmouse); +- break; +- } +-} +- + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -765,14 +769,14 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) if (((psmouse->packet[3] | psmouse->packet[4] | psmouse->packet[5]) & 0x80) || - (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { + (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { psmouse_dbg(psmouse, - "refusing packet %x %x %x %x (suspected interleaved ps/2)\n", - psmouse->packet[3], psmouse->packet[4], -@@ -846,7 +844,6 @@ static void alps_flush_packet(unsigned long data) + "refusing packet %4ph (suspected interleaved ps/2)\n", + psmouse->packet + 3); + return PSMOUSE_BAD_DATA; + } + +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + + /* Continue with the next packet */ + psmouse->packet[0] = psmouse->packet[6]; +@@ -816,6 +820,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + static void alps_flush_packet(unsigned long data) + { + struct psmouse *psmouse = (struct psmouse *)data; ++ struct alps_data *priv = psmouse->private; + + serio_pause_rx(psmouse->ps2dev.serio); + +@@ -833,7 +838,7 @@ static void alps_flush_packet(unsigned long data) + "refusing packet %3ph (suspected interleaved ps/2)\n", + psmouse->packet + 3); + } else { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + } + psmouse->pktcnt = 0; + } +@@ -844,7 +849,6 @@ static void alps_flush_packet(unsigned long data) static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -234,7 +414,7 @@ index cf5af1f..9664e94 100644 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ if (psmouse->pktcnt == 3) { -@@ -859,15 +856,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -857,15 +861,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ @@ -253,181 +433,67 @@ index cf5af1f..9664e94 100644 return PSMOUSE_BAD_DATA; } -@@ -1192,16 +1189,16 @@ static int alps_poll(struct psmouse *psmouse) - unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, false); - -- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) -+ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) - return -1; - - if ((psmouse->badbyte & 0xc8) == 0x08) { -@@ -1219,9 +1216,8 @@ static int alps_poll(struct psmouse *psmouse) - static int alps_hw_init_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } -@@ -1236,7 +1232,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) - return -1; +@@ -879,7 +883,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) } -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } -@@ -1522,10 +1518,9 @@ error: - static int alps_hw_init(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - int ret = -1; - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - ret = alps_hw_init_v1_v2(psmouse); -@@ -1587,7 +1582,10 @@ int alps_init(struct psmouse *psmouse) - if (!model) - goto init_fail; - -- priv->i = model; -+ priv->proto_version = model->proto_version; -+ priv->byte0 = model->byte0; -+ priv->mask0 = model->mask0; -+ priv->flags = model->flags; - - if (alps_hw_init(psmouse)) - goto init_fail; -@@ -1611,7 +1609,7 @@ int alps_init(struct psmouse *psmouse) - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -@@ -1635,17 +1633,17 @@ int alps_init(struct psmouse *psmouse) - - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - -- if (model->flags & ALPS_WHEEL) { -+ if (priv->flags & ALPS_WHEEL) { - dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); - dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); + if (psmouse->pktcnt == psmouse->pktsize) { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + return PSMOUSE_FULL_PACKET; } -- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { -+ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); - dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); - } +@@ -967,24 +971,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, + return __alps_command_mode_write_reg(psmouse, value); + } -- if (model->flags & ALPS_FOUR_BUTTONS) { -+ if (priv->flags & ALPS_FOUR_BUTTONS) { - dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); - dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); - dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); -@@ -1656,7 +1654,8 @@ int alps_init(struct psmouse *psmouse) - - snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys; -- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; -+ dev2->name = (priv->flags & ALPS_DUALPOINT) ? -+ "DualPoint Stick" : "PS/2 Mouse"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_ALPS; -@@ -1675,7 +1674,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; -+ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 67be4e5..efd0eea 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -63,10 +63,15 @@ struct alps_nibble_commands { - * struct alps_data - private data structure for the ALPS driver - * @dev2: "Relative" device used to report trackstick or mouse activity. - * @phys: Physical path for the relative device. -- * @i: Information on the detected touchpad model. - * @nibble_commands: Command mapping used for touchpad register accesses. - * @addr_command: Command used to tell the touchpad that a register address - * follows. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. - * @multi_data: Saved multi-packet data. -@@ -81,9 +86,14 @@ struct alps_nibble_commands { - struct alps_data { - struct input_dev *dev2; - char phys[32]; -- const struct alps_model_info *i; ++static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, ++ int repeated_command, unsigned char *param) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; + -+ /* these are autodetected when the device is identified */ - const struct alps_nibble_commands *nibble_commands; - int addr_command; -+ unsigned char proto_version; -+ unsigned char byte0, mask0; -+ unsigned char flags; ++ param[0] = 0; ++ if (init_command && ps2_command(ps2dev, param, init_command)) ++ return -EIO; + - int prev_fin; - int multi_packet; - unsigned char multi_data[6]; --- -1.8.1.2 - - -From 7b9d630645b501a484e498461259167858d331e6 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:57:04 -0800 -Subject: [PATCH 03/15] Input: ALPS - move alps_get_model() down below hw_init - code - -This will minimize the number of forward declarations needed when -alps_get_model() starts assigning function pointers. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 186 ++++++++++++++++++++++----------------------- - 1 file changed, 93 insertions(+), 93 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 9664e94..3c15fd3 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -1000,99 +1000,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) ++ if (ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command)) ++ return -EIO; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -EIO; ++ ++ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", ++ repeated_command, param[0], param[1], param[2]); ++ return 0; ++} ++ + static int alps_enter_command_mode(struct psmouse *psmouse, + unsigned char *resp) + { + unsigned char param[4]; +- struct ps2dev *ps2dev = &psmouse->ps2dev; + +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { + psmouse_err(psmouse, "failed to enter command mode\n"); + return -1; + } + +- if (param[0] != 0x88 && param[1] != 0x07) { ++ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { + psmouse_dbg(psmouse, +- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", +- param[0], param[1], param[2]); ++ "unknown response while entering command mode\n"); + return -1; + } + +@@ -1001,99 +1023,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) return 0; } @@ -527,182 +593,7 @@ index 9664e94..3c15fd3 100644 /* * For DualPoint devices select the device that should respond to * subsequent commands. It looks like glidepad is behind stickpointer, -@@ -1536,6 +1443,99 @@ static int alps_hw_init(struct psmouse *psmouse) - return ret; - } - -+static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; -+ unsigned char param[4]; -+ const struct alps_model_info *model = NULL; -+ int i; -+ -+ /* -+ * First try "E6 report". -+ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. -+ * The bits 0-2 of the first byte will be 1s if some buttons are -+ * pressed. -+ */ -+ param[0] = 0; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) -+ return NULL; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return NULL; -+ -+ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", -+ param[0], param[1], param[2]); -+ -+ if ((param[0] & 0xf8) != 0 || param[1] != 0 || -+ (param[2] != 10 && param[2] != 100)) -+ return NULL; -+ -+ /* -+ * Now try "E7 report". Allowed responses are in -+ * alps_model_data[].signature -+ */ -+ param[0] = 0; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) -+ return NULL; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return NULL; -+ -+ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", -+ param[0], param[1], param[2]); -+ -+ if (version) { -+ for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) -+ /* empty */; -+ *version = (param[0] << 8) | (param[1] << 4) | i; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (!memcmp(param, alps_model_data[i].signature, -+ sizeof(alps_model_data[i].signature))) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ -+ if (model && model->proto_version > ALPS_PROTO_V2) { -+ /* -+ * Need to check command mode response to identify -+ * model -+ */ -+ model = NULL; -+ if (alps_enter_command_mode(psmouse, param)) { -+ psmouse_warn(psmouse, -+ "touchpad failed to enter command mode\n"); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -+ alps_model_data[i].command_mode_resp == param[0]) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ alps_exit_command_mode(psmouse); -+ -+ if (!model) -+ psmouse_dbg(psmouse, -+ "Unknown command mode response %2.2x\n", -+ param[0]); -+ } -+ } -+ -+ return model; -+} -+ - static int alps_reconnect(struct psmouse *psmouse) - { - const struct alps_model_info *model; --- -1.8.1.2 - - -From 59f721fed5e707eeae2d084dff0963f0cb02901a Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:19:01 -0800 -Subject: [PATCH 04/15] Input: ALPS - introduce helper function for repeated - commands - -Several ALPS driver init sequences repeat a command three times, then -issue PSMOUSE_CMD_GETINFO to read the result. Move this into a helper -function to simplify the code. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 71 ++++++++++++++++++++-------------------------- - 1 file changed, 30 insertions(+), 41 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 3c15fd3..c03ce3f 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -966,24 +966,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, - return __alps_command_mode_write_reg(psmouse, value); - } - -+static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, -+ int repeated_command, unsigned char *param) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ param[0] = 0; -+ if (init_command && ps2_command(ps2dev, param, init_command)) -+ return -EIO; -+ -+ if (ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command)) -+ return -EIO; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -EIO; -+ -+ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", -+ repeated_command, param[0], param[1], param[2]); -+ return 0; -+} -+ - static int alps_enter_command_mode(struct psmouse *psmouse, - unsigned char *resp) - { - unsigned char param[4]; -- struct ps2dev *ps2dev = &psmouse->ps2dev; - -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { - psmouse_err(psmouse, "failed to enter command mode\n"); - return -1; - } - - if (param[0] != 0x88 && param[1] != 0x07) { - psmouse_dbg(psmouse, -- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -- param[0], param[1], param[2]); -+ "unknown response while entering command mode\n"); - return -1; - } - -@@ -1043,18 +1061,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) +@@ -1137,18 +1066,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) static int alps_get_status(struct psmouse *psmouse, char *param) { @@ -722,1273 +613,47 @@ index 3c15fd3..c03ce3f 100644 return 0; } -@@ -1445,7 +1455,6 @@ static int alps_hw_init(struct psmouse *psmouse) +@@ -1190,16 +1111,16 @@ static int alps_poll(struct psmouse *psmouse) + unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; - static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) - { -- struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; - const struct alps_model_info *model = NULL; -@@ -1457,20 +1466,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, -+ param)) - return NULL; +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, true); -- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- - if ((param[0] & 0xf8) != 0 || param[1] != 0 || - (param[2] != 10 && param[2] != 100)) - return NULL; -@@ -1479,20 +1478,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * Now try "E7 report". Allowed responses are in - * alps_model_data[].signature - */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, -+ param)) - return NULL; + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; -- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- - if (version) { - for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) - /* empty */; --- -1.8.1.2 - - -From b07564337687bf94d1872b0bb0d072e56434d821 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:19:59 -0800 -Subject: [PATCH 05/15] Input: ALPS - rework detection sequence - -If the E6 report test passes, get the E7 and EC reports right away and -then try to match an entry in the table. - -Pass in the alps_data struct, so that the detection code will be able to -set operating parameters based on information found during detection. - -Change the version (psmouse->model) to report the protocol version only, -in preparation for supporting models that do not show up in the ID table. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 124 +++++++++++++++++++-------------------------- - drivers/input/mouse/alps.h | 8 +-- - 2 files changed, 56 insertions(+), 76 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index c03ce3f..c11b47e 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -1453,86 +1453,76 @@ static int alps_hw_init(struct psmouse *psmouse) - return ret; - } +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, false); --static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -+static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, -+ unsigned char *e7, unsigned char *ec) - { -- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; -- unsigned char param[4]; -- const struct alps_model_info *model = NULL; -+ const struct alps_model_info *model; - int i; - -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ model = &alps_model_data[i]; -+ -+ if (!memcmp(e7, model->signature, sizeof(model->signature)) && -+ (!model->command_mode_resp || -+ model->command_mode_resp == ec[2])) { -+ -+ priv->proto_version = model->proto_version; -+ priv->flags = model->flags; -+ priv->byte0 = model->byte0; -+ priv->mask0 = model->mask0; -+ -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) -+{ -+ unsigned char e6[4], e7[4], ec[4]; -+ - /* - * First try "E6 report". - * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ -- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, -- param)) -- return NULL; -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE11, e6)) -+ return -EIO; - -- if ((param[0] & 0xf8) != 0 || param[1] != 0 || -- (param[2] != 10 && param[2] != 100)) -- return NULL; -+ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) -+ return -EINVAL; - - /* -- * Now try "E7 report". Allowed responses are in -- * alps_model_data[].signature -+ * Now get the "E7" and "EC" reports. These will uniquely identify -+ * most ALPS touchpads. - */ -- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, -- param)) -- return NULL; -- -- if (version) { -- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) -- /* empty */; -- *version = (param[0] << 8) | (param[1] << 4) | i; -- } -- -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (!memcmp(param, alps_model_data[i].signature, -- sizeof(alps_model_data[i].signature))) { -- model = alps_model_data + i; -- break; -- } -- } -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE21, e7) || -+ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_RESET_WRAP, ec) || -+ alps_exit_command_mode(psmouse)) -+ return -EIO; - -- if (model && model->proto_version > ALPS_PROTO_V2) { -- /* -- * Need to check command mode response to identify -- * model -- */ -- model = NULL; -- if (alps_enter_command_mode(psmouse, param)) { -- psmouse_warn(psmouse, -- "touchpad failed to enter command mode\n"); -- } else { -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -- alps_model_data[i].command_mode_resp == param[0]) { -- model = alps_model_data + i; -- break; -- } -- } -- alps_exit_command_mode(psmouse); -+ if (alps_match_table(psmouse, priv, e7, ec) == 0) -+ return 0; - -- if (!model) -- psmouse_dbg(psmouse, -- "Unknown command mode response %2.2x\n", -- param[0]); -- } -- } -+ psmouse_info(psmouse, -+ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", -+ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); - -- return model; -+ return -EINVAL; - } - - static int alps_reconnect(struct psmouse *psmouse) - { -- const struct alps_model_info *model; -+ struct alps_data *priv = psmouse->private; - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, NULL); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) +- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) ++ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) return -1; - return alps_hw_init(psmouse); -@@ -1551,9 +1541,7 @@ static void alps_disconnect(struct psmouse *psmouse) - int alps_init(struct psmouse *psmouse) - { - struct alps_data *priv; -- const struct alps_model_info *model; - struct input_dev *dev1 = psmouse->dev, *dev2; -- int version; - - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); - dev2 = input_allocate_device(); -@@ -1567,15 +1555,9 @@ int alps_init(struct psmouse *psmouse) - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) - goto init_fail; - -- priv->proto_version = model->proto_version; -- priv->byte0 = model->byte0; -- priv->mask0 = model->mask0; -- priv->flags = model->flags; -- - if (alps_hw_init(psmouse)) - goto init_fail; - -@@ -1680,18 +1662,16 @@ init_fail: - - int alps_detect(struct psmouse *psmouse, bool set_properties) - { -- int version; -- const struct alps_model_info *model; -+ struct alps_data dummy; - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, &dummy) < 0) - return -1; - - if (set_properties) { - psmouse->vendor = "ALPS"; -- psmouse->name = model->flags & ALPS_DUALPOINT ? -+ psmouse->name = dummy.flags & ALPS_DUALPOINT ? - "DualPoint TouchPad" : "GlidePoint"; -- psmouse->model = version; -+ psmouse->model = dummy.proto_version << 8; - } - return 0; - } -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index efd0eea..a81b318 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -12,10 +12,10 @@ - #ifndef _ALPS_H - #define _ALPS_H - --#define ALPS_PROTO_V1 0 --#define ALPS_PROTO_V2 1 --#define ALPS_PROTO_V3 2 --#define ALPS_PROTO_V4 3 -+#define ALPS_PROTO_V1 1 -+#define ALPS_PROTO_V2 2 -+#define ALPS_PROTO_V3 3 -+#define ALPS_PROTO_V4 4 - - /** - * struct alps_model_info - touchpad ID table --- -1.8.1.2 - - -From 3291afbdc14314b4eb4b97efc9017a26f00bb143 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:22:08 -0800 -Subject: [PATCH 06/15] Input: ALPS - use function pointers for different - protocol handlers - -In anticipation of adding more ALPS protocols and more per-device quirks, -use function pointers instead of switch statements to call functions that -differ from one device to the next. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 101 +++++++++++++++++++++------------------------ - drivers/input/mouse/alps.h | 7 ++++ - 2 files changed, 54 insertions(+), 54 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index c11b47e..3cca3ef 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -114,6 +114,11 @@ static const struct alps_model_info alps_model_data[] = { - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1); -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1); -+ - /* - * XXX - this entry is suspicious. First byte has zero lower nibble, - * which is what a normal mouse would report. Also, the value 0x0e -@@ -695,24 +700,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - input_sync(dev); - } - --static void alps_process_packet(struct psmouse *psmouse) --{ -- struct alps_data *priv = psmouse->private; -- -- switch (priv->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- alps_process_packet_v1_v2(psmouse); -- break; -- case ALPS_PROTO_V3: -- alps_process_packet_v3(psmouse); -- break; -- case ALPS_PROTO_V4: -- alps_process_packet_v4(psmouse); -- break; -- } --} -- - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -771,7 +758,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - - /* Continue with the next packet */ - psmouse->packet[0] = psmouse->packet[6]; -@@ -815,6 +802,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - static void alps_flush_packet(unsigned long data) - { - struct psmouse *psmouse = (struct psmouse *)data; -+ struct alps_data *priv = psmouse->private; - - serio_pause_rx(psmouse->ps2dev.serio); - -@@ -833,7 +821,7 @@ static void alps_flush_packet(unsigned long data) - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5]); - } else { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - } - psmouse->pktcnt = 0; - } -@@ -878,7 +866,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - } - - if (psmouse->pktcnt == psmouse->pktsize) { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } - -@@ -1432,25 +1420,26 @@ error: - return -1; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static void alps_set_defaults(struct alps_data *priv) - { -- struct alps_data *priv = psmouse->private; -- int ret = -1; -- - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -- ret = alps_hw_init_v1_v2(psmouse); -+ priv->hw_init = alps_hw_init_v1_v2; -+ priv->process_packet = alps_process_packet_v1_v2; -+ priv->set_abs_params = alps_set_abs_params_st; - break; - case ALPS_PROTO_V3: -- ret = alps_hw_init_v3(psmouse); -+ priv->hw_init = alps_hw_init_v3; -+ priv->process_packet = alps_process_packet_v3; -+ priv->set_abs_params = alps_set_abs_params_mt; - break; - case ALPS_PROTO_V4: -- ret = alps_hw_init_v4(psmouse); -+ priv->hw_init = alps_hw_init_v4; -+ priv->process_packet = alps_process_packet_v4; -+ priv->set_abs_params = alps_set_abs_params_mt; - break; - } -- -- return ret; - } - - static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, -@@ -1467,6 +1456,8 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, - model->command_mode_resp == ec[2])) { - - priv->proto_version = model->proto_version; -+ alps_set_defaults(priv); -+ - priv->flags = model->flags; - priv->byte0 = model->byte0; - priv->mask0 = model->mask0; -@@ -1525,7 +1516,7 @@ static int alps_reconnect(struct psmouse *psmouse) - if (alps_identify(psmouse, priv) < 0) - return -1; - -- return alps_hw_init(psmouse); -+ return priv->hw_init(psmouse); - } - - static void alps_disconnect(struct psmouse *psmouse) -@@ -1538,6 +1529,29 @@ static void alps_disconnect(struct psmouse *psmouse) - kfree(priv); - } - -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+} -+ -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ -+ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+} -+ - int alps_init(struct psmouse *psmouse) - { - struct alps_data *priv; -@@ -1558,7 +1572,7 @@ int alps_init(struct psmouse *psmouse) - if (alps_identify(psmouse, priv) < 0) - goto init_fail; - -- if (alps_hw_init(psmouse)) -+ if (priv->hw_init(psmouse)) - goto init_fail; - - /* -@@ -1580,28 +1594,7 @@ int alps_init(struct psmouse *psmouse) - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - -- switch (priv->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -- break; -- case ALPS_PROTO_V3: -- case ALPS_PROTO_V4: -- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -- input_mt_init_slots(dev1, 2, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- -- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -- -- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- break; -- } -- -+ priv->set_abs_params(priv, dev1); - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (priv->flags & ALPS_WHEEL) { -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index a81b318..0934f8b 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -72,6 +72,9 @@ struct alps_nibble_commands { - * mask0, should match byte0. - * @mask0: The mask used to check the first byte of the report. - * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * @hw_init: Protocol-specific hardware init function. -+ * @process_packet: Protocol-specific function to process a report packet. -+ * @set_abs_params: Protocol-specific function to configure the input_dev. - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. - * @multi_data: Saved multi-packet data. -@@ -94,6 +97,10 @@ struct alps_data { - unsigned char byte0, mask0; - unsigned char flags; - -+ int (*hw_init)(struct psmouse *psmouse); -+ void (*process_packet)(struct psmouse *psmouse); -+ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); -+ - int prev_fin; - int multi_packet; - unsigned char multi_data[6]; --- -1.8.1.2 - - -From 9984c4d8611c9ecb4942349f1058b4ad1fcfb7c8 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:23:04 -0800 -Subject: [PATCH 07/15] Input: ALPS - move {addr,nibble}_command settings into - alps_set_defaults() - -This allows alps_identify() to override these settings based on the -device characteristics, if it is ever necessary. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 3cca3ef..22f5ef1 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -1192,14 +1192,10 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) - - static int alps_hw_init_v3(struct psmouse *psmouse) - { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; - -- priv->nibble_commands = alps_v3_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -- - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -@@ -1345,13 +1341,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) - - static int alps_hw_init_v4(struct psmouse *psmouse) - { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - -- priv->nibble_commands = alps_v4_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_DISABLE; -- - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -@@ -1433,11 +1425,15 @@ static void alps_set_defaults(struct alps_data *priv) - priv->hw_init = alps_hw_init_v3; - priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - break; - case ALPS_PROTO_V4: - priv->hw_init = alps_hw_init_v4; - priv->process_packet = alps_process_packet_v4; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; - break; - } - } --- -1.8.1.2 - - -From a8e2c2b0cc44c0ec2cb59a79c1a341f5608248cc Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:23:34 -0800 -Subject: [PATCH 08/15] Input: ALPS - rework detection of Pinnacle AGx - touchpads - -The official ALPS driver uses the EC report, not the E7 report, to detect -these devices. Also, they check for a range of values; the original -table-based code only checked for two specific ones. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 22f5ef1..f70a930 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -109,8 +109,6 @@ static const struct alps_model_info alps_model_data[] = { - { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ - { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - -@@ -1414,6 +1412,10 @@ error: - - static void alps_set_defaults(struct alps_data *priv) - { -+ priv->byte0 = 0x8f; -+ priv->mask0 = 0x8f; -+ priv->flags = ALPS_DUALPOINT; -+ - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -@@ -1493,8 +1495,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - alps_exit_command_mode(psmouse)) - return -EIO; - -- if (alps_match_table(psmouse, priv, e7, ec) == 0) -+ if (alps_match_table(psmouse, priv, e7, ec) == 0) { -+ return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x07 && -+ ec[2] >= 0x90 && ec[2] <= 0x9d) { -+ priv->proto_version = ALPS_PROTO_V3; -+ alps_set_defaults(priv); -+ - return 0; -+ } - - psmouse_info(psmouse, - "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", --- -1.8.1.2 - - -From a5f89d7393f5582efeb3e83bd4bc3eb146528371 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:24:22 -0800 -Subject: [PATCH 09/15] Input: ALPS - fix command mode check - -Pinnacle class devices should return "88 07 xx" or "88 08 xx" when -entering command mode. If either the first byte or the second byte is -invalid, return an error. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index f70a930..15c1eb5 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -985,7 +985,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - return -1; - } - -- if (param[0] != 0x88 && param[1] != 0x07) { -+ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { - psmouse_dbg(psmouse, - "unknown response while entering command mode\n"); - return -1; --- -1.8.1.2 - - -From 8b9993ec92c4ba02b2c155da6d5f5aa3502aa672 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:24:55 -0800 -Subject: [PATCH 10/15] Input: ALPS - move pixel and bitmap info into alps_data - struct - -Newer touchpads use different constants, so make them runtime- -configurable. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 47 ++++++++++++++++++++++++---------------------- - drivers/input/mouse/alps.h | 8 ++++++++ - 2 files changed, 33 insertions(+), 22 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 15c1eb5..9199d2d 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -27,12 +27,6 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ --#define ALPS_V3_X_MAX 2000 --#define ALPS_V3_Y_MAX 1400 -- --#define ALPS_BITMAP_X_BITS 15 --#define ALPS_BITMAP_Y_BITS 11 -- - #define ALPS_CMD_NIBBLE_10 0x01f2 - - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -269,7 +263,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - * These points are returned in x1, y1, x2, and y2 when the return value - * is greater than 0. - */ --static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+static int alps_process_bitmap(struct alps_data *priv, -+ unsigned int x_map, unsigned int y_map, - int *x1, int *y1, int *x2, int *y2) - { - struct alps_bitmap_point { -@@ -311,7 +306,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - * y bitmap is reversed for what we need (lower positions are in - * higher bits), so we process from the top end. - */ -- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); - prev_bit = 0; - point = &y_low; - for (i = 0; y_map != 0; i++, y_map <<= 1) { -@@ -357,16 +352,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - } - } - -- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - - if (fingers > 1) { -- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x2 = (priv->x_max * -+ (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y2 = (priv->y_max * -+ (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - } - - return fingers; -@@ -484,7 +481,8 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - ((packet[2] & 0x7f) << 1) | - (packet[4] & 0x01); - -- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ bmap_fingers = alps_process_bitmap(priv, -+ x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* -@@ -641,7 +639,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - ((priv->multi_data[3] & 0x1f) << 5) | - (priv->multi_data[1] & 0x1f); - -- fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* Store MT data.*/ -@@ -1416,6 +1414,11 @@ static void alps_set_defaults(struct alps_data *priv) - priv->mask0 = 0x8f; - priv->flags = ALPS_DUALPOINT; - -+ priv->x_max = 2000; -+ priv->y_max = 1400; -+ priv->x_bits = 15; -+ priv->y_bits = 11; -+ - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -@@ -1546,15 +1549,15 @@ static void alps_set_abs_params_mt(struct alps_data *priv, - { - set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); - input_mt_init_slots(dev1, 2, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); - - set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); - set_bit(BTN_TOOL_QUADTAP, dev1->keybit); - -- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); - } - - int alps_init(struct psmouse *psmouse) -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 0934f8b..5e638be 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -72,6 +72,10 @@ struct alps_nibble_commands { - * mask0, should match byte0. - * @mask0: The mask used to check the first byte of the report. - * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * @x_max: Largest possible X position value. -+ * @y_max: Largest possible Y position value. -+ * @x_bits: Number of X bits in the MT bitmap. -+ * @y_bits: Number of Y bits in the MT bitmap. - * @hw_init: Protocol-specific hardware init function. - * @process_packet: Protocol-specific function to process a report packet. - * @set_abs_params: Protocol-specific function to configure the input_dev. -@@ -96,6 +100,10 @@ struct alps_data { - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; -+ int x_max; -+ int y_max; -+ int x_bits; -+ int y_bits; - - int (*hw_init)(struct psmouse *psmouse); - void (*process_packet)(struct psmouse *psmouse); --- -1.8.1.2 - - -From 3e8674cc18aece18d3a9cdd484f157d44a5682b8 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:26:11 -0800 -Subject: [PATCH 11/15] Input: ALPS - make the V3 packet field decoder - "pluggable" - -A number of different ALPS touchpad protocols can reuse -alps_process_touchpad_packet_v3() with small tweaks to the bitfield -decoding. Create a new priv->decode_fields() callback that handles the -per-model differences. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 101 +++++++++++++++++++++++++-------------------- - drivers/input/mouse/alps.h | 38 +++++++++++++++++ - 2 files changed, 95 insertions(+), 44 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 9199d2d..7f0855e 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -447,17 +447,49 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - return; - } - -+static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) -+{ -+ f->left = !!(p[3] & 0x01); -+ f->right = !!(p[3] & 0x02); -+ f->middle = !!(p[3] & 0x04); -+ -+ f->ts_left = !!(p[3] & 0x10); -+ f->ts_right = !!(p[3] & 0x20); -+ f->ts_middle = !!(p[3] & 0x40); -+} -+ -+static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) -+{ -+ f->first_mp = !!(p[4] & 0x40); -+ f->is_mp = !!(p[0] & 0x40); -+ -+ f->fingers = (p[5] & 0x3) + 1; -+ f->x_map = ((p[4] & 0x7e) << 8) | -+ ((p[1] & 0x7f) << 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y_map = ((p[3] & 0x70) << 4) | -+ ((p[2] & 0x7f) << 1) | -+ (p[4] & 0x01); -+ -+ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); -+ f->z = p[5] & 0x7f; -+ -+ alps_decode_buttons_v3(f, p); -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + if ((psmouse->badbyte & 0xc8) == 0x08) { +@@ -1217,9 +1138,8 @@ static int alps_poll(struct psmouse *psmouse) + static int alps_hw_init_v1_v2(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; -- int x, y, z; -- int left, right, middle; - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - int fingers = 0, bmap_fingers; -- unsigned int x_bitmap, y_bitmap; -+ struct alps_fields f; -+ -+ priv->decode_fields(&f, packet); +- const struct alps_model_info *model = priv->i; - /* - * There's no single feature of touchpad position and bitmap packets -@@ -472,17 +504,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * packet. Check for this, and when it happens process the - * position packet as usual. - */ -- if (packet[0] & 0x40) { -- fingers = (packet[5] & 0x3) + 1; -- x_bitmap = ((packet[4] & 0x7e) << 8) | -- ((packet[1] & 0x7f) << 2) | -- ((packet[0] & 0x30) >> 4); -- y_bitmap = ((packet[3] & 0x70) << 4) | -- ((packet[2] & 0x7f) << 1) | -- (packet[4] & 0x01); -- -+ if (f.is_mp) { -+ fingers = f.fingers; - bmap_fingers = alps_process_bitmap(priv, -- x_bitmap, y_bitmap, -+ f.x_map, f.y_map, - &x1, &y1, &x2, &y2); - - /* -@@ -493,7 +518,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - fingers = bmap_fingers; - - /* Now process position packet */ -- packet = priv->multi_data; -+ priv->decode_fields(&f, priv->multi_data); - } else { - priv->multi_packet = 0; - } -@@ -507,10 +532,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * out misidentified bitmap packets, we reject anything with this - * bit set. - */ -- if (packet[0] & 0x40) -+ if (f.is_mp) - return; - -- if (!priv->multi_packet && (packet[4] & 0x40)) { -+ if (!priv->multi_packet && f.first_mp) { - priv->multi_packet = 1; - memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); - return; -@@ -518,22 +543,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - priv->multi_packet = 0; - -- left = packet[3] & 0x01; -- right = packet[3] & 0x02; -- middle = packet[3] & 0x04; -- -- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -- ((packet[0] & 0x30) >> 4); -- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -- z = packet[5] & 0x7f; -- - /* - * Sometimes the hardware sends a single packet with z = 0 - * in the middle of a stream. Real releases generate packets - * with x, y, and z all zero, so these seem to be flukes. - * Ignore them. - */ -- if (x && y && !z) -+ if (f.x && f.y && !f.z) - return; - - /* -@@ -541,12 +557,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * to rely on ST data. - */ - if (!fingers) { -- x1 = x; -- y1 = y; -- fingers = z > 0 ? 1 : 0; -+ x1 = f.x; -+ y1 = f.y; -+ fingers = f.z > 0 ? 1 : 0; +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } +@@ -1234,7 +1154,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) + return -1; } -- if (z >= 64) -+ if (f.z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); -@@ -555,26 +571,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - input_mt_report_finger_count(dev, fingers); - -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -+ input_report_key(dev, BTN_LEFT, f.left); -+ input_report_key(dev, BTN_RIGHT, f.right); -+ input_report_key(dev, BTN_MIDDLE, f.middle); - -- if (z > 0) { -- input_report_abs(dev, ABS_X, x); -- input_report_abs(dev, ABS_Y, y); -+ if (f.z > 0) { -+ input_report_abs(dev, ABS_X, f.x); -+ input_report_abs(dev, ABS_Y, f.y); +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, false)) { + return -1; } -- input_report_abs(dev, ABS_PRESSURE, z); -+ input_report_abs(dev, ABS_PRESSURE, f.z); - - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -- left = packet[3] & 0x10; -- right = packet[3] & 0x20; -- middle = packet[3] & 0x40; -- -- input_report_key(dev2, BTN_LEFT, left); -- input_report_key(dev2, BTN_RIGHT, right); -- input_report_key(dev2, BTN_MIDDLE, middle); -+ input_report_key(dev2, BTN_LEFT, f.ts_left); -+ input_report_key(dev2, BTN_RIGHT, f.ts_right); -+ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); - input_sync(dev2); - } - } -@@ -1430,6 +1442,7 @@ static void alps_set_defaults(struct alps_data *priv) - priv->hw_init = alps_hw_init_v3; - priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->decode_fields = alps_decode_pinnacle; - priv->nibble_commands = alps_v3_nibble_commands; - priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - break; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 5e638be..9704805 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -60,6 +60,42 @@ struct alps_nibble_commands { - }; - - /** -+ * struct alps_fields - decoded version of the report packet -+ * @x_map: Bitmap of active X positions for MT. -+ * @y_map: Bitmap of active Y positions for MT. -+ * @fingers: Number of fingers for MT. -+ * @x: X position for ST. -+ * @y: Y position for ST. -+ * @z: Z position for ST. -+ * @first_mp: Packet is the first of a multi-packet report. -+ * @is_mp: Packet is part of a multi-packet report. -+ * @left: Left touchpad button is active. -+ * @right: Right touchpad button is active. -+ * @middle: Middle touchpad button is active. -+ * @ts_left: Left trackstick button is active. -+ * @ts_right: Right trackstick button is active. -+ * @ts_middle: Middle trackstick button is active. -+ */ -+struct alps_fields { -+ unsigned int x_map; -+ unsigned int y_map; -+ unsigned int fingers; -+ unsigned int x; -+ unsigned int y; -+ unsigned int z; -+ unsigned int first_mp:1; -+ unsigned int is_mp:1; -+ -+ unsigned int left:1; -+ unsigned int right:1; -+ unsigned int middle:1; -+ -+ unsigned int ts_left:1; -+ unsigned int ts_right:1; -+ unsigned int ts_middle:1; -+}; -+ -+/** - * struct alps_data - private data structure for the ALPS driver - * @dev2: "Relative" device used to report trackstick or mouse activity. - * @phys: Physical path for the relative device. -@@ -78,6 +114,7 @@ struct alps_nibble_commands { - * @y_bits: Number of Y bits in the MT bitmap. - * @hw_init: Protocol-specific hardware init function. - * @process_packet: Protocol-specific function to process a report packet. -+ * @decode_fields: Protocol-specific function to read packet bitfields. - * @set_abs_params: Protocol-specific function to configure the input_dev. - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. -@@ -107,6 +144,7 @@ struct alps_data { - - int (*hw_init)(struct psmouse *psmouse); - void (*process_packet)(struct psmouse *psmouse); -+ void (*decode_fields)(struct alps_fields *f, unsigned char *p); - void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); - - int prev_fin; --- -1.8.1.2 - - -From 8852c5c13a191156db0f4d4428165f0dee9ce29e Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:27:08 -0800 -Subject: [PATCH 12/15] Input: ALPS - add support for "Rushmore" touchpads - -Rushmore touchpads are found on Dell E6230/E6430/E6530. They use the V3 -protocol with slightly tweaked init sequences and report formats. - -The E7 report is 73 03 0a, and the EC report is 88 08 1d - -Credits: Emmanuel Thome reported the MT bitmap changes. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 52 insertions(+) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 7f0855e..956c523 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -479,6 +479,14 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) - alps_decode_buttons_v3(f, p); - } - -+static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) -+{ -+ alps_decode_pinnacle(f, p); -+ -+ f->x_map |= (p[5] & 0x10) << 11; -+ f->y_map |= (p[5] & 0x20) << 6; -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -1331,6 +1339,40 @@ error: - return -1; - } - -+static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val, ret = -1; -+ -+ if (alps_enter_command_mode(psmouse, NULL) || -+ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || -+ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) -+ goto error; -+ -+ /* enter absolute mode */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); -+ -+error: -+ alps_exit_command_mode(psmouse); -+ return ret; -+} -+ - /* Must be in command mode when calling this function */ - static int alps_absolute_mode_v4(struct psmouse *psmouse) - { -@@ -1513,6 +1555,16 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - - if (alps_match_table(psmouse, priv, e7, ec) == 0) { - return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x08) { -+ priv->proto_version = ALPS_PROTO_V3; -+ alps_set_defaults(priv); -+ -+ priv->hw_init = alps_hw_init_rushmore_v3; -+ priv->decode_fields = alps_decode_rushmore; -+ priv->x_bits = 16; -+ priv->y_bits = 12; -+ -+ return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x07 && - ec[2] >= 0x90 && ec[2] <= 0x9d) { - priv->proto_version = ALPS_PROTO_V3; --- -1.8.1.2 - - -From dd22ae0f4aad37dc8371fe265e43a8426a3d4b1d Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:28:07 -0800 -Subject: [PATCH 13/15] Input: ALPS - enable trackstick on Rushmore touchpads - -Separate out the common trackstick probe/setup sequences, then call them -from each of the v3 init functions. - -Credits: Emmanual Thome furnished the information on the trackstick init -and how it affected the report format. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 185 ++++++++++++++++++++++++++++----------------- - 1 file changed, 115 insertions(+), 70 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 956c523..618ae44 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -29,6 +29,9 @@ - */ - #define ALPS_CMD_NIBBLE_10 0x01f2 - -+#define ALPS_REG_BASE_RUSHMORE 0xc2c0 -+#define ALPS_REG_BASE_PINNACLE 0x0000 -+ - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { - { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ - { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -@@ -1168,26 +1171,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) +@@ -1249,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) } /* @@ -2029,16 +694,20 @@ index 956c523..618ae44 100644 } /* Must be in command mode when calling this function */ -@@ -1206,69 +1214,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) +@@ -1287,73 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) return 0; } -static int alps_hw_init_v3(struct psmouse *psmouse) +static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) { +- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; +- +- priv->nibble_commands = alps_v3_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + int ret = -EIO, reg_val; if (alps_enter_command_mode(psmouse, NULL)) @@ -2181,7 +850,7 @@ index 956c523..618ae44 100644 psmouse_err(psmouse, "Failed to enter absolute mode\n"); goto error; } -@@ -1305,14 +1346,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) +@@ -1390,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) goto error; @@ -2196,7 +865,7 @@ index 956c523..618ae44 100644 alps_exit_command_mode(psmouse); /* Set rate and enable data reporting */ -@@ -1325,10 +1358,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) +@@ -1410,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) return 0; @@ -2207,14 +876,16 @@ index 956c523..618ae44 100644 error: /* * Leaving the touchpad in command mode will essentially render -@@ -1341,9 +1370,19 @@ error: +@@ -1424,6 +1366,50 @@ error: + return -1; + } - static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) - { ++static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) ++{ + struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val, ret = -1; - ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val, ret = -1; ++ + if (priv->flags & ALPS_DUALPOINT) { + reg_val = alps_setup_trackstick_v3(psmouse, + ALPS_REG_BASE_RUSHMORE); @@ -2224,271 +895,511 @@ index 956c523..618ae44 100644 + priv->flags &= ~ALPS_DUALPOINT; + } + - if (alps_enter_command_mode(psmouse, NULL) || - alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || - alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) -@@ -1564,6 +1603,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - priv->x_bits = 16; - priv->y_bits = 12; ++ if (alps_enter_command_mode(psmouse, NULL) || ++ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || ++ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) ++ goto error; ++ ++ /* enter absolute mode */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); ++ ++error: ++ alps_exit_command_mode(psmouse); ++ return ret; ++} ++ + /* Must be in command mode when calling this function */ + static int alps_absolute_mode_v4(struct psmouse *psmouse) + { +@@ -1442,13 +1428,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) + static int alps_hw_init_v4(struct psmouse *psmouse) + { +- struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + +- priv->nibble_commands = alps_v4_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_DISABLE; +- + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +@@ -1517,39 +1499,140 @@ error: + return -1; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static void alps_set_defaults(struct alps_data *priv) + { +- struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; +- int ret = -1; ++ priv->byte0 = 0x8f; ++ priv->mask0 = 0x8f; ++ priv->flags = ALPS_DUALPOINT; ++ ++ priv->x_max = 2000; ++ priv->y_max = 1400; ++ priv->x_bits = 15; ++ priv->y_bits = 11; + +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +- ret = alps_hw_init_v1_v2(psmouse); ++ priv->hw_init = alps_hw_init_v1_v2; ++ priv->process_packet = alps_process_packet_v1_v2; ++ priv->set_abs_params = alps_set_abs_params_st; + break; + case ALPS_PROTO_V3: +- ret = alps_hw_init_v3(psmouse); ++ priv->hw_init = alps_hw_init_v3; ++ priv->process_packet = alps_process_packet_v3; ++ priv->set_abs_params = alps_set_abs_params_mt; ++ priv->decode_fields = alps_decode_pinnacle; ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + break; + case ALPS_PROTO_V4: +- ret = alps_hw_init_v4(psmouse); ++ priv->hw_init = alps_hw_init_v4; ++ priv->process_packet = alps_process_packet_v4; ++ priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; + break; + } ++} + +- return ret; ++static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, ++ unsigned char *e7, unsigned char *ec) ++{ ++ const struct alps_model_info *model; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ model = &alps_model_data[i]; ++ ++ if (!memcmp(e7, model->signature, sizeof(model->signature)) && ++ (!model->command_mode_resp || ++ model->command_mode_resp == ec[2])) { ++ ++ priv->proto_version = model->proto_version; ++ alps_set_defaults(priv); ++ ++ priv->flags = model->flags; ++ priv->byte0 = model->byte0; ++ priv->mask0 = model->mask0; ++ ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ++{ ++ unsigned char e6[4], e7[4], ec[4]; ++ ++ /* ++ * First try "E6 report". ++ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. ++ * The bits 0-2 of the first byte will be 1s if some buttons are ++ * pressed. ++ */ ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE11, e6)) ++ return -EIO; ++ ++ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) ++ return -EINVAL; ++ ++ /* ++ * Now get the "E7" and "EC" reports. These will uniquely identify ++ * most ALPS touchpads. ++ */ ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE21, e7) || ++ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_RESET_WRAP, ec) || ++ alps_exit_command_mode(psmouse)) ++ return -EIO; ++ ++ if (alps_match_table(psmouse, priv, e7, ec) == 0) { ++ return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x08) { ++ priv->proto_version = ALPS_PROTO_V3; ++ alps_set_defaults(priv); ++ ++ priv->hw_init = alps_hw_init_rushmore_v3; ++ priv->decode_fields = alps_decode_rushmore; ++ priv->x_bits = 16; ++ priv->y_bits = 12; ++ + /* hack to make addr_command, nibble_command available */ + psmouse->private = priv; + + if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) + priv->flags &= ~ALPS_DUALPOINT; + - return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x07 && - ec[2] >= 0x90 && ec[2] <= 0x9d) { --- -1.8.1.2 - - -From 1c89f1435ea5344dc2dbb5c59f56b2d12d852fdc Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Sat, 16 Feb 2013 22:40:03 -0800 -Subject: [PATCH 14/15] Input: ALPS - Remove unused argument to - alps_enter_command_mode() - -Now that alps_identify() explicitly issues an EC report using -alps_rpt_cmd(), we no longer need to look at the magic numbers returned -by alps_enter_command_mode(). - -Signed-off-by: Kevin Cernekee ---- - drivers/input/mouse/alps.c | 18 +++++++----------- - 1 file changed, 7 insertions(+), 11 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 618ae44..8e01c31 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -996,8 +996,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, - return 0; - } - --static int alps_enter_command_mode(struct psmouse *psmouse, -- unsigned char *resp) -+static int alps_enter_command_mode(struct psmouse *psmouse) - { - unsigned char param[4]; - -@@ -1011,9 +1010,6 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - "unknown response while entering command mode\n"); - return -1; - } -- -- if (resp) -- *resp = param[2]; - return 0; - } - -@@ -1178,7 +1174,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, - { - int reg_val, ret = -1; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - return -1; - - reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); -@@ -1218,7 +1214,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) - { - int ret = -EIO, reg_val; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - goto error; - - reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); -@@ -1281,7 +1277,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) - * supported by this driver. If bit 1 isn't set the packet - * format is different. - */ -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_command_mode_write_reg(psmouse, - reg_base + 0x08, 0x82) || - alps_exit_command_mode(psmouse)) -@@ -1308,7 +1304,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) - goto error; - -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_absolute_mode_v3(psmouse)) { - psmouse_err(psmouse, "Failed to enter absolute mode\n"); - goto error; -@@ -1383,7 +1379,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) - priv->flags &= ~ALPS_DUALPOINT; - } - -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || - alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) - goto error; -@@ -1433,7 +1429,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - goto error; - - if (alps_absolute_mode_v4(psmouse)) { --- -1.8.1.2 - - -From 35458ea14080b1d529ecee4c01dabc91e8ff9f25 Mon Sep 17 00:00:00 2001 -From: Dave Turvene -Date: Sat, 16 Feb 2013 22:40:04 -0800 -Subject: [PATCH 15/15] Input: ALPS - Add "Dolphin V1" touchpad support - -These touchpads use a different protocol; they have been seen on Dell -N5110, Dell 17R SE, and others. - -The official ALPS driver identifies them by looking for an exact match -on the E7 report: 73 03 50. Dolphin V1 returns an EC report of -73 01 xx (02 and 0d have been seen); Dolphin V2 returns an EC report of -73 02 xx (02 has been seen). - -Dolphin V2 probably needs a different initialization sequence and/or -report parser, so it is left for a future commit. - -Signed-off-by: Dave Turvene -Signed-off-by: Kevin Cernekee ---- - drivers/input/mouse/alps.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/alps.h | 1 + - 2 files changed, 66 insertions(+), 2 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 8e01c31..b7abd40 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) - f->y_map |= (p[5] & 0x20) << 6; - } - -+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) -+{ -+ f->first_mp = !!(p[0] & 0x02); -+ f->is_mp = !!(p[0] & 0x20); -+ -+ f->fingers = ((p[0] & 0x6) >> 1 | -+ (p[0] & 0x10) >> 2); -+ f->x_map = ((p[2] & 0x60) >> 5) | -+ ((p[4] & 0x7f) << 2) | -+ ((p[5] & 0x7f) << 9) | -+ ((p[3] & 0x07) << 16) | -+ ((p[3] & 0x70) << 15) | -+ ((p[0] & 0x01) << 22); -+ f->y_map = (p[1] & 0x7f) | -+ ((p[2] & 0x1f) << 7); -+ -+ f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); -+ f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); -+ f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; -+ -+ alps_decode_buttons_v3(f, p); -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -876,7 +899,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - } - - /* Bytes 2 - pktsize should have 0 in the highest bit */ -- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && -+ if (priv->proto_version != ALPS_PROTO_V5 && -+ psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, -@@ -1005,7 +1029,8 @@ static int alps_enter_command_mode(struct psmouse *psmouse) - return -1; - } - -- if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { -+ if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && -+ param[0] != 0x73) { - psmouse_dbg(psmouse, - "unknown response while entering command mode\n"); - return -1; -@@ -1497,6 +1522,23 @@ error: - return -1; - } - -+static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[2]; -+ -+ /* This is dolphin "v1" as empirically defined by florin9doi */ -+ param[0] = 0x64; -+ param[1] = 0x28; -+ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || -+ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) -+ return -1; -+ -+ return 0; -+} -+ - static void alps_set_defaults(struct alps_data *priv) - { - priv->byte0 = 0x8f; -@@ -1530,6 +1572,21 @@ static void alps_set_defaults(struct alps_data *priv) - priv->nibble_commands = alps_v4_nibble_commands; - priv->addr_command = PSMOUSE_CMD_DISABLE; - break; -+ case ALPS_PROTO_V5: -+ priv->hw_init = alps_hw_init_dolphin_v1; -+ priv->process_packet = alps_process_packet_v3; -+ priv->decode_fields = alps_decode_dolphin; -+ priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -+ priv->byte0 = 0xc8; -+ priv->mask0 = 0xc8; -+ priv->flags = 0; -+ priv->x_max = 1360; -+ priv->y_max = 660; -+ priv->x_bits = 23; -+ priv->y_bits = 12; -+ break; - } - } - -@@ -1590,6 +1647,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - - if (alps_match_table(psmouse, priv, e7, ec) == 0) { - return 0; -+ } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && -+ ec[0] == 0x73 && ec[1] == 0x01) { -+ priv->proto_version = ALPS_PROTO_V5; ++ return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x07 && ++ ec[2] >= 0x90 && ec[2] <= 0x9d) { ++ priv->proto_version = ALPS_PROTO_V3; + alps_set_defaults(priv); + + return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x08) { - priv->proto_version = ALPS_PROTO_V3; - alps_set_defaults(priv); ++ } ++ ++ psmouse_info(psmouse, ++ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", ++ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); ++ ++ return -EINVAL; + } + + static int alps_reconnect(struct psmouse *psmouse) + { +- const struct alps_model_info *model; ++ struct alps_data *priv = psmouse->private; + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, NULL); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) + return -1; + +- return alps_hw_init(psmouse); ++ return priv->hw_init(psmouse); + } + + static void alps_disconnect(struct psmouse *psmouse) +@@ -1562,12 +1645,33 @@ static void alps_disconnect(struct psmouse *psmouse) + kfree(priv); + } + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++} ++ ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ ++ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); ++} ++ + int alps_init(struct psmouse *psmouse) + { + struct alps_data *priv; +- const struct alps_model_info *model; + struct input_dev *dev1 = psmouse->dev, *dev2; +- int version; + + priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + dev2 = input_allocate_device(); +@@ -1581,13 +1685,10 @@ int alps_init(struct psmouse *psmouse) + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) + goto init_fail; + +- priv->i = model; +- +- if (alps_hw_init(psmouse)) ++ if (priv->hw_init(psmouse)) + goto init_fail; + + /* +@@ -1609,41 +1710,20 @@ int alps_init(struct psmouse *psmouse) + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); + +- switch (model->proto_version) { +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); +- break; +- case ALPS_PROTO_V3: +- case ALPS_PROTO_V4: +- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); +- input_mt_init_slots(dev1, 2, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- +- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); +- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); +- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); +- +- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- break; +- } +- ++ priv->set_abs_params(priv, dev1); + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + +- if (model->flags & ALPS_WHEEL) { ++ if (priv->flags & ALPS_WHEEL) { + dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); + dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); + } + +- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { ++ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); + dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); + } + +- if (model->flags & ALPS_FOUR_BUTTONS) { ++ if (priv->flags & ALPS_FOUR_BUTTONS) { + dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); + dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); + dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); +@@ -1654,7 +1734,8 @@ int alps_init(struct psmouse *psmouse) + + snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); + dev2->phys = priv->phys; +- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; ++ dev2->name = (priv->flags & ALPS_DUALPOINT) ? ++ "DualPoint Stick" : "PS/2 Mouse"; + dev2->id.bustype = BUS_I8042; + dev2->id.vendor = 0x0002; + dev2->id.product = PSMOUSE_ALPS; +@@ -1673,7 +1754,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; ++ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +@@ -1690,18 +1771,16 @@ init_fail: + + int alps_detect(struct psmouse *psmouse, bool set_properties) + { +- int version; +- const struct alps_model_info *model; ++ struct alps_data dummy; + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, &dummy) < 0) + return -1; + + if (set_properties) { + psmouse->vendor = "ALPS"; +- psmouse->name = model->flags & ALPS_DUALPOINT ? ++ psmouse->name = dummy.flags & ALPS_DUALPOINT ? + "DualPoint TouchPad" : "GlidePoint"; +- psmouse->model = version; ++ psmouse->model = dummy.proto_version << 8; + } + return 0; + } diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 9704805..eee5985 100644 +index ae1ac35..9704805 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h -@@ -16,6 +16,7 @@ - #define ALPS_PROTO_V2 2 - #define ALPS_PROTO_V3 3 - #define ALPS_PROTO_V4 4 -+#define ALPS_PROTO_V5 5 +@@ -12,35 +12,146 @@ + #ifndef _ALPS_H + #define _ALPS_H - /** - * struct alps_model_info - touchpad ID table --- -1.8.1.2 - +-#define ALPS_PROTO_V1 0 +-#define ALPS_PROTO_V2 1 +-#define ALPS_PROTO_V3 2 +-#define ALPS_PROTO_V4 3 ++#define ALPS_PROTO_V1 1 ++#define ALPS_PROTO_V2 2 ++#define ALPS_PROTO_V3 3 ++#define ALPS_PROTO_V4 4 + ++/** ++ * struct alps_model_info - touchpad ID table ++ * @signature: E7 response string to match. ++ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response ++ * (aka command mode response) identifies the firmware minor version. This ++ * can be used to distinguish different hardware models which are not ++ * uniquely identifiable through their E7 responses. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * ++ * Many (but not all) ALPS touchpads can be identified by looking at the ++ * values returned in the "E7 report" and/or the "EC report." This table ++ * lists a number of such touchpads. ++ */ + struct alps_model_info { +- unsigned char signature[3]; +- unsigned char command_mode_resp; /* v3/v4 only */ ++ unsigned char signature[3]; ++ unsigned char command_mode_resp; + unsigned char proto_version; +- unsigned char byte0, mask0; +- unsigned char flags; ++ unsigned char byte0, mask0; ++ unsigned char flags; + }; + ++/** ++ * struct alps_nibble_commands - encodings for register accesses ++ * @command: PS/2 command used for the nibble ++ * @data: Data supplied as an argument to the PS/2 command, if applicable ++ * ++ * The ALPS protocol uses magic sequences to transmit binary data to the ++ * touchpad, as it is generally not OK to send arbitrary bytes out the ++ * PS/2 port. Each of the sequences in this table sends one nibble of the ++ * register address or (write) data. Different versions of the ALPS protocol ++ * use slightly different encodings. ++ */ + struct alps_nibble_commands { + int command; + unsigned char data; + }; + ++/** ++ * struct alps_fields - decoded version of the report packet ++ * @x_map: Bitmap of active X positions for MT. ++ * @y_map: Bitmap of active Y positions for MT. ++ * @fingers: Number of fingers for MT. ++ * @x: X position for ST. ++ * @y: Y position for ST. ++ * @z: Z position for ST. ++ * @first_mp: Packet is the first of a multi-packet report. ++ * @is_mp: Packet is part of a multi-packet report. ++ * @left: Left touchpad button is active. ++ * @right: Right touchpad button is active. ++ * @middle: Middle touchpad button is active. ++ * @ts_left: Left trackstick button is active. ++ * @ts_right: Right trackstick button is active. ++ * @ts_middle: Middle trackstick button is active. ++ */ ++struct alps_fields { ++ unsigned int x_map; ++ unsigned int y_map; ++ unsigned int fingers; ++ unsigned int x; ++ unsigned int y; ++ unsigned int z; ++ unsigned int first_mp:1; ++ unsigned int is_mp:1; ++ ++ unsigned int left:1; ++ unsigned int right:1; ++ unsigned int middle:1; ++ ++ unsigned int ts_left:1; ++ unsigned int ts_right:1; ++ unsigned int ts_middle:1; ++}; ++ ++/** ++ * struct alps_data - private data structure for the ALPS driver ++ * @dev2: "Relative" device used to report trackstick or mouse activity. ++ * @phys: Physical path for the relative device. ++ * @nibble_commands: Command mapping used for touchpad register accesses. ++ * @addr_command: Command used to tell the touchpad that a register address ++ * follows. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * @x_max: Largest possible X position value. ++ * @y_max: Largest possible Y position value. ++ * @x_bits: Number of X bits in the MT bitmap. ++ * @y_bits: Number of Y bits in the MT bitmap. ++ * @hw_init: Protocol-specific hardware init function. ++ * @process_packet: Protocol-specific function to process a report packet. ++ * @decode_fields: Protocol-specific function to read packet bitfields. ++ * @set_abs_params: Protocol-specific function to configure the input_dev. ++ * @prev_fin: Finger bit from previous packet. ++ * @multi_packet: Multi-packet data in progress. ++ * @multi_data: Saved multi-packet data. ++ * @x1: First X coordinate from last MT report. ++ * @x2: Second X coordinate from last MT report. ++ * @y1: First Y coordinate from last MT report. ++ * @y2: Second Y coordinate from last MT report. ++ * @fingers: Number of fingers from last MT report. ++ * @quirks: Bitmap of ALPS_QUIRK_*. ++ * @timer: Timer for flushing out the final report packet in the stream. ++ */ + struct alps_data { +- struct input_dev *dev2; /* Relative device */ +- char phys[32]; /* Phys */ +- const struct alps_model_info *i;/* Info */ ++ struct input_dev *dev2; ++ char phys[32]; ++ ++ /* these are autodetected when the device is identified */ + const struct alps_nibble_commands *nibble_commands; +- int addr_command; /* Command to set register address */ +- int prev_fin; /* Finger bit from previous packet */ +- int multi_packet; /* Multi-packet data in progress */ +- unsigned char multi_data[6]; /* Saved multi-packet data */ +- int x1, x2, y1, y2; /* Coordinates from last MT report */ +- int fingers; /* Number of fingers from MT report */ ++ int addr_command; ++ unsigned char proto_version; ++ unsigned char byte0, mask0; ++ unsigned char flags; ++ int x_max; ++ int y_max; ++ int x_bits; ++ int y_bits; ++ ++ int (*hw_init)(struct psmouse *psmouse); ++ void (*process_packet)(struct psmouse *psmouse); ++ void (*decode_fields)(struct alps_fields *f, unsigned char *p); ++ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); ++ ++ int prev_fin; ++ int multi_packet; ++ unsigned char multi_data[6]; ++ int x1, x2, y1, y2; ++ int fingers; + u8 quirks; + struct timer_list timer; + }; diff --git a/kernel.spec b/kernel.spec index 2147b9ce3..6ab0b20a0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,7 +789,7 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch Patch22263: tmpfs-fix-use-after-free-of-mempolicy-object.patch #rhbz 812111 -Patch24000: alps-v2-3.7.patch +Patch24000: alps.patch #rhbz 892060 Patch24001: ipv6-dst-from-ptr-race.patch @@ -1505,7 +1505,7 @@ ApplyPatch ath9k_rx_dma_stop_check.patch ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch #rhbz 812111 -#ApplyPatch alps-v2-3.7.patch +ApplyPatch alps.patch #rhbz 892060 ApplyPatch ipv6-dst-from-ptr-race.patch @@ -2392,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Wed Feb 27 2013 Dave Jones +- Update ALPS patch to what got merged in 3.9-rc + * Wed Feb 27 2013 Dave Jones - 3.8.0 Dropped (merged in 3.8) @@ -2413,11 +2416,9 @@ fi - arm-tegra-nvec-kconfig.patch - arm-tegra-sdhci-module-fix.patch Needs reworking: - - alps-v2-3.7.patch - usb-cypress-supertop.patch - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch - - userns-avoid-recursion-in-put_user_ns.patch * Tue Feb 26 2013 Justin M. Forbes - Avoid recursion in put_user_ns, potential overflow From 1d266453e38f2dc1ae529e67c94ccbf3e9239f2b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 12:45:37 -0500 Subject: [PATCH 204/492] Update usb-cypress-supertop.patch --- kernel.spec | 6 ++++-- usb-cypress-supertop.patch | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index 6ab0b20a0..c4870e2af 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1496,7 +1496,7 @@ ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch ApplyPatch ath9k_rx_dma_stop_check.patch #rhbz 909591 -#ApplyPatch usb-cypress-supertop.patch +ApplyPatch usb-cypress-supertop.patch #rhbz 844750 #ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch @@ -2392,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 28 2013 Dave Jones +- Update usb-cypress-supertop.patch + * Wed Feb 27 2013 Dave Jones - Update ALPS patch to what got merged in 3.9-rc @@ -2416,7 +2419,6 @@ fi - arm-tegra-nvec-kconfig.patch - arm-tegra-sdhci-module-fix.patch Needs reworking: - - usb-cypress-supertop.patch - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch diff --git a/usb-cypress-supertop.patch b/usb-cypress-supertop.patch index 3887dc59c..37c89b8b8 100644 --- a/usb-cypress-supertop.patch +++ b/usb-cypress-supertop.patch @@ -24,7 +24,7 @@ diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual index 2c85530..65a6a75 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h -@@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, +@@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), @@ -33,6 +33,3 @@ index 2c85530..65a6a75 100644 "Super Top", "USB 2.0 SATA BRIDGE", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), --- -1.8.1.2 - From d08ec557c7cba330b777b877fafbc699fd00a377 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 12:47:07 -0500 Subject: [PATCH 205/492] already applied --- ...upport-for-Foxconn-Hon-Hai-0489-e056.patch | 56 ------------------- kernel.spec | 8 +-- 2 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch diff --git a/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch b/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch deleted file mode 100644 index 322a3c262..000000000 --- a/Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch +++ /dev/null @@ -1,56 +0,0 @@ -From a5b6b6d3574e57559ec44865f48022cd116dd669 Mon Sep 17 00:00:00 2001 -From: AceLan Kao -Date: Thu, 3 Jan 2013 12:25:00 +0800 -Subject: [PATCH] Bluetooth: Add support for Foxconn / Hon Hai [0489:e056] - -Add support for the AR9462 chip - -T: Bus=01 Lev=02 Prnt=02 Port=05 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 -D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=0489 ProdID=e056 Rev=00.01 -C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA -I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb -I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb - -Signed-off-by: AceLan Kao -Signed-off-by: Gustavo Padovan ---- - drivers/bluetooth/ath3k.c | 2 ++ - drivers/bluetooth/btusb.c | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index b00000e..b86ea45 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -81,6 +81,7 @@ static struct usb_device_id ath3k_table[] = { - { USB_DEVICE(0x0CF3, 0xE004) }, - { USB_DEVICE(0x0930, 0x0219) }, - { USB_DEVICE(0x0489, 0xe057) }, -+ { USB_DEVICE(0x0489, 0xe056) }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xE02C) }, -@@ -108,6 +109,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, - - /* Atheros AR5BBU22 with sflash firmware */ - { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index a1d4ede..c76030e 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -139,6 +139,7 @@ static struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, --- -1.8.1.2 - diff --git a/kernel.spec b/kernel.spec index c4870e2af..5294a1b86 100644 --- a/kernel.spec +++ b/kernel.spec @@ -773,9 +773,6 @@ Patch22257: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #rhbz 906055 Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch -#rhbz 879408 -Patch22259: Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch - #CVE-2013-1763 rhbz 915052,915057 Patch22260: sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch @@ -1510,9 +1507,6 @@ ApplyPatch alps.patch #rhbz 892060 ApplyPatch ipv6-dst-from-ptr-race.patch -#rhbz 879408 -#ApplyPatch Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch - #CVE-2013-1763 rhbz 915052,915057 ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch @@ -2415,11 +2409,11 @@ fi - brcmsmac-updates-rhbz892428.patch - silence-brcmsmac-warning.patch - net-fix-infinite-loop-in-__skb_recv_datagram.patch + - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch Needs checking: - arm-tegra-nvec-kconfig.patch - arm-tegra-sdhci-module-fix.patch Needs reworking: - - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch * Tue Feb 26 2013 Justin M. Forbes From dca57f8f98c3f9af3c9069f4dd82833d5f56c856 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 12:48:06 -0500 Subject: [PATCH 206/492] already applied --- ...pport-for-atheros-04ca-3004-device-t.patch | 47 ------------------- kernel.spec | 9 +--- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch diff --git a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch deleted file mode 100644 index cfa1710de..000000000 --- a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 95e9fe367b98a8f4f3c7538fc40a4f94d7f5e35f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 18 Feb 2013 10:32:13 -0500 -Subject: [PATCH] bluetooth: Add support for atheros 04ca:3004 device to ath3k - -Yet another version of the atheros bluetooth chipset - -Reported-by: niktr@mail.ru -Signed-off-by: Josh Boyer ---- - drivers/bluetooth/ath3k.c | 2 ++ - drivers/bluetooth/btusb.c | 1 + - 2 files changed, 3 insertions(+) - - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index b00000e..284658c 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = { - { USB_DEVICE(0x0CF3, 0x3004) }, - { USB_DEVICE(0x0CF3, 0x311D) }, - { USB_DEVICE(0x13d3, 0x3375) }, -+ { USB_DEVICE(0x04CA, 0x3004) }, - { USB_DEVICE(0x04CA, 0x3005) }, - { USB_DEVICE(0x13d3, 0x3362) }, - { USB_DEVICE(0x0CF3, 0xE004) }, -@@ -103,6 +104,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index a1d4ede..fa59179 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, diff --git a/kernel.spec b/kernel.spec index 5294a1b86..d827021dd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -767,9 +767,6 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 909591 Patch22255: usb-cypress-supertop.patch -#rhbz 844750 -Patch22257: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch - #rhbz 906055 Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch @@ -1495,9 +1492,6 @@ ApplyPatch ath9k_rx_dma_stop_check.patch #rhbz 909591 ApplyPatch usb-cypress-supertop.patch -#rhbz 844750 -#ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch - #rhbz 906055 ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch @@ -2410,11 +2404,10 @@ fi - silence-brcmsmac-warning.patch - net-fix-infinite-loop-in-__skb_recv_datagram.patch - Bluetooth-Add-support-for-Foxconn-Hon-Hai-0489-e056.patch + - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch Needs checking: - arm-tegra-nvec-kconfig.patch - arm-tegra-sdhci-module-fix.patch - Needs reworking: - - 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch * Tue Feb 26 2013 Justin M. Forbes - Avoid recursion in put_user_ns, potential overflow From 42cc12eb2a8084a87a649c1d41c240cbacd41aea Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:04:11 -0500 Subject: [PATCH 207/492] 3.8.1 --- drm-i915-lvds-reclock-fix.patch | 72 ---------- ipv6-dst-from-ptr-race.patch | 134 ------------------ kernel.spec | 45 ++---- ...period-symbol_conf.field_sep-display.patch | 48 ------- ...-bounds-access-to-sock_diag_handlers.patch | 86 ----------- sources | 1 + usb-cypress-supertop.patch | 35 ----- 7 files changed, 12 insertions(+), 409 deletions(-) delete mode 100644 drm-i915-lvds-reclock-fix.patch delete mode 100644 ipv6-dst-from-ptr-race.patch delete mode 100644 perf-hists-Fix-period-symbol_conf.field_sep-display.patch delete mode 100644 sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch delete mode 100644 usb-cypress-supertop.patch diff --git a/drm-i915-lvds-reclock-fix.patch b/drm-i915-lvds-reclock-fix.patch deleted file mode 100644 index 28b7d6731..000000000 --- a/drm-i915-lvds-reclock-fix.patch +++ /dev/null @@ -1,72 +0,0 @@ -Origin: - -http://cgit.freedesktop.org/~danvet/drm-intel/commit/?h=drm-intel-next&id=725a5b54028916cd2511a251c5b5b13d1715addc - -Rediffed for 3.7.x, and any bugs introduced, by ajax - -diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c ---- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c.jx 2013-02-14 12:40:21.068832043 -0500 -+++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/i915_gem.c 2013-02-14 12:41:16.645147300 -0500 -@@ -1919,9 +1919,6 @@ i915_gem_object_move_to_inactive(struct - BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS); - BUG_ON(!obj->active); - -- if (obj->pin_count) /* are we a framebuffer? */ -- intel_mark_fb_idle(obj); -- - list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); - - list_del_init(&obj->ring_list); -diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c ---- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c.jx 2013-02-14 12:40:22.022854621 -0500 -+++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_display.c 2013-02-14 12:41:16.648147371 -0500 -@@ -6094,11 +6094,6 @@ void intel_mark_busy(struct drm_device * - - void intel_mark_idle(struct drm_device *dev) - { --} -- --void intel_mark_fb_busy(struct drm_i915_gem_object *obj) --{ -- struct drm_device *dev = obj->base.dev; - struct drm_crtc *crtc; - - if (!i915_powersave) -@@ -6108,12 +6103,11 @@ void intel_mark_fb_busy(struct drm_i915_ - if (!crtc->fb) - continue; - -- if (to_intel_framebuffer(crtc->fb)->obj == obj) -- intel_increase_pllclock(crtc); -+ intel_decrease_pllclock(crtc); - } - } - --void intel_mark_fb_idle(struct drm_i915_gem_object *obj) -+void intel_mark_fb_busy(struct drm_i915_gem_object *obj) - { - struct drm_device *dev = obj->base.dev; - struct drm_crtc *crtc; -@@ -6126,7 +6120,7 @@ void intel_mark_fb_idle(struct drm_i915_ - continue; - - if (to_intel_framebuffer(crtc->fb)->obj == obj) -- intel_decrease_pllclock(crtc); -+ intel_increase_pllclock(crtc); - } - } - -diff -up linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h.jx linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h ---- linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h.jx 2013-02-14 12:40:21.071832114 -0500 -+++ linux-3.7.7-202.fc18.x86_64/drivers/gpu/drm/i915/intel_drv.h 2013-02-14 12:41:16.648147371 -0500 -@@ -417,9 +417,8 @@ extern bool intel_sdvo_init(struct drm_d - extern void intel_dvo_init(struct drm_device *dev); - extern void intel_tv_init(struct drm_device *dev); - extern void intel_mark_busy(struct drm_device *dev); --extern void intel_mark_idle(struct drm_device *dev); - extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj); --extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj); -+extern void intel_mark_idle(struct drm_device *dev); - extern bool intel_lvds_init(struct drm_device *dev); - extern void intel_dp_init(struct drm_device *dev, int output_reg, - enum port port); diff --git a/ipv6-dst-from-ptr-race.patch b/ipv6-dst-from-ptr-race.patch deleted file mode 100644 index d1cab3230..000000000 --- a/ipv6-dst-from-ptr-race.patch +++ /dev/null @@ -1,134 +0,0 @@ -diff -up ./include/net/dst.h.orig ./include/net/dst.h ---- ./include/net/dst.h.orig 2012-12-10 22:30:57.000000000 -0500 -+++ ./include/net/dst.h 2013-02-20 09:42:49.541777989 -0500 -@@ -36,13 +36,9 @@ struct dst_entry { - struct net_device *dev; - struct dst_ops *ops; - unsigned long _metrics; -- union { -- unsigned long expires; -- /* point to where the dst_entry copied from */ -- struct dst_entry *from; -- }; -+ unsigned long expires; - struct dst_entry *path; -- void *__pad0; -+ struct dst_entry *from; - #ifdef CONFIG_XFRM - struct xfrm_state *xfrm; - #else -diff -up ./include/net/ip6_fib.h.orig ./include/net/ip6_fib.h ---- ./include/net/ip6_fib.h.orig 2012-12-10 22:30:57.000000000 -0500 -+++ ./include/net/ip6_fib.h 2013-02-20 09:42:49.597779552 -0500 -@@ -157,50 +157,35 @@ static inline struct inet6_dev *ip6_dst_ - - static inline void rt6_clean_expires(struct rt6_info *rt) - { -- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) -- dst_release(rt->dst.from); -- - rt->rt6i_flags &= ~RTF_EXPIRES; -- rt->dst.from = NULL; - } - - static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) - { -- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) -- dst_release(rt->dst.from); -- -- rt->rt6i_flags |= RTF_EXPIRES; - rt->dst.expires = expires; -+ rt->rt6i_flags |= RTF_EXPIRES; - } - --static inline void rt6_update_expires(struct rt6_info *rt, int timeout) -+static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) - { -- if (!(rt->rt6i_flags & RTF_EXPIRES)) { -- if (rt->dst.from) -- dst_release(rt->dst.from); -- /* dst_set_expires relies on expires == 0 -- * if it has not been set previously. -- */ -- rt->dst.expires = 0; -- } -+ struct rt6_info *rt; - -- dst_set_expires(&rt->dst, timeout); -- rt->rt6i_flags |= RTF_EXPIRES; -+ for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); -+ rt = (struct rt6_info *)rt->dst.from); -+ if (rt && rt != rt0) -+ rt0->dst.expires = rt->dst.expires; -+ -+ dst_set_expires(&rt0->dst, timeout); -+ rt0->rt6i_flags |= RTF_EXPIRES; - } - - static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) - { - struct dst_entry *new = (struct dst_entry *) from; - -- if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) { -- if (new == rt->dst.from) -- return; -- dst_release(rt->dst.from); -- } -- - rt->rt6i_flags &= ~RTF_EXPIRES; -- rt->dst.from = new; - dst_hold(new); -+ rt->dst.from = new; - } - - struct fib6_walker_t { -diff -up ./net/core/dst.c.orig ./net/core/dst.c ---- ./net/core/dst.c.orig 2012-12-10 22:30:57.000000000 -0500 -+++ ./net/core/dst.c 2013-02-20 09:42:49.984790357 -0500 -@@ -179,6 +179,7 @@ void *dst_alloc(struct dst_ops *ops, str - dst_init_metrics(dst, dst_default_metrics, true); - dst->expires = 0UL; - dst->path = dst; -+ dst->from = NULL; - #ifdef CONFIG_XFRM - dst->xfrm = NULL; - #endif -diff -up ./net/ipv6/route.c.orig ./net/ipv6/route.c ---- ./net/ipv6/route.c.orig 2012-12-10 22:30:57.000000000 -0500 -+++ ./net/ipv6/route.c 2013-02-20 09:42:50.238797449 -0500 -@@ -297,6 +297,7 @@ static void ip6_dst_destroy(struct dst_e - { - struct rt6_info *rt = (struct rt6_info *)dst; - struct inet6_dev *idev = rt->rt6i_idev; -+ struct dst_entry *from = dst->from; - - if (rt->n) - neigh_release(rt->n); -@@ -309,8 +310,8 @@ static void ip6_dst_destroy(struct dst_e - in6_dev_put(idev); - } - -- if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) -- dst_release(dst->from); -+ dst->from = NULL; -+ dst_release(from); - - if (rt6_has_peer(rt)) { - struct inet_peer *peer = rt6_peer_ptr(rt); -@@ -998,7 +999,6 @@ struct dst_entry *ip6_blackhole_route(st - - rt->rt6i_gateway = ort->rt6i_gateway; - rt->rt6i_flags = ort->rt6i_flags; -- rt6_clean_expires(rt); - rt->rt6i_metric = 0; - - memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); -@@ -1814,8 +1814,6 @@ static struct rt6_info *ip6_rt_copy(stru - if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == - (RTF_DEFAULT | RTF_ADDRCONF)) - rt6_set_from(rt, ort); -- else -- rt6_clean_expires(rt); - rt->rt6i_metric = 0; - - #ifdef CONFIG_IPV6_SUBTREES diff --git a/kernel.spec b/kernel.spec index d827021dd..886f36baa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -700,8 +700,6 @@ Patch1825: drm-i915-dp-stfu.patch # mustard patch to shut abrt up. please drop (and notify ajax) whenever it # fails to apply Patch1826: drm-i915-tv-detect-hush.patch -# d-i-n backport for https://bugzilla.redhat.com/show_bug.cgi?id=901951 -Patch1827: drm-i915-lvds-reclock-fix.patch # Quiet boot fixes # silence the ACPI blacklist code @@ -764,30 +762,15 @@ Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch -#rhbz 909591 -Patch22255: usb-cypress-supertop.patch - -#rhbz 906055 -Patch22258: perf-hists-Fix-period-symbol_conf.field_sep-display.patch - -#CVE-2013-1763 rhbz 915052,915057 -Patch22260: sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch - #rhbz 903192 Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch -#CVE-2013-1767 rhbz 915592,915716 -Patch22263: tmpfs-fix-use-after-free-of-mempolicy-object.patch - #rhbz 812111 Patch24000: alps.patch -#rhbz 892060 -Patch24001: ipv6-dst-from-ptr-race.patch - Patch24100: userns-avoid-recursion-in-put_user_ns.patch @@ -1441,7 +1424,6 @@ ApplyPatch secure-boot-20130218.patch ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-tv-detect-hush.patch -ApplyPatch drm-i915-lvds-reclock-fix.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -1489,30 +1471,15 @@ ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch -#rhbz 909591 -ApplyPatch usb-cypress-supertop.patch - -#rhbz 906055 -ApplyPatch perf-hists-Fix-period-symbol_conf.field_sep-display.patch - #rhbz 812111 ApplyPatch alps.patch -#rhbz 892060 -ApplyPatch ipv6-dst-from-ptr-race.patch - -#CVE-2013-1763 rhbz 915052,915057 -ApplyPatch sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch - #rhbz 903192 ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch -#CVE-2013-1767 rhbz 915592,915716 -ApplyPatch tmpfs-fix-use-after-free-of-mempolicy-object.patch - ApplyPatch userns-avoid-recursion-in-put_user_ns.patch @@ -2380,6 +2347,16 @@ fi # ||----w | # || || %changelog +* Thu Feb 28 2013 Dave Jones +- Linux 3.8.1 + Dropped (merged in 3.8.1) + - drm-i915-lvds-reclock-fix.patch + - usb-cypress-supertop.patch + - perf-hists-Fix-period-symbol_conf.field_sep-display.patch + - ipv6-dst-from-ptr-race.patch + - sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch + - tmpfs-fix-use-after-free-of-mempolicy-object.patch + * Thu Feb 28 2013 Dave Jones - Update usb-cypress-supertop.patch diff --git a/perf-hists-Fix-period-symbol_conf.field_sep-display.patch b/perf-hists-Fix-period-symbol_conf.field_sep-display.patch deleted file mode 100644 index f81755cdf..000000000 --- a/perf-hists-Fix-period-symbol_conf.field_sep-display.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 755b5f5715c117f4723ec04a81a46da85c9179a3 Mon Sep 17 00:00:00 2001 -From: Jiri Olsa -Date: Sat, 20 Oct 2012 22:14:10 +0200 -Subject: [PATCH] perf hists: Fix period symbol_conf.field_sep display - -Upstream commit c0d246b85fc7d42688d7a5d999ea671777caf65b - -Currently we don't properly display hist data with symbol_conf.field_sep -separator. We need to display either space or separator. - -Signed-off-by: Jiri Olsa -Cc: Arnaldo Carvalho de Melo -Cc: Peter Zijlstra -Cc: Ingo Molnar -Cc: Paul Mackerras -Cc: Corey Ashford -Cc: Frederic Weisbecker -Cc: Namhyung Kim -Link: http://lkml.kernel.org/n/tip-cyggwys0bz5kqdowwvfd8h72@git.kernel.org -Signed-off-by: Arnaldo Carvalho de Melo ---- - tools/perf/ui/hist.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c -index f5a1e4f..947e20a 100644 ---- a/tools/perf/ui/hist.c -+++ b/tools/perf/ui/hist.c -@@ -363,11 +363,15 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, - if (!perf_hpp__format[i].cond) - continue; - -+ /* -+ * If there's no field_sep, we still need -+ * to display initial ' '. -+ */ - if (!sep || !first) { - ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); - advance_hpp(hpp, ret); -+ } else - first = false; -- } - - if (color && perf_hpp__format[i].color) - ret = perf_hpp__format[i].color(hpp, he); --- -1.8.1.2 - diff --git a/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch b/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch deleted file mode 100644 index 7508a7676..000000000 --- a/sock_diag-Fix-out-of-bounds-access-to-sock_diag_handlers.patch +++ /dev/null @@ -1,86 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Mathias Krause -Newsgroups: gmane.linux.network -Subject: [PATCH 1/2] sock_diag: Fix out-of-bounds access to sock_diag_handlers[] -Date: Sat, 23 Feb 2013 12:13:47 +0100 -Lines: 28 -Approved: news@gmane.org -Message-ID: <1361618028-9024-2-git-send-email-minipli@googlemail.com> -References: <1361618028-9024-1-git-send-email-minipli@googlemail.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: ger.gmane.org 1361618069 2156 80.91.229.3 (23 Feb 2013 11:14:29 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Sat, 23 Feb 2013 11:14:29 +0000 (UTC) -Cc: netdev@vger.kernel.org, Mathias Krause -To: "David S. Miller" -Original-X-From: netdev-owner@vger.kernel.org Sat Feb 23 12:14:49 2013 -Return-path: -Envelope-to: linux-netdev-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1U9D3z-0003H8-6Z - for linux-netdev-2@plane.gmane.org; Sat, 23 Feb 2013 12:14:43 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757811Ab3BWLOQ (ORCPT ); - Sat, 23 Feb 2013 06:14:16 -0500 -Original-Received: from mail-bk0-f53.google.com ([209.85.214.53]:46309 "EHLO - mail-bk0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1757044Ab3BWLOM (ORCPT - ); Sat, 23 Feb 2013 06:14:12 -0500 -Original-Received: by mail-bk0-f53.google.com with SMTP id j10so635828bkw.40 - for ; Sat, 23 Feb 2013 03:14:11 -0800 (PST) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=googlemail.com; s=20120113; - h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to - :references; - bh=NM4oEi0qkLdUhxSK1IKpg60DjwOeNtHa0EKsIVngex0=; - b=xdMKHhwMk8BGqDXVGVKf/KcWjSwJajtfpzPDCVugS7vLJh2HtrJnhKiBOUta3XNtTK - ibjB4FQuAenC9ZjXfuEPdo4ct1CIQC2xN2sW/VmeqhYip/xDJ/csVRnX/BxNYWDTFkHo - Uva0peiyrsvR1W0oTeqNLQ1fYIm4f1UwYHzhouschB9mlYHfrCDQFuI7TDfOTUNN1lmY - D5T4vV1aWKsxHx1OYFSRS3aUo3l0Tyzx0zeSPJH+aL3mrhoBDc84RtjsmRafY7RiEXi8 - ropiUO1Q9ATcLZd1/2+L/ausYzkP7NiU16SdbkQWuZkP1J8nBK7n5pahlYnDcktklyGM - od5Q== -X-Received: by 10.204.149.196 with SMTP id u4mr2435753bkv.23.1361618051168; - Sat, 23 Feb 2013 03:14:11 -0800 (PST) -Original-Received: from jig.fritz.box (pD9EB2658.dip.t-dialin.net. [217.235.38.88]) - by mx.google.com with ESMTPS id gy3sm1474145bkc.16.2013.02.23.03.14.09 - (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); - Sat, 23 Feb 2013 03:14:10 -0800 (PST) -X-Mailer: git-send-email 1.7.10.4 -In-Reply-To: <1361618028-9024-1-git-send-email-minipli@googlemail.com> -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:260061 -Archived-At: - -Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY -with a family greater or equal then AF_MAX -- the array size of -sock_diag_handlers[]. The current code does not test for this -condition therefore is vulnerable to an out-of-bound access opening -doors for a privilege escalation. - -Signed-off-by: Mathias Krause ---- - net/core/sock_diag.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c -index 602cd63..750f44f 100644 ---- a/net/core/sock_diag.c -+++ b/net/core/sock_diag.c -@@ -121,6 +121,9 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) - if (nlmsg_len(nlh) < sizeof(*req)) - return -EINVAL; - -+ if (req->sdiag_family >= AF_MAX) -+ return -EINVAL; -+ - hndl = sock_diag_lock_handler(req->sdiag_family); - if (hndl == NULL) - err = -ENOENT; --- -1.7.10.4 - diff --git a/sources b/sources index bf83e961e..52a909507 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz +50a68679086c346dddb34dedccfae7ee patch-3.8.1.xz diff --git a/usb-cypress-supertop.patch b/usb-cypress-supertop.patch deleted file mode 100644 index 37c89b8b8..000000000 --- a/usb-cypress-supertop.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 1cd59b0d0b82c66135bf10ed3a87213a87e318ab Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 14 Feb 2013 09:29:55 -0500 -Subject: [PATCH] USB: usb-storage: unusual_devs update for Super TOP SATA - bridge - -The current entry in unusual_cypress.h for the Super TOP SATA bridge devices -seems to be causing corruption on newer revisions of this device. This has -been reported in Arch Linux and Fedora. The original patch was tested on -devices with bcdDevice of 1.60, whereas the newer devices report bcdDevice -as 2.20. Limit the UNUSUAL_DEV entry to devices less than 2.20. - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=909591 - -Reported-by: Carsten S. -Tested-by: Carsten S. -CC: -Signed-off-by: Josh Boyer ---- - drivers/usb/storage/unusual_cypress.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h -index 2c85530..65a6a75 100644 ---- a/drivers/usb/storage/unusual_cypress.h -+++ b/drivers/usb/storage/unusual_cypress.h -@@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x - "Cypress ISD-300LP", - USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), - --UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, -+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219, - "Super Top", - "USB 2.0 SATA BRIDGE", - USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), From 1d052c76dfc2a254ee6dd06da17d696df52d9982 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:37:54 -0500 Subject: [PATCH 208/492] drop sparc --- Makefile.config | 9 +- config-sparc64-generic | 217 ----------------------------------------- kernel.spec | 26 ++--- 3 files changed, 8 insertions(+), 244 deletions(-) delete mode 100644 config-sparc64-generic diff --git a/Makefile.config b/Makefile.config index 777b30283..21c2a837b 100644 --- a/Makefile.config +++ b/Makefile.config @@ -14,10 +14,9 @@ CONFIGFILES = \ $(CFG)-armv7l-omap.config $(CFG)-armv7hl-omap.config \ $(CFG)-armv7l-tegra.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ - $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64p7.config $(CFG)-ppc64-debug.config -PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x sparc64 arm +PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x arm TEMPFILES = $(addprefix temp-, $(addsuffix -generic, $(PLATFORMS))) configs: $(CONFIGFILES) @@ -68,9 +67,6 @@ temp-x86_64-generic: temp-x86-64 temp-generic temp-x86_64-debug-generic: temp-x86-64 temp-debug-generic perl merge.pl $^ > $@ -temp-sparc64-generic: config-sparc64-generic temp-generic - perl merge.pl $^ > $@ - temp-powerpc-generic: config-powerpc-generic temp-generic perl merge.pl $^ > $@ @@ -104,9 +100,6 @@ kernel-$(VERSION)-x86_64.config: /dev/null temp-x86_64-generic kernel-$(VERSION)-x86_64-debug.config: /dev/null temp-x86_64-debug-generic perl merge.pl $^ x86_64 > $@ -kernel-$(VERSION)-sparc64.config: /dev/null temp-sparc64-generic - perl merge.pl $^ sparc64 > $@ - kernel-$(VERSION)-ppc64.config: /dev/null temp-powerpc64-generic perl merge.pl $^ powerpc > $@ diff --git a/config-sparc64-generic b/config-sparc64-generic deleted file mode 100644 index e15e2ef18..000000000 --- a/config-sparc64-generic +++ /dev/null @@ -1,217 +0,0 @@ -CONFIG_SMP=y -CONFIG_SPARC=y -CONFIG_SPARC64=y -CONFIG_SECCOMP=y -CONFIG_HZ_100=y -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - -CONFIG_US3_FREQ=m -CONFIG_US2E_FREQ=m - -CONFIG_SUN_LDOMS=y -CONFIG_SCHED_SMT=y -CONFIG_SCHED_MC=y -CONFIG_64BIT=y -# CONFIG_BBC_I2C is not set -CONFIG_HUGETLB_PAGE_SIZE_4MB=y -# CONFIG_HUGETLB_PAGE_SIZE_512K is not set -# CONFIG_HUGETLB_PAGE_SIZE_64K is not set -CONFIG_NR_CPUS=256 -CONFIG_US3_FREQ=m -CONFIG_US2E_FREQ=m -CONFIG_SUN_OPENPROMFS=m -CONFIG_COMPAT=y -CONFIG_UID16=y -CONFIG_BINFMT_ELF32=y -CONFIG_ENVCTRL=m -CONFIG_DISPLAY7SEG=m -CONFIG_WATCHDOG_CP1XXX=m -CONFIG_WATCHDOG_RIO=m -# CONFIG_CMDLINE_BOOL is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_PARPORT is not set -# CONFIG_BLK_DEV_FD is not set -# CONFIG_LIRC_PARALLEL is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_SIMTEC is not set -CONFIG_I2C_ALI1535=m -# CONFIG_VGASTATE is not set -# CONFIG_FB_DDC is not set -# CONFIG_FB_BW2 is not set -# CONFIG_FB_GRVGA is not set -CONFIG_FB_CG3=y -CONFIG_FB_CG6=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -CONFIG_FB_ATY=y -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -CONFIG_FB_SBUS=y -CONFIG_FB_FFB=y -# CONFIG_FB_TCX is not set -# CONFIG_FB_CG14 is not set -CONFIG_FB_PM2=y -CONFIG_FB_P9100=y -# CONFIG_FB_LEO is not set -CONFIG_FB_XVR500=y -CONFIG_FB_XVR2500=y -# CONFIG_VGASTATE is not set -# CONFIG_FB_DDC is not set -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_KYRO is not set -# CONFIG_AGP is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_10x18 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_SUN8x16=y -CONFIG_FONT_SUN12x22=y -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_SUNZILOG=y -CONFIG_SERIAL_SUNZILOG_CONSOLE=y -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -CONFIG_SERIAL_SUNSAB=y -CONFIG_SERIAL_SUNSAB_CONSOLE=y -CONFIG_SERIAL_SUNHV=y -CONFIG_SUN_OPENPROMIO=y -CONFIG_OBP_FLASH=m -# CONFIG_SERIO_SERPORT is not set -CONFIG_BLK_DEV_FD=y -CONFIG_SUNVDC=m -CONFIG_SUNVNET=m -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_QLOGICPTI=m -CONFIG_SCSI_SUNESP=m -CONFIG_SUNLANCE=m -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m -# CONFIG_DM9102 is not set -# CONFIG_HAMACHI is not set -# CONFIG_R8169 is not set -CONFIG_ATM_FORE200E_USE_TASKLET=y -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E_TX_RETRY=16 -# CONFIG_DRM_TDFX is not set -CONFIG_KEYBOARD_ATKBD=y -CONFIG_KEYBOARD_SUNKBD=y -# CONFIG_INPUT_PCSPKR is not set -CONFIG_INPUT_SPARCSPKR=m -# CONFIG_SOUND_PRIME is not set -# CONFIG_SND_SUN_AMD7930 is not set -CONFIG_SND_SUN_CS4231=m -# CONFIG_SND_SUN_DBRI is not set -CONFIG_PARPORT_SUNBPP=m -CONFIG_LOGO_SUN_CLUT224=y -CONFIG_MTD_SUN_UFLASH=m -CONFIG_MYRI_SBUS=m -# CONFIG_SGI_IOC4 is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_IEEE1394_SBP2 is not set -# CONFIG_USB_NET2280 is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_DCFLUSH is not set -# CONFIG_DEBUG_BOOTMEM is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_LOCKDEP is not set -# CONFIG_STACK_DEBUG is not set - -CONFIG_SPARSEMEM_VMEMMAP=y - -# CONFIG_THERMAL is not set - -CONFIG_FRAME_WARN=2048 - -CONFIG_NUMA=y - -CONFIG_SND_SPARC=y - -CONFIG_HW_RANDOM_N2RNG=m - -# drivers/isdn/hardware/mISDN/hfcmulti.c:5255:2: error: #error "not running on big endian machines now" -# CONFIG_MISDN_HFCMULTI is not set - -CONFIG_US3_MC=y -CONFIG_SENSORS_ULTRA45=m -CONFIG_LEDS_SUNFIRE=m -CONFIG_TADPOLE_TS102_UCTRL=m - -CONFIG_RCU_FANOUT=64 -CONFIG_RCU_FANOUT_LEAF=16 - -CONFIG_LIRC_ENE0100=m -# CONFIG_BATTERY_DS2782 is not set -CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SN9C20X_EVDEV=y -CONFIG_LSM_MMAP_MIN_ADDR=65536 - -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - -CONFIG_EARLYFB=y -CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m - -CONFIG_GRETH=m -CONFIG_FB_XVR1000=y - -CONFIG_CRYPTO_DEV_NIAGARA2=y - -# CONFIG_MTD_OF_PARTS is not set -# CONFIG_MTD_PHYSMAP_OF is not set -# CONFIG_MMC_SDHCI_OF is not set -# CONFIG_OF_SELFTEST is not set - -CONFIG_BPF_JIT=y -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_IRQ_DOMAIN_DEBUG is not set - -# CONFIG_MDIO_BUS_MUX_MMIOREG is not set -# CONFIG_MFD_SYSCON is not set -# CONFIG_RTC_DRV_SNVS is not set -# CONFIG_CRYPTO_CRC32C_SPARC64 is not set -# CONFIG_CRYPTO_MD5_SPARC64 is not set -# CONFIG_CRYPTO_SHA1_SPARC64 is not set -# CONFIG_CRYPTO_SHA256_SPARC64 is not set -# CONFIG_CRYPTO_SHA512_SPARC64 is not set -# CONFIG_CRYPTO_AES_SPARC64 is not set -# CONFIG_CRYPTO_CAMELLIA_SPARC64 is not set -# CONFIG_CRYPTO_DES_SPARC64 is not set -# CONFIG_ASYMMETRIC_KEY_TYPE is not set - diff --git a/kernel.spec b/kernel.spec index 886f36baa..ce157a4c4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -336,8 +336,8 @@ Summary: The Linux kernel %define with_bootwrapper 0 %endif -# sparse blows up on ppc64 and sparc64 -%ifarch ppc64 ppc sparc64 ppc64p7 +# sparse blows up on ppc64 +%ifarch ppc64 ppc ppc64p7 %define with_sparse 0 %endif @@ -378,19 +378,6 @@ Summary: The Linux kernel %define with_tools 0 %endif -%ifarch sparc64 -%define asmarch sparc -%define all_arch_configs kernel-%{version}-sparc64*.config -%define make_target vmlinux -%define kernel_image vmlinux -%define image_install_path boot -%define with_tools 0 -%endif - -%ifarch sparcv9 -%define hdrarch sparc -%endif - %ifarch ppc %define asmarch powerpc %define hdrarch powerpc @@ -435,7 +422,7 @@ Summary: The Linux kernel # Which is a BadThing(tm). # We only build kernel-headers on the following... -%define nobuildarches i386 s390 sparc sparcv9 +%define nobuildarches i386 s390 %ifarch %nobuildarches %define with_up 0 @@ -523,7 +510,7 @@ Version: %{rpmversion} Release: %{pkg_release} # DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. # SET %%nobuildarches (ABOVE) INSTEAD -ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ppc64p7 %{sparc} s390 s390x %{arm} +ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ppc64p7 s390 s390x %{arm} ExclusiveOS: Linux %kernel_reqprovconf @@ -591,8 +578,6 @@ Source54: config-powerpc64p7 Source70: config-s390x -Source90: config-sparc64-generic - # Unified ARM kernels Source100: config-armv7 @@ -2347,6 +2332,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 28 2013 Dave Jones +- Drop SPARC64 support. + * Thu Feb 28 2013 Dave Jones - Linux 3.8.1 Dropped (merged in 3.8.1) From 171d2934e0030a81fcf6f90a4b4c6ef8a4695e66 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:48:29 -0500 Subject: [PATCH 209/492] remove devinit annotations. --- arm-tegra-sdhci-module-fix.patch | 2 +- dmar-disable-when-ricoh-multifunction.patch | 2 +- linux-2.6-silence-noise.patch | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arm-tegra-sdhci-module-fix.patch b/arm-tegra-sdhci-module-fix.patch index 24ba278ed..0c5d2448f 100644 --- a/arm-tegra-sdhci-module-fix.patch +++ b/arm-tegra-sdhci-module-fix.patch @@ -7,5 +7,5 @@ -MODULE_DEVICE_TABLE(of, sdhci_dt_ids); +MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); - static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata( + static struct tegra_sdhci_platform_data * sdhci_tegra_dt_parse_pdata( struct platform_device *pdev) diff --git a/dmar-disable-when-ricoh-multifunction.patch b/dmar-disable-when-ricoh-multifunction.patch index a4528617e..839db5940 100644 --- a/dmar-disable-when-ricoh-multifunction.patch +++ b/dmar-disable-when-ricoh-multifunction.patch @@ -16,7 +16,7 @@ index 4789f8e..5923914 100644 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); +/* https://bugzilla.redhat.com/show_bug.cgi?id=605888 */ -+static void __devinit quirk_ricoh_multifunction(struct pci_dev *dev) ++static void quirk_ricoh_multifunction(struct pci_dev *dev) +{ + dmar_disabled = 1; +} diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 1e4d7c57f..bcd5baa0b 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -14,7 +14,7 @@ diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 170f71e..4f3e632 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c -@@ -701,10 +701,8 @@ static int __devinit i8042_check_aux(void) +@@ -701,10 +701,8 @@ static int i8042_check_aux(void) static int i8042_controller_check(void) { From f1077a4b1c4da04f47f7fcc43a32d26df8e96ac8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:49:47 -0500 Subject: [PATCH 210/492] we want to do the oldconfigs on other arches otherwise we don't find out about missed config options until we get to koji --- kernel.spec | 7 ------- 1 file changed, 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index ce157a4c4..f3f714024 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1485,13 +1485,6 @@ touch .scmversion mkdir configs -# Remove configs not for the buildarch -for cfg in kernel-%{version}-*.config; do - if [ `echo %{all_arch_configs} | grep -c $cfg` -eq 0 ]; then - rm -f $cfg - fi -done - %if !%{debugbuildsenabled} rm -f kernel-%{version}-*debug.config %endif From e0af4e2a56c000bd028227b05d379de8ac9b786d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:55:02 -0500 Subject: [PATCH 211/492] patch renaming to match rawhide --- ...op.patch => acpi-debug-infinite-loop.patch | 0 ...pi-video-dos.patch => acpi-video-dos.patch | 0 ...compile-fixes.patch => compile-fixes.patch | 0 ...6-crash-driver.patch => crash-driver.patch | 0 ...i-video.patch => defaults-acpi-video.patch | 0 ...tevina.patch => e1000-ich9-montevina.patch | 0 ....patch => input-kill-stupid-messages.patch | 0 kernel.spec | 68 +++++++++---------- ...er_link.patch => makefile-after_link.patch | 0 ...modalias.patch => no-pcspkr-modalias.patch | 0 ...serial-460800.patch => serial-460800.patch | 0 ...list.patch => silence-acpi-blacklist.patch | 0 ...con-logo.patch => silence-fbcon-logo.patch | 0 ...silence-noise.patch => silence-noise.patch | 0 ...am-reverts.patch => upstream-reverts.patch | 0 ...mental.patch => v4l-dvb-experimental.patch | 0 ...v4l-dvb-fixes.patch => v4l-dvb-fixes.patch | 0 ...l-dvb-update.patch => v4l-dvb-update.patch | 0 18 files changed, 34 insertions(+), 34 deletions(-) rename linux-2.6-acpi-debug-infinite-loop.patch => acpi-debug-infinite-loop.patch (100%) rename linux-2.6-acpi-video-dos.patch => acpi-video-dos.patch (100%) rename linux-2.6-compile-fixes.patch => compile-fixes.patch (100%) rename linux-2.6-crash-driver.patch => crash-driver.patch (100%) rename linux-2.6-defaults-acpi-video.patch => defaults-acpi-video.patch (100%) rename linux-2.6-e1000-ich9-montevina.patch => e1000-ich9-montevina.patch (100%) rename linux-2.6-input-kill-stupid-messages.patch => input-kill-stupid-messages.patch (100%) rename linux-2.6-makefile-after_link.patch => makefile-after_link.patch (100%) rename linux-2.6.30-no-pcspkr-modalias.patch => no-pcspkr-modalias.patch (100%) rename linux-2.6-serial-460800.patch => serial-460800.patch (100%) rename linux-2.6-silence-acpi-blacklist.patch => silence-acpi-blacklist.patch (100%) rename linux-2.6-silence-fbcon-logo.patch => silence-fbcon-logo.patch (100%) rename linux-2.6-silence-noise.patch => silence-noise.patch (100%) rename linux-2.6-upstream-reverts.patch => upstream-reverts.patch (100%) rename linux-2.6-v4l-dvb-experimental.patch => v4l-dvb-experimental.patch (100%) rename linux-2.6-v4l-dvb-fixes.patch => v4l-dvb-fixes.patch (100%) rename linux-2.6-v4l-dvb-update.patch => v4l-dvb-update.patch (100%) diff --git a/linux-2.6-acpi-debug-infinite-loop.patch b/acpi-debug-infinite-loop.patch similarity index 100% rename from linux-2.6-acpi-debug-infinite-loop.patch rename to acpi-debug-infinite-loop.patch diff --git a/linux-2.6-acpi-video-dos.patch b/acpi-video-dos.patch similarity index 100% rename from linux-2.6-acpi-video-dos.patch rename to acpi-video-dos.patch diff --git a/linux-2.6-compile-fixes.patch b/compile-fixes.patch similarity index 100% rename from linux-2.6-compile-fixes.patch rename to compile-fixes.patch diff --git a/linux-2.6-crash-driver.patch b/crash-driver.patch similarity index 100% rename from linux-2.6-crash-driver.patch rename to crash-driver.patch diff --git a/linux-2.6-defaults-acpi-video.patch b/defaults-acpi-video.patch similarity index 100% rename from linux-2.6-defaults-acpi-video.patch rename to defaults-acpi-video.patch diff --git a/linux-2.6-e1000-ich9-montevina.patch b/e1000-ich9-montevina.patch similarity index 100% rename from linux-2.6-e1000-ich9-montevina.patch rename to e1000-ich9-montevina.patch diff --git a/linux-2.6-input-kill-stupid-messages.patch b/input-kill-stupid-messages.patch similarity index 100% rename from linux-2.6-input-kill-stupid-messages.patch rename to input-kill-stupid-messages.patch diff --git a/kernel.spec b/kernel.spec index f3f714024..972401916 100644 --- a/kernel.spec +++ b/kernel.spec @@ -630,16 +630,16 @@ Patch00: patch-3.%{base_sublevel}-git%{gitrev}.xz %endif # we also need compile fixes for -vanilla -Patch04: linux-2.6-compile-fixes.patch +Patch04: compile-fixes.patch # build tweak for build ID magic, even for -vanilla -Patch05: linux-2.6-makefile-after_link.patch +Patch05: makefile-after_link.patch %if !%{nopatches} # revert upstream patches we get via other methods -Patch09: linux-2.6-upstream-reverts.patch +Patch09: upstream-reverts.patch # Git trees. # Standalone patches @@ -648,26 +648,26 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch -Patch390: linux-2.6-defaults-acpi-video.patch -Patch391: linux-2.6-acpi-video-dos.patch -Patch394: linux-2.6-acpi-debug-infinite-loop.patch +Patch390: defaults-acpi-video.patch +Patch391: acpi-video-dos.patch +Patch394: acpi-debug-infinite-loop.patch Patch396: acpi-sony-nonvs-blacklist.patch -Patch450: linux-2.6-input-kill-stupid-messages.patch -Patch452: linux-2.6.30-no-pcspkr-modalias.patch +Patch450: input-kill-stupid-messages.patch +Patch452: no-pcspkr-modalias.patch -Patch460: linux-2.6-serial-460800.patch +Patch460: serial-460800.patch Patch470: die-floppy-die.patch -Patch510: linux-2.6-silence-noise.patch +Patch510: silence-noise.patch Patch520: quite-apm.patch -Patch530: linux-2.6-silence-fbcon-logo.patch +Patch530: silence-fbcon-logo.patch Patch540: silence-empty-ipi-mask-warning.patch -Patch700: linux-2.6-e1000-ich9-montevina.patch +Patch700: e1000-ich9-montevina.patch -Patch800: linux-2.6-crash-driver.patch +Patch800: crash-driver.patch # secure boot Patch1000: secure-boot-20130218.patch @@ -688,12 +688,12 @@ Patch1826: drm-i915-tv-detect-hush.patch # Quiet boot fixes # silence the ACPI blacklist code -Patch2802: linux-2.6-silence-acpi-blacklist.patch +Patch2802: silence-acpi-blacklist.patch # media patches -Patch2899: linux-2.6-v4l-dvb-fixes.patch -Patch2900: linux-2.6-v4l-dvb-update.patch -Patch2901: linux-2.6-v4l-dvb-experimental.patch +Patch2899: v4l-dvb-fixes.patch +Patch2900: v4l-dvb-update.patch +Patch2901: v4l-dvb-experimental.patch # fs fixes @@ -1295,17 +1295,17 @@ do done %endif -ApplyPatch linux-2.6-makefile-after_link.patch +ApplyPatch makefile-after_link.patch # # misc small stuff to make things compile # -ApplyOptionalPatch linux-2.6-compile-fixes.patch +ApplyOptionalPatch compile-fixes.patch %if !%{nopatches} # revert patches from upstream that conflict or that we get via other means -ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R +ApplyOptionalPatch upstream-reverts.patch -R ApplyPatch taint-vbox.patch @@ -1345,9 +1345,9 @@ ApplyPatch arm-alignment-faults.patch # WMI # ACPI -ApplyPatch linux-2.6-defaults-acpi-video.patch -ApplyPatch linux-2.6-acpi-video-dos.patch -ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch +ApplyPatch defaults-acpi-video.patch +ApplyPatch acpi-video-dos.patch +ApplyPatch acpi-debug-infinite-loop.patch ApplyPatch acpi-sony-nonvs-blacklist.patch # @@ -1366,21 +1366,21 @@ ApplyPatch acpi-sony-nonvs-blacklist.patch # Misc fixes # The input layer spews crap no-one cares about. -ApplyPatch linux-2.6-input-kill-stupid-messages.patch +ApplyPatch input-kill-stupid-messages.patch # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch -ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch +ApplyPatch no-pcspkr-modalias.patch # Allow to use 480600 baud on 16C950 UARTs -ApplyPatch linux-2.6-serial-460800.patch +ApplyPatch serial-460800.patch # Silence some useless messages that still get printed with 'quiet' -ApplyPatch linux-2.6-silence-noise.patch +ApplyPatch silence-noise.patch # Make fbcon not show the penguins with 'quiet' -ApplyPatch linux-2.6-silence-fbcon-logo.patch +ApplyPatch silence-fbcon-logo.patch # no-one cares about these warnings. ApplyPatch silence-empty-ipi-mask-warning.patch @@ -1389,10 +1389,10 @@ ApplyPatch silence-empty-ipi-mask-warning.patch # /dev/crash driver. -ApplyPatch linux-2.6-crash-driver.patch +ApplyPatch crash-driver.patch # Hack e1000e to work on Montevina SDV -ApplyPatch linux-2.6-e1000-ich9-montevina.patch +ApplyPatch e1000-ich9-montevina.patch # secure boot ApplyPatch secure-boot-20130218.patch @@ -1411,14 +1411,14 @@ ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-tv-detect-hush.patch # silence the ACPI blacklist code -ApplyPatch linux-2.6-silence-acpi-blacklist.patch +ApplyPatch silence-acpi-blacklist.patch ApplyPatch quite-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty -ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch +ApplyOptionalPatch v4l-dvb-fixes.patch +ApplyOptionalPatch v4l-dvb-update.patch +ApplyOptionalPatch v4l-dvb-experimental.patch # Patches headed upstream ApplyPatch fs-proc-devtree-remove_proc_entry.patch diff --git a/linux-2.6-makefile-after_link.patch b/makefile-after_link.patch similarity index 100% rename from linux-2.6-makefile-after_link.patch rename to makefile-after_link.patch diff --git a/linux-2.6.30-no-pcspkr-modalias.patch b/no-pcspkr-modalias.patch similarity index 100% rename from linux-2.6.30-no-pcspkr-modalias.patch rename to no-pcspkr-modalias.patch diff --git a/linux-2.6-serial-460800.patch b/serial-460800.patch similarity index 100% rename from linux-2.6-serial-460800.patch rename to serial-460800.patch diff --git a/linux-2.6-silence-acpi-blacklist.patch b/silence-acpi-blacklist.patch similarity index 100% rename from linux-2.6-silence-acpi-blacklist.patch rename to silence-acpi-blacklist.patch diff --git a/linux-2.6-silence-fbcon-logo.patch b/silence-fbcon-logo.patch similarity index 100% rename from linux-2.6-silence-fbcon-logo.patch rename to silence-fbcon-logo.patch diff --git a/linux-2.6-silence-noise.patch b/silence-noise.patch similarity index 100% rename from linux-2.6-silence-noise.patch rename to silence-noise.patch diff --git a/linux-2.6-upstream-reverts.patch b/upstream-reverts.patch similarity index 100% rename from linux-2.6-upstream-reverts.patch rename to upstream-reverts.patch diff --git a/linux-2.6-v4l-dvb-experimental.patch b/v4l-dvb-experimental.patch similarity index 100% rename from linux-2.6-v4l-dvb-experimental.patch rename to v4l-dvb-experimental.patch diff --git a/linux-2.6-v4l-dvb-fixes.patch b/v4l-dvb-fixes.patch similarity index 100% rename from linux-2.6-v4l-dvb-fixes.patch rename to v4l-dvb-fixes.patch diff --git a/linux-2.6-v4l-dvb-update.patch b/v4l-dvb-update.patch similarity index 100% rename from linux-2.6-v4l-dvb-update.patch rename to v4l-dvb-update.patch From 676b781d62cc5ac2332a57c03c3b378f166a5cc1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:55:42 -0500 Subject: [PATCH 212/492] Remove no longer needed E1000 hack. --- e1000-ich9-montevina.patch | 46 -------------------------------------- kernel.spec | 8 +++---- 2 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 e1000-ich9-montevina.patch diff --git a/e1000-ich9-montevina.patch b/e1000-ich9-montevina.patch deleted file mode 100644 index ec38a3902..000000000 --- a/e1000-ich9-montevina.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 802e6d8c8477a553a677b23a247d6d2638e01958 Mon Sep 17 00:00:00 2001 -From: Dave Jones -Date: Wed, 26 Oct 2011 13:31:47 -0400 -Subject: [PATCH] e1000e: ich9 montevina - -This only showed up in one SDV (Montevina). -The PCIE slots don't seem to like network cards, so this is the only hope -to get networking working. It's never going upstream, but it's low impact -enough to carry just to keep those SDVs working. ---- - drivers/net/ethernet/intel/e1000e/ich8lan.c | 6 ++++++ - drivers/net/ethernet/intel/e1000e/netdev.c | 1 + - 2 files changed, 7 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c -index 6a17c62..0e40975 100644 ---- a/drivers/net/ethernet/intel/e1000e/ich8lan.c -+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c -@@ -452,6 +452,12 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) - - /* Verify phy id */ - switch (phy->id) { -+ case 0: -+ if (hw->adapter->pdev->device == 0x10be) -+ e_dbg("got 0 phy id, trying anyway"); -+ /* Fall through to IGP03E1000 case below */ -+ else -+ return -E1000_ERR_PHY; - case IGP03E1000_E_PHY_ID: - phy->type = e1000_phy_igp_3; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; -diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c -index a855db1..edac30b 100644 ---- a/drivers/net/ethernet/intel/e1000e/netdev.c -+++ b/drivers/net/ethernet/intel/e1000e/netdev.c -@@ -6359,6 +6359,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, -+ { PCI_VDEVICE(INTEL, 0x10be), board_ich9lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, --- -1.7.6.4 - diff --git a/kernel.spec b/kernel.spec index 972401916..2643468cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -665,8 +665,6 @@ Patch520: quite-apm.patch Patch530: silence-fbcon-logo.patch Patch540: silence-empty-ipi-mask-warning.patch -Patch700: e1000-ich9-montevina.patch - Patch800: crash-driver.patch # secure boot @@ -1391,9 +1389,6 @@ ApplyPatch silence-empty-ipi-mask-warning.patch # /dev/crash driver. ApplyPatch crash-driver.patch -# Hack e1000e to work on Montevina SDV -ApplyPatch e1000-ich9-montevina.patch - # secure boot ApplyPatch secure-boot-20130218.patch @@ -2325,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 28 2013 Dave Jones +- Remove no longer needed E1000 hack. + * Thu Feb 28 2013 Dave Jones - Drop SPARC64 support. From 1d1375420763e8f8810a43ed3745a4590a9d972b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Feb 2013 13:56:36 -0500 Subject: [PATCH 213/492] rename typo. --- kernel.spec | 4 ++-- quite-apm.patch => quiet-apm.patch | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename quite-apm.patch => quiet-apm.patch (100%) diff --git a/kernel.spec b/kernel.spec index 2643468cb..022a5c699 100644 --- a/kernel.spec +++ b/kernel.spec @@ -661,7 +661,7 @@ Patch460: serial-460800.patch Patch470: die-floppy-die.patch Patch510: silence-noise.patch -Patch520: quite-apm.patch +Patch520: quiet-apm.patch Patch530: silence-fbcon-logo.patch Patch540: silence-empty-ipi-mask-warning.patch @@ -1407,7 +1407,7 @@ ApplyPatch drm-i915-tv-detect-hush.patch # silence the ACPI blacklist code ApplyPatch silence-acpi-blacklist.patch -ApplyPatch quite-apm.patch +ApplyPatch quiet-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty diff --git a/quite-apm.patch b/quiet-apm.patch similarity index 100% rename from quite-apm.patch rename to quiet-apm.patch From c4229021957651648239209144e60aff542ef037 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 28 Feb 2013 20:06:17 +0000 Subject: [PATCH 214/492] Update ARM config for 3.8 --- config-arm-generic | 112 ++++++++++++++++++++++++++++++++++++++++++-- config-arm-kirkwood | 1 + config-arm-omap | 12 +++-- config-arm-tegra | 7 +++ config-armv7 | 7 +-- config-nodebug | 2 + kernel.spec | 3 ++ 7 files changed, 130 insertions(+), 14 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index f1306225b..7951f541f 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -38,6 +38,7 @@ CONFIG_ARM_ERRATA_742231=y CONFIG_ARM_ERRATA_754327=y CONFIG_ARM_ERRATA_764369=y CONFIG_ARM_ERRATA_775420=y +CONFIG_PL310_ERRATA_753970=y # Generic ARM config options CONFIG_ZBOOT_ROM_TEXT=0 @@ -54,6 +55,8 @@ CONFIG_PL330_DMA=y # CONFIG_PID_IN_CONTEXTIDR is not set # Generic options we want for ARM that aren't defualt +CONFIG_EARLY_PRINTK=y + CONFIG_HIGHMEM=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -121,6 +124,7 @@ CONFIG_SND_DESIGNWARE_I2S=m CONFIG_SND_SIMPLE_CARD=m # CONFIG_SND_SOC_CACHE_LZO is not set CONFIG_SND_SOC_ALL_CODECS=m +CONFIG_SND_SPI=y CONFIG_AX88796=m CONFIG_AX88796_93CX6=y @@ -153,6 +157,7 @@ CONFIG_MMC_SDHCI_PXAV2=m # CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set +CONFIG_SPI=y # Generic GPIO options CONFIG_GENERIC_GPIO=y @@ -217,6 +222,10 @@ CONFIG_MTD_NAND_ORION=m # CONFIG_MTD_PLATRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_SLRAM is not set +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y +CONFIG_MTD_DATAFLASH_OTP=y +CONFIG_MTD_SST25L=m CONFIG_MTD_UBI=m CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_RESERVE=1 @@ -258,6 +267,7 @@ CONFIG_OF=y CONFIG_USE_OF=y CONFIG_OF_DEVICE=y CONFIG_OF_IRQ=y +CONFIG_OF_GPIO=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y CONFIG_PROC_DEVICETREE=y @@ -280,25 +290,77 @@ CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_RTC_DRV_88PM80X=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_MC13XXX=m +CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_PL030=m CONFIG_RTC_DRV_PL031=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m CONFIG_RTC_DRV_SNVS=m + CONFIG_RFKILL_REGULATOR=m CONFIG_INPUT_88PM80X_ONKEY=y CONFIG_INPUT_GP2A=m CONFIG_INPUT_GPIO_TILT_POLLED=m CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_ARIZONA_HAPTICS=m +CONFIG_INPUT_MC13783_PWRBUTTON=m + CONFIG_SERIAL_AMBA_PL010=m CONFIG_SERIAL_AMBA_PL011=m -CONFIG_GPIO_PL061=y -CONFIG_GPIO_MCP23S08=m +CONFIG_SERIAL_MAX3100=m +CONFIG_SERIAL_MAX310X=y +CONFIG_SERIAL_IFX6X60=m + +CONFIG_GPIO_74X164=m CONFIG_GPIO_ADNP=m -CONFIG_PL310_ERRATA_753970=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_PL061=y + +CONFIG_SPI_ALTERA=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_OC_TINY=m +CONFIG_SPI_PL022=m +CONFIG_SPI_SC18IS602=m +CONFIG_SPI_XCOMM=m +CONFIG_SPI_XILINX=m +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m +CONFIG_BMP085_SPI=m +CONFIG_BMP085_SPI=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93XX46=m +CONFIG_KS8851=m +CONFIG_MICREL_KS8995MA=m +CONFIG_LIBERTAS_SPI=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y CONFIG_MFD_CORE=m CONFIG_MFD_88PM800=m CONFIG_MFD_88PM805=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_MC13XXX_SPI=m CONFIG_MFD_SYSCON=y +# CONFIG_MFD_WM5102 is not set +# CONFIG_MFD_WM5110 is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set # CONFIG_MFD_TPS80031 is not set # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_SMSC is not set @@ -311,6 +373,7 @@ CONFIG_REGULATOR_USERSPACE_CONSUMER=m CONFIG_REGULATOR_GPIO=m CONFIG_REGULATOR_AD5398=m CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_ARIZONA=m CONFIG_REGULATOR_FAN53555=m CONFIG_REGULATOR_ISL6271A=m CONFIG_REGULATOR_LP3972=m @@ -319,14 +382,28 @@ CONFIG_REGULATOR_MAX8649=m CONFIG_REGULATOR_MAX8660=m CONFIG_REGULATOR_MAX8952=m CONFIG_REGULATOR_MAX8973=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_MC13892=m CONFIG_REGULATOR_LP3971=m CONFIG_REGULATOR_TPS51632=m CONFIG_REGULATOR_TPS62360=m CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6524X=m CONFIG_REGULATOR_TPS6507X=m CONFIG_CHARGER_MANAGER=y CONFIG_EXTCON_GPIO=m +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MC13783_ADC=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_LIS3_SPI=m + +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m + # CONFIG_ARM_VIRT_EXT is not set # CONFIG_PINCTRL_EXYNOS4 is not set # CONFIG_PINCTRL_EXYNOS5440 is not set @@ -346,6 +423,9 @@ CONFIG_EXTCON_GPIO=m # CONFIG_GPIO_EM is not set # CONFIG_HVC_DCC is not set # CONFIG_LEDS_RENESAS_TPU is not set +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_MC13783=m + # CONFIG_VIRTIO_CONSOLE is not set # Possibly part of Snowball @@ -388,16 +468,40 @@ CONFIG_EXTCON_GPIO=m # CONFIG_DRM_NOUVEAU is not set # CONFIG_MLX4_EN is not set +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_MC13783=m + # drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] # CONFIG_TOUCHSCREEN_EETI is not set # CONFIG_TOUCHSCREEN_EGALAX is not set # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set -# + +# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_PANEL_ACX565AKM is not set +# CONFIG_PANEL_N8X0 is not set + +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set + # CONFIG_FB_MX3 is not set # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set # CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_CS89x0 is not set # CONFIG_DVB_USB_PCTV452E is not set # CONFIG_PINCTRL_EXYNOS is not set + +# CONFIG_EZX_PCAP is not set + +# CONFIG_EXTCON_ARIZONA is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index f4fea2955..9f80aaf4a 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -43,6 +43,7 @@ CONFIG_MACH_TS219_DT=y CONFIG_MACH_TS41X=y CONFIG_MACH_T5325=y +# CONFIG_SPI is not set CONFIG_CACHE_FEROCEON_L2=y CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y CONFIG_MTD_NAND_ORION=m diff --git a/config-arm-omap b/config-arm-omap index a53983357..976d4381d 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -103,7 +103,6 @@ CONFIG_OUTER_CACHE_SYNC=y CONFIG_CACHE_L2X0=y CONFIG_CACHE_PL310=y CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_CPU_HAS_PMU=y CONFIG_ARM_ERRATA_430973=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set @@ -133,7 +132,6 @@ CONFIG_CMDLINE="" # CONFIG_AUTO_ZRELADDR is not set CONFIG_VFPv3=y CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_PM_DEBUG=y # CONFIG_PM_ADVANCED_DEBUG is not set @@ -143,6 +141,8 @@ CONFIG_PM_SLEEP_SMP=y CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y +# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES +CONFIG_OMAP_BANDGAP=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y @@ -151,7 +151,9 @@ CONFIG_OMAP5_THERMAL=y # CONFIG_WL_TI=y CONFIG_WLCORE_SDIO=m +CONFIG_WLCORE_SPI=m CONFIG_TI_ST=m +CONFIG_TI_DAC7512=m # CONFIG_TI_CPSW is not set CONFIG_MTD_NAND_OMAP2=y CONFIG_MTD_NAND_OMAP_PREFETCH=y @@ -160,6 +162,10 @@ CONFIG_WL1251_SPI=m CONFIG_WL12XX_SPI=m CONFIG_WL12XX_SDIO_TEST=m CONFIG_WL18XX=m +CONFIG_SPI_DAVINCI=m +CONFIG_SPI_OMAP24XX=y +CONFIG_MFD_TI_SSP=m +CONFIG_SPI_TI_SSP=m CONFIG_NFC_WILINK=m CONFIG_INPUT_TWL4030_PWRBUTTON=m CONFIG_INPUT_TWL4030_VIBRA=m @@ -192,7 +198,6 @@ CONFIG_LEDS_LP8788=m CONFIG_MTD_ONENAND_OMAP2=y CONFIG_HDQ_MASTER_OMAP=m CONFIG_I2C_OMAP=m -CONFIG_SPI_OMAP24XX=m CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MFD_WL1273_CORE=m CONFIG_MFD_LP8788=y @@ -329,7 +334,6 @@ CONFIG_PWM_TWL_LED=m # CONFIG_TIDSPBRIDGE_BACKTRACE is not set # CONFIG_OMAP_REMOTEPROC is not set -# CONFIG_OMAP_BANDGAP is not set # CONFIG_OMAP_IOVMM is not set CONFIG_CRYPTO_DEV_OMAP_SHAM=m diff --git a/config-arm-tegra b/config-arm-tegra index 869b1728a..80a15dda4 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -40,6 +40,8 @@ CONFIG_TEGRA_SYSTEM_DMA=y CONFIG_TEGRA_EMC_SCALING_ENABLE=y CONFIG_TEGRA_AHB=y CONFIG_TEGRA20_APB_DMA=y +CONFIG_SPI_TEGRA20_SFLASH=m +CONFIG_SPI_TEGRA20_SLINK=m CONFIG_ARM_THUMBEE=y CONFIG_SWP_EMULATE=y # CONFIG_CPU_BPREDICT_DISABLE is not set @@ -64,6 +66,8 @@ CONFIG_ARM_ERRATA_720789=y CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_MCP23S08 is not set # CONFIG_KEYBOARD_TEGRA is not set +CONFIG_PINCTRL_TEGRA=y +CONFIG_PINCTRL_TEGRA20=y CONFIG_USB_EHCI_TEGRA=y CONFIG_RTC_DRV_TEGRA=y @@ -107,3 +111,6 @@ CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y # CONFIG_DRM_TEGRA_DEBUG is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_DW_PCI is not set diff --git a/config-armv7 b/config-armv7 index c3af272a1..d59ab36be 100644 --- a/config-armv7 +++ b/config-armv7 @@ -121,10 +121,6 @@ CONFIG_CC_STACKPROTECTOR=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_UTS_NS is not set -# CONFIG_IPC_NS is not set -# CONFIG_PID_NS is not set -# CONFIG_NET_NS is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y @@ -200,7 +196,6 @@ CONFIG_MVNETA=m CONFIG_SATA_MV=m CONFIG_MARVELL_PHY=m CONFIG_RTC_DRV_S35390A=y -CONFIG_USB_EHCI_MV=m # Allwinner a1x # CONFIG_SUNXI_RFKILL=y @@ -275,9 +270,9 @@ CONFIG_ARM_APPENDED_DTB=y CONFIG_PROC_DEVICETREE=y # CONFIG_OF_SELFTEST is not set CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_OF_GPIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y +CONFIG_OF_GPIO=y CONFIG_I2C_MUX_PINCTRL=m CONFIG_OF_MDIO=m diff --git a/config-nodebug b/config-nodebug index c471b853e..f5cbe10b9 100644 --- a/config-nodebug +++ b/config-nodebug @@ -114,3 +114,5 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y # CONFIG_MAC80211_MESSAGE_TRACING is not set # CONFIG_EDAC_DEBUG is not set + +# CONFIG_SPI_DEBUG is not set diff --git a/kernel.spec b/kernel.spec index 022a5c699..8be5db7c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2320,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Thu Feb 28 2013 Peter Robinson +- Update ARM config for 3.8 + * Thu Feb 28 2013 Dave Jones - Remove no longer needed E1000 hack. From 2da82c8fb5f9c1c32896e22e7821f7fbc91f4d17 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Mar 2013 08:58:09 -0500 Subject: [PATCH 215/492] Add patches to fix sunrpc panic (rhbz 904870) --- ...age_temp_xprts-enqueue-under-sv_lock.patch | 69 ++++++++ ...svcrpc-fix-rpc-server-shutdown-races.patch | 154 ++++++++++++++++++ kernel.spec | 13 +- 3 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch create mode 100644 0002-svcrpc-fix-rpc-server-shutdown-races.patch diff --git a/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch b/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch new file mode 100644 index 000000000..ce80a9d6f --- /dev/null +++ b/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch @@ -0,0 +1,69 @@ +From e75bafbff2270993926abcc31358361db74a9bc2 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Sun, 10 Feb 2013 11:33:48 -0500 +Subject: [PATCH 1/2] svcrpc: make svc_age_temp_xprts enqueue under sv_lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +svc_age_temp_xprts expires xprts in a two-step process: first it takes +the sv_lock and moves the xprts to expire off their server-wide list +(sv_tempsocks or sv_permsocks) to a local list. Then it drops the +sv_lock and enqueues and puts each one. + +I see no reason for this: svc_xprt_enqueue() will take sp_lock, but the +sv_lock and sp_lock are not otherwise nested anywhere (and documentation +at the top of this file claims it's correct to nest these with sp_lock +inside.) + +Cc: stable@kernel.org +Tested-by: Jason Tibbitts +Tested-by: PaweÅ‚ Sikora +Signed-off-by: J. Bruce Fields +--- + net/sunrpc/svc_xprt.c | 15 ++------------- + 1 file changed, 2 insertions(+), 13 deletions(-) + +diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c +index 5a9d40c..11a33c8 100644 +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -863,7 +863,6 @@ static void svc_age_temp_xprts(unsigned long closure) + struct svc_serv *serv = (struct svc_serv *)closure; + struct svc_xprt *xprt; + struct list_head *le, *next; +- LIST_HEAD(to_be_aged); + + dprintk("svc_age_temp_xprts\n"); + +@@ -884,25 +883,15 @@ static void svc_age_temp_xprts(unsigned long closure) + if (atomic_read(&xprt->xpt_ref.refcount) > 1 || + test_bit(XPT_BUSY, &xprt->xpt_flags)) + continue; +- svc_xprt_get(xprt); +- list_move(le, &to_be_aged); ++ list_del_init(le); + set_bit(XPT_CLOSE, &xprt->xpt_flags); + set_bit(XPT_DETACHED, &xprt->xpt_flags); +- } +- spin_unlock_bh(&serv->sv_lock); +- +- while (!list_empty(&to_be_aged)) { +- le = to_be_aged.next; +- /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */ +- list_del_init(le); +- xprt = list_entry(le, struct svc_xprt, xpt_list); +- + dprintk("queuing xprt %p for closing\n", xprt); + + /* a thread will dequeue and close it soon */ + svc_xprt_enqueue(xprt); +- svc_xprt_put(xprt); + } ++ spin_unlock_bh(&serv->sv_lock); + + mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); + } +-- +1.8.1.2 + diff --git a/0002-svcrpc-fix-rpc-server-shutdown-races.patch b/0002-svcrpc-fix-rpc-server-shutdown-races.patch new file mode 100644 index 000000000..25f0e3797 --- /dev/null +++ b/0002-svcrpc-fix-rpc-server-shutdown-races.patch @@ -0,0 +1,154 @@ +From cc630d9f476445927fca599f81182c7f06f79058 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Sun, 10 Feb 2013 16:08:11 -0500 +Subject: [PATCH 2/2] svcrpc: fix rpc server shutdown races +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rewrite server shutdown to remove the assumption that there are no +longer any threads running (no longer true, for example, when shutting +down the service in one network namespace while it's still running in +others). + +Do that by doing what we'd do in normal circumstances: just CLOSE each +socket, then enqueue it. + +Since there may not be threads to handle the resulting queued xprts, +also run a simplified version of the svc_recv() loop run by a server to +clean up any closed xprts afterwards. + +Cc: stable@kernel.org +Tested-by: Jason Tibbitts +Tested-by: PaweÅ‚ Sikora +Acked-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +--- + net/sunrpc/svc.c | 9 -------- + net/sunrpc/svc_xprt.c | 57 +++++++++++++++++++++++++++++---------------------- + 2 files changed, 32 insertions(+), 34 deletions(-) + +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index b9ba2a8..89a588b 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -515,15 +515,6 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); + + void svc_shutdown_net(struct svc_serv *serv, struct net *net) + { +- /* +- * The set of xprts (contained in the sv_tempsocks and +- * sv_permsocks lists) is now constant, since it is modified +- * only by accepting new sockets (done by service threads in +- * svc_recv) or aging old ones (done by sv_temptimer), or +- * configuration changes (excluded by whatever locking the +- * caller is using--nfsd_mutex in the case of nfsd). So it's +- * safe to traverse those lists and shut everything down: +- */ + svc_close_net(serv, net); + + if (serv->sv_shutdown) +diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c +index 11a33c8..80a6640 100644 +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -955,21 +955,24 @@ void svc_close_xprt(struct svc_xprt *xprt) + } + EXPORT_SYMBOL_GPL(svc_close_xprt); + +-static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) ++static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) + { + struct svc_xprt *xprt; ++ int ret = 0; + + spin_lock(&serv->sv_lock); + list_for_each_entry(xprt, xprt_list, xpt_list) { + if (xprt->xpt_net != net) + continue; ++ ret++; + set_bit(XPT_CLOSE, &xprt->xpt_flags); +- set_bit(XPT_BUSY, &xprt->xpt_flags); ++ svc_xprt_enqueue(xprt); + } + spin_unlock(&serv->sv_lock); ++ return ret; + } + +-static void svc_clear_pools(struct svc_serv *serv, struct net *net) ++static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net) + { + struct svc_pool *pool; + struct svc_xprt *xprt; +@@ -984,42 +987,46 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net) + if (xprt->xpt_net != net) + continue; + list_del_init(&xprt->xpt_ready); ++ spin_unlock_bh(&pool->sp_lock); ++ return xprt; + } + spin_unlock_bh(&pool->sp_lock); + } ++ return NULL; + } + +-static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) ++static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net) + { + struct svc_xprt *xprt; +- struct svc_xprt *tmp; +- LIST_HEAD(victims); +- +- spin_lock(&serv->sv_lock); +- list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { +- if (xprt->xpt_net != net) +- continue; +- list_move(&xprt->xpt_list, &victims); +- } +- spin_unlock(&serv->sv_lock); + +- list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) ++ while ((xprt = svc_dequeue_net(serv, net))) { ++ set_bit(XPT_CLOSE, &xprt->xpt_flags); + svc_delete_xprt(xprt); ++ } + } + ++/* ++ * Server threads may still be running (especially in the case where the ++ * service is still running in other network namespaces). ++ * ++ * So we shut down sockets the same way we would on a running server, by ++ * setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do ++ * the close. In the case there are no such other threads, ++ * threads running, svc_clean_up_xprts() does a simple version of a ++ * server's main event loop, and in the case where there are other ++ * threads, we may need to wait a little while and then check again to ++ * see if they're done. ++ */ + void svc_close_net(struct svc_serv *serv, struct net *net) + { +- svc_close_list(serv, &serv->sv_tempsocks, net); +- svc_close_list(serv, &serv->sv_permsocks, net); ++ int delay = 0; + +- svc_clear_pools(serv, net); +- /* +- * At this point the sp_sockets lists will stay empty, since +- * svc_xprt_enqueue will not add new entries without taking the +- * sp_lock and checking XPT_BUSY. +- */ +- svc_clear_list(serv, &serv->sv_tempsocks, net); +- svc_clear_list(serv, &serv->sv_permsocks, net); ++ while (svc_close_list(serv, &serv->sv_permsocks, net) + ++ svc_close_list(serv, &serv->sv_tempsocks, net)) { ++ ++ svc_clean_up_xprts(serv, net); ++ msleep(delay++); ++ } + } + + /* +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 8be5db7c6..601b29d4f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -751,6 +751,10 @@ Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +#rhbz 904870 +Patch22263: 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch +Patch22264: 0002-svcrpc-fix-rpc-server-shutdown-races.patch + #rhbz 812111 Patch24000: alps.patch @@ -1462,6 +1466,10 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch ApplyPatch userns-avoid-recursion-in-put_user_ns.patch +#rhbz 904870 +ApplyPatch 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch +ApplyPatch 0002-svcrpc-fix-rpc-server-shutdown-races.patch + # END OF PATCH APPLICATIONS @@ -2320,6 +2328,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 01 2013 Josh Boyer +- Add patches to fix sunrpc panic (rhbz 904870) + * Thu Feb 28 2013 Peter Robinson - Update ARM config for 3.8 From 1f0249effe9a49bc2b1dc833d23e6eba5b04e02b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 1 Mar 2013 11:09:57 -0500 Subject: [PATCH 216/492] Silence "tty is NULL" trace. --- kernel.spec | 5 +++++ silence-tty-null.patch | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 silence-tty-null.patch diff --git a/kernel.spec b/kernel.spec index 601b29d4f..31360c7fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -664,6 +664,7 @@ Patch510: silence-noise.patch Patch520: quiet-apm.patch Patch530: silence-fbcon-logo.patch Patch540: silence-empty-ipi-mask-warning.patch +Patch541: silence-tty-null.patch Patch800: crash-driver.patch @@ -1386,6 +1387,7 @@ ApplyPatch silence-fbcon-logo.patch # no-one cares about these warnings. ApplyPatch silence-empty-ipi-mask-warning.patch +ApplyPatch silence-tty-null.patch # Changes to upstream defaults. @@ -2328,6 +2330,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 01 2013 Dave Jones +- Silence "tty is NULL" trace. + * Fri Mar 01 2013 Josh Boyer - Add patches to fix sunrpc panic (rhbz 904870) diff --git a/silence-tty-null.patch b/silence-tty-null.patch new file mode 100644 index 000000000..00f64239b --- /dev/null +++ b/silence-tty-null.patch @@ -0,0 +1,13 @@ +This should be fixed in 3.9, but is unlikely to be backported. + +--- linux-3.8.1-201.fc18.x86_64/drivers/tty/tty_buffer.c~ 2013-03-01 11:07:37.498291384 -0500 ++++ linux-3.8.1-201.fc18.x86_64/drivers/tty/tty_buffer.c 2013-03-01 11:08:11.088250537 -0500 +@@ -473,7 +473,7 @@ static void flush_to_ldisc(struct work_s + struct tty_ldisc *disc; + + tty = port->itty; +- if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n")) ++ if (tty == NULL) + return; + + disc = tty_ldisc_ref(tty); From 6e30b2ba8cd48fddf5e3ea144c23f26cf307be7b Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 4 Mar 2013 11:46:44 +0000 Subject: [PATCH 217/492] Fix DTB generation on ARM --- config-armv7 | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-armv7 b/config-armv7 index d59ab36be..cc9307422 100644 --- a/config-armv7 +++ b/config-armv7 @@ -348,7 +348,7 @@ CONFIG_PINCTRL_SINGLE=m # GPIO CONFIG_GPIO_GENERIC_PLATFORM=m -CONFIG_GPIO_EM=m +# CONFIG_GPIO_EM is not set CONFIG_GPIO_ADNP=m CONFIG_GPIO_MCP23S08=m CONFIG_POWER_RESET_GPIO=y diff --git a/kernel.spec b/kernel.spec index 31360c7fc..5c5d30bc7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1604,7 +1604,7 @@ BuildKernel() { make -s ARCH=$Arch V=1 dtbs mkdir -p $RPM_BUILD_ROOT/%{image_install_path}/dtb-$KernelVer - install -m 644 arch/arm/boot/*.dtb $RPM_BUILD_ROOT/boot/dtb-$KernelVer/ + install -m 644 arch/arm/boot/dts/*.dtb $RPM_BUILD_ROOT/boot/dtb-$KernelVer/ %else make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} %endif @@ -2330,6 +2330,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 4 2013 Peter Robinson +- Fix DTB generation on ARM + * Fri Mar 01 2013 Dave Jones - Silence "tty is NULL" trace. From 0c05d73610d0acc864b36d0f9643f97c3e1c8b03 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 4 Mar 2013 09:19:31 -0600 Subject: [PATCH 218/492] Linux v3.8.2 --- ...age_temp_xprts-enqueue-under-sv_lock.patch | 69 -------- ...svcrpc-fix-rpc-server-shutdown-races.patch | 154 ------------------ kernel.spec | 15 +- sources | 2 +- 4 files changed, 6 insertions(+), 234 deletions(-) delete mode 100644 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch delete mode 100644 0002-svcrpc-fix-rpc-server-shutdown-races.patch diff --git a/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch b/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch deleted file mode 100644 index ce80a9d6f..000000000 --- a/0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e75bafbff2270993926abcc31358361db74a9bc2 Mon Sep 17 00:00:00 2001 -From: "J. Bruce Fields" -Date: Sun, 10 Feb 2013 11:33:48 -0500 -Subject: [PATCH 1/2] svcrpc: make svc_age_temp_xprts enqueue under sv_lock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -svc_age_temp_xprts expires xprts in a two-step process: first it takes -the sv_lock and moves the xprts to expire off their server-wide list -(sv_tempsocks or sv_permsocks) to a local list. Then it drops the -sv_lock and enqueues and puts each one. - -I see no reason for this: svc_xprt_enqueue() will take sp_lock, but the -sv_lock and sp_lock are not otherwise nested anywhere (and documentation -at the top of this file claims it's correct to nest these with sp_lock -inside.) - -Cc: stable@kernel.org -Tested-by: Jason Tibbitts -Tested-by: PaweÅ‚ Sikora -Signed-off-by: J. Bruce Fields ---- - net/sunrpc/svc_xprt.c | 15 ++------------- - 1 file changed, 2 insertions(+), 13 deletions(-) - -diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c -index 5a9d40c..11a33c8 100644 ---- a/net/sunrpc/svc_xprt.c -+++ b/net/sunrpc/svc_xprt.c -@@ -863,7 +863,6 @@ static void svc_age_temp_xprts(unsigned long closure) - struct svc_serv *serv = (struct svc_serv *)closure; - struct svc_xprt *xprt; - struct list_head *le, *next; -- LIST_HEAD(to_be_aged); - - dprintk("svc_age_temp_xprts\n"); - -@@ -884,25 +883,15 @@ static void svc_age_temp_xprts(unsigned long closure) - if (atomic_read(&xprt->xpt_ref.refcount) > 1 || - test_bit(XPT_BUSY, &xprt->xpt_flags)) - continue; -- svc_xprt_get(xprt); -- list_move(le, &to_be_aged); -+ list_del_init(le); - set_bit(XPT_CLOSE, &xprt->xpt_flags); - set_bit(XPT_DETACHED, &xprt->xpt_flags); -- } -- spin_unlock_bh(&serv->sv_lock); -- -- while (!list_empty(&to_be_aged)) { -- le = to_be_aged.next; -- /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */ -- list_del_init(le); -- xprt = list_entry(le, struct svc_xprt, xpt_list); -- - dprintk("queuing xprt %p for closing\n", xprt); - - /* a thread will dequeue and close it soon */ - svc_xprt_enqueue(xprt); -- svc_xprt_put(xprt); - } -+ spin_unlock_bh(&serv->sv_lock); - - mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); - } --- -1.8.1.2 - diff --git a/0002-svcrpc-fix-rpc-server-shutdown-races.patch b/0002-svcrpc-fix-rpc-server-shutdown-races.patch deleted file mode 100644 index 25f0e3797..000000000 --- a/0002-svcrpc-fix-rpc-server-shutdown-races.patch +++ /dev/null @@ -1,154 +0,0 @@ -From cc630d9f476445927fca599f81182c7f06f79058 Mon Sep 17 00:00:00 2001 -From: "J. Bruce Fields" -Date: Sun, 10 Feb 2013 16:08:11 -0500 -Subject: [PATCH 2/2] svcrpc: fix rpc server shutdown races -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Rewrite server shutdown to remove the assumption that there are no -longer any threads running (no longer true, for example, when shutting -down the service in one network namespace while it's still running in -others). - -Do that by doing what we'd do in normal circumstances: just CLOSE each -socket, then enqueue it. - -Since there may not be threads to handle the resulting queued xprts, -also run a simplified version of the svc_recv() loop run by a server to -clean up any closed xprts afterwards. - -Cc: stable@kernel.org -Tested-by: Jason Tibbitts -Tested-by: PaweÅ‚ Sikora -Acked-by: Stanislav Kinsbursky -Signed-off-by: J. Bruce Fields ---- - net/sunrpc/svc.c | 9 -------- - net/sunrpc/svc_xprt.c | 57 +++++++++++++++++++++++++++++---------------------- - 2 files changed, 32 insertions(+), 34 deletions(-) - -diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c -index b9ba2a8..89a588b 100644 ---- a/net/sunrpc/svc.c -+++ b/net/sunrpc/svc.c -@@ -515,15 +515,6 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); - - void svc_shutdown_net(struct svc_serv *serv, struct net *net) - { -- /* -- * The set of xprts (contained in the sv_tempsocks and -- * sv_permsocks lists) is now constant, since it is modified -- * only by accepting new sockets (done by service threads in -- * svc_recv) or aging old ones (done by sv_temptimer), or -- * configuration changes (excluded by whatever locking the -- * caller is using--nfsd_mutex in the case of nfsd). So it's -- * safe to traverse those lists and shut everything down: -- */ - svc_close_net(serv, net); - - if (serv->sv_shutdown) -diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c -index 11a33c8..80a6640 100644 ---- a/net/sunrpc/svc_xprt.c -+++ b/net/sunrpc/svc_xprt.c -@@ -955,21 +955,24 @@ void svc_close_xprt(struct svc_xprt *xprt) - } - EXPORT_SYMBOL_GPL(svc_close_xprt); - --static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) -+static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) - { - struct svc_xprt *xprt; -+ int ret = 0; - - spin_lock(&serv->sv_lock); - list_for_each_entry(xprt, xprt_list, xpt_list) { - if (xprt->xpt_net != net) - continue; -+ ret++; - set_bit(XPT_CLOSE, &xprt->xpt_flags); -- set_bit(XPT_BUSY, &xprt->xpt_flags); -+ svc_xprt_enqueue(xprt); - } - spin_unlock(&serv->sv_lock); -+ return ret; - } - --static void svc_clear_pools(struct svc_serv *serv, struct net *net) -+static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net) - { - struct svc_pool *pool; - struct svc_xprt *xprt; -@@ -984,42 +987,46 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net) - if (xprt->xpt_net != net) - continue; - list_del_init(&xprt->xpt_ready); -+ spin_unlock_bh(&pool->sp_lock); -+ return xprt; - } - spin_unlock_bh(&pool->sp_lock); - } -+ return NULL; - } - --static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) -+static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net) - { - struct svc_xprt *xprt; -- struct svc_xprt *tmp; -- LIST_HEAD(victims); -- -- spin_lock(&serv->sv_lock); -- list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { -- if (xprt->xpt_net != net) -- continue; -- list_move(&xprt->xpt_list, &victims); -- } -- spin_unlock(&serv->sv_lock); - -- list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) -+ while ((xprt = svc_dequeue_net(serv, net))) { -+ set_bit(XPT_CLOSE, &xprt->xpt_flags); - svc_delete_xprt(xprt); -+ } - } - -+/* -+ * Server threads may still be running (especially in the case where the -+ * service is still running in other network namespaces). -+ * -+ * So we shut down sockets the same way we would on a running server, by -+ * setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do -+ * the close. In the case there are no such other threads, -+ * threads running, svc_clean_up_xprts() does a simple version of a -+ * server's main event loop, and in the case where there are other -+ * threads, we may need to wait a little while and then check again to -+ * see if they're done. -+ */ - void svc_close_net(struct svc_serv *serv, struct net *net) - { -- svc_close_list(serv, &serv->sv_tempsocks, net); -- svc_close_list(serv, &serv->sv_permsocks, net); -+ int delay = 0; - -- svc_clear_pools(serv, net); -- /* -- * At this point the sp_sockets lists will stay empty, since -- * svc_xprt_enqueue will not add new entries without taking the -- * sp_lock and checking XPT_BUSY. -- */ -- svc_clear_list(serv, &serv->sv_tempsocks, net); -- svc_clear_list(serv, &serv->sv_permsocks, net); -+ while (svc_close_list(serv, &serv->sv_permsocks, net) + -+ svc_close_list(serv, &serv->sv_tempsocks, net)) { -+ -+ svc_clean_up_xprts(serv, net); -+ msleep(delay++); -+ } - } - - /* --- -1.8.1.2 - diff --git a/kernel.spec b/kernel.spec index 5c5d30bc7..c09a20e2f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -752,10 +752,6 @@ Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch -#rhbz 904870 -Patch22263: 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch -Patch22264: 0002-svcrpc-fix-rpc-server-shutdown-races.patch - #rhbz 812111 Patch24000: alps.patch @@ -1468,10 +1464,6 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch ApplyPatch userns-avoid-recursion-in-put_user_ns.patch -#rhbz 904870 -ApplyPatch 0001-svcrpc-make-svc_age_temp_xprts-enqueue-under-sv_lock.patch -ApplyPatch 0002-svcrpc-fix-rpc-server-shutdown-races.patch - # END OF PATCH APPLICATIONS @@ -2330,6 +2322,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 05 2013 Justin M. Forbes - 3.8.2-201 +- Linux v3.8.2 + * Mon Mar 4 2013 Peter Robinson - Fix DTB generation on ARM diff --git a/sources b/sources index 52a909507..9ada6af78 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -50a68679086c346dddb34dedccfae7ee patch-3.8.1.xz +e282fcff76e975e121e0636018e31a56 patch-3.8.2.xz From 20dc0199176106e2eb3005c8735b01928f5d3d53 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Mar 2013 13:38:45 -0500 Subject: [PATCH 219/492] Fix issues in nx crypto driver from Kent Yoder (rhbz 916544) --- ...x-fix-init-race-alignmasks-and-GCM-b.patch | 83 +++++++++++++++++++ kernel.spec | 13 ++- 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch diff --git a/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch b/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch new file mode 100644 index 000000000..c8d30455e --- /dev/null +++ b/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch @@ -0,0 +1,83 @@ +From b05ceba560e094d27ff716f6df1e2d5ef670d4d3 Mon Sep 17 00:00:00 2001 +From: Kent Yoder +Date: Wed, 27 Feb 2013 15:50:27 -0600 +Subject: [PATCH] drivers/crypto/nx: fix init race, alignmasks and GCM bug + + Fixes a race on driver init with registering algorithms where the +driver status flag wasn't being set before self testing started. + + Added the cra_alignmask field for CBC and ECB modes. + + Fixed a bug in GCM where AES block size was being used instead of +authsize. + +Signed-off-by: Kent Yoder +--- + drivers/crypto/nx/nx-aes-cbc.c | 1 + + drivers/crypto/nx/nx-aes-ecb.c | 1 + + drivers/crypto/nx/nx-aes-gcm.c | 2 +- + drivers/crypto/nx/nx.c | 4 ++-- + 4 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c +index a76d4c4..35d483f 100644 +--- a/drivers/crypto/nx/nx-aes-cbc.c ++++ b/drivers/crypto/nx/nx-aes-cbc.c +@@ -126,6 +126,7 @@ struct crypto_alg nx_cbc_aes_alg = { + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nx_crypto_ctx), + .cra_type = &crypto_blkcipher_type, ++ .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + .cra_init = nx_crypto_ctx_aes_cbc_init, + .cra_exit = nx_crypto_ctx_exit, +diff --git a/drivers/crypto/nx/nx-aes-ecb.c b/drivers/crypto/nx/nx-aes-ecb.c +index ba5f161..7bbc9a8 100644 +--- a/drivers/crypto/nx/nx-aes-ecb.c ++++ b/drivers/crypto/nx/nx-aes-ecb.c +@@ -123,6 +123,7 @@ struct crypto_alg nx_ecb_aes_alg = { + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_alignmask = 0xf, + .cra_ctxsize = sizeof(struct nx_crypto_ctx), + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, +diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c +index c8109ed..6cca6c3 100644 +--- a/drivers/crypto/nx/nx-aes-gcm.c ++++ b/drivers/crypto/nx/nx-aes-gcm.c +@@ -219,7 +219,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc) + if (enc) + NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; + else +- nbytes -= AES_BLOCK_SIZE; ++ nbytes -= crypto_aead_authsize(crypto_aead_reqtfm(req)); + + csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8; + +diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c +index c767f23..7621d05 100644 +--- a/drivers/crypto/nx/nx.c ++++ b/drivers/crypto/nx/nx.c +@@ -454,6 +454,8 @@ static int nx_register_algs(void) + if (rc) + goto out; + ++ nx_driver.of.status = NX_OKAY; ++ + rc = crypto_register_alg(&nx_ecb_aes_alg); + if (rc) + goto out; +@@ -498,8 +500,6 @@ static int nx_register_algs(void) + if (rc) + goto out_unreg_s512; + +- nx_driver.of.status = NX_OKAY; +- + goto out; + + out_unreg_s512: +-- +1.7.11.7 + diff --git a/kernel.spec b/kernel.spec index c09a20e2f..009e933c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -752,6 +752,9 @@ Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +#rhbz 916544 +Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch + #rhbz 812111 Patch24000: alps.patch @@ -1462,6 +1465,9 @@ ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 914737 ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +#rhbz 916544 +ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch + ApplyPatch userns-avoid-recursion-in-put_user_ns.patch @@ -2322,7 +2328,10 @@ fi # ||----w | # || || %changelog -* Mon Mar 05 2013 Justin M. Forbes - 3.8.2-201 +* Mon Mar 04 2013 Josh Boyer +- Fix issues in nx crypto driver from Kent Yoder (rhbz 916544) + +* Mon Mar 04 2013 Justin M. Forbes - 3.8.2-201 - Linux v3.8.2 * Mon Mar 4 2013 Peter Robinson From 65ffa65d32a3efb008d536fd42c40159a97de3bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Mar 2013 09:46:26 -0500 Subject: [PATCH 220/492] Enable CONFIG_IP6_NF_TARGET_MASQUERADE --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index d7424a451..69d546064 100644 --- a/config-generic +++ b/config-generic @@ -926,7 +926,7 @@ CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_HL=m CONFIG_NF_NAT_IPV6=m -# CONFIG_IP6_NF_TARGET_MASQUERADE is not set +CONFIG_IP6_NF_TARGET_MASQUERADE=m # CONFIG_IP6_NF_TARGET_NPT is not set # diff --git a/kernel.spec b/kernel.spec index 009e933c6..2fa849870 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2328,6 +2328,9 @@ fi # ||----w | # || || %changelog +* Tue Mar 05 2013 Josh Boyer +- Enable CONFIG_IP6_NF_TARGET_MASQUERADE + * Mon Mar 04 2013 Josh Boyer - Fix issues in nx crypto driver from Kent Yoder (rhbz 916544) From 90bc19a94cf36a88e65e1b4774e41c9a88b2e15a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Mar 2013 10:26:49 -0500 Subject: [PATCH 221/492] Backport 4 fixes for efivarfs (rhbz 917984) --- efi-fixes-3.8.patch | 736 ++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 efi-fixes-3.8.patch diff --git a/efi-fixes-3.8.patch b/efi-fixes-3.8.patch new file mode 100644 index 000000000..f53dac078 --- /dev/null +++ b/efi-fixes-3.8.patch @@ -0,0 +1,736 @@ +From 27857f8a3240e35c61dedb88cbdbfbaabbd8ad2b Mon Sep 17 00:00:00 2001 +From: Seiji Aguchi +Date: Tue, 12 Feb 2013 12:59:07 -0800 +Subject: [PATCH 1/4] efivars: Disable external interrupt while holding + efivars->lock + +[Problem] +There is a scenario which efi_pstore fails to log messages in a panic case. + + - CPUA holds an efi_var->lock in either efivarfs parts + or efi_pstore with interrupt enabled. + - CPUB panics and sends IPI to CPUA in smp_send_stop(). + - CPUA stops with holding the lock. + - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC) + but it returns without logging messages. + +[Patch Description] +This patch disables an external interruption while holding efivars->lock +as follows. + +In efi_pstore_write() and get_var_data(), spin_lock/spin_unlock is +replaced by spin_lock_irqsave/spin_unlock_irqrestore because they may +be called in an interrupt context. + +In other functions, they are replaced by spin_lock_irq/spin_unlock_irq. +because they are all called from a process context. + +By applying this patch, we can avoid the problem above with +a following senario. + + - CPUA holds an efi_var->lock with interrupt disabled. + - CPUB panics and sends IPI to CPUA in smp_send_stop(). + - CPUA receives the IPI after releasing the lock because it is + disabling interrupt while holding the lock. + - CPUB waits for one sec until CPUA releases the lock. + - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC) + And it can hold the lock successfully. + +Signed-off-by: Seiji Aguchi +Acked-by: Mike Waychison +Acked-by: Matt Fleming +Signed-off-by: Tony Luck +--- + drivers/firmware/efivars.c | 84 ++++++++++++++++++++++++---------------------- + 1 file changed, 43 insertions(+), 41 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index bcb201c..a9277cc 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -406,10 +406,11 @@ static efi_status_t + get_var_data(struct efivars *efivars, struct efi_variable *var) + { + efi_status_t status; ++ unsigned long flags; + +- spin_lock(&efivars->lock); ++ spin_lock_irqsave(&efivars->lock, flags); + status = get_var_data_locked(efivars, var); +- spin_unlock(&efivars->lock); ++ spin_unlock_irqrestore(&efivars->lock, flags); + + if (status != EFI_SUCCESS) { + printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", +@@ -538,14 +539,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) + return -EINVAL; + } + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + status = efivars->ops->set_variable(new_var->VariableName, + &new_var->VendorGuid, + new_var->Attributes, + new_var->DataSize, + new_var->Data); + +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + if (status != EFI_SUCCESS) { + printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", +@@ -714,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file, + * amounts of memory. Pick a default size of 64K if + * QueryVariableInfo() isn't supported by the firmware. + */ +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + if (!efivars->ops->query_variable_info) + status = EFI_UNSUPPORTED; +@@ -724,7 +725,7 @@ static ssize_t efivarfs_file_write(struct file *file, + &remaining_size, &max_size); + } + +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + if (status != EFI_SUCCESS) { + if (status != EFI_UNSUPPORTED) +@@ -755,7 +756,7 @@ static ssize_t efivarfs_file_write(struct file *file, + * set_variable call, and removal of the variable from the efivars + * list (in the case of an authenticated delete). + */ +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, +@@ -763,7 +764,7 @@ static ssize_t efivarfs_file_write(struct file *file, + data); + + if (status != EFI_SUCCESS) { +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + kfree(data); + + return efi_status_to_err(status); +@@ -784,21 +785,21 @@ static ssize_t efivarfs_file_write(struct file *file, + NULL); + + if (status == EFI_BUFFER_TOO_SMALL) { +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + mutex_lock(&inode->i_mutex); + i_size_write(inode, newdatasize + sizeof(attributes)); + mutex_unlock(&inode->i_mutex); + + } else if (status == EFI_NOT_FOUND) { + list_del(&var->list); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + efivar_unregister(var); + drop_nlink(inode); + d_delete(file->f_dentry); + dput(file->f_dentry); + + } else { +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + pr_warn("efivarfs: inconsistent EFI variable implementation? " + "status = %lx\n", status); + } +@@ -820,11 +821,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + void *data; + ssize_t size = 0; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, NULL); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + if (status != EFI_BUFFER_TOO_SMALL) + return efi_status_to_err(status); +@@ -834,12 +835,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, + if (!data) + return -ENOMEM; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + status = efivars->ops->get_variable(var->var.VariableName, + &var->var.VendorGuid, + &attributes, &datasize, + (data + sizeof(attributes))); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + if (status != EFI_SUCCESS) { + size = efi_status_to_err(status); +@@ -1005,9 +1006,9 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, + goto out; + + kobject_uevent(&var->kobj, KOBJ_ADD); +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + list_add(&var->list, &efivars->list); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + d_instantiate(dentry, inode); + dget(dentry); + out: +@@ -1024,7 +1025,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) + struct efivars *efivars = var->efivars; + efi_status_t status; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, +@@ -1032,14 +1033,14 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) + + if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { + list_del(&var->list); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + efivar_unregister(var); + drop_nlink(dentry->d_inode); + dput(dentry); + return 0; + } + +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return -EINVAL; + }; + +@@ -1184,13 +1185,13 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + /* copied by the above to local storage in the dentry. */ + kfree(name); + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + efivars->ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, + &entry->var.Attributes, + &size, + NULL); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + mutex_lock(&inode->i_mutex); + inode->i_private = entry; +@@ -1253,7 +1254,7 @@ static int efi_pstore_open(struct pstore_info *psi) + { + struct efivars *efivars = psi->data; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + efivars->walk_entry = list_first_entry(&efivars->list, + struct efivar_entry, list); + return 0; +@@ -1263,7 +1264,7 @@ static int efi_pstore_close(struct pstore_info *psi) + { + struct efivars *efivars = psi->data; + +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return 0; + } + +@@ -1339,8 +1340,9 @@ static int efi_pstore_write(enum pstore_type_id type, + int i, ret = 0; + u64 storage_space, remaining_space, max_variable_size; + efi_status_t status = EFI_NOT_FOUND; ++ unsigned long flags; + +- spin_lock(&efivars->lock); ++ spin_lock_irqsave(&efivars->lock, flags); + + /* + * Check if there is a space enough to log. +@@ -1352,7 +1354,7 @@ static int efi_pstore_write(enum pstore_type_id type, + &remaining_space, + &max_variable_size); + if (status || remaining_space < size + DUMP_NAME_LEN * 2) { +- spin_unlock(&efivars->lock); ++ spin_unlock_irqrestore(&efivars->lock, flags); + *id = part; + return -ENOSPC; + } +@@ -1366,7 +1368,7 @@ static int efi_pstore_write(enum pstore_type_id type, + efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, + size, psi->buf); + +- spin_unlock(&efivars->lock); ++ spin_unlock_irqrestore(&efivars->lock, flags); + + if (size) + ret = efivar_create_sysfs_entry(efivars, +@@ -1393,7 +1395,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, + sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count, + time.tv_sec); + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + for (i = 0; i < DUMP_NAME_LEN; i++) + efi_name[i] = name[i]; +@@ -1437,7 +1439,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, + if (found) + list_del(&found->list); + +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + if (found) + efivar_unregister(found); +@@ -1507,7 +1509,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, + return -EINVAL; + } + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + /* + * Does this variable already exist? +@@ -1525,7 +1527,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, + } + } + if (found) { +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return -EINVAL; + } + +@@ -1539,10 +1541,10 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, + if (status != EFI_SUCCESS) { + printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", + status); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return -EIO; + } +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + /* Create the entry in sysfs. Locking is not required here */ + status = efivar_create_sysfs_entry(efivars, +@@ -1570,7 +1572,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + + /* + * Does this variable already exist? +@@ -1588,7 +1590,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, + } + } + if (!found) { +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return -EINVAL; + } + /* force the Attributes/DataSize to 0 to ensure deletion */ +@@ -1604,12 +1606,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, + if (status != EFI_SUCCESS) { + printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", + status); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + return -EIO; + } + list_del(&search_efivar->list); + /* We need to release this lock before unregistering. */ +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + efivar_unregister(search_efivar); + + /* It's dead Jim.... */ +@@ -1724,9 +1726,9 @@ efivar_create_sysfs_entry(struct efivars *efivars, + kfree(short_name); + short_name = NULL; + +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + list_add(&new_efivar->list, &efivars->list); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + + return 0; + } +@@ -1795,9 +1797,9 @@ void unregister_efivars(struct efivars *efivars) + struct efivar_entry *entry, *n; + + list_for_each_entry_safe(entry, n, &efivars->list, list) { +- spin_lock(&efivars->lock); ++ spin_lock_irq(&efivars->lock); + list_del(&entry->list); +- spin_unlock(&efivars->lock); ++ spin_unlock_irq(&efivars->lock); + efivar_unregister(entry); + } + if (efivars->new_var) +-- +1.8.1.2 + + +From 19adc04301476eaa15e035b66e92cb333223c352 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sat, 2 Mar 2013 19:40:17 -0500 +Subject: [PATCH 2/4] efi: be more paranoid about available space when creating + variables + +UEFI variables are typically stored in flash. For various reasons, avaiable +space is typically not reclaimed immediately upon the deletion of a +variable - instead, the system will garbage collect during initialisation +after a reboot. + +Some systems appear to handle this garbage collection extremely poorly, +failing if more than 50% of the system flash is in use. This can result in +the machine refusing to boot. The safest thing to do for the moment is to +forbid writes if they'd end up using more than half of the storage space. +We can make this more finegrained later if we come up with a method for +identifying the broken machines. + +Signed-off-by: Matthew Garrett +Cc: +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 106 +++++++++++++++++++++++++++++++++------------ + 1 file changed, 79 insertions(+), 27 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index a9277cc..919862b 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -419,6 +419,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var) + return status; + } + ++static efi_status_t ++check_var_size_locked(struct efivars *efivars, u32 attributes, ++ unsigned long size) ++{ ++ u64 storage_size, remaining_size, max_size; ++ efi_status_t status; ++ const struct efivar_operations *fops = efivars->ops; ++ ++ if (!efivars->ops->query_variable_info) ++ return EFI_UNSUPPORTED; ++ ++ status = fops->query_variable_info(attributes, &storage_size, ++ &remaining_size, &max_size); ++ ++ if (status != EFI_SUCCESS) ++ return status; ++ ++ if (!storage_size || size > remaining_size || size > max_size || ++ (remaining_size - size) < (storage_size / 2)) ++ return EFI_OUT_OF_RESOURCES; ++ ++ return status; ++} ++ ++ ++static efi_status_t ++check_var_size(struct efivars *efivars, u32 attributes, unsigned long size) ++{ ++ efi_status_t status; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&efivars->lock, flags); ++ status = check_var_size_locked(efivars, attributes, size); ++ spin_unlock_irqrestore(&efivars->lock, flags); ++ ++ return status; ++} ++ + static ssize_t + efivar_guid_read(struct efivar_entry *entry, char *buf) + { +@@ -540,11 +578,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) + } + + spin_lock_irq(&efivars->lock); +- status = efivars->ops->set_variable(new_var->VariableName, +- &new_var->VendorGuid, +- new_var->Attributes, +- new_var->DataSize, +- new_var->Data); ++ ++ status = check_var_size_locked(efivars, new_var->Attributes, ++ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); ++ ++ if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) ++ status = efivars->ops->set_variable(new_var->VariableName, ++ &new_var->VendorGuid, ++ new_var->Attributes, ++ new_var->DataSize, ++ new_var->Data); + + spin_unlock_irq(&efivars->lock); + +@@ -695,8 +738,7 @@ static ssize_t efivarfs_file_write(struct file *file, + u32 attributes; + struct inode *inode = file->f_mapping->host; + unsigned long datasize = count - sizeof(attributes); +- unsigned long newdatasize; +- u64 storage_size, remaining_size, max_size; ++ unsigned long newdatasize, varsize; + ssize_t bytes = 0; + + if (count < sizeof(attributes)) +@@ -715,28 +757,18 @@ static ssize_t efivarfs_file_write(struct file *file, + * amounts of memory. Pick a default size of 64K if + * QueryVariableInfo() isn't supported by the firmware. + */ +- spin_lock_irq(&efivars->lock); + +- if (!efivars->ops->query_variable_info) +- status = EFI_UNSUPPORTED; +- else { +- const struct efivar_operations *fops = efivars->ops; +- status = fops->query_variable_info(attributes, &storage_size, +- &remaining_size, &max_size); +- } +- +- spin_unlock_irq(&efivars->lock); ++ varsize = datasize + utf16_strsize(var->var.VariableName, 1024); ++ status = check_var_size(efivars, attributes, varsize); + + if (status != EFI_SUCCESS) { + if (status != EFI_UNSUPPORTED) + return efi_status_to_err(status); + +- remaining_size = 65536; ++ if (datasize > 65536) ++ return -ENOSPC; + } + +- if (datasize > remaining_size) +- return -ENOSPC; +- + data = kmalloc(datasize, GFP_KERNEL); + if (!data) + return -ENOMEM; +@@ -758,6 +790,19 @@ static ssize_t efivarfs_file_write(struct file *file, + */ + spin_lock_irq(&efivars->lock); + ++ /* ++ * Ensure that the available space hasn't shrunk below the safe level ++ */ ++ ++ status = check_var_size_locked(efivars, attributes, varsize); ++ ++ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) { ++ spin_unlock_irq(&efivars->lock); ++ kfree(data); ++ ++ return efi_status_to_err(status); ++ } ++ + status = efivars->ops->set_variable(var->var.VariableName, + &var->var.VendorGuid, + attributes, datasize, +@@ -1338,7 +1383,6 @@ static int efi_pstore_write(enum pstore_type_id type, + efi_guid_t vendor = LINUX_EFI_CRASH_GUID; + struct efivars *efivars = psi->data; + int i, ret = 0; +- u64 storage_space, remaining_space, max_variable_size; + efi_status_t status = EFI_NOT_FOUND; + unsigned long flags; + +@@ -1349,11 +1393,11 @@ static int efi_pstore_write(enum pstore_type_id type, + * size: a size of logging data + * DUMP_NAME_LEN * 2: a maximum size of variable name + */ +- status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES, +- &storage_space, +- &remaining_space, +- &max_variable_size); +- if (status || remaining_space < size + DUMP_NAME_LEN * 2) { ++ ++ status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES, ++ size + DUMP_NAME_LEN * 2); ++ ++ if (status) { + spin_unlock_irqrestore(&efivars->lock, flags); + *id = part; + return -ENOSPC; +@@ -1531,6 +1575,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, + return -EINVAL; + } + ++ status = check_var_size_locked(efivars, new_var->Attributes, ++ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); ++ ++ if (status && status != EFI_UNSUPPORTED) { ++ spin_unlock_irq(&efivars->lock); ++ return efi_status_to_err(status); ++ } ++ + /* now *really* create the variable via EFI */ + status = efivars->ops->set_variable(new_var->VariableName, + &new_var->VendorGuid, +-- +1.8.1.2 + + +From 46b6e1db3a81203deaf4615637616a0266a2e6e6 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 5 Mar 2013 07:40:16 +0000 +Subject: [PATCH 3/4] efivars: efivarfs_valid_name() should handle pstore + syntax + +Stricter validation was introduced with commit da27a24383b2b +("efivarfs: guid part of filenames are case-insensitive") and commit +47f531e8ba3b ("efivarfs: Validate filenames much more aggressively"), +which is necessary for the guid portion of efivarfs filenames, but we +don't need to be so strict with the first part, the variable name. The +UEFI specification doesn't impose any constraints on variable names +other than they be a NULL-terminated string. + +The above commits caused a regression that resulted in users seeing +the following message, + + $ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory + +whenever pstore EFI variables were present in the variable store, +since their variable names failed to pass the following check, + + /* GUID should be right after the first '-' */ + if (s - 1 != strchr(str, '-')) + +as a typical pstore filename is of the form, dump-type0-10-1-. +The fix is trivial since the guid portion of the filename is GUID_LEN +bytes, we can use (len - GUID_LEN) to ensure the '-' character is +where we expect it to be. + +(The bogus ENOMEM error value will be fixed in a separate patch.) + +Reported-by: Joseph Yasi +Reported-by: Lingzhu Xiang +Cc: Josh Boyer +Cc: Jeremy Kerr +Cc: Matthew Garrett +Cc: +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index 919862b..fc54ddd 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -967,8 +967,8 @@ static bool efivarfs_valid_name(const char *str, int len) + if (len < GUID_LEN + 2) + return false; + +- /* GUID should be right after the first '-' */ +- if (s - 1 != strchr(str, '-')) ++ /* GUID must be preceded by a '-' */ ++ if (*(s - 1) != '-') + return false; + + /* +-- +1.8.1.2 + + +From f751b6c973fe5a480ff12c97df4b8ac4e9a666a7 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Tue, 5 Mar 2013 12:46:30 +0000 +Subject: [PATCH 4/4] efivarfs: return accurate error code in + efivarfs_fill_super() + +Joseph was hitting a failure case when mounting efivarfs which +resulted in an incorrect error message, + + $ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory + +triggered when efivarfs_valid_name() returned -EINVAL. + +Make sure we pass accurate return values up the stack if +efivarfs_fill_super() fails to build inodes for EFI variables. + +Reported-by: Joseph Yasi +Reported-by: Lingzhu Xiang +Cc: Josh Boyer +Cc: Jeremy Kerr +Cc: Matthew Garrett +Cc: +Signed-off-by: Matt Fleming +--- + drivers/firmware/efivars.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c +index fc54ddd..2a2e145 100644 +--- a/drivers/firmware/efivars.c ++++ b/drivers/firmware/efivars.c +@@ -1156,15 +1156,22 @@ static struct dentry_operations efivarfs_d_ops = { + + static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) + { ++ struct dentry *d; + struct qstr q; ++ int err; + + q.name = name; + q.len = strlen(name); + +- if (efivarfs_d_hash(NULL, NULL, &q)) +- return NULL; ++ err = efivarfs_d_hash(NULL, NULL, &q); ++ if (err) ++ return ERR_PTR(err); ++ ++ d = d_alloc(parent, &q); ++ if (d) ++ return d; + +- return d_alloc(parent, &q); ++ return ERR_PTR(-ENOMEM); + } + + static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) +@@ -1174,6 +1181,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; + char *name; ++ int err = -ENOMEM; + + efivarfs_sb = sb; + +@@ -1224,8 +1232,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) + goto fail_name; + + dentry = efivarfs_alloc_dentry(root, name); +- if (!dentry) ++ if (IS_ERR(dentry)) { ++ err = PTR_ERR(dentry); + goto fail_inode; ++ } + + /* copied by the above to local storage in the dentry. */ + kfree(name); +@@ -1252,7 +1262,7 @@ fail_inode: + fail_name: + kfree(name); + fail: +- return -ENOMEM; ++ return err; + } + + static struct dentry *efivarfs_mount(struct file_system_type *fs_type, +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 2fa849870..9c6a88fab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -755,6 +755,9 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch +#rhbz 917984 +Patch22264: efi-fixes-3.8.patch + #rhbz 812111 Patch24000: alps.patch @@ -1468,6 +1471,9 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #rhbz 916544 ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch +#rhbz 917984 +ApplyPatch efi-fixes-3.8.patch + ApplyPatch userns-avoid-recursion-in-put_user_ns.patch @@ -2329,6 +2335,7 @@ fi # || || %changelog * Tue Mar 05 2013 Josh Boyer +- Backport 4 fixes for efivarfs (rhbz 917984) - Enable CONFIG_IP6_NF_TARGET_MASQUERADE * Mon Mar 04 2013 Josh Boyer From 3b5b67be2b874eb91a878e2c0835478b8a712857 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 5 Mar 2013 19:33:16 +0000 Subject: [PATCH 222/492] Fix Beagle (omap), update vexpress --- config-arm-omap | 22 +++++++++++++++------- config-armv7 | 23 +++++++++++++++++++++++ kernel.spec | 4 ++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/config-arm-omap b/config-arm-omap index 976d4381d..38a73b4b1 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -6,8 +6,6 @@ CONFIG_ARCH_OMAP2PLUS=y # # OMAP Feature Selections # -CONFIG_OMAP_SMARTREFLEX=y -CONFIG_OMAP_SMARTREFLEX_CLASS3=y CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX=y # CONFIG_OMAP_MUX_DEBUG is not set @@ -28,8 +26,6 @@ CONFIG_HWSPINLOCK_OMAP=m CONFIG_DMA_OMAP=y # CONFIG_DMADEVICES_VDEBUG is not set -CONFIG_ARM_OMAP2PLUS_CPUFREQ=y - # # TI OMAP2/3/4 Specific Features # @@ -146,6 +142,13 @@ CONFIG_OMAP_BANDGAP=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y +# OMAP3 thermal/power +CONFIG_POWER_AVS=y +CONFIG_POWER_AVS_OMAP=y +CONFIG_POWER_AVS_OMAP_CLASS3=y + +CONFIG_ARM_OMAP2PLUS_CPUFREQ=y + # # OMAP Hardware # @@ -211,10 +214,15 @@ CONFIG_REGULATOR_TPS65910=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_VPFE_CAPTURE=m CONFIG_VIDEO_OMAP2_VOUT=m -CONFIG_VIDEO_DM6446_CCDC=m -# CONFIG_VIDEO_OMAP3 is not set +CONFIG_VIDEO_OMAP3=m +CONFIG_VIDEO_VPFE_CAPTURE=m +# The ones below are for TI Davinci +# CONFIG_VIDEO_VPSS_SYSTEM is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_VIDEO_DM644X_VPBE is not set +# CONFIG_VIDEO_DM355_CCDC is not set +# CONFIG_VIDEO_ISIF is not set # Also enable vivi driver - useful for testing a full kernelspace V4L2 driver CONFIG_V4L_TEST_DRIVERS=y CONFIG_VIDEO_VIVI=m diff --git a/config-armv7 b/config-armv7 index cc9307422..0f8477544 100644 --- a/config-armv7 +++ b/config-armv7 @@ -138,8 +138,10 @@ CONFIG_EARLY_PRINTK=y CONFIG_LBDAF=y CONFIG_COMMON_CLK=y +CONFIG_REGULATOR=y # Versatile and highbank +CONFIG_VEXPRESS_CONFIG=y CONFIG_ARM_TIMER_SP804=y CONFIG_SERIO_AMBAKMI=m @@ -177,6 +179,7 @@ CONFIG_I2C_VERSATILE=m CONFIG_OC_ETM=y CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y CONFIG_SENSORS_VEXPRESS=m +CONFIG_REGULATOR_VEXPRESS=m # unknown and needs review CONFIG_ARM_AMBA=y @@ -367,6 +370,26 @@ CONFIG_FB_SSD1307=m # Regulator drivers CONFIG_REGULATOR_FAN53555=m +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_RFKILL_REGULATOR=m +CONFIG_REGULATOR_GPIO=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8973=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_LP3972=m +CONFIG_REGULATOR_TPS51632=m +CONFIG_REGULATOR_TPS62360=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m + # Needs work/investigation # CONFIG_ARM_CHARLCD is not set diff --git a/kernel.spec b/kernel.spec index 9c6a88fab..fa33e72e4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1609,6 +1609,7 @@ BuildKernel() { make -s ARCH=$Arch V=1 dtbs mkdir -p $RPM_BUILD_ROOT/%{image_install_path}/dtb-$KernelVer install -m 644 arch/arm/boot/dts/*.dtb $RPM_BUILD_ROOT/boot/dtb-$KernelVer/ + rm -f arch/arm/boot/dts/*.dtb %else make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} %endif @@ -2334,6 +2335,9 @@ fi # ||----w | # || || %changelog +* Tue Mar 5 2013 Peter Robinson +- Fix Beagle (omap), update vexpress + * Tue Mar 05 2013 Josh Boyer - Backport 4 fixes for efivarfs (rhbz 917984) - Enable CONFIG_IP6_NF_TARGET_MASQUERADE From c03b60fe04081fb220366d516ca25575916be3a3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 6 Mar 2013 08:53:40 -0500 Subject: [PATCH 223/492] crypto: info leaks in report API (rhbz 918512 918521) --- ...to-user-fix-info-leaks-in-report-API.patch | 223 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 crypto-user-fix-info-leaks-in-report-API.patch diff --git a/crypto-user-fix-info-leaks-in-report-API.patch b/crypto-user-fix-info-leaks-in-report-API.patch new file mode 100644 index 000000000..1b64e1844 --- /dev/null +++ b/crypto-user-fix-info-leaks-in-report-API.patch @@ -0,0 +1,223 @@ +From 9a5467bf7b6e9e02ec9c3da4e23747c05faeaac6 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Tue, 5 Feb 2013 18:19:13 +0100 +Subject: [PATCH] crypto: user - fix info leaks in report API + +Three errors resulting in kernel memory disclosure: + +1/ The structures used for the netlink based crypto algorithm report API +are located on the stack. As snprintf() does not fill the remainder of +the buffer with null bytes, those stack bytes will be disclosed to users +of the API. Switch to strncpy() to fix this. + +2/ crypto_report_one() does not initialize all field of struct +crypto_user_alg. Fix this to fix the heap info leak. + +3/ For the module name we should copy only as many bytes as +module_name() returns -- not as much as the destination buffer could +hold. But the current code does not and therefore copies random data +from behind the end of the module name, as the module name is always +shorter than CRYPTO_MAX_ALG_NAME. + +Also switch to use strncpy() to copy the algorithm's name and +driver_name. They are strings, after all. + +Signed-off-by: Mathias Krause +Cc: Steffen Klassert +Signed-off-by: Herbert Xu +--- + crypto/ablkcipher.c | 12 ++++++------ + crypto/aead.c | 9 ++++----- + crypto/ahash.c | 2 +- + crypto/blkcipher.c | 6 +++--- + crypto/crypto_user.c | 22 +++++++++++----------- + crypto/pcompress.c | 3 +-- + crypto/rng.c | 2 +- + crypto/shash.c | 3 ++- + 8 files changed, 29 insertions(+), 30 deletions(-) + +diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c +index 533de95..7d4a8d2 100644 +--- a/crypto/ablkcipher.c ++++ b/crypto/ablkcipher.c +@@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_blkcipher rblkcipher; + +- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher"); +- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", +- alg->cra_ablkcipher.geniv ?: ""); ++ strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", ++ sizeof(rblkcipher.geniv)); + + rblkcipher.blocksize = alg->cra_blocksize; + rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; +@@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_blkcipher rblkcipher; + +- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher"); +- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", +- alg->cra_ablkcipher.geniv ?: ""); ++ strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", ++ sizeof(rblkcipher.geniv)); + + rblkcipher.blocksize = alg->cra_blocksize; + rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; +diff --git a/crypto/aead.c b/crypto/aead.c +index 4d04e12..547491e 100644 +--- a/crypto/aead.c ++++ b/crypto/aead.c +@@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) + struct crypto_report_aead raead; + struct aead_alg *aead = &alg->cra_aead; + +- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead"); +- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", +- aead->geniv ?: ""); ++ strncpy(raead.type, "aead", sizeof(raead.type)); ++ strncpy(raead.geniv, aead->geniv ?: "", sizeof(raead.geniv)); + + raead.blocksize = alg->cra_blocksize; + raead.maxauthsize = aead->maxauthsize; +@@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) + struct crypto_report_aead raead; + struct aead_alg *aead = &alg->cra_aead; + +- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead"); +- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv); ++ strncpy(raead.type, "nivaead", sizeof(raead.type)); ++ strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv)); + + raead.blocksize = alg->cra_blocksize; + raead.maxauthsize = aead->maxauthsize; +diff --git a/crypto/ahash.c b/crypto/ahash.c +index 3887856..793a27f 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_hash rhash; + +- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash"); ++ strncpy(rhash.type, "ahash", sizeof(rhash.type)); + + rhash.blocksize = alg->cra_blocksize; + rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; +diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c +index e9e7244..a79e7e9 100644 +--- a/crypto/blkcipher.c ++++ b/crypto/blkcipher.c +@@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_blkcipher rblkcipher; + +- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher"); +- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", +- alg->cra_blkcipher.geniv ?: ""); ++ strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); ++ strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", ++ sizeof(rblkcipher.geniv)); + + rblkcipher.blocksize = alg->cra_blocksize; + rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize; +diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c +index 35d700a..f6d9baf 100644 +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_cipher rcipher; + +- snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher"); ++ strncpy(rcipher.type, "cipher", sizeof(rcipher.type)); + + rcipher.blocksize = alg->cra_blocksize; + rcipher.min_keysize = alg->cra_cipher.cia_min_keysize; +@@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_comp rcomp; + +- snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression"); +- ++ strncpy(rcomp.type, "compression", sizeof(rcomp.type)); + if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, + sizeof(struct crypto_report_comp), &rcomp)) + goto nla_put_failure; +@@ -108,12 +107,14 @@ nla_put_failure: + static int crypto_report_one(struct crypto_alg *alg, + struct crypto_user_alg *ualg, struct sk_buff *skb) + { +- memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name)); +- memcpy(&ualg->cru_driver_name, &alg->cra_driver_name, +- sizeof(ualg->cru_driver_name)); +- memcpy(&ualg->cru_module_name, module_name(alg->cra_module), +- CRYPTO_MAX_ALG_NAME); +- ++ strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name)); ++ strncpy(ualg->cru_driver_name, alg->cra_driver_name, ++ sizeof(ualg->cru_driver_name)); ++ strncpy(ualg->cru_module_name, module_name(alg->cra_module), ++ sizeof(ualg->cru_module_name)); ++ ++ ualg->cru_type = 0; ++ ualg->cru_mask = 0; + ualg->cru_flags = alg->cra_flags; + ualg->cru_refcnt = atomic_read(&alg->cra_refcnt); + +@@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg, + if (alg->cra_flags & CRYPTO_ALG_LARVAL) { + struct crypto_report_larval rl; + +- snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval"); +- ++ strncpy(rl.type, "larval", sizeof(rl.type)); + if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL, + sizeof(struct crypto_report_larval), &rl)) + goto nla_put_failure; +diff --git a/crypto/pcompress.c b/crypto/pcompress.c +index 04e083f..7140fe7 100644 +--- a/crypto/pcompress.c ++++ b/crypto/pcompress.c +@@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_comp rpcomp; + +- snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp"); +- ++ strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type)); + if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, + sizeof(struct crypto_report_comp), &rpcomp)) + goto nla_put_failure; +diff --git a/crypto/rng.c b/crypto/rng.c +index f3b7894..e0a25c2 100644 +--- a/crypto/rng.c ++++ b/crypto/rng.c +@@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) + { + struct crypto_report_rng rrng; + +- snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng"); ++ strncpy(rrng.type, "rng", sizeof(rrng.type)); + + rrng.seedsize = alg->cra_rng.seedsize; + +diff --git a/crypto/shash.c b/crypto/shash.c +index f426330f..929058a 100644 +--- a/crypto/shash.c ++++ b/crypto/shash.c +@@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) + struct crypto_report_hash rhash; + struct shash_alg *salg = __crypto_shash_alg(alg); + +- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash"); ++ strncpy(rhash.type, "shash", sizeof(rhash.type)); ++ + rhash.blocksize = alg->cra_blocksize; + rhash.digestsize = salg->digestsize; + +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index fa33e72e4..8686d86cd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -758,6 +758,9 @@ Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch #rhbz 917984 Patch22264: efi-fixes-3.8.patch +#rhbz 918512 918521 +Patch22265: crypto-user-fix-info-leaks-in-report-API.patch + #rhbz 812111 Patch24000: alps.patch @@ -1474,6 +1477,9 @@ ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch #rhbz 917984 ApplyPatch efi-fixes-3.8.patch +#rhbz 918512 918521 +ApplyPatch crypto-user-fix-info-leaks-in-report-API.patch + ApplyPatch userns-avoid-recursion-in-put_user_ns.patch @@ -2335,6 +2341,9 @@ fi # ||----w | # || || %changelog +* Wed Mar 06 2013 Josh Boyer +- crypto: info leaks in report API (rhbz 918512 918521) + * Tue Mar 5 2013 Peter Robinson - Fix Beagle (omap), update vexpress From c1caf663bff8ee1b777edf277c54597fafa10fc7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 6 Mar 2013 09:00:46 -0500 Subject: [PATCH 224/492] Fix regression in secure-boot acpi_rsdp patch (rhbz 906225) --- kernel.spec | 5 +++-- ...130218.patch => secure-boot-20130219.patch | 21 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) rename secure-boot-20130218.patch => secure-boot-20130219.patch (98%) diff --git a/kernel.spec b/kernel.spec index 8686d86cd..496da7ed8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -669,7 +669,7 @@ Patch541: silence-tty-null.patch Patch800: crash-driver.patch # secure boot -Patch1000: secure-boot-20130218.patch +Patch1000: secure-boot-20130219.patch # virt + ksm patches @@ -1401,7 +1401,7 @@ ApplyPatch silence-tty-null.patch ApplyPatch crash-driver.patch # secure boot -ApplyPatch secure-boot-20130218.patch +ApplyPatch secure-boot-20130219.patch # Assorted Virt Fixes @@ -2342,6 +2342,7 @@ fi # || || %changelog * Wed Mar 06 2013 Josh Boyer +- Fix regression in secure-boot acpi_rsdp patch (rhbz 906225) - crypto: info leaks in report API (rhbz 918512 918521) * Tue Mar 5 2013 Peter Robinson diff --git a/secure-boot-20130218.patch b/secure-boot-20130219.patch similarity index 98% rename from secure-boot-20130218.patch rename to secure-boot-20130219.patch index 29ac46cd9..368cfed17 100644 --- a/secure-boot-20130218.patch +++ b/secure-boot-20130219.patch @@ -1092,7 +1092,7 @@ index fc28099..b5df7a8 100644 1.8.1.2 -From fe27dd192ef250abcbaba973a14d43b21d7be497 Mon Sep 17 00:00:00 2001 +From 19640bebdcabe48ce1789ce7a6a0d0d5b925f0b5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -1100,7 +1100,10 @@ Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure This option allows userspace to pass the RSDP address to the kernel. This could potentially be used to circumvent the secure boot trust model. -We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. +This is setup through the setup_arch function, which is called before the +security_init function sets up the security_ops, so we cannot use a +capable call here. We ignore the setting if we are booted in Secure Boot +mode. Signed-off-by: Josh Boyer --- @@ -1108,7 +1111,7 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index bd22f86..88251d2 100644 +index bd22f86..d68c04f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); @@ -1116,7 +1119,7 @@ index bd22f86..88251d2 100644 { #ifdef CONFIG_KEXEC - if (acpi_rsdp) -+ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) ++ if (acpi_rsdp && !efi_enabled(EFI_SECURE_BOOT)) return acpi_rsdp; #endif @@ -1124,7 +1127,7 @@ index bd22f86..88251d2 100644 1.8.1.2 -From c937b2c8e179bfdadb6617c0028f558e4d701e46 Mon Sep 17 00:00:00 2001 +From b9ab9c0b3356d9cde36f3ef3a0719623df2ee2d3 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 15/19] kexec: Disable in a secure boot environment @@ -1156,7 +1159,7 @@ index 5e4bd78..dd464e0 100644 1.8.1.2 -From f08e390045266d53543a55afa16ca4be5a1c6316 Mon Sep 17 00:00:00 2001 +From 23e0646e1df8a0b4c31333b71796294801355032 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot @@ -1218,7 +1221,7 @@ index eab0827..93a16dc 100644 1.8.1.2 -From 54ba1eec5847d964b1d458a240b50271b9a356a4 Mon Sep 17 00:00:00 2001 +From 833c54471c85e70e46d76f9f7ffa30197b9f135d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment @@ -1332,7 +1335,7 @@ index 4ed81e7..b11a0f4 100644 1.8.1.2 -From 686090054f6c3784218b318c7adcc3c1f0ca5069 Mon Sep 17 00:00:00 2001 +From 1a9afaa05489b817ebe84c61d22e958856aa0737 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Feb 2013 19:25:05 -0500 Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode @@ -1391,7 +1394,7 @@ index 96bd86b..6e1331c 100644 1.8.1.2 -From df607d2d5061b04f8a686cd74edd72c1f2836d8c Mon Sep 17 00:00:00 2001 +From 763f18d6a1e2d5f4d84ce3382ef91434240c80d6 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 8 Feb 2013 11:12:13 -0800 Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot From b266fd2521aefe3a8dbf226ffddd0f32a38c71ca Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 6 Mar 2013 10:07:15 -0600 Subject: [PATCH 225/492] Remove Ricoh multifunction DMAR patch as it's no longer needed (rhbz 880051) --- dmar-disable-when-ricoh-multifunction.patch | 33 --------------------- kernel.spec | 8 ++--- 2 files changed, 3 insertions(+), 38 deletions(-) delete mode 100644 dmar-disable-when-ricoh-multifunction.patch diff --git a/dmar-disable-when-ricoh-multifunction.patch b/dmar-disable-when-ricoh-multifunction.patch deleted file mode 100644 index 839db5940..000000000 --- a/dmar-disable-when-ricoh-multifunction.patch +++ /dev/null @@ -1,33 +0,0 @@ -From da7662784dcced04a5b7a3a5b2bbb8276d699522 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Sun, 17 Oct 2010 15:55:32 -0400 -Subject: [PATCH] dmar: disable if ricoh multifunction detected - ---- - drivers/pci/intel-iommu.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c -index 4789f8e..5923914 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c -@@ -3784,6 +3784,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_g - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); - -+/* https://bugzilla.redhat.com/show_bug.cgi?id=605888 */ -+static void quirk_ricoh_multifunction(struct pci_dev *dev) -+{ -+ dmar_disabled = 1; -+} -+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe822, quirk_ricoh_multifunction); -+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe230, quirk_ricoh_multifunction); -+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe832, quirk_ricoh_multifunction); -+DECLARE_PCI_FIXUP_HEADER(0x1180, 0xe476, quirk_ricoh_multifunction); -+ - /* On Tylersburg chipsets, some BIOSes have been known to enable the - ISOCH DMAR unit for the Azalia sound device, but not give it any - TLB entries, which causes it to deadlock. Check for that. We do --- -1.7.3.1 - diff --git a/kernel.spec b/kernel.spec index 496da7ed8..c20db58ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -703,8 +703,6 @@ Patch10000: fs-proc-devtree-remove_proc_entry.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12303: dmar-disable-when-ricoh-multifunction.patch - Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: hibernate-freeze-filesystems.patch @@ -1431,9 +1429,6 @@ ApplyPatch fs-proc-devtree-remove_proc_entry.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -# rhbz#605888 -ApplyPatch dmar-disable-when-ricoh-multifunction.patch - ApplyPatch efi-dont-map-boot-services-on-32bit.patch # FIXME: REBASE @@ -2341,6 +2336,9 @@ fi # ||----w | # || || %changelog +* Wed Mar 06 2013 Justin M. Forbes +- Remove Ricoh multifunction DMAR patch as it's no longer needed (rhbz 880051) + * Wed Mar 06 2013 Josh Boyer - Fix regression in secure-boot acpi_rsdp patch (rhbz 906225) - crypto: info leaks in report API (rhbz 918512 918521) From 831372f875b4cafe76f1e9154bdfe887f1c1f4ca Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 6 Mar 2013 13:20:45 -0600 Subject: [PATCH 226/492] Fix destroy_conntrack GPF (rhbz 859346) --- fix-destroy_conntrack-GPF.patch | 92 +++++++++++++++++++++++++++++++++ kernel.spec | 6 +++ 2 files changed, 98 insertions(+) create mode 100644 fix-destroy_conntrack-GPF.patch diff --git a/fix-destroy_conntrack-GPF.patch b/fix-destroy_conntrack-GPF.patch new file mode 100644 index 000000000..35ffa581d --- /dev/null +++ b/fix-destroy_conntrack-GPF.patch @@ -0,0 +1,92 @@ +On Wed, 2013-03-06 at 10:59 -0500, Dave Jones wrote: +> I know 3.7.9 is EOL, but this code doesn't look like it's changed in current. +> (unless the cause/fix was in code unrelated to these paths) +> +> A user reported the following GPF.. +> +> general protection fault: 0000 [#1] SMP +> Modules linked in: ipheth fuse ebtable_nat xt_CHECKSUM bridge stp llc ip6t_REJECT iptable_mangle nf_conntrack(-) ebtable_filter ebtables snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc hp_wmi snd_timer coretemp iTCO_wdt tg3 snd sparse_keymap rfkill soundcore iTCO_vendor_support lpc_ich i7core_edac edac_core serio_raw microcode mfd_core vhost_net tun macvtap macvlan kvm_intel kvm binfmt_misc uinput nouveau mxm_wmi crc32c_intel video i2c_algo_bit drm_kms_helper ttm firewire_ohci firewire_core drm crc_itu_t i2c_core wmi [last unloaded: xt_conntrack] +> CPU 2 +> Pid: 25407, comm: qemu-kvm Not tainted 3.7.9-205.fc18.x86_64 #1 Hewlett-Packard HP Z400 Workstation/0B4Ch +> RIP: 0010:[] [] destroy_conntrack+0x35/0x120 [nf_conntrack] +> RSP: 0018:ffff880276913d78 EFLAGS: 00010206 +> RAX: 50626b6b7876376c RBX: ffff88026e530d68 RCX: ffff88028d158e00 +> RDX: ffff88026d0d5470 RSI: 0000000000000011 RDI: 0000000000000002 +> RBP: ffff880276913d88 R08: 0000000000000000 R09: ffff880295002900 +> R10: 0000000000000000 R11: 0000000000000003 R12: ffffffff81ca3b40 +> R13: ffffffff8151a8e0 R14: ffff880270875000 R15: 0000000000000002 +> FS: 00007ff3bce38a00(0000) GS:ffff88029fc40000(0000) knlGS:0000000000000000 +> CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +> CR2: 00007fd1430bd000 CR3: 000000027042b000 CR4: 00000000000027e0 +> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +> Process qemu-kvm (pid: 25407, threadinfo ffff880276912000, task ffff88028c369720) +> Stack: +> ffff880156f59100 ffff880156f59100 ffff880276913d98 ffffffff815534f7 +> ffff880276913db8 ffffffff8151a74b ffff880270875000 ffff880156f59100 +> ffff880276913dd8 ffffffff8151a5a6 ffff880276913dd8 ffff88026d0d5470 +> Call Trace: +> [] nf_conntrack_destroy+0x17/0x20 +> [] skb_release_head_state+0x7b/0x100 +> [] __kfree_skb+0x16/0xa0 +> [] kfree_skb+0x36/0xa0 +> [] skb_queue_purge+0x20/0x40 +> [] __tun_detach+0x117/0x140 [tun] +> [] tun_chr_close+0x3c/0xd0 [tun] +> [] __fput+0xec/0x240 +> [] ____fput+0xe/0x10 +> [] task_work_run+0xa7/0xe0 +> [] do_notify_resume+0x71/0xb0 +> [] int_signal+0x12/0x17 +> Code: 00 00 04 48 89 e5 41 54 53 48 89 fb 4c 8b a7 e8 00 00 00 0f 85 de 00 00 00 0f b6 73 3e 0f b7 7b 2a e8 10 40 00 00 48 85 c0 74 0e <48> 8b 40 28 48 85 c0 74 05 48 89 df ff d0 48 c7 c7 08 6a 3a a0 +> RIP [] destroy_conntrack+0x35/0x120 [nf_conntrack] +> RSP +> +> +> +> /* To make sure we don't get any weird locking issues here: +> * destroy_conntrack() MUST NOT be called with a write lock +> * to nf_conntrack_lock!!! -HW */ +> rcu_read_lock(); +> l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); +> 1378: 0f b6 b3 86 00 00 00 movzbl 0x86(%rbx),%esi +> 137f: 0f b7 7b 72 movzwl 0x72(%rbx),%edi +> 1383: e8 00 00 00 00 callq 1388 +> if (l4proto && l4proto->destroy) +> 1388: 48 85 c0 test %rax,%rax +> 138b: 74 0e je 139b +> 138d: 48 8b 40 28 mov 0x28(%rax),%rax <----- HERE +> 1391: 48 85 c0 test %rax,%rax +> 1394: 74 05 je 139b +> l4proto->destroy(ct); +> 1396: 48 89 df mov %rbx,%rdi +> 1399: ff d0 callq *%rax +> +> +> l4proto (%rax) is garbage (0x50626b6b7876376c) which looks a little like ascii, +> but P>kkxv7l doesn't mean much to me. +> +> https://bugzilla.redhat.com/show_bug.cgi?id=917792 is the original report, but +> there aren't any further details yet. +> +> Dave +> + +tun driver lacks a nf_reset(skb) call + +I would try : + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 2c6a22e..b7c457a 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -747,6 +747,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + goto drop; + skb_orphan(skb); + ++ nf_reset(skb); ++ + /* Enqueue packet */ + skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); + + diff --git a/kernel.spec b/kernel.spec index c20db58ff..a9a0b7fd8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -764,6 +764,9 @@ Patch24000: alps.patch Patch24100: userns-avoid-recursion-in-put_user_ns.patch +#rhbz 859346 +Patch24101: fix-destroy_conntrack-GPF.patch + # END OF PATCH DEFINITIONS @@ -1477,6 +1480,8 @@ ApplyPatch crypto-user-fix-info-leaks-in-report-API.patch ApplyPatch userns-avoid-recursion-in-put_user_ns.patch +#rhbz 859346 +ApplyPatch fix-destroy_conntrack-GPF.patch # END OF PATCH APPLICATIONS @@ -2338,6 +2343,7 @@ fi %changelog * Wed Mar 06 2013 Justin M. Forbes - Remove Ricoh multifunction DMAR patch as it's no longer needed (rhbz 880051) +- Fix destroy_conntrack GPF (rhbz 859346) * Wed Mar 06 2013 Josh Boyer - Fix regression in secure-boot acpi_rsdp patch (rhbz 906225) From 2926c94913f8ef1cbf3a6499bc71598b8716cadf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 7 Mar 2013 07:56:22 -0500 Subject: [PATCH 227/492] CVE-2013-1792 keys: race condition in install_user_keyrings (rhbz 916646 919021) --- kernel.spec | 10 +++++++++- ...ce-with-concurrent-install_user_keyrings.patch | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 keys-fix-race-with-concurrent-install_user_keyrings.patch diff --git a/kernel.spec b/kernel.spec index a9a0b7fd8..ec8ad44dd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 205 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -759,6 +759,9 @@ Patch22264: efi-fixes-3.8.patch #rhbz 918512 918521 Patch22265: crypto-user-fix-info-leaks-in-report-API.patch +# CVE-2013-1792 rhbz 916646,919021 +Patch22266: keys-fix-race-with-concurrent-install_user_keyrings.patch + #rhbz 812111 Patch24000: alps.patch @@ -1483,6 +1486,8 @@ ApplyPatch userns-avoid-recursion-in-put_user_ns.patch #rhbz 859346 ApplyPatch fix-destroy_conntrack-GPF.patch +# CVE-2013-1792 rhbz 916646,919021 +ApplyPatch keys-fix-race-with-concurrent-install_user_keyrings.patch # END OF PATCH APPLICATIONS @@ -2341,6 +2346,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 07 2013 Josh Boyer +- CVE-2013-1792 keys: race condition in install_user_keyrings (rhbz 916646 919021) + * Wed Mar 06 2013 Justin M. Forbes - Remove Ricoh multifunction DMAR patch as it's no longer needed (rhbz 880051) - Fix destroy_conntrack GPF (rhbz 859346) diff --git a/keys-fix-race-with-concurrent-install_user_keyrings.patch b/keys-fix-race-with-concurrent-install_user_keyrings.patch new file mode 100644 index 000000000..ba7b30a6d --- /dev/null +++ b/keys-fix-race-with-concurrent-install_user_keyrings.patch @@ -0,0 +1,15 @@ +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index 58dfe08..c5ec083 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -57,7 +57,7 @@ int install_user_keyrings(void) + + kenter("%p{%u}", user, uid); + +- if (user->uid_keyring) { ++ if (user->uid_keyring && user->session_keyring) { + kleave(" = 0 [exist]"); + return 0; + } + + \ No newline at end of file From 500b36064772e8e7a1524d6ad4641f7d2d7c1a74 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 7 Mar 2013 13:10:52 -0500 Subject: [PATCH 228/492] Fix logitech-dj HID bug from Benjamin Tissoires (rhbz 840391) --- kernel.spec | 7 ++ ...l-hid_output_raw_report-during-probe.patch | 66 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch diff --git a/kernel.spec b/kernel.spec index ec8ad44dd..ccab30304 100644 --- a/kernel.spec +++ b/kernel.spec @@ -762,6 +762,9 @@ Patch22265: crypto-user-fix-info-leaks-in-report-API.patch # CVE-2013-1792 rhbz 916646,919021 Patch22266: keys-fix-race-with-concurrent-install_user_keyrings.patch +#rhbz 840391 +Patch22267: logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch + #rhbz 812111 Patch24000: alps.patch @@ -1489,6 +1492,9 @@ ApplyPatch fix-destroy_conntrack-GPF.patch # CVE-2013-1792 rhbz 916646,919021 ApplyPatch keys-fix-race-with-concurrent-install_user_keyrings.patch +#rhbz 840391 +ApplyPatch logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch + # END OF PATCH APPLICATIONS %endif @@ -2347,6 +2353,7 @@ fi # || || %changelog * Thu Mar 07 2013 Josh Boyer +- Fix logitech-dj HID bug from Benjamin Tissoires (rhbz 840391) - CVE-2013-1792 keys: race condition in install_user_keyrings (rhbz 916646 919021) * Wed Mar 06 2013 Justin M. Forbes diff --git a/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch b/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch new file mode 100644 index 000000000..68a524a94 --- /dev/null +++ b/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch @@ -0,0 +1,66 @@ +From dcd9006b1b053c7b1cebe81333261d4fd492ffeb Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Tue, 05 Mar 2013 16:09:00 +0000 +Subject: HID: logitech-dj: do not directly call hid_output_raw_report() during probe + +hid_output_raw_report() makes a direct call to usb_control_msg(). However, +some USB3 boards have shown that the usb device is not ready during the +.probe(). This blocks the entire usb device, and the paired mice, keyboards +are not functional. The dmesg output is the following: + +[ 11.912287] logitech-djreceiver 0003:046D:C52B.0003: hiddev0,hidraw0: USB HID v1.11 Device [Logitech USB Receiver] on usb-0000:00:14.0-2/input2 +[ 11.912537] logitech-djreceiver 0003:046D:C52B.0003: logi_dj_probe:logi_dj_recv_query_paired_devices error:-32 +[ 11.912636] logitech-djreceiver: probe of 0003:046D:C52B.0003 failed with error -32 + +Relying on the scheduled call to usbhid_submit_report() fixes the problem. + +related bugs: +https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1072082 +https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1039143 +https://bugzilla.redhat.com/show_bug.cgi?id=840391 +https://bugzilla.kernel.org/show_bug.cgi?id=49781 + +Reported-and-tested-by: Bob Bowles +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +--- +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 9500f2f..8758f38c 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, + struct dj_report *dj_report) + { + struct hid_device *hdev = djrcv_dev->hdev; +- int sent_bytes; ++ struct hid_report *report; ++ struct hid_report_enum *output_report_enum; ++ u8 *data = (u8 *)(&dj_report->device_index); ++ int i; + +- if (!hdev->hid_output_raw_report) { +- dev_err(&hdev->dev, "%s:" +- "hid_output_raw_report is null\n", __func__); ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (!report) { ++ dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__); + return -ENODEV; + } + +- sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report, +- sizeof(struct dj_report), +- HID_OUTPUT_REPORT); ++ for (i = 0; i < report->field[0]->report_count; i++) ++ report->field[0]->value[i] = data[i]; ++ ++ usbhid_submit_report(hdev, report, USB_DIR_OUT); + +- return (sent_bytes < 0) ? sent_bytes : 0; ++ return 0; + } + + static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) +-- +cgit v0.9.1 From 45e320120e43f6b516b9a596637bee48aa902d1d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 7 Mar 2013 14:42:38 -0500 Subject: [PATCH 229/492] Fix DMI regression (rhbz 916444) --- ...or-_dmi_-signature-in-smbios_present.patch | 47 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 54 insertions(+) create mode 100644 dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch diff --git a/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch b/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch new file mode 100644 index 000000000..f105a7e6a --- /dev/null +++ b/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch @@ -0,0 +1,47 @@ +From: Ben Hutchings +Subject: dmi_scan: fix missing check for _DMI_ signature in smbios_present() + +Commit 9f9c9cbb6057 ('drivers/firmware/dmi_scan.c: fetch dmi version from +SMBIOS if it exists') hoisted the check for "_DMI_" into +dmi_scan_machine(), which means that we don't bother to check for "_DMI_" +at offset 16 in an SMBIOS entry. smbios_present() may also call +dmi_present() for an address where we found "_SM_", if it failed further +validation. + +Check for "_DMI_" in smbios_present() before calling dmi_present(). + +Signed-off-by: Ben Hutchings +Reported-by: Tim McGrath +Tested-by: Tim Mcgrath +Cc: Zhenzhong Duan +Cc: +Signed-off-by: Andrew Morton +--- + + drivers/firmware/dmi_scan.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff -puN drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present drivers/firmware/dmi_scan.c +--- a/drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present ++++ a/drivers/firmware/dmi_scan.c +@@ -442,7 +442,6 @@ static int __init dmi_present(const char + static int __init smbios_present(const char __iomem *p) + { + u8 buf[32]; +- int offset = 0; + + memcpy_fromio(buf, p, 32); + if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { +@@ -461,9 +460,9 @@ static int __init smbios_present(const c + dmi_ver = 0x0206; + break; + } +- offset = 16; ++ return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); + } +- return dmi_present(buf + offset); ++ return 1; + } + + void __init dmi_scan_machine(void) +_ diff --git a/kernel.spec b/kernel.spec index ccab30304..324121c9c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -765,6 +765,9 @@ Patch22266: keys-fix-race-with-concurrent-install_user_keyrings.patch #rhbz 840391 Patch22267: logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch +#rhbz 916444 +Patch22268: dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch + #rhbz 812111 Patch24000: alps.patch @@ -1495,6 +1498,9 @@ ApplyPatch keys-fix-race-with-concurrent-install_user_keyrings.patch #rhbz 840391 ApplyPatch logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch +#rhbz 916444 +ApplyPatch dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch + # END OF PATCH APPLICATIONS %endif @@ -2353,6 +2359,7 @@ fi # || || %changelog * Thu Mar 07 2013 Josh Boyer +- Fix DMI regression (rhbz 916444) - Fix logitech-dj HID bug from Benjamin Tissoires (rhbz 840391) - CVE-2013-1792 keys: race condition in install_user_keyrings (rhbz 916646 919021) From a614d46fe4463c871cf104f0a69f2ebd51752a36 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Fri, 8 Mar 2013 07:23:52 +0000 Subject: [PATCH 230/492] - Have kernel provide kernel-highbank for upgrade to unified - Update mvebu configs - Drop unused ARM patches --- arm-fix-omapdrm.patch | 10 --------- arm-read_current_timer.patch | 39 ------------------------------------ config-armv7 | 9 +++++++-- kernel.spec | 15 +++++++------- 4 files changed, 15 insertions(+), 58 deletions(-) delete mode 100644 arm-fix-omapdrm.patch delete mode 100644 arm-read_current_timer.patch diff --git a/arm-fix-omapdrm.patch b/arm-fix-omapdrm.patch deleted file mode 100644 index f70b861fa..000000000 --- a/arm-fix-omapdrm.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- linux-3.6.0-0.rc3.git2.1.fc18.x86_64/drivers/staging/omapdrm/omap_drv.c.orig 2012-08-28 22:52:35.950826671 +0100 -+++ linux-3.6.0-0.rc3.git2.1.fc18.x86_64/drivers/staging/omapdrm/omap_drv.c 2012-08-28 22:52:49.393910353 +0100 -@@ -761,7 +761,6 @@ - .irq_postinstall = dev_irq_postinstall, - .irq_uninstall = dev_irq_uninstall, - .irq_handler = dev_irq_handler, -- .reclaim_buffers = drm_core_reclaim_buffers, - #ifdef CONFIG_DEBUG_FS - .debugfs_init = omap_debugfs_init, - .debugfs_cleanup = omap_debugfs_cleanup, diff --git a/arm-read_current_timer.patch b/arm-read_current_timer.patch deleted file mode 100644 index dc6a4447d..000000000 --- a/arm-read_current_timer.patch +++ /dev/null @@ -1,39 +0,0 @@ -read_current_timer is used in the get_cycles() function when -ARM_ARCH_TIMER is set, and that function can be inlined into -driver modules, so we should export the function to avoid -errors like - -ERROR: "read_current_timer" [drivers/video/udlfb.ko] undefined! -ERROR: "read_current_timer" [crypto/tcrypt.ko] undefined! - -Signed-off-by: Arnd Bergmann -Cc: Shinya Kuribayashi -Cc: Stephen Boyd -Cc: Will Deacon -Cc: Russell King ---- - arch/arm/kernel/arch_timer.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c -index cf25880..6327d1f 100644 ---- a/arch/arm/kernel/arch_timer.c -+++ b/arch/arm/kernel/arch_timer.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -232,6 +233,7 @@ int read_current_timer(unsigned long *timer_val) - *timer_val = arch_counter_get_cntpct(); - return 0; - } -+EXPORT_SYMBOL_GPL(read_current_timer); - - static struct clocksource clocksource_counter = { - .name = "arch_sys_counter", --- -1.7.10 diff --git a/config-armv7 b/config-armv7 index 0f8477544..fa0ea0ff1 100644 --- a/config-armv7 +++ b/config-armv7 @@ -186,7 +186,6 @@ CONFIG_ARM_AMBA=y # mvebu CONFIG_MV_XOR=y -CONFIG_RTC_DRV_88PM80X=m CONFIG_CRYPTO_DEV_MV_CESA=m CONFIG_MV643XX_ETH=m CONFIG_I2C_MV64XXX=m @@ -195,10 +194,16 @@ CONFIG_PINCTRL_ARMADA_370=y CONFIG_PINCTRL_ARMADA_XP=y CONFIG_PINCTRL_DOVE=y CONFIG_EDAC_MV64X60=m -CONFIG_MVNETA=m CONFIG_SATA_MV=m CONFIG_MARVELL_PHY=m CONFIG_RTC_DRV_S35390A=y +CONFIG_RTC_DRV_88PM80X=m +CONFIG_RTC_DRV_MV=m +CONFIG_MVMDIO=m +CONFIG_MVNETA=m +CONFIG_GPIO_MVEBU=y +CONFIG_MVEBU_CLK_CORE=y +CONFIG_MVEBU_CLK_GATING=y # Allwinner a1x # CONFIG_SUNXI_RFKILL=y diff --git a/kernel.spec b/kernel.spec index 324121c9c..2b824c457 100644 --- a/kernel.spec +++ b/kernel.spec @@ -256,9 +256,9 @@ Summary: The Linux kernel # kernel up (versatile express), tegra and omap are only built on armv7 hfp/sfp %ifnarch armv7hl armv7l +%endif %define with_omap 0 %define with_tegra 0 -%endif # kernel-kirkwood is only built for armv5 %ifnarch armv5tel @@ -485,6 +485,8 @@ Provides: kernel-drm = 4.3.0\ Provides: kernel-drm-nouveau = 16\ Provides: kernel-modeset = 1\ Provides: kernel-uname-r = %{KVERREL}%{?1:.%{1}}\ +Provides: kernel-highbank\ +Provides: kernel-highbank-uname-r = %{KVERREL}%{?1:.%{1}}\ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ @@ -714,13 +716,9 @@ Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM -Patch21000: arm-read_current_timer.patch # http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/137164.html Patch21002: arm-alignment-faults.patch -# OMAP -Patch21003: arm-fix-omapdrm.patch - # ARM tegra Patch21004: arm-tegra-nvec-kconfig.patch Patch21005: arm-tegra-usb-no-reset-linux33.patch @@ -1336,8 +1334,6 @@ ApplyPatch vmbugon-warnon.patch # # ARM # -#ApplyPatch arm-read_current_timer.patch -#ApplyPatch arm-fix-omapdrm.patch #ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch @@ -2358,6 +2354,11 @@ fi # ||----w | # || || %changelog +* Fri Mar 8 2013 Peter Robinson +- Have kernel provide kernel-highbank for upgrade to unified +- Update mvebu configs +- Drop unused ARM patches + * Thu Mar 07 2013 Josh Boyer - Fix DMI regression (rhbz 916444) - Fix logitech-dj HID bug from Benjamin Tissoires (rhbz 840391) From 21268df59d7895812f8c3ae07be48c7554304d9f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 8 Mar 2013 08:31:19 -0500 Subject: [PATCH 231/492] CVE-2013-1828 sctp: SCTP_GET_ASSOC_STATS stack buffer overflow (rhbz 919315 919316) --- kernel.spec | 9 ++++ ...e-parameter-size-for-SCTP_GET_ASSOC_.patch | 54 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch diff --git a/kernel.spec b/kernel.spec index 2b824c457..5cd41dfec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -766,6 +766,9 @@ Patch22267: logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe. #rhbz 916444 Patch22268: dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch +#CVE-2013-1828 rhbz 919315 919316 +Patch22269: net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch + #rhbz 812111 Patch24000: alps.patch @@ -1497,6 +1500,9 @@ ApplyPatch logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.p #rhbz 916444 ApplyPatch dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch +#CVE-2013-1828 rhbz 919315 919316 +ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch + # END OF PATCH APPLICATIONS %endif @@ -2354,6 +2360,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 08 2013 Josh Boyer +- CVE-2013-1828 sctp: SCTP_GET_ASSOC_STATS stack buffer overflow (rhbz 919315 919316) + * Fri Mar 8 2013 Peter Robinson - Have kernel provide kernel-highbank for upgrade to unified - Update mvebu configs diff --git a/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch b/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch new file mode 100644 index 000000000..bb976c593 --- /dev/null +++ b/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch @@ -0,0 +1,54 @@ +From 726bc6b092da4c093eb74d13c07184b18c1af0f1 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Wed, 27 Feb 2013 10:57:31 +0000 +Subject: [PATCH] net/sctp: Validate parameter size for SCTP_GET_ASSOC_STATS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Building sctp may fail with: + +In function ‘copy_from_user’, + inlined from ‘sctp_getsockopt_assoc_stats’ at + net/sctp/socket.c:5656:20: +arch/x86/include/asm/uaccess_32.h:211:26: error: call to + ‘copy_from_user_overflow’ declared with attribute error: copy_from_user() + buffer size is not provably correct + +if built with W=1 due to a missing parameter size validation +before the call to copy_from_user. + +Signed-off-by: Guenter Roeck +Acked-by: Vlad Yasevich +Signed-off-by: David S. Miller +--- + net/sctp/socket.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index cedd9bf..9ef5c73 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, + if (len < sizeof(sctp_assoc_t)) + return -EINVAL; + ++ /* Allow the struct to grow and fill in as much as possible */ ++ len = min_t(size_t, len, sizeof(sas)); ++ + if (copy_from_user(&sas, optval, len)) + return -EFAULT; + +@@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, + /* Mark beginning of a new observation period */ + asoc->stats.max_obs_rto = asoc->rto_min; + +- /* Allow the struct to grow and fill in as much as possible */ +- len = min_t(size_t, len, sizeof(sas)); +- + if (put_user(len, optlen)) + return -EFAULT; + +-- +1.8.1.2 + From 0a5c26d7c81b2e31826a54998800942baadc1c21 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 8 Mar 2013 07:35:01 -0600 Subject: [PATCH 232/492] Revert write backlight harder until better solution is found (rhbz 917353) --- backlight_revert.patch | 61 ++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 10 ++++++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 backlight_revert.patch diff --git a/backlight_revert.patch b/backlight_revert.patch new file mode 100644 index 000000000..6d2957c2a --- /dev/null +++ b/backlight_revert.patch @@ -0,0 +1,61 @@ +commit cf0a6584aa6d382f802f2c3cacac23ccbccde0cd +Author: Daniel Vetter +Date: Wed Feb 6 11:24:41 2013 +0100 + + drm/i915: write backlight harder + + 770c12312ad617172b1a65b911d3e6564fc5aca8 is the first bad commit + commit 770c12312ad617172b1a65b911d3e6564fc5aca8 + Author: Takashi Iwai + Date: Sat Aug 11 08:56:42 2012 +0200 + + drm/i915: Fix blank panel at reopening lid + + changed the register write sequence for restoring the backlight, which + helped prevent non-working backlights on some machines. Turns out that + the original sequence was the right thing to do for a different set of + machines. Worse, setting the backlight level _after_ enabling it seems + to reset it somehow. So we need to make that one conditional upon the + backlight having been reset to zero, and add the old one back. + + Cargo-culting at it's best, but it seems to work. + + Cc: stable@vger.kernel.org + Cc: Takashi Iwai + Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47941 + Reviewed-by: Jani Nikula + Acked-by: Takashi Iwai + Signed-off-by: Daniel Vetter + +diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c +index bee8cb6..a3730e0 100644 +--- a/drivers/gpu/drm/i915/intel_panel.c ++++ b/drivers/gpu/drm/i915/intel_panel.c +@@ -321,6 +321,9 @@ void intel_panel_enable_backlight(struct drm_device *dev, + if (dev_priv->backlight_level == 0) + dev_priv->backlight_level = intel_panel_get_max_backlight(dev); + ++ dev_priv->backlight_enabled = true; ++ intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); ++ + if (INTEL_INFO(dev)->gen >= 4) { + uint32_t reg, tmp; + +@@ -356,12 +359,12 @@ void intel_panel_enable_backlight(struct drm_device *dev, + } + + set_level: +- /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. +- * BLC_PWM_CPU_CTL may be cleared to zero automatically when these +- * registers are set. ++ /* Check the current backlight level and try to set again if it's zero. ++ * On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically ++ * when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written. + */ +- dev_priv->backlight_enabled = true; +- intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); ++ if (!intel_panel_get_backlight(dev)) ++ intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); + } + + static void intel_panel_init_backlight(struct drm_device *dev) diff --git a/kernel.spec b/kernel.spec index 5cd41dfec..423793ceb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 205 +%global baserelease 206 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -777,6 +777,8 @@ Patch24100: userns-avoid-recursion-in-put_user_ns.patch #rhbz 859346 Patch24101: fix-destroy_conntrack-GPF.patch +#rhbz 917353 +Patch24102: backlight_revert.patch # END OF PATCH DEFINITIONS @@ -1503,6 +1505,9 @@ ApplyPatch dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patc #CVE-2013-1828 rhbz 919315 919316 ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch +#rhbz 917353 +ApplyPatch backlight_revert.patch -R + # END OF PATCH APPLICATIONS %endif @@ -2360,6 +2365,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 08 2013 Justin M. Forbes +- Revert "write backlight harder" until better solution is found (rhbz 917353) + * Fri Mar 08 2013 Josh Boyer - CVE-2013-1828 sctp: SCTP_GET_ASSOC_STATS stack buffer overflow (rhbz 919315 919316) From 9436a43c32c6b35849d8e7a362886489705557a7 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 8 Mar 2013 07:56:38 -0600 Subject: [PATCH 233/492] Update team driver from net-next from Jiri Pirko --- kernel.spec | 6 + team-net-next-update-20130307.patch | 608 ++++++++++++++++++++++++++++ 2 files changed, 614 insertions(+) create mode 100644 team-net-next-update-20130307.patch diff --git a/kernel.spec b/kernel.spec index 423793ceb..d0780e69e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -711,6 +711,8 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch +Patch14011: team-net-next-update-20130307.patch + Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -1508,6 +1510,9 @@ ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch #rhbz 917353 ApplyPatch backlight_revert.patch -R +#Team Driver update +ApplyPatch team-net-next-update-20130307.patch + # END OF PATCH APPLICATIONS %endif @@ -2367,6 +2372,7 @@ fi %changelog * Fri Mar 08 2013 Justin M. Forbes - Revert "write backlight harder" until better solution is found (rhbz 917353) +- Update team driver from net-next from Jiri Pirko * Fri Mar 08 2013 Josh Boyer - CVE-2013-1828 sctp: SCTP_GET_ASSOC_STATS stack buffer overflow (rhbz 919315 919316) diff --git a/team-net-next-update-20130307.patch b/team-net-next-update-20130307.patch new file mode 100644 index 000000000..ebaa06762 --- /dev/null +++ b/team-net-next-update-20130307.patch @@ -0,0 +1,608 @@ +Update team driver to 3.9-rc1. + +Split patches available here: +http://people.redhat.com/jpirko/f18_team_update_4/ + +Flavio Leitner (5): + team: implement carrier change + team: add ethtool support + team: update master carrier state + team: use strlcpy with ethtool_drvinfo fields + team: allow userspace to take control over carrier + +Jiri Pirko (5): + rtnl: expose carrier value with possibility to set it + net: add change_carrier netdev op + team: handle sending port list in the same way option list is sent + team: move netlink event notifiers after team_port_leave() + team: ab: set active port option as changed when port is leaving + + Documentation/networking/operstates.txt | 4 + + drivers/net/team/team.c | 246 +++++++++++++++++++----------- + drivers/net/team/team_mode_activebackup.c | 13 +- + include/linux/if_team.h | 1 + + include/linux/netdevice.h | 12 ++ + include/uapi/linux/if_link.h | 1 + + net/core/dev.c | 19 +++ + net/core/rtnetlink.c | 10 ++ + 8 files changed, 215 insertions(+), 91 deletions(-) + +Signed-off-by: Jiri Pirko + +diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt +index 1a77a3c..9769457 100644 +--- a/Documentation/networking/operstates.txt ++++ b/Documentation/networking/operstates.txt +@@ -88,6 +88,10 @@ set this flag. On netif_carrier_off(), the scheduler stops sending + packets. The name 'carrier' and the inversion are historical, think of + it as lower layer. + ++Note that for certain kind of soft-devices, which are not managing any ++real hardware, there is possible to set this bit from userpsace. ++One should use TVL IFLA_CARRIER to do so. ++ + netif_carrier_ok() can be used to query that bit. + + __LINK_STATE_DORMANT, maps to IFF_DORMANT: +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index ad86660..9e68014 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #define DRV_NAME "team" +@@ -507,6 +508,7 @@ static bool team_is_mode_set(struct team *team) + + static void team_set_no_mode(struct team *team) + { ++ team->user_carrier_enabled = false; + team->mode = &__team_no_mode; + } + +@@ -1129,10 +1131,6 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + return -ENOENT; + } + +- __team_option_inst_mark_removed_port(team, port); +- __team_options_change_check(team); +- __team_option_inst_del_port(team, port); +- __team_port_change_port_removed(port); + team_port_disable(team, port); + list_del_rcu(&port->list); + netdev_rx_handler_unregister(port_dev); +@@ -1141,6 +1139,12 @@ static int team_port_del(struct team *team, struct net_device *port_dev) + vlan_vids_del_by_dev(port_dev, dev); + dev_close(port_dev); + team_port_leave(team, port); ++ ++ __team_option_inst_mark_removed_port(team, port); ++ __team_options_change_check(team); ++ __team_option_inst_del_port(team, port); ++ __team_port_change_port_removed(port); ++ + team_port_set_orig_dev_addr(port); + dev_set_mtu(port_dev, port->orig.mtu); + synchronize_rcu(); +@@ -1399,13 +1403,11 @@ static void team_destructor(struct net_device *dev) + + static int team_open(struct net_device *dev) + { +- netif_carrier_on(dev); + return 0; + } + + static int team_close(struct net_device *dev) + { +- netif_carrier_off(dev); + return 0; + } + +@@ -1707,6 +1709,19 @@ static netdev_features_t team_fix_features(struct net_device *dev, + return features; + } + ++static int team_change_carrier(struct net_device *dev, bool new_carrier) ++{ ++ struct team *team = netdev_priv(dev); ++ ++ team->user_carrier_enabled = true; ++ ++ if (new_carrier) ++ netif_carrier_on(dev); ++ else ++ netif_carrier_off(dev); ++ return 0; ++} ++ + static const struct net_device_ops team_netdev_ops = { + .ndo_init = team_init, + .ndo_uninit = team_uninit, +@@ -1729,8 +1744,24 @@ static const struct net_device_ops team_netdev_ops = { + .ndo_add_slave = team_add_slave, + .ndo_del_slave = team_del_slave, + .ndo_fix_features = team_fix_features, ++ .ndo_change_carrier = team_change_carrier, + }; + ++/*********************** ++ * ethtool interface ++ ***********************/ ++ ++static void team_ethtool_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *drvinfo) ++{ ++ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version)); ++} ++ ++static const struct ethtool_ops team_ethtool_ops = { ++ .get_drvinfo = team_ethtool_get_drvinfo, ++ .get_link = ethtool_op_get_link, ++}; + + /*********************** + * rt netlink interface +@@ -1780,6 +1811,7 @@ static void team_setup(struct net_device *dev) + ether_setup(dev); + + dev->netdev_ops = &team_netdev_ops; ++ dev->ethtool_ops = &team_ethtool_ops; + dev->destructor = team_destructor; + dev->tx_queue_len = 0; + dev->flags |= IFF_MULTICAST; +@@ -1941,30 +1973,6 @@ static void team_nl_team_put(struct team *team) + dev_put(team->dev); + } + +-static int team_nl_send_generic(struct genl_info *info, struct team *team, +- int (*fill_func)(struct sk_buff *skb, +- struct genl_info *info, +- int flags, struct team *team)) +-{ +- struct sk_buff *skb; +- int err; +- +- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +- if (!skb) +- return -ENOMEM; +- +- err = fill_func(skb, info, NLM_F_ACK, team); +- if (err < 0) +- goto err_fill; +- +- err = genlmsg_unicast(genl_info_net(info), skb, info->snd_portid); +- return err; +- +-err_fill: +- nlmsg_free(skb); +- return err; +-} +- + typedef int team_nl_send_func_t(struct sk_buff *skb, + struct team *team, u32 portid); + +@@ -2309,16 +2317,57 @@ team_put: + return err; + } + +-static int team_nl_fill_port_list_get(struct sk_buff *skb, +- u32 portid, u32 seq, int flags, +- struct team *team, +- bool fillall) ++static int team_nl_fill_one_port_get(struct sk_buff *skb, ++ struct team_port *port) ++{ ++ struct nlattr *port_item; ++ ++ port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); ++ if (!port_item) ++ goto nest_cancel; ++ if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) ++ goto nest_cancel; ++ if (port->changed) { ++ if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) ++ goto nest_cancel; ++ port->changed = false; ++ } ++ if ((port->removed && ++ nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || ++ (port->state.linkup && ++ nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || ++ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || ++ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) ++ goto nest_cancel; ++ nla_nest_end(skb, port_item); ++ return 0; ++ ++nest_cancel: ++ nla_nest_cancel(skb, port_item); ++ return -EMSGSIZE; ++} ++ ++static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq, ++ int flags, team_nl_send_func_t *send_func, ++ struct team_port *one_port) + { + struct nlattr *port_list; ++ struct nlmsghdr *nlh; + void *hdr; + struct team_port *port; ++ int err; ++ struct sk_buff *skb = NULL; ++ bool incomplete; ++ int i; ++ ++ port = list_first_entry(&team->port_list, struct team_port, list); + +- hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags, ++start_again: ++ err = __send_and_alloc_skb(&skb, team, portid, send_func); ++ if (err) ++ return err; ++ ++ hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, + TEAM_CMD_PORT_LIST_GET); + if (!hdr) + return -EMSGSIZE; +@@ -2329,47 +2378,54 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, + if (!port_list) + goto nla_put_failure; + +- list_for_each_entry(port, &team->port_list, list) { +- struct nlattr *port_item; ++ i = 0; ++ incomplete = false; + +- /* Include only changed ports if fill all mode is not on */ +- if (!fillall && !port->changed) +- continue; +- port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); +- if (!port_item) +- goto nla_put_failure; +- if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) +- goto nla_put_failure; +- if (port->changed) { +- if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) +- goto nla_put_failure; +- port->changed = false; ++ /* If one port is selected, called wants to send port list containing ++ * only this port. Otherwise go through all listed ports and send all ++ */ ++ if (one_port) { ++ err = team_nl_fill_one_port_get(skb, one_port); ++ if (err) ++ goto errout; ++ } else { ++ list_for_each_entry(port, &team->port_list, list) { ++ err = team_nl_fill_one_port_get(skb, port); ++ if (err) { ++ if (err == -EMSGSIZE) { ++ if (!i) ++ goto errout; ++ incomplete = true; ++ break; ++ } ++ goto errout; ++ } ++ i++; + } +- if ((port->removed && +- nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || +- (port->state.linkup && +- nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || +- nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || +- nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) +- goto nla_put_failure; +- nla_nest_end(skb, port_item); + } + + nla_nest_end(skb, port_list); +- return genlmsg_end(skb, hdr); ++ genlmsg_end(skb, hdr); ++ if (incomplete) ++ goto start_again; ++ ++send_done: ++ nlh = nlmsg_put(skb, portid, seq, NLMSG_DONE, 0, flags | NLM_F_MULTI); ++ if (!nlh) { ++ err = __send_and_alloc_skb(&skb, team, portid, send_func); ++ if (err) ++ goto errout; ++ goto send_done; ++ } ++ ++ return send_func(skb, team, portid); + + nla_put_failure: ++ err = -EMSGSIZE; ++errout: + genlmsg_cancel(skb, hdr); +- return -EMSGSIZE; +-} +- +-static int team_nl_fill_port_list_get_all(struct sk_buff *skb, +- struct genl_info *info, int flags, +- struct team *team) +-{ +- return team_nl_fill_port_list_get(skb, info->snd_portid, +- info->snd_seq, NLM_F_ACK, +- team, true); ++ nlmsg_free(skb); ++ return err; + } + + static int team_nl_cmd_port_list_get(struct sk_buff *skb, +@@ -2382,7 +2438,8 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb, + if (!team) + return -EINVAL; + +- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all); ++ err = team_nl_send_port_list_get(team, info->snd_portid, info->snd_seq, ++ NLM_F_ACK, team_nl_send_unicast, NULL); + + team_nl_team_put(team); + +@@ -2433,27 +2490,11 @@ static int team_nl_send_event_options_get(struct team *team, + sel_opt_inst_list); + } + +-static int team_nl_send_event_port_list_get(struct team *team) ++static int team_nl_send_event_port_get(struct team *team, ++ struct team_port *port) + { +- struct sk_buff *skb; +- int err; +- struct net *net = dev_net(team->dev); +- +- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +- if (!skb) +- return -ENOMEM; +- +- err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false); +- if (err < 0) +- goto err_fill; +- +- err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, +- GFP_KERNEL); +- return err; +- +-err_fill: +- nlmsg_free(skb); +- return err; ++ return team_nl_send_port_list_get(team, 0, 0, 0, team_nl_send_multicast, ++ port); + } + + static int team_nl_init(void) +@@ -2526,28 +2567,53 @@ static void __team_port_change_send(struct team_port *port, bool linkup) + port->state.duplex = 0; + + send_event: +- err = team_nl_send_event_port_list_get(port->team); ++ err = team_nl_send_event_port_get(port->team, port); + if (err && err != -ESRCH) + netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", + port->dev->name, err); + + } + ++static void __team_carrier_check(struct team *team) ++{ ++ struct team_port *port; ++ bool team_linkup; ++ ++ if (team->user_carrier_enabled) ++ return; ++ ++ team_linkup = false; ++ list_for_each_entry(port, &team->port_list, list) { ++ if (port->linkup) { ++ team_linkup = true; ++ break; ++ } ++ } ++ ++ if (team_linkup) ++ netif_carrier_on(team->dev); ++ else ++ netif_carrier_off(team->dev); ++} ++ + static void __team_port_change_check(struct team_port *port, bool linkup) + { + if (port->state.linkup != linkup) + __team_port_change_send(port, linkup); ++ __team_carrier_check(port->team); + } + + static void __team_port_change_port_added(struct team_port *port, bool linkup) + { + __team_port_change_send(port, linkup); ++ __team_carrier_check(port->team); + } + + static void __team_port_change_port_removed(struct team_port *port) + { + port->removed = true; + __team_port_change_send(port, false); ++ __team_carrier_check(port->team); + } + + static void team_port_change_check(struct team_port *port, bool linkup) +diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c +index 6262b4d..40fd338 100644 +--- a/drivers/net/team/team_mode_activebackup.c ++++ b/drivers/net/team/team_mode_activebackup.c +@@ -19,6 +19,7 @@ + + struct ab_priv { + struct team_port __rcu *active_port; ++ struct team_option_inst_info *ap_opt_inst_info; + }; + + static struct ab_priv *ab_priv(struct team *team) +@@ -54,8 +55,17 @@ drop: + + static void ab_port_leave(struct team *team, struct team_port *port) + { +- if (ab_priv(team)->active_port == port) ++ if (ab_priv(team)->active_port == port) { + RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); ++ team_option_inst_set_change(ab_priv(team)->ap_opt_inst_info); ++ } ++} ++ ++static int ab_active_port_init(struct team *team, ++ struct team_option_inst_info *info) ++{ ++ ab_priv(team)->ap_opt_inst_info = info; ++ return 0; + } + + static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) +@@ -88,6 +98,7 @@ static const struct team_option ab_options[] = { + { + .name = "activeport", + .type = TEAM_OPTION_TYPE_U32, ++ .init = ab_active_port_init, + .getter = ab_active_port_get, + .setter = ab_active_port_set, + }, +diff --git a/include/linux/if_team.h b/include/linux/if_team.h +index 0245def..4648d80 100644 +--- a/include/linux/if_team.h ++++ b/include/linux/if_team.h +@@ -186,6 +186,7 @@ struct team { + + const struct team_mode *mode; + struct team_mode_ops ops; ++ bool user_carrier_enabled; + bool queue_override_enabled; + struct list_head *qom_lists; /* array of queue override mapping lists */ + long mode_priv[TEAM_MODE_PRIV_LONGS]; +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 9ef07d0..7ebddc7 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -894,6 +894,14 @@ struct netdev_fcoe_hbainfo { + * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh) + * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq, + * struct net_device *dev) ++ * ++ * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); ++ * Called to change device carrier. Soft-devices (like dummy, team, etc) ++ * which do not represent real hardware may define this to allow their ++ * userspace components to manage their virtual carrier state. Devices ++ * that determine carrier state from physical hardware properties (eg ++ * network cables) or protocol-dependent mechanisms (eg ++ * USB_CDC_NOTIFY_NETWORK_CONNECTION) should NOT implement this function. + */ + struct net_device_ops { + int (*ndo_init)(struct net_device *dev); +@@ -1011,6 +1019,8 @@ struct net_device_ops { + int (*ndo_bridge_getlink)(struct sk_buff *skb, + u32 pid, u32 seq, + struct net_device *dev); ++ int (*ndo_change_carrier)(struct net_device *dev, ++ bool new_carrier); + }; + + /* +@@ -2197,6 +2207,8 @@ extern int dev_set_mtu(struct net_device *, int); + extern void dev_set_group(struct net_device *, int); + extern int dev_set_mac_address(struct net_device *, + struct sockaddr *); ++extern int dev_change_carrier(struct net_device *, ++ bool new_carrier); + extern int dev_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev, + struct netdev_queue *txq); +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 60f3b6b..c4edfe1 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -142,6 +142,7 @@ enum { + #define IFLA_PROMISCUITY IFLA_PROMISCUITY + IFLA_NUM_TX_QUEUES, + IFLA_NUM_RX_QUEUES, ++ IFLA_CARRIER, + __IFLA_MAX + }; + +diff --git a/net/core/dev.c b/net/core/dev.c +index f64e439..e0045ba 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -5027,6 +5027,25 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) + } + EXPORT_SYMBOL(dev_set_mac_address); + ++/** ++ * dev_change_carrier - Change device carrier ++ * @dev: device ++ * @new_carries: new value ++ * ++ * Change device carrier ++ */ ++int dev_change_carrier(struct net_device *dev, bool new_carrier) ++{ ++ const struct net_device_ops *ops = dev->netdev_ops; ++ ++ if (!ops->ndo_change_carrier) ++ return -EOPNOTSUPP; ++ if (!netif_device_present(dev)) ++ return -ENODEV; ++ return ops->ndo_change_carrier(dev, new_carrier); ++} ++EXPORT_SYMBOL(dev_change_carrier); ++ + /* + * Perform the SIOCxIFxxx calls, inside rcu_read_lock() + */ +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 1868625..2ef7a56 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -780,6 +780,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + + nla_total_size(4) /* IFLA_MTU */ + + nla_total_size(4) /* IFLA_LINK */ + + nla_total_size(4) /* IFLA_MASTER */ ++ + nla_total_size(1) /* IFLA_CARRIER */ + + nla_total_size(4) /* IFLA_PROMISCUITY */ + + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */ + + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ +@@ -909,6 +910,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, + nla_put_u32(skb, IFLA_LINK, dev->iflink)) || + (dev->master && + nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) || ++ nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) || + (dev->qdisc && + nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || + (dev->ifalias && +@@ -1108,6 +1110,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { + [IFLA_MTU] = { .type = NLA_U32 }, + [IFLA_LINK] = { .type = NLA_U32 }, + [IFLA_MASTER] = { .type = NLA_U32 }, ++ [IFLA_CARRIER] = { .type = NLA_U8 }, + [IFLA_TXQLEN] = { .type = NLA_U32 }, + [IFLA_WEIGHT] = { .type = NLA_U32 }, + [IFLA_OPERSTATE] = { .type = NLA_U8 }, +@@ -1438,6 +1441,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, + modified = 1; + } + ++ if (tb[IFLA_CARRIER]) { ++ err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER])); ++ if (err) ++ goto errout; ++ modified = 1; ++ } ++ + if (tb[IFLA_TXQLEN]) + dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); + From 3bcafa2d7a81daa1bf3cbaab4865f5ecc353f244 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 8 Mar 2013 17:30:59 -0500 Subject: [PATCH 234/492] Add turbostat and x86_engery_perf_policy debuginfo to kernel-tools-debuginfo --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d0780e69e..69ee03852 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 206 +%global baserelease 207 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -931,7 +931,7 @@ This package provides debug information for package kernel-tools. # symlinks because of the trailing nonmatching alternation and # the leading .*, because of find-debuginfo.sh's buggy handling # of matching the pattern against the symlinks file. -%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|XXX' -o kernel-tools-debuginfo.list} +%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|.*%%{_bindir}/turbostat(\.debug)?|.*%%{_bindir}/x86_energy_perf_policy(\.debug)?|XXX' -o kernel-tools-debuginfo.list} %endif # with_tools @@ -2370,6 +2370,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 08 2013 Josh Boyer +- Add turbostat and x86_engery_perf_policy debuginfo to kernel-tools-debuginfo + * Fri Mar 08 2013 Justin M. Forbes - Revert "write backlight harder" until better solution is found (rhbz 917353) - Update team driver from net-next from Jiri Pirko From e39dc443b87f602ab846c80e2987b22b3bf85eba Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sat, 9 Mar 2013 10:45:05 +0000 Subject: [PATCH 235/492] renable accidentally disabled omap/tegra kernels --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 69ee03852..953c36675 100644 --- a/kernel.spec +++ b/kernel.spec @@ -256,9 +256,9 @@ Summary: The Linux kernel # kernel up (versatile express), tegra and omap are only built on armv7 hfp/sfp %ifnarch armv7hl armv7l -%endif %define with_omap 0 %define with_tegra 0 +%endif # kernel-kirkwood is only built for armv5 %ifnarch armv5tel From a886d7d7b96840e744ac4458267b0235828a313d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Mar 2013 09:06:11 -0400 Subject: [PATCH 236/492] Add patch to fix broken tty handling (rhbz 904182) --- TTY-do-not-reset-master-s-packet-mode.patch | 63 +++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 TTY-do-not-reset-master-s-packet-mode.patch diff --git a/TTY-do-not-reset-master-s-packet-mode.patch b/TTY-do-not-reset-master-s-packet-mode.patch new file mode 100644 index 000000000..633bfcf46 --- /dev/null +++ b/TTY-do-not-reset-master-s-packet-mode.patch @@ -0,0 +1,63 @@ +From b81273a132177edd806476b953f6afeb17b786d5 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Tue, 15 Jan 2013 23:26:22 +0100 +Subject: [PATCH] TTY: do not reset master's packet mode + +Now that login from util-linux is forced to drop all references to a +TTY which it wants to hangup (to reach reference count 1) we are +seeing issues with telnet. When login closes its last reference to the +slave PTY, it also resets packet mode on the *master* side. And we +have a race here. + +What telnet does is fork+exec of `login'. Then there are two +scenarios: +* `login' closes the slave TTY and resets thus master's packet mode, + but even now telnet properly sets the mode, or +* `telnetd' sets packet mode on the master, `login' closes the slave + TTY and resets master's packet mode. + +The former case is OK. However the latter happens in much more cases, +by the order of magnitude to be precise. So when one tries to login to +such a messed telnet setup, they see the following: +inux login: + ogin incorrect + +Note the missing first letters -- telnet thinks it is still in the +packet mode, so when it receives "linux login" from `login', it +considers "l" as the type of the packet and strips it. + +SuS does not mention how the implementation should behave. Both BSDs I +checked (Free and Net) do not reset the flag upon the last close. + +By this I am resurrecting an old bug, see References. We are hitting +it regularly now, i.e. with updated util-linux, ergo login. + +Here, I am changing a behavior introduced back in 2.1 times. It would +better have a long time testing before goes upstream. + +Signed-off-by: Jiri Slaby +Cc: Mauro Carvalho Chehab +Cc: Bryan Mason +References: https://lkml.org/lkml/2009/11/11/223 +References: https://bugzilla.redhat.com/show_bug.cgi?id=504703 +References: https://bugzilla.novell.com/show_bug.cgi?id=797042 +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/pty.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c +index 4ec11f3..40ff2bf 100644 +--- a/drivers/tty/pty.c ++++ b/drivers/tty/pty.c +@@ -47,7 +47,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) + /* Review - krefs on tty_link ?? */ + if (!tty->link) + return; +- tty->link->packet = 0; + set_bit(TTY_OTHER_CLOSED, &tty->link->flags); + wake_up_interruptible(&tty->link->read_wait); + wake_up_interruptible(&tty->link->write_wait); +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 953c36675..a1b59c009 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 207 +%global baserelease 208 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -782,6 +782,9 @@ Patch24101: fix-destroy_conntrack-GPF.patch #rhbz 917353 Patch24102: backlight_revert.patch +#rhbz 904182 +Patch24103: TTY-do-not-reset-master-s-packet-mode.patch + # END OF PATCH DEFINITIONS %endif @@ -1513,6 +1516,9 @@ ApplyPatch backlight_revert.patch -R #Team Driver update ApplyPatch team-net-next-update-20130307.patch +#rhbz 904182 +ApplyPatch TTY-do-not-reset-master-s-packet-mode.patch + # END OF PATCH APPLICATIONS %endif @@ -2370,6 +2376,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 11 2013 Josh Boyer +- Add patch to fix broken tty handling (rhbz 904182) + * Fri Mar 08 2013 Josh Boyer - Add turbostat and x86_engery_perf_policy debuginfo to kernel-tools-debuginfo From 3f1daf9e62aac23c1bd91c0091d8fc80d30a3c18 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Mar 2013 09:15:31 -0400 Subject: [PATCH 237/492] Add patch to fix w1_search oops (rhbz 857954) --- kernel.spec | 7 ++ ...x-oops-when-w1_search-is-called-from.patch | 111 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 w1-fix-oops-when-w1_search-is-called-from.patch diff --git a/kernel.spec b/kernel.spec index a1b59c009..457b1ff0d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,9 @@ Patch24102: backlight_revert.patch #rhbz 904182 Patch24103: TTY-do-not-reset-master-s-packet-mode.patch +#rhbz 857954 +Patch24105: w1-fix-oops-when-w1_search-is-called-from.patch + # END OF PATCH DEFINITIONS %endif @@ -1519,6 +1522,9 @@ ApplyPatch team-net-next-update-20130307.patch #rhbz 904182 ApplyPatch TTY-do-not-reset-master-s-packet-mode.patch +#rhbz 857954 +ApplyPatch w1-fix-oops-when-w1_search-is-called-from.patch + # END OF PATCH APPLICATIONS %endif @@ -2377,6 +2383,7 @@ fi # || || %changelog * Mon Mar 11 2013 Josh Boyer +- Add patch to fix w1_search oops (rhbz 857954) - Add patch to fix broken tty handling (rhbz 904182) * Fri Mar 08 2013 Josh Boyer diff --git a/w1-fix-oops-when-w1_search-is-called-from.patch b/w1-fix-oops-when-w1_search-is-called-from.patch new file mode 100644 index 000000000..0a54eff17 --- /dev/null +++ b/w1-fix-oops-when-w1_search-is-called-from.patch @@ -0,0 +1,111 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.101.212.35 with SMTP id o35csp6769anq; + Sat, 2 Mar 2013 05:50:51 -0800 (PST) +X-Received: by 10.68.137.42 with SMTP id qf10mr19122124pbb.80.1362232251119; + Sat, 02 Mar 2013 05:50:51 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id pu7si8560937pbc.232.2013.03.02.05.50.50; + Sat, 02 Mar 2013 05:50:51 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org; + dkim=neutral (body hash did not verify) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1752198Ab3CBNuU (ORCPT + + 99 others); Sat, 2 Mar 2013 08:50:20 -0500 +Received: from mail-ee0-f48.google.com ([74.125.83.48]:46431 "EHLO + mail-ee0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1752038Ab3CBNuT (ORCPT + ); + Sat, 2 Mar 2013 08:50:19 -0500 +Received: by mail-ee0-f48.google.com with SMTP id t10so2921534eei.7 + for ; Sat, 02 Mar 2013 05:50:18 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=x-received:date:from:to:cc:subject:message-id:references + :mime-version:content-type:content-disposition:in-reply-to + :user-agent; + bh=8ABPYEMGQsyhtGtpdGpnD1kQchBrqYm9rJ3sEUcIQOc=; + b=hx/4GjbvaME9C3c+WOrfUkkwnJ5jJXefsOhCKmPCE8kmswk3Tvm11198r4+y1jM/Bl + 1wtIYby6sFgA08JUldm09fPpsKfbdeDnFAI5WmUAGJjahFXXRrQPocI6E0+s2BcM+t3H + Ii8g8ZvYJ+YMgbbSmp7mwMv98aa0+qdY6TIF4P/wNwAWrsjFh5TBgc/QyB0MzyQQ2tMp + LfA7n/2sH11vofS6FLSaWhtwGIIexPZ+oxWpvwBcCIYX+gTrSHPZqnLQkvhQ5oZDx7WF + 6QlNEqlmL+usW1ApRCAwcL4jOaORDAC2MytGH4jdZNic0PqdzonfbJTRE6YmZ45FHtNG + l+6w== +X-Received: by 10.15.101.204 with SMTP id bp52mr38431150eeb.31.1362232218031; + Sat, 02 Mar 2013 05:50:18 -0800 (PST) +Received: from gmail.com (aek101.neoplus.adsl.tpnet.pl. [83.25.114.101]) + by mx.google.com with ESMTPS id o3sm22363368eem.15.2013.03.02.05.50.16 + (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); + Sat, 02 Mar 2013 05:50:17 -0800 (PST) +Date: Sat, 2 Mar 2013 14:50:15 +0100 +From: Marcin Jurkowski +To: Sven Geggus +Cc: Evgeniy Polyakov , linux-kernel@vger.kernel.org +Subject: [PATCH 1/1] w1: fix oops when w1_search is called from netlink + connector +Message-ID: <20130302135015.GA21448@gmail.com> +References: <20130116141627.GA23638@ioremap.net> + <20130302001103.GB18026@gmail.com> + <20130302094510.GA4695@geggus.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20130302094510.GA4695@geggus.net> +User-Agent: Mutt/1.5.21 (2010-09-15) +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +On Sat, Mar 02, 2013 at 10:45:10AM +0100, Sven Geggus wrote: +> This is the bad commit I found doing git bisect: +> 04f482faf50535229a5a5c8d629cf963899f857c is the first bad commit +> commit 04f482faf50535229a5a5c8d629cf963899f857c +> Author: Patrick McHardy +> Date: Mon Mar 28 08:39:36 2011 +0000 + +Good job. I was too lazy to bisect for bad commit;) + +Reading the code I found problematic kthread_should_stop call from netlink +connector which causes the oops. After applying a patch, I've been testing +owfs+w1 setup for nearly two days and it seems to work very reliable (no +hangs, no memleaks etc). +More detailed description and possible fix is given below: + +Function w1_search can be called from either kthread or netlink callback. +While the former works fine, the latter causes oops due to kthread_should_stop +invocation. + +This patch adds a check if w1_search is serving netlink command, skipping +kthread_should_stop invocation if so. + +Signed-off-by: Marcin Jurkowski +--- + drivers/w1/w1.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c +index 7994d933..7e2220d 100644 +--- a/drivers/w1/w1.c ++++ b/drivers/w1/w1.c +@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb + tmp64 = (triplet_ret >> 2); + rn |= (tmp64 << i); + +- if (kthread_should_stop()) { ++ /* ensure we're called from kthread and not by netlink callback */ ++ if (!dev->priv && kthread_should_stop()) { + mutex_unlock(&dev->bus_mutex); + dev_dbg(&dev->dev, "Abort w1_search\n"); + return; +-- +1.7.12.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ From 24b5163c13ea9ede506bdec648889d764e4ef89f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Mar 2013 14:59:03 -0400 Subject: [PATCH 238/492] Add patch to allow "8250." prefix to keep working (rhbz 911771) --- kernel.spec | 7 +++ ...-8250.-xxxx-module-options-functiona.patch | 63 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 serial-8250-Keep-8250.-xxxx-module-options-functiona.patch diff --git a/kernel.spec b/kernel.spec index 457b1ff0d..944cb267b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,9 @@ Patch24103: TTY-do-not-reset-master-s-packet-mode.patch #rhbz 857954 Patch24105: w1-fix-oops-when-w1_search-is-called-from.patch +#rhbz 911771 +Patch24106: serial-8250-Keep-8250.-xxxx-module-options-functiona.patch + # END OF PATCH DEFINITIONS %endif @@ -1525,6 +1528,9 @@ ApplyPatch TTY-do-not-reset-master-s-packet-mode.patch #rhbz 857954 ApplyPatch w1-fix-oops-when-w1_search-is-called-from.patch +#rhbz 911771 +ApplyPatch serial-8250-Keep-8250.-xxxx-module-options-functiona.patch + # END OF PATCH APPLICATIONS %endif @@ -2383,6 +2389,7 @@ fi # || || %changelog * Mon Mar 11 2013 Josh Boyer +- Add patch to allow "8250." prefix to keep working (rhbz 911771) - Add patch to fix w1_search oops (rhbz 857954) - Add patch to fix broken tty handling (rhbz 904182) diff --git a/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch b/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch new file mode 100644 index 000000000..b16be4417 --- /dev/null +++ b/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch @@ -0,0 +1,63 @@ +From e94256528a988231ccc7a2a0b6b206a1131cb358 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 8 Mar 2013 21:13:52 -0500 +Subject: [PATCH] serial: 8250: Keep 8250. module options functional + after driver rename + +With commit 835d844d1 (8250_pnp: do pnp probe before legacy probe), the +8250 driver was renamed to 8250_core. This means any existing usage of +the 8259. module parameters or as a kernel command line switch is +now broken, as the 8250_core driver doesn't parse options belonging to +something called "8250". + +To solve this, we redefine the module options in a dummy function using +a redefined MODULE_PARAM_PREFX when built into the kernel. In the case +where we're building as a module, we provide an alias to the old 8250 +name. The dummy function prevents compiler errors due to global variable +redefinitions that happen as part of the module_param_ macro expansions. + +Signed-off-by: Josh Boyer +--- + drivers/tty/serial/8250/8250.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index 0efc815..f982633 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -3396,3 +3396,32 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); + MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); + #endif + MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); ++ ++#ifndef MODULE ++/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name ++ * working as well for the module options so we don't break people. We ++ * need to keep the names identical and the convenient macros will happily ++ * refuse to let us do that by failing the build with redefinition errors ++ * of global variables. So we stick them inside a dummy function to avoid ++ * those conflicts. The options still get parsed, and the redefined ++ * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. ++ * ++ * This is hacky. I'm sorry. ++ */ ++static void __used s8250_options(void) ++{ ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "8250." ++ ++ module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644); ++ module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644); ++ module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644); ++#ifdef CONFIG_SERIAL_8250_RSA ++ __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, ++ ¶m_array_ops, .arr = &__param_arr_probe_rsa, ++ 0444, -1); ++#endif ++} ++#else ++MODULE_ALIAS("8250"); ++#endif +-- +1.8.1.2 + From 7c71bc7d4275f85ccc098104664171d78fe7aced Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Mar 2013 16:27:54 -0400 Subject: [PATCH 239/492] Add patch to fix usb_submit_urb error in uvcvideo (rhbz 879462) --- kernel.spec | 8 ++++++++ uvcvideo-suspend-fix.patch | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 uvcvideo-suspend-fix.patch diff --git a/kernel.spec b/kernel.spec index 944cb267b..d2ba57d7b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch24105: w1-fix-oops-when-w1_search-is-called-from.patch #rhbz 911771 Patch24106: serial-8250-Keep-8250.-xxxx-module-options-functiona.patch +#rhbz 879462 +Patch24107: uvcvideo-suspend-fix.patch + # END OF PATCH DEFINITIONS %endif @@ -1531,6 +1534,10 @@ ApplyPatch w1-fix-oops-when-w1_search-is-called-from.patch #rhbz 911771 ApplyPatch serial-8250-Keep-8250.-xxxx-module-options-functiona.patch +#rhbz 879462 +ApplyPatch uvcvideo-suspend-fix.patch + + # END OF PATCH APPLICATIONS %endif @@ -2389,6 +2396,7 @@ fi # || || %changelog * Mon Mar 11 2013 Josh Boyer +- Add patch to fix usb_submit_urb error in uvcvideo (rhbz 879462) - Add patch to allow "8250." prefix to keep working (rhbz 911771) - Add patch to fix w1_search oops (rhbz 857954) - Add patch to fix broken tty handling (rhbz 904182) diff --git a/uvcvideo-suspend-fix.patch b/uvcvideo-suspend-fix.patch new file mode 100644 index 000000000..e8d825217 --- /dev/null +++ b/uvcvideo-suspend-fix.patch @@ -0,0 +1,38 @@ +From a82a45f65377b05fe8cd3167c7b0a70c508356b8 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 10 Jan 2013 07:04:55 -0300 +Subject: [PATCH] [media] uvcvideo: Fix race of open and suspend in error case + +Ming Lei reported: +IMO, there is a minor fault in the error handling path of +uvc_status_start() inside uvc_v4l2_open(), and the 'users' count should +have been decreased before usb_autopm_put_interface(). In theory, a [URB +resubmission] warning can be triggered when the device is opened just +between usb_autopm_put_interface() and atomic_dec(&stream->dev->users). +The fix is trivial. + +Reported-by: Ming Lei +Signed-off-by: Oliver Neukum +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/usb/uvc/uvc_v4l2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c +index 97a4ffd..b2dc326 100644 +--- a/drivers/media/usb/uvc/uvc_v4l2.c ++++ b/drivers/media/usb/uvc/uvc_v4l2.c +@@ -501,8 +501,8 @@ static int uvc_v4l2_open(struct file *file) + if (atomic_inc_return(&stream->dev->users) == 1) { + ret = uvc_status_start(stream->dev); + if (ret < 0) { +- usb_autopm_put_interface(stream->dev->intf); + atomic_dec(&stream->dev->users); ++ usb_autopm_put_interface(stream->dev->intf); + kfree(handle); + return ret; + } +-- +1.8.1.2 + From 8df7f55b924e9f112689cdfc1d9e93b334c18520 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 Mar 2013 11:06:04 -0300 Subject: [PATCH 240/492] Fix amd64_edac report with the new API Signed-off-by: Mauro Carvalho Chehab --- amd64_edac_fix_rank_count.patch | 182 ++++++++++++++++++++++++++++++++ kernel.spec | 10 +- 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 amd64_edac_fix_rank_count.patch diff --git a/amd64_edac_fix_rank_count.patch b/amd64_edac_fix_rank_count.patch new file mode 100644 index 000000000..eb58f0d03 --- /dev/null +++ b/amd64_edac_fix_rank_count.patch @@ -0,0 +1,182 @@ +From 56ba4c93d909ef9dfab4f1101a8c3bf75bc4cdab Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Mon, 11 Mar 2013 08:19:52 -0400 +Subject: [PATCH EDAC] edac: merge mci.mem_is_per_rank with mci.csbased + +Both mci.mem_is_per_rank and mci.csbased have the same meaning: +the memory controller is csrows based. Merge both fields into one. + +There's no need for the driver to actually fill it, as the core +detectsi it by checking if one of the layes has the csrows type +as part of the memory hierarchy: + + if (layers[i].type == EDAC_MC_LAYER_CHIP_SELECT) + per_rank = true; +... + mci->csbased = per_rank; + +Signed-off-by: Mauro Carvalho Chehab + +From 2b6018dbd206e4af16edcfb80497b73105e97803 Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Mon, 11 Mar 2013 08:18:24 -0400 +Subject: [PATCH EDAC] amd64_edac: Correct dimm sizes + +We were filling the csrow size with a wrong value. 16a528ee3975 ("EDAC: +Fix csrow size reported in sysfs") tried to address the issue. It fixed +the report with the old API but not with the new one. Correct it for the +new API too. + +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Borislav Petkov +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index ad8bf2a..10ed0c7 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -2148,12 +2148,18 @@ static int init_csrows(struct mem_ctl_info *mci) + edac_dbg(1, "MC node: %d, csrow: %d\n", + pvt->mc_node_id, i); + +- if (row_dct0) ++ if (row_dct0) { + nr_pages = amd64_csrow_nr_pages(pvt, 0, i); ++ csrow->channels[0]->dimm->nr_pages = nr_pages; ++ } + + /* K8 has only one DCT */ +- if (boot_cpu_data.x86 != 0xf && row_dct1) +- nr_pages += amd64_csrow_nr_pages(pvt, 1, i); ++ if (boot_cpu_data.x86 != 0xf && row_dct1) { ++ int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i); ++ ++ csrow->channels[1]->dimm->nr_pages = row_dct1_pages; ++ nr_pages += row_dct1_pages; ++ } + + mtype = amd64_determine_memory_type(pvt, i); + +@@ -2172,9 +2178,7 @@ static int init_csrows(struct mem_ctl_info *mci) + dimm = csrow->channels[j]->dimm; + dimm->mtype = mtype; + dimm->edac_mode = edac_mode; +- dimm->nr_pages = nr_pages; + } +- csrow->nr_pages = nr_pages; + } + + return empty; +@@ -2519,7 +2523,6 @@ static int amd64_init_one_instance(struct pci_dev *F2) + + mci->pvt_info = pvt; + mci->pdev = &pvt->F2->dev; +- mci->csbased = 1; + + setup_mci_misc_attrs(mci, fam_type); + +diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c +index cdb81aa..27e86d9 100644 +--- a/drivers/edac/edac_mc.c ++++ b/drivers/edac/edac_mc.c +@@ -86,7 +86,7 @@ static void edac_mc_dump_dimm(struct dimm_info *dimm, int number) + edac_dimm_info_location(dimm, location, sizeof(location)); + + edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", +- dimm->mci->mem_is_per_rank ? "rank" : "dimm", ++ dimm->mci->csbased ? "rank" : "dimm", + number, location, dimm->csrow, dimm->cschannel); + edac_dbg(4, " dimm = %p\n", dimm); + edac_dbg(4, " dimm->label = '%s'\n", dimm->label); +@@ -341,7 +341,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, + memcpy(mci->layers, layers, sizeof(*layer) * n_layers); + mci->nr_csrows = tot_csrows; + mci->num_cschannel = tot_channels; +- mci->mem_is_per_rank = per_rank; ++ mci->csbased = per_rank; + + /* + * Alocate and fill the csrow/channels structs +@@ -1235,7 +1235,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, + * incrementing the compat API counters + */ + edac_dbg(4, "%s csrows map: (%d,%d)\n", +- mci->mem_is_per_rank ? "rank" : "dimm", ++ mci->csbased ? "rank" : "dimm", + dimm->csrow, dimm->cschannel); + if (row == -1) + row = dimm->csrow; +diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c +index 4f4b613..6ab4a50 100644 +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -180,9 +180,6 @@ static ssize_t csrow_size_show(struct device *dev, + int i; + u32 nr_pages = 0; + +- if (csrow->mci->csbased) +- return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages)); +- + for (i = 0; i < csrow->nr_channels; i++) + nr_pages += csrow->channels[i]->dimm->nr_pages; + return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); +@@ -612,7 +609,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, + device_initialize(&dimm->dev); + + dimm->dev.parent = &mci->dev; +- if (mci->mem_is_per_rank) ++ if (mci->csbased) + dev_set_name(&dimm->dev, "rank%d", index); + else + dev_set_name(&dimm->dev, "dimm%d", index); +@@ -778,14 +775,10 @@ static ssize_t mci_size_mb_show(struct device *dev, + for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { + struct csrow_info *csrow = mci->csrows[csrow_idx]; + +- if (csrow->mci->csbased) { +- total_pages += csrow->nr_pages; +- } else { +- for (j = 0; j < csrow->nr_channels; j++) { +- struct dimm_info *dimm = csrow->channels[j]->dimm; ++ for (j = 0; j < csrow->nr_channels; j++) { ++ struct dimm_info *dimm = csrow->channels[j]->dimm; + +- total_pages += dimm->nr_pages; +- } ++ total_pages += dimm->nr_pages; + } + } + +diff --git a/include/linux/edac.h b/include/linux/edac.h +index 4fd4999..0b76327 100644 +--- a/include/linux/edac.h ++++ b/include/linux/edac.h +@@ -561,7 +561,6 @@ struct csrow_info { + + u32 ue_count; /* Uncorrectable Errors for this csrow */ + u32 ce_count; /* Correctable Errors for this csrow */ +- u32 nr_pages; /* combined pages count of all channels */ + + struct mem_ctl_info *mci; /* the parent */ + +@@ -676,11 +675,11 @@ struct mem_ctl_info { + * sees memory sticks ("dimms"), and the ones that sees memory ranks. + * All old memory controllers enumerate memories per rank, but most + * of the recent drivers enumerate memories per DIMM, instead. +- * When the memory controller is per rank, mem_is_per_rank is true. ++ * When the memory controller is per rank, csbased is true. + */ + unsigned n_layers; + struct edac_mc_layer *layers; +- bool mem_is_per_rank; ++ bool csbased; + + /* + * DIMM info. Will eventually remove the entire csrows_info some day +@@ -741,8 +740,6 @@ struct mem_ctl_info { + u32 fake_inject_ue; + u16 fake_inject_count; + #endif +- __u8 csbased : 1, /* csrow-based memory controller */ +- __resv : 7; + }; + + #endif diff --git a/kernel.spec b/kernel.spec index d2ba57d7b..c8e3402f6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 208 +%global baserelease 209 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -794,6 +794,9 @@ Patch24106: serial-8250-Keep-8250.-xxxx-module-options-functiona.patch #rhbz 879462 Patch24107: uvcvideo-suspend-fix.patch +# AMD64 EDAC reports a wrong dimm count with new API. Fix it +Patch25000: amd64_edac_fix_rank_count.patch + # END OF PATCH DEFINITIONS %endif @@ -1522,6 +1525,8 @@ ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch #rhbz 917353 ApplyPatch backlight_revert.patch -R +ApplyPatch amd64_edac_fix_rank_count.patch + #Team Driver update ApplyPatch team-net-next-update-20130307.patch @@ -2395,6 +2400,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 11 2013 Mauro Carvalho Chehab - 3.8.2-209 +- fix amd64_edac twice-mem-size-report on dual-channel machines and new EDAC API + * Mon Mar 11 2013 Josh Boyer - Add patch to fix usb_submit_urb error in uvcvideo (rhbz 879462) - Add patch to allow "8250." prefix to keep working (rhbz 911771) From f4081f48cf5dec1ed63b9a1d67c8baad63da8183 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 12 Mar 2013 11:56:15 +0000 Subject: [PATCH 241/492] drop long unused config-arm-versatile --- config-arm-versatile | 102 ------------------------------------------- 1 file changed, 102 deletions(-) delete mode 100644 config-arm-versatile diff --git a/config-arm-versatile b/config-arm-versatile deleted file mode 100644 index 758a78c76..000000000 --- a/config-arm-versatile +++ /dev/null @@ -1,102 +0,0 @@ -CONFIG_ARCH_VEXPRESS=y -CONFIG_ARCH_VEXPRESS_CA9X4=y -CONFIG_ARCH_VEXPRESS_DT=y -CONFIG_PLAT_VERSATILE_CLCD=y -CONFIG_PLAT_VERSATILE_SCHED_CLOCK=y -CONFIG_PLAT_VERSATILE=y -CONFIG_ARM_TIMER_SP804=y - -CONFIG_CPU_V7=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_HAS_PMU=y - -# Need to verify whether these are generic or vexpress specific -CONFIG_ARM_AMBA=y - -CONFIG_VFP=y -CONFIG_VFPv3=y - -CONFIG_CPUSETS=y -# CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11 is not set -# CONFIG_THUMB2_KERNEL is not set -CONFIG_TICK_ONESHOT=y - -CONFIG_ARM_ASM_UNIFIED=y -CONFIG_ARM_CPU_TOPOLOGY=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y - -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_751472=y -CONFIG_ARM_ERRATA_753970=y - -CONFIG_ARM_GIC=y -CONFIG_ARM_L1_CACHE_SHIFT=5 - -CONFIG_ARM_THUMB=y -CONFIG_ARM_TIMER_SP804=y -CONFIG_ARM_UNWIND=y - -CONFIG_FB=y -CONFIG_FB_ARMCLCD=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y - -CONFIG_TOUCHSCREEN_ADS7846=m - -CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/sda1 rootdelay=20" - -CONFIG_SERIO_AMBAKMI=m -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - -CONFIG_FB_ARMCLCD=m - -CONFIG_MMC_ARMMMCI=y -CONFIG_MMC_DW=m -# CONFIG_MMC_DW_IDMAC is not set - -# CONFIG_ARM_CHARLCD is not set -CONFIG_PL330_DMA=y -CONFIG_RTC_DRV_PL030=y -CONFIG_RTC_DRV_PL031=y - -CONFIG_I2C_VERSATILE=m - -CONFIG_OC_ETM=y - -CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y -CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_NEON=y -CONFIG_PATA_PLATFORM=m -CONFIG_PATA_OF_PLATFORM=m -# CONFIG_NET_VENDOR_BROADCOM is not set - -# unset on versatille for jon masters -# CONFIG_GPIOLIB is not set -# CONFIG_ARCH_MULTI_V4 is not set -# CONFIG_ARCH_MULTI_V4T is not set -# CONFIG_ARCH_MULTI_V6 is not set -# CONFIG_DRM_EXYNOS is not set - From c9c43cfcbaefb90ea8f382983353de722fe1b2ee Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 08:51:34 -0400 Subject: [PATCH 242/492] CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) --- kernel.spec | 9 ++ ...l-always-clear-sa_restorer-on-execve.patch | 113 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 signal-always-clear-sa_restorer-on-execve.patch diff --git a/kernel.spec b/kernel.spec index c8e3402f6..c12f3bd01 100644 --- a/kernel.spec +++ b/kernel.spec @@ -794,6 +794,9 @@ Patch24106: serial-8250-Keep-8250.-xxxx-module-options-functiona.patch #rhbz 879462 Patch24107: uvcvideo-suspend-fix.patch +#CVE-2013-0914 rhbz 920499 920510 +Patch24108: signal-always-clear-sa_restorer-on-execve.patch + # AMD64 EDAC reports a wrong dimm count with new API. Fix it Patch25000: amd64_edac_fix_rank_count.patch @@ -1542,6 +1545,9 @@ ApplyPatch serial-8250-Keep-8250.-xxxx-module-options-functiona.patch #rhbz 879462 ApplyPatch uvcvideo-suspend-fix.patch +#CVE-2013-0914 rhbz 920499 920510 +ApplyPatch signal-always-clear-sa_restorer-on-execve.patch + # END OF PATCH APPLICATIONS @@ -2400,6 +2406,9 @@ fi # ||----w | # || || %changelog +* Tue Mar 12 2013 Josh Boyer +- CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) + * Mon Mar 11 2013 Mauro Carvalho Chehab - 3.8.2-209 - fix amd64_edac twice-mem-size-report on dual-channel machines and new EDAC API diff --git a/signal-always-clear-sa_restorer-on-execve.patch b/signal-always-clear-sa_restorer-on-execve.patch new file mode 100644 index 000000000..feb005c44 --- /dev/null +++ b/signal-always-clear-sa_restorer-on-execve.patch @@ -0,0 +1,113 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.169.233 with SMTP id ah9csp99159oac; + Mon, 11 Mar 2013 13:14:17 -0700 (PDT) +X-Received: by 10.68.179.1 with SMTP id dc1mr24297029pbc.128.1363032856671; + Mon, 11 Mar 2013 13:14:16 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id tx10si24737165pbc.272.2013.03.11.13.14.10; + Mon, 11 Mar 2013 13:14:16 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754069Ab3CKUN4 (ORCPT + 99 others); + Mon, 11 Mar 2013 16:13:56 -0400 +Received: from smtp.outflux.net ([198.145.64.163]:59839 "EHLO smtp.outflux.net" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1753913Ab3CKUN4 (ORCPT ); + Mon, 11 Mar 2013 16:13:56 -0400 +Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) + by vinyl.outflux.net (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id r2BKDgjn022201; + Mon, 11 Mar 2013 13:13:43 -0700 +Date: Mon, 11 Mar 2013 13:13:42 -0700 +From: Kees Cook +To: linux-kernel@vger.kernel.org +Cc: Al Viro , Oleg Nesterov , + Andrew Morton , + "Eric W. Biederman" , + Serge Hallyn , + Emese Revfy , + PaX Team , jln@google.com +Subject: [PATCH v2] signal: always clear sa_restorer on execve +Message-ID: <20130311201342.GA19824@www.outflux.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +X-MIMEDefang-Filter: outflux$Revision: 1.316 $ +X-HELO: www.outflux.net +X-Scanned-By: MIMEDefang 2.71 on 10.2.0.1 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +When the new signal handlers are set up, the location of sa_restorer +is not cleared, leaking a parent process's address space location to +children. This allows for a potential bypass of the parent's ASLR by +examining the sa_restorer value returned when calling sigaction(). + +Based on what should be considered "secret" about addresses, it only +matters across the exec not the fork (since the VMAs haven't changed +until the exec). But since exec sets SIG_DFL and keeps sa_restorer, +this is where it should be fixed. + +Given the few uses of sa_restorer, a "set" function was not written +since this would be the only use. Instead, we use __ARCH_HAS_SA_RESTORER, +as already done in other places. + +Example of the leak before applying this patch: + +$ cat /proc/$$/maps +... +7fb9f3083000-7fb9f3238000 r-xp 00000000 fd:01 404469 .../libc-2.15.so +... +$ ./leak +... +7f278bc74000-7f278be29000 r-xp 00000000 fd:01 404469 .../libc-2.15.so +... +1 0 (nil) 0x7fb9f30b94a0 +2 4000000 (nil) 0x7f278bcaa4a0 +3 4000000 (nil) 0x7f278bcaa4a0 +4 0 (nil) 0x7fb9f30b94a0 +... + +Signed-off-by: Kees Cook +Reported-by: Emese Revfy +Cc: Emese Revfy +Cc: PaX Team +Cc: stable@vger.kernel.org +--- +v2: + - clarify commit, explain use of #ifdef. +--- + kernel/signal.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/signal.c b/kernel/signal.c +index 2ec870a..8c8e3ca 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct *t, int force_default) + if (force_default || ka->sa.sa_handler != SIG_IGN) + ka->sa.sa_handler = SIG_DFL; + ka->sa.sa_flags = 0; ++#ifdef __ARCH_HAS_SA_RESTORER ++ ka->sa.sa_restorer = NULL; ++#endif + sigemptyset(&ka->sa.sa_mask); + ka++; + } +-- +1.7.9.5 + + +-- +Kees Cook +Chrome OS Security +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ From dfee514436f03d5298d66231eea07148f6d5e722 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 09:07:02 -0400 Subject: [PATCH 243/492] CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) --- ...ds-check-execbuffer-relocation-count.patch | 51 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 58 insertions(+) create mode 100644 drm-i915-bounds-check-execbuffer-relocation-count.patch diff --git a/drm-i915-bounds-check-execbuffer-relocation-count.patch b/drm-i915-bounds-check-execbuffer-relocation-count.patch new file mode 100644 index 000000000..a6c9d4b12 --- /dev/null +++ b/drm-i915-bounds-check-execbuffer-relocation-count.patch @@ -0,0 +1,51 @@ +From e896e9dde50fd9a44cbbed205cc0beb869e2193b Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 11 Mar 2013 17:31:45 -0700 +Subject: [PATCH] drm/i915: bounds check execbuffer relocation count + +It is possible to wrap the counter used to allocate the buffer for +relocation copies. This could lead to heap writing overflows. + +CVE-2013-0913 + +v3: collapse test, improve comment +v2: move check into validate_exec_list + +Signed-off-by: Kees Cook +Reported-by: Pinkie Pie +Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index 26d08bb..7adf5a7 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -706,15 +706,20 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, + int count) + { + int i; ++ int relocs_total = 0; ++ int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); + + for (i = 0; i < count; i++) { + char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; + int length; /* limited by fault_in_pages_readable() */ + +- /* First check for malicious input causing overflow */ +- if (exec[i].relocation_count > +- INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) ++ /* First check for malicious input causing overflow in ++ * the worst case where we need to allocate the entire ++ * relocation tree as a single array. ++ */ ++ if (exec[i].relocation_count > relocs_max - relocs_total) + return -EINVAL; ++ relocs_total += exec[i].relocation_count; + + length = exec[i].relocation_count * + sizeof(struct drm_i915_gem_relocation_entry); +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index c12f3bd01..e54dcf41b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,9 @@ Patch24107: uvcvideo-suspend-fix.patch #CVE-2013-0914 rhbz 920499 920510 Patch24108: signal-always-clear-sa_restorer-on-execve.patch +#CVE-2013-0913 rhbz 920471 920529 +Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch + # AMD64 EDAC reports a wrong dimm count with new API. Fix it Patch25000: amd64_edac_fix_rank_count.patch @@ -1548,6 +1551,9 @@ ApplyPatch uvcvideo-suspend-fix.patch #CVE-2013-0914 rhbz 920499 920510 ApplyPatch signal-always-clear-sa_restorer-on-execve.patch +#CVE-2013-0913 rhbz 920471 920529 +ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch + # END OF PATCH APPLICATIONS @@ -2407,6 +2413,7 @@ fi # || || %changelog * Tue Mar 12 2013 Josh Boyer +- CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) - CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) * Mon Mar 11 2013 Mauro Carvalho Chehab - 3.8.2-209 From 61bbeae79e5006132b5596536922844823b11b98 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 09:23:46 -0400 Subject: [PATCH 244/492] Use SA_RESTORER, as __ARCH_HAS_SA_RESTORER was added in 3.9 --- signal-always-clear-sa_restorer-on-execve.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signal-always-clear-sa_restorer-on-execve.patch b/signal-always-clear-sa_restorer-on-execve.patch index feb005c44..658f97a96 100644 --- a/signal-always-clear-sa_restorer-on-execve.patch +++ b/signal-always-clear-sa_restorer-on-execve.patch @@ -93,7 +93,7 @@ index 2ec870a..8c8e3ca 100644 if (force_default || ka->sa.sa_handler != SIG_IGN) ka->sa.sa_handler = SIG_DFL; ka->sa.sa_flags = 0; -+#ifdef __ARCH_HAS_SA_RESTORER ++#ifdef SA_RESTORER + ka->sa.sa_restorer = NULL; +#endif sigemptyset(&ka->sa.sa_mask); From 9f63d7d2bb7edd40b39b6a1d228c6eb5ff8ff21d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 10:22:33 -0400 Subject: [PATCH 245/492] Add patch to fix Cypress trackpad on XPS 12 machines (rhbz 912166) --- ...s2-fix-trackpadi-found-in-Dell-XPS12.patch | 71 +++++++++++++++++++ kernel.spec | 9 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch diff --git a/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch b/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch new file mode 100644 index 000000000..15abce521 --- /dev/null +++ b/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch @@ -0,0 +1,71 @@ +From 81bb5d31fbf3893a8e041c649dea704dd11d5272 Mon Sep 17 00:00:00 2001 +From: Kamal Mostafa +Date: Thu, 21 Feb 2013 11:55:05 -0800 +Subject: [PATCH] Input: cypress_ps2 - fix trackpadi found in Dell XPS12 + +Avoid firmware glitch in Cypress PS/2 Trackpad firmware version 11 +(as observed in Dell XPS12) which prevents driver from recognizing +the trackpad. + +BugLink: http://launchpad.net/bugs/1103594 + +Signed-off-by: Kamal Mostafa +Cc: Dudley Du +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/cypress_ps2.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c +index 1673dc6..f51765f 100644 +--- a/drivers/input/mouse/cypress_ps2.c ++++ b/drivers/input/mouse/cypress_ps2.c +@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse) + cytp->fw_version = param[2] & FW_VERSION_MASX; + cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; + ++ /* ++ * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to ++ * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594. ++ */ ++ if (cytp->fw_version >= 11) ++ cytp->tp_metrics_supported = 0; ++ + psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); + psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", + cytp->tp_metrics_supported); +@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) + cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; + cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; + ++ if (!cytp->tp_metrics_supported) ++ return 0; ++ + memset(param, 0, sizeof(param)); + if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { + /* Update trackpad parameters. */ +@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) + + static int cypress_query_hardware(struct psmouse *psmouse) + { +- struct cytp_data *cytp = psmouse->private; + int ret; + + ret = cypress_read_fw_version(psmouse); + if (ret) + return ret; + +- if (cytp->tp_metrics_supported) { +- ret = cypress_read_tp_metrics(psmouse); +- if (ret) +- return ret; +- } ++ ret = cypress_read_tp_metrics(psmouse); ++ if (ret) ++ return ret; + + return 0; + } +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index e54dcf41b..27ee3d054 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 209 +%global baserelease 210 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -741,6 +741,9 @@ Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch Patch22240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch +#rhbz 912166 +Patch22243: Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch + #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch @@ -1490,6 +1493,9 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch +#rhbz 912166 +ApplyPatch Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch + #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch @@ -2413,6 +2419,7 @@ fi # || || %changelog * Tue Mar 12 2013 Josh Boyer +- Add patch to fix Cypress trackpad on XPS 12 machines (rhbz 912166) - CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) - CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) From 337ba2cf7b363ea331f944d007ff521c9693574e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 12:24:21 -0400 Subject: [PATCH 246/492] Add patches to fix cfg80211 issues with suspend (rhbz 856863) --- cfg80211-mac80211-disconnect-on-suspend.patch | 227 ++++++++++++++++++ kernel.spec | 8 + ...-crash-due-to-un-canceled-work-items.patch | 67 ++++++ 3 files changed, 302 insertions(+) create mode 100644 cfg80211-mac80211-disconnect-on-suspend.patch create mode 100644 mac80211-Fix-crash-due-to-un-canceled-work-items.patch diff --git a/cfg80211-mac80211-disconnect-on-suspend.patch b/cfg80211-mac80211-disconnect-on-suspend.patch new file mode 100644 index 000000000..940ac2cc4 --- /dev/null +++ b/cfg80211-mac80211-disconnect-on-suspend.patch @@ -0,0 +1,227 @@ +From ad3a7b84092599eef931bce4de54e18e47612f9f Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Thu, 28 Feb 2013 09:55:25 +0000 +Subject: [PATCH] cfg80211/mac80211: disconnect on suspend + +If possible that after suspend, cfg80211 will receive request to +disconnect what require action on interface that was removed during +suspend. + +Problem can manifest itself by various warnings similar to below one: + +WARNING: at net/mac80211/driver-ops.h:12 ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211]() +wlan0: Failed check-sdata-in-driver check, flags: 0x4 +Call Trace: + [] warn_slowpath_fmt+0x33/0x40 + [] ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211] + [] ieee80211_recalc_ps_vif+0x2a/0x30 [mac80211] + [] ieee80211_set_disassoc+0xf6/0x500 [mac80211] + [] ieee80211_mgd_deauth+0x1f1/0x280 [mac80211] + [] ieee80211_deauth+0x16/0x20 [mac80211] + [] cfg80211_mlme_down+0x70/0xc0 [cfg80211] + [] __cfg80211_disconnect+0x1b1/0x1d0 [cfg80211] + +To fix the problem disconnect from any associated network before +suspend. User space is responsible to establish connection again +after resume. This basically need to be done by user space anyway, +because associated stations can go away during suspend (for example +NetworkManager disconnects on suspend and connect on resume by default). + +Patch also handle situation when driver refuse to suspend with wowlan +configured and try to suspend again without it. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Johannes Berg +--- + net/mac80211/pm.c | 2 +- + net/wireless/core.c | 73 +++++++++++++++++++++++++++---------------------- + net/wireless/core.h | 3 ++ + net/wireless/rdev-ops.h | 7 +++-- + net/wireless/sysfs.c | 25 +++++++++++++---- + 5 files changed, 69 insertions(+), 41 deletions(-) + +diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c +index 79a48f3..ce4f973 100644 +--- a/net/mac80211/pm.c ++++ b/net/mac80211/pm.c +@@ -92,7 +92,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) + return err; + } else if (err > 0) { + WARN_ON(err != 1); +- local->wowlan = false; ++ return err; + } else { + list_for_each_entry(sdata, &local->interfaces, list) { + cancel_work_sync(&sdata->work); +diff --git a/net/wireless/core.c b/net/wireless/core.c +index b677eab..66cc98d 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -806,6 +806,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, + rdev->num_running_monitor_ifaces += num; + } + ++void cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev) ++{ ++ struct net_device *dev = wdev->netdev; ++ ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_ADHOC: ++ cfg80211_leave_ibss(rdev, dev, true); ++ break; ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_STATION: ++ mutex_lock(&rdev->sched_scan_mtx); ++ __cfg80211_stop_sched_scan(rdev, false); ++ mutex_unlock(&rdev->sched_scan_mtx); ++ ++ wdev_lock(wdev); ++#ifdef CONFIG_CFG80211_WEXT ++ kfree(wdev->wext.ie); ++ wdev->wext.ie = NULL; ++ wdev->wext.ie_len = 0; ++ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; ++#endif ++ __cfg80211_disconnect(rdev, dev, ++ WLAN_REASON_DEAUTH_LEAVING, true); ++ cfg80211_mlme_down(rdev, dev); ++ wdev_unlock(wdev); ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ cfg80211_leave_mesh(rdev, dev); ++ break; ++ case NL80211_IFTYPE_AP: ++ cfg80211_stop_ap(rdev, dev); ++ break; ++ default: ++ break; ++ } ++ ++ wdev->beacon_interval = 0; ++} ++ + static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + unsigned long state, + void *ndev) +@@ -874,38 +914,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + dev->priv_flags |= IFF_DONT_BRIDGE; + break; + case NETDEV_GOING_DOWN: +- switch (wdev->iftype) { +- case NL80211_IFTYPE_ADHOC: +- cfg80211_leave_ibss(rdev, dev, true); +- break; +- case NL80211_IFTYPE_P2P_CLIENT: +- case NL80211_IFTYPE_STATION: +- mutex_lock(&rdev->sched_scan_mtx); +- __cfg80211_stop_sched_scan(rdev, false); +- mutex_unlock(&rdev->sched_scan_mtx); +- +- wdev_lock(wdev); +-#ifdef CONFIG_CFG80211_WEXT +- kfree(wdev->wext.ie); +- wdev->wext.ie = NULL; +- wdev->wext.ie_len = 0; +- wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; +-#endif +- __cfg80211_disconnect(rdev, dev, +- WLAN_REASON_DEAUTH_LEAVING, true); +- cfg80211_mlme_down(rdev, dev); +- wdev_unlock(wdev); +- break; +- case NL80211_IFTYPE_MESH_POINT: +- cfg80211_leave_mesh(rdev, dev); +- break; +- case NL80211_IFTYPE_AP: +- cfg80211_stop_ap(rdev, dev); +- break; +- default: +- break; +- } +- wdev->beacon_interval = 0; ++ cfg80211_leave(rdev, wdev); + break; + case NETDEV_DOWN: + cfg80211_update_iface_num(rdev, wdev->iftype, -1); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 3563097..49d79d9 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -481,6 +481,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, + void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, + enum nl80211_iftype iftype, int num); + ++void cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev); ++ + #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 + + #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 6c0c819..08e4145 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -6,11 +6,12 @@ + #include "core.h" + #include "trace.h" + +-static inline int rdev_suspend(struct cfg80211_registered_device *rdev) ++static inline int rdev_suspend(struct cfg80211_registered_device *rdev, ++ struct cfg80211_wowlan *wowlan) + { + int ret; +- trace_rdev_suspend(&rdev->wiphy, rdev->wowlan); +- ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); ++ trace_rdev_suspend(&rdev->wiphy, wowlan); ++ ret = rdev->ops->suspend(&rdev->wiphy, wowlan); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c +index 1f6f01e..a6a108b 100644 +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) ++{ ++ struct wireless_dev *wdev; ++ ++ list_for_each_entry(wdev, &rdev->wdev_list, list) ++ cfg80211_leave(rdev, wdev); ++} ++ + static int wiphy_suspend(struct device *dev, pm_message_t state) + { + struct cfg80211_registered_device *rdev = dev_to_rdev(dev); +@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) + + rdev->suspend_at = get_seconds(); + +- if (rdev->ops->suspend) { +- rtnl_lock(); +- if (rdev->wiphy.registered) +- ret = rdev_suspend(rdev); +- rtnl_unlock(); ++ rtnl_lock(); ++ if (rdev->wiphy.registered) { ++ if (!rdev->wowlan) ++ cfg80211_leave_all(rdev); ++ if (rdev->ops->suspend) ++ ret = rdev_suspend(rdev, rdev->wowlan); ++ if (ret == 1) { ++ /* Driver refuse to configure wowlan */ ++ cfg80211_leave_all(rdev); ++ ret = rdev_suspend(rdev, NULL); ++ } + } ++ rtnl_unlock(); + + return ret; + } +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 27ee3d054..db65fafc3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -803,6 +803,10 @@ Patch24108: signal-always-clear-sa_restorer-on-execve.patch #CVE-2013-0913 rhbz 920471 920529 Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch +#rhbz 865863 +Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch +Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch + # AMD64 EDAC reports a wrong dimm count with new API. Fix it Patch25000: amd64_edac_fix_rank_count.patch @@ -1560,6 +1564,9 @@ ApplyPatch signal-always-clear-sa_restorer-on-execve.patch #CVE-2013-0913 rhbz 920471 920529 ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch +#rhbz 856863 +ApplyPatch mac80211-Fix-crash-due-to-un-canceled-work-items.patch +ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch # END OF PATCH APPLICATIONS @@ -2419,6 +2426,7 @@ fi # || || %changelog * Tue Mar 12 2013 Josh Boyer +- Add patches to fix cfg80211 issues with suspend (rhbz 856863) - Add patch to fix Cypress trackpad on XPS 12 machines (rhbz 912166) - CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) - CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) diff --git a/mac80211-Fix-crash-due-to-un-canceled-work-items.patch b/mac80211-Fix-crash-due-to-un-canceled-work-items.patch new file mode 100644 index 000000000..71fd5963b --- /dev/null +++ b/mac80211-Fix-crash-due-to-un-canceled-work-items.patch @@ -0,0 +1,67 @@ +From 499218595a2e8296b7492af32fcca141b7b8184a Mon Sep 17 00:00:00 2001 +From: Ben Greear +Date: Wed, 20 Feb 2013 09:41:09 -0800 +Subject: [PATCH] mac80211: Fix crash due to un-canceled work-items + +Some mlme work structs are not cancelled on disassociation +nor interface deletion, which leads to them running after +the memory has been freed + +There is not a clean way to cancel these in the disassociation +logic because they must be canceled outside of the ifmgd->mtx +lock, so just cancel them in mgd_stop logic that tears down +the station. + +This fixes the crashes we see in 3.7.9+. The crash stack +trace itself isn't so helpful, but this warning gives +more useful info: + +WARNING: at /home/greearb/git/linux-3.7.dev.y/lib/debugobjects.c:261 debug_print_object+0x7c/0x8d() +ODEBUG: free active (active state 0) object type: work_struct hint: ieee80211_sta_monitor_work+0x0/0x14 [mac80211] +Modules linked in: [...] +Pid: 14743, comm: iw Tainted: G C O 3.7.9+ #11 +Call Trace: + [] warn_slowpath_common+0x80/0x98 + [] warn_slowpath_fmt+0x41/0x43 + [] debug_print_object+0x7c/0x8d + [] debug_check_no_obj_freed+0x95/0x1c3 + [] slab_free_hook+0x70/0x79 + [] kfree+0x62/0xb7 + [] netdev_release+0x39/0x3e + [] device_release+0x52/0x8a + [] kobject_release+0x121/0x158 + [] kobject_put+0x4c/0x50 + [] netdev_run_todo+0x25c/0x27e + +Cc: stable@vger.kernel.org +Signed-off-by: Ben Greear +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 6044c6d..b756d29 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4319,6 +4319,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + ++ /* ++ * Make sure some work items will not run after this, ++ * they will not do anything but might not have been ++ * cancelled when disconnecting. ++ */ ++ cancel_work_sync(&ifmgd->monitor_work); ++ cancel_work_sync(&ifmgd->beacon_connection_loss_work); ++ cancel_work_sync(&ifmgd->request_smps_work); ++ cancel_work_sync(&ifmgd->csa_connection_drop_work); ++ cancel_work_sync(&ifmgd->chswitch_work); ++ + mutex_lock(&ifmgd->mtx); + if (ifmgd->assoc_data) + ieee80211_destroy_assoc_data(sdata, false); +-- +1.8.1.2 + From f032373d45ef89603d7baaa40d7c5ae4416f4f5d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 12 Mar 2013 12:49:55 -0400 Subject: [PATCH 247/492] Add patch to fix ieee80211_do_stop (rhbz 892599) --- kernel.spec | 7 +- ...ieee80211_do_stop_while_suspend_v3.8.patch | 71 +++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch diff --git a/kernel.spec b/kernel.spec index db65fafc3..0fd7b7a9e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -803,9 +803,10 @@ Patch24108: signal-always-clear-sa_restorer-on-execve.patch #CVE-2013-0913 rhbz 920471 920529 Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch -#rhbz 865863 +#rhbz 856863 892599 Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch +Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch # AMD64 EDAC reports a wrong dimm count with new API. Fix it Patch25000: amd64_edac_fix_rank_count.patch @@ -1564,9 +1565,10 @@ ApplyPatch signal-always-clear-sa_restorer-on-execve.patch #CVE-2013-0913 rhbz 920471 920529 ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch -#rhbz 856863 +#rhbz 856863 892599 ApplyPatch mac80211-Fix-crash-due-to-un-canceled-work-items.patch ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch +ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch # END OF PATCH APPLICATIONS @@ -2426,6 +2428,7 @@ fi # || || %changelog * Tue Mar 12 2013 Josh Boyer +- Add patch to fix ieee80211_do_stop (rhbz 892599) - Add patches to fix cfg80211 issues with suspend (rhbz 856863) - Add patch to fix Cypress trackpad on XPS 12 machines (rhbz 912166) - CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) diff --git a/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch b/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch new file mode 100644 index 000000000..8249ab38c --- /dev/null +++ b/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch @@ -0,0 +1,71 @@ +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 8be854e..6d2bab7 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -605,7 +605,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + } + + ieee80211_adjust_monitor_flags(sdata, 1); +- ieee80211_configure_filter(local); ++ /* tell driver latter (if not suspended) */ + + netif_carrier_on(dev); + break; +@@ -804,8 +804,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + sdata->dev->addr_len); + spin_unlock_bh(&local->filter_lock); + netif_addr_unlock_bh(sdata->dev); +- +- ieee80211_configure_filter(local); ++ /* configure filter latter (if not suspended) */ + } + + del_timer_sync(&local->dynamic_ps_timer); +@@ -872,32 +871,30 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + */ + ieee80211_free_keys(sdata); + +- if (going_down) ++ if (going_down && !local->suspended) + drv_remove_interface(local, sdata); + } + + sdata->bss = NULL; + +- mutex_lock(&local->mtx); +- hw_reconf_flags |= __ieee80211_recalc_idle(local); +- mutex_unlock(&local->mtx); +- +- ieee80211_recalc_ps(local, -1); ++ if (!local->suspended) { ++ if (local->open_count == 0) { ++ if (local->ops->napi_poll) ++ napi_disable(&local->napi); ++ ieee80211_clear_tx_pending(local); ++ ieee80211_stop_device(local); ++ } else { ++ ieee80211_recalc_ps(local, -1); + +- if (local->open_count == 0) { +- if (local->ops->napi_poll) +- napi_disable(&local->napi); +- ieee80211_clear_tx_pending(local); +- ieee80211_stop_device(local); ++ mutex_lock(&local->mtx); ++ hw_reconf_flags |= __ieee80211_recalc_idle(local); ++ mutex_unlock(&local->mtx); + +- /* no reconfiguring after stop! */ +- hw_reconf_flags = 0; ++ if (hw_reconf_flags) ++ ieee80211_hw_config(local, hw_reconf_flags); ++ } + } + +- /* do after stop to avoid reconfiguring when we stop anyway */ +- if (hw_reconf_flags) +- ieee80211_hw_config(local, hw_reconf_flags); +- + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { + skb_queue_walk_safe(&local->pending[i], skb, tmp) { From a707d2a493811ee26eb5b53c2002d93fd99fd8ae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 Mar 2013 07:53:50 -0300 Subject: [PATCH 248/492] Fix i7300_edac size report on single DIMM mode Signed-off-by: Mauro Carvalho Chehab --- i7300_edac_single_mode_fixup.patch | 108 +++++++++++++++++++++++++++++ kernel.spec | 16 ++++- 2 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 i7300_edac_single_mode_fixup.patch diff --git a/i7300_edac_single_mode_fixup.patch b/i7300_edac_single_mode_fixup.patch new file mode 100644 index 000000000..ed08ab961 --- /dev/null +++ b/i7300_edac_single_mode_fixup.patch @@ -0,0 +1,108 @@ +commit 8ed5b5d41168a98cffa63e2f6c51c3243e159706 +Author: Mauro Carvalho Chehab +Date: Wed Mar 13 22:56:33 2013 -0300 + + i7300_edac: Fix memory detection in single mode + + When the machine is on single mode, only branch 0 channel 0 + is valid. However, the code is not honouring it: + + [ 1952.639341] EDAC DEBUG: i7300_get_mc_regs: Memory controller operating on single mode + ... + [ 1952.639351] EDAC DEBUG: i7300_init_csrows: AMB-present CH0 = 0x1: + [ 1952.639353] EDAC DEBUG: i7300_init_csrows: AMB-present CH1 = 0x0: + [ 1952.639355] EDAC DEBUG: i7300_init_csrows: AMB-present CH2 = 0x0: + [ 1952.639358] EDAC DEBUG: i7300_init_csrows: AMB-present CH3 = 0x0: + ... + [ 1952.639360] EDAC DEBUG: decode_mtr: MTR0 CH0: DIMMs are Present (mtr) + [ 1952.639362] EDAC DEBUG: decode_mtr: WIDTH: x8 + [ 1952.639363] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled + [ 1952.639364] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s) + [ 1952.639366] EDAC DEBUG: decode_mtr: NUMRANK: single + [ 1952.639367] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows + [ 1952.639368] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns + [ 1952.639370] EDAC DEBUG: decode_mtr: SIZE: 512 MB + [ 1952.639371] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code + [ 1952.639373] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode + [ 1952.639374] EDAC DEBUG: decode_mtr: MTR0 CH1: DIMMs are Present (mtr) + [ 1952.639376] EDAC DEBUG: decode_mtr: WIDTH: x8 + [ 1952.639377] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled + [ 1952.639379] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s) + [ 1952.639380] EDAC DEBUG: decode_mtr: NUMRANK: single + [ 1952.639381] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows + [ 1952.639383] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns + [ 1952.639384] EDAC DEBUG: decode_mtr: SIZE: 512 MB + [ 1952.639385] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code + [ 1952.639387] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode + ... + [ 1952.639449] EDAC DEBUG: print_dimm_size: channel 0 | channel 1 | channel 2 | channel 3 | + [ 1952.639451] EDAC DEBUG: print_dimm_size: ------------------------------------------------------------- + [ 1952.639453] EDAC DEBUG: print_dimm_size: csrow/SLOT 0 512 MB | 512 MB | 0 MB | 0 MB | + [ 1952.639456] EDAC DEBUG: print_dimm_size: csrow/SLOT 1 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639458] EDAC DEBUG: print_dimm_size: csrow/SLOT 2 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639460] EDAC DEBUG: print_dimm_size: csrow/SLOT 3 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639462] EDAC DEBUG: print_dimm_size: csrow/SLOT 4 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639464] EDAC DEBUG: print_dimm_size: csrow/SLOT 5 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639466] EDAC DEBUG: print_dimm_size: csrow/SLOT 6 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639468] EDAC DEBUG: print_dimm_size: csrow/SLOT 7 0 MB | 0 MB | 0 MB | 0 MB | + [ 1952.639470] EDAC DEBUG: print_dimm_size: ------------------------------------------------------------- + + Instead of detecting a single memory at channel 0, it is showing + twice the memory. + + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c +index 087c27b..9004c64 100644 +--- a/drivers/edac/i7300_edac.c ++++ b/drivers/edac/i7300_edac.c +@@ -750,15 +750,23 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) + struct i7300_dimm_info *dinfo; + int rc = -ENODEV; + int mtr; +- int ch, branch, slot, channel; ++ int ch, branch, slot, channel, max_channel, max_branch; + struct dimm_info *dimm; + + pvt = mci->pvt_info; + + edac_dbg(2, "Memory Technology Registers:\n"); + ++ if (IS_SINGLE_MODE(pvt->mc_settings_a)) { ++ max_branch = 1; ++ max_channel = 1; ++ } else { ++ max_branch = MAX_BRANCHES; ++ max_channel = MAX_CH_PER_BRANCH; ++ } ++ + /* Get the AMB present registers for the four channels */ +- for (branch = 0; branch < MAX_BRANCHES; branch++) { ++ for (branch = 0; branch < max_branch; branch++) { + /* Read and dump branch 0's MTRs */ + channel = to_channel(0, branch); + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], +@@ -767,6 +775,9 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) + edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); + ++ if (max_channel == 1) ++ continue; ++ + channel = to_channel(1, branch); + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], + AMBPRESENT_1, +@@ -778,11 +789,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) + /* Get the set of MTR[0-7] regs by each branch */ + for (slot = 0; slot < MAX_SLOTS; slot++) { + int where = mtr_regs[slot]; +- for (branch = 0; branch < MAX_BRANCHES; branch++) { ++ for (branch = 0; branch < max_branch; branch++) { + pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], + where, + &pvt->mtr[slot][branch]); +- for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) { ++ for (ch = 0; ch < max_channel; ch++) { + int channel = to_channel(ch, branch); + + dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, diff --git a/kernel.spec b/kernel.spec index 0fd7b7a9e..b83f1fb92 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,9 +808,12 @@ Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch -# AMD64 EDAC reports a wrong dimm count with new API. Fix it +#rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch +#rhbz 921500 +Patch25001: i7300_edac_single_mode_fixup.patch + # END OF PATCH DEFINITIONS %endif @@ -1542,8 +1545,12 @@ ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch #rhbz 917353 ApplyPatch backlight_revert.patch -R +#rhbz 920586 ApplyPatch amd64_edac_fix_rank_count.patch +#rhbz 921500 +ApplyPatch i7300_edac_single_mode_fixup.patch + #Team Driver update ApplyPatch team-net-next-update-20130307.patch @@ -2427,6 +2434,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 14 2013 Mauro Carvalho Chehab +- fix i7300_edac twice-mem-size-report via EDAC API (rhbz 921500) + * Tue Mar 12 2013 Josh Boyer - Add patch to fix ieee80211_do_stop (rhbz 892599) - Add patches to fix cfg80211 issues with suspend (rhbz 856863) @@ -2434,8 +2444,8 @@ fi - CVE-2013-0913 drm/i915: head writing overflow (rhbz 920471 920529) - CVE-2013-0914 sa_restorer information leak (rhbz 920499 920510) -* Mon Mar 11 2013 Mauro Carvalho Chehab - 3.8.2-209 -- fix amd64_edac twice-mem-size-report on dual-channel machines and new EDAC API +* Mon Mar 11 2013 Mauro Carvalho Chehab +- fix amd64_edac twice-mem-size-report via EDAC API (rhbz 920586) * Mon Mar 11 2013 Josh Boyer - Add patch to fix usb_submit_urb error in uvcvideo (rhbz 879462) From f330a83bcb8625d13c65dda72f618e4480ef3a0d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Mar 2013 07:45:49 -0400 Subject: [PATCH 249/492] Fix divide by zero on host TSC calibration failure (rhbz 859282) --- ...-handle-host-TSC-calibration-failure.patch | 58 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 67 insertions(+) create mode 100644 VMX-x86-handle-host-TSC-calibration-failure.patch diff --git a/VMX-x86-handle-host-TSC-calibration-failure.patch b/VMX-x86-handle-host-TSC-calibration-failure.patch new file mode 100644 index 000000000..6b6ddd2d2 --- /dev/null +++ b/VMX-x86-handle-host-TSC-calibration-failure.patch @@ -0,0 +1,58 @@ +@@ -, +, @@ + VMX: x86: handle host TSC calibration failure + + If the host TSC calibration fails, tsc_khz is zero (see tsc_init.c). + Handle such case properly in KVM (instead of dividing by zero). + + https://bugzilla.redhat.com/show_bug.cgi?id=859282 + + Signed-off-by: Marcelo Tosatti + Signed-off-by: Gleb Natapov +--- a/arch/x86/kvm/x86.c ++++ a/arch/x86/kvm/x86.c +@@ -1079,6 +1079,10 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz) + u32 thresh_lo, thresh_hi; + int use_scaling = 0; + ++ /* tsc_khz can be zero if TSC calibration fails */ ++ if (this_tsc_khz == 0) ++ return; ++ + /* Compute a scale to convert nanoseconds in TSC cycles */ + kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000, + &vcpu->arch.virtual_tsc_shift, +@@ -1156,20 +1160,23 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) + ns = get_kernel_ns(); + elapsed = ns - kvm->arch.last_tsc_nsec; + +- /* n.b - signed multiplication and division required */ +- usdiff = data - kvm->arch.last_tsc_write; ++ if (vcpu->arch.virtual_tsc_khz) { ++ /* n.b - signed multiplication and division required */ ++ usdiff = data - kvm->arch.last_tsc_write; + #ifdef CONFIG_X86_64 +- usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; ++ usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; + #else +- /* do_div() only does unsigned */ +- asm("idivl %2; xor %%edx, %%edx" +- : "=A"(usdiff) +- : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); ++ /* do_div() only does unsigned */ ++ asm("idivl %2; xor %%edx, %%edx" ++ : "=A"(usdiff) ++ : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); + #endif +- do_div(elapsed, 1000); +- usdiff -= elapsed; +- if (usdiff < 0) +- usdiff = -usdiff; ++ do_div(elapsed, 1000); ++ usdiff -= elapsed; ++ if (usdiff < 0) ++ usdiff = -usdiff; ++ } else ++ usdiff = USEC_PER_SEC; /* disable TSC match window below */ + + /* + * Special case: TSC write with a small delta (1 second) of virtual diff --git a/kernel.spec b/kernel.spec index b83f1fb92..d1021bdfa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,6 +808,9 @@ Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch +#rhbz 859282 +Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch + #rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch @@ -1577,6 +1580,9 @@ ApplyPatch mac80211-Fix-crash-due-to-un-canceled-work-items.patch ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch +#rhbz 859282 +ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch + # END OF PATCH APPLICATIONS %endif @@ -2434,6 +2440,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 14 2013 Josh Boyer +- Fix divide by zero on host TSC calibration failure (rhbz 859282) + * Thu Mar 14 2013 Mauro Carvalho Chehab - fix i7300_edac twice-mem-size-report via EDAC API (rhbz 921500) From f7c0765d63a8544c89b9d958faa91ad0d3ffa9a9 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 14 Mar 2013 16:03:05 -0500 Subject: [PATCH 250/492] Linux v3.8.3 --- arm-alignment-faults.patch | 127 --- ...to-user-fix-info-leaks-in-report-API.patch | 223 ------ ...or-_dmi_-signature-in-smbios_present.patch | 47 -- efi-fixes-3.8.patch | 736 ------------------ kernel.spec | 44 +- ...ith-concurrent-install_user_keyrings.patch | 15 - ...l-hid_output_raw_report-during-probe.patch | 66 -- ...-crash-due-to-un-canceled-work-items.patch | 67 -- sources | 2 +- 9 files changed, 7 insertions(+), 1320 deletions(-) delete mode 100644 arm-alignment-faults.patch delete mode 100644 crypto-user-fix-info-leaks-in-report-API.patch delete mode 100644 dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch delete mode 100644 efi-fixes-3.8.patch delete mode 100644 keys-fix-race-with-concurrent-install_user_keyrings.patch delete mode 100644 logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch delete mode 100644 mac80211-Fix-crash-due-to-un-canceled-work-items.patch diff --git a/arm-alignment-faults.patch b/arm-alignment-faults.patch deleted file mode 100644 index d386a5c3e..000000000 --- a/arm-alignment-faults.patch +++ /dev/null @@ -1,127 +0,0 @@ - arch/arm/kernel/traps.c | 34 +++++++--------------------------- - arch/arm/mm/alignment.c | 11 ++++------- - 2 files changed, 11 insertions(+), 34 deletions(-) - -diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c -index b0179b8..62f429e 100644 ---- a/arch/arm/kernel/traps.c -+++ b/arch/arm/kernel/traps.c -@@ -89,17 +89,8 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - unsigned long top) - { - unsigned long first; -- mm_segment_t fs; - int i; - -- /* -- * We need to switch to kernel mode so that we can use __get_user -- * to safely read from kernel space. Note that we now dump the -- * code first, just in case the backtrace kills us. -- */ -- fs = get_fs(); -- set_fs(KERNEL_DS); -- - printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top); - - for (first = bottom & ~31; first < top; first += 32) { -@@ -112,7 +103,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { - if (p >= bottom && p < top) { - unsigned long val; -- if (__get_user(val, (unsigned long *)p) == 0) -+ if (probe_kernel_address(p, val) == 0) - sprintf(str + i * 9, " %08lx", val); - else - sprintf(str + i * 9, " ????????"); -@@ -120,8 +111,6 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - } - printk("%s%04lx:%s\n", lvl, first & 0xffff, str); - } -- -- set_fs(fs); - } - - static void dump_instr(const char *lvl, struct pt_regs *regs) -@@ -129,25 +118,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) - unsigned long addr = instruction_pointer(regs); - const int thumb = thumb_mode(regs); - const int width = thumb ? 4 : 8; -- mm_segment_t fs; - char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; - int i; - -- /* -- * We need to switch to kernel mode so that we can use __get_user -- * to safely read from kernel space. Note that we now dump the -- * code first, just in case the backtrace kills us. -- */ -- fs = get_fs(); -- set_fs(KERNEL_DS); -- - for (i = -4; i < 1 + !!thumb; i++) { - unsigned int val, bad; - -- if (thumb) -- bad = __get_user(val, &((u16 *)addr)[i]); -- else -- bad = __get_user(val, &((u32 *)addr)[i]); -+ if (thumb) { -+ u16 instr; -+ bad = probe_kernel_address(addr, instr); -+ val = instr; -+ } else -+ bad = probe_kernel_address(addr, val); - - if (!bad) - p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", -@@ -158,8 +140,6 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) - } - } - printk("%sCode: %s\n", lvl, str); -- -- set_fs(fs); - } - - #ifdef CONFIG_ARM_UNWIND -diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c -index b9f60eb..f8f14fc 100644 ---- a/arch/arm/mm/alignment.c -+++ b/arch/arm/mm/alignment.c -@@ -749,7 +749,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) - unsigned long instr = 0, instrptr; - int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); - unsigned int type; -- mm_segment_t fs; - unsigned int fault; - u16 tinstr = 0; - int isize = 4; -@@ -760,16 +759,15 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) - - instrptr = instruction_pointer(regs); - -- fs = get_fs(); -- set_fs(KERNEL_DS); - if (thumb_mode(regs)) { -- fault = __get_user(tinstr, (u16 *)(instrptr & ~1)); -+ unsigned long ptr = instrptr; -+ fault = probe_kernel_address(ptr, tinstr); - if (!fault) { - if (cpu_architecture() >= CPU_ARCH_ARMv7 && - IS_T32(tinstr)) { - /* Thumb-2 32-bit */ - u16 tinst2 = 0; -- fault = __get_user(tinst2, (u16 *)(instrptr+2)); -+ fault = probe_kernel_address(ptr + 2, tinst2); - instr = (tinstr << 16) | tinst2; - thumb2_32b = 1; - } else { -@@ -778,8 +776,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) - } - } - } else -- fault = __get_user(instr, (u32 *)instrptr); -- set_fs(fs); -+ fault = probe_kernel_address(instrptr, instr); - - if (fault) { - type = TYPE_FAULT; diff --git a/crypto-user-fix-info-leaks-in-report-API.patch b/crypto-user-fix-info-leaks-in-report-API.patch deleted file mode 100644 index 1b64e1844..000000000 --- a/crypto-user-fix-info-leaks-in-report-API.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 9a5467bf7b6e9e02ec9c3da4e23747c05faeaac6 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Tue, 5 Feb 2013 18:19:13 +0100 -Subject: [PATCH] crypto: user - fix info leaks in report API - -Three errors resulting in kernel memory disclosure: - -1/ The structures used for the netlink based crypto algorithm report API -are located on the stack. As snprintf() does not fill the remainder of -the buffer with null bytes, those stack bytes will be disclosed to users -of the API. Switch to strncpy() to fix this. - -2/ crypto_report_one() does not initialize all field of struct -crypto_user_alg. Fix this to fix the heap info leak. - -3/ For the module name we should copy only as many bytes as -module_name() returns -- not as much as the destination buffer could -hold. But the current code does not and therefore copies random data -from behind the end of the module name, as the module name is always -shorter than CRYPTO_MAX_ALG_NAME. - -Also switch to use strncpy() to copy the algorithm's name and -driver_name. They are strings, after all. - -Signed-off-by: Mathias Krause -Cc: Steffen Klassert -Signed-off-by: Herbert Xu ---- - crypto/ablkcipher.c | 12 ++++++------ - crypto/aead.c | 9 ++++----- - crypto/ahash.c | 2 +- - crypto/blkcipher.c | 6 +++--- - crypto/crypto_user.c | 22 +++++++++++----------- - crypto/pcompress.c | 3 +-- - crypto/rng.c | 2 +- - crypto/shash.c | 3 ++- - 8 files changed, 29 insertions(+), 30 deletions(-) - -diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c -index 533de95..7d4a8d2 100644 ---- a/crypto/ablkcipher.c -+++ b/crypto/ablkcipher.c -@@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_blkcipher rblkcipher; - -- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher"); -- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", -- alg->cra_ablkcipher.geniv ?: ""); -+ strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); -+ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", -+ sizeof(rblkcipher.geniv)); - - rblkcipher.blocksize = alg->cra_blocksize; - rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; -@@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_blkcipher rblkcipher; - -- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher"); -- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", -- alg->cra_ablkcipher.geniv ?: ""); -+ strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); -+ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", -+ sizeof(rblkcipher.geniv)); - - rblkcipher.blocksize = alg->cra_blocksize; - rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; -diff --git a/crypto/aead.c b/crypto/aead.c -index 4d04e12..547491e 100644 ---- a/crypto/aead.c -+++ b/crypto/aead.c -@@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) - struct crypto_report_aead raead; - struct aead_alg *aead = &alg->cra_aead; - -- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead"); -- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", -- aead->geniv ?: ""); -+ strncpy(raead.type, "aead", sizeof(raead.type)); -+ strncpy(raead.geniv, aead->geniv ?: "", sizeof(raead.geniv)); - - raead.blocksize = alg->cra_blocksize; - raead.maxauthsize = aead->maxauthsize; -@@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) - struct crypto_report_aead raead; - struct aead_alg *aead = &alg->cra_aead; - -- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead"); -- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv); -+ strncpy(raead.type, "nivaead", sizeof(raead.type)); -+ strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv)); - - raead.blocksize = alg->cra_blocksize; - raead.maxauthsize = aead->maxauthsize; -diff --git a/crypto/ahash.c b/crypto/ahash.c -index 3887856..793a27f 100644 ---- a/crypto/ahash.c -+++ b/crypto/ahash.c -@@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_hash rhash; - -- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash"); -+ strncpy(rhash.type, "ahash", sizeof(rhash.type)); - - rhash.blocksize = alg->cra_blocksize; - rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; -diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c -index e9e7244..a79e7e9 100644 ---- a/crypto/blkcipher.c -+++ b/crypto/blkcipher.c -@@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_blkcipher rblkcipher; - -- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher"); -- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", -- alg->cra_blkcipher.geniv ?: ""); -+ strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); -+ strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", -+ sizeof(rblkcipher.geniv)); - - rblkcipher.blocksize = alg->cra_blocksize; - rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize; -diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c -index 35d700a..f6d9baf 100644 ---- a/crypto/crypto_user.c -+++ b/crypto/crypto_user.c -@@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_cipher rcipher; - -- snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher"); -+ strncpy(rcipher.type, "cipher", sizeof(rcipher.type)); - - rcipher.blocksize = alg->cra_blocksize; - rcipher.min_keysize = alg->cra_cipher.cia_min_keysize; -@@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_comp rcomp; - -- snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression"); -- -+ strncpy(rcomp.type, "compression", sizeof(rcomp.type)); - if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, - sizeof(struct crypto_report_comp), &rcomp)) - goto nla_put_failure; -@@ -108,12 +107,14 @@ nla_put_failure: - static int crypto_report_one(struct crypto_alg *alg, - struct crypto_user_alg *ualg, struct sk_buff *skb) - { -- memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name)); -- memcpy(&ualg->cru_driver_name, &alg->cra_driver_name, -- sizeof(ualg->cru_driver_name)); -- memcpy(&ualg->cru_module_name, module_name(alg->cra_module), -- CRYPTO_MAX_ALG_NAME); -- -+ strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name)); -+ strncpy(ualg->cru_driver_name, alg->cra_driver_name, -+ sizeof(ualg->cru_driver_name)); -+ strncpy(ualg->cru_module_name, module_name(alg->cra_module), -+ sizeof(ualg->cru_module_name)); -+ -+ ualg->cru_type = 0; -+ ualg->cru_mask = 0; - ualg->cru_flags = alg->cra_flags; - ualg->cru_refcnt = atomic_read(&alg->cra_refcnt); - -@@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg, - if (alg->cra_flags & CRYPTO_ALG_LARVAL) { - struct crypto_report_larval rl; - -- snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval"); -- -+ strncpy(rl.type, "larval", sizeof(rl.type)); - if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL, - sizeof(struct crypto_report_larval), &rl)) - goto nla_put_failure; -diff --git a/crypto/pcompress.c b/crypto/pcompress.c -index 04e083f..7140fe7 100644 ---- a/crypto/pcompress.c -+++ b/crypto/pcompress.c -@@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_comp rpcomp; - -- snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp"); -- -+ strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type)); - if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, - sizeof(struct crypto_report_comp), &rpcomp)) - goto nla_put_failure; -diff --git a/crypto/rng.c b/crypto/rng.c -index f3b7894..e0a25c2 100644 ---- a/crypto/rng.c -+++ b/crypto/rng.c -@@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) - { - struct crypto_report_rng rrng; - -- snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng"); -+ strncpy(rrng.type, "rng", sizeof(rrng.type)); - - rrng.seedsize = alg->cra_rng.seedsize; - -diff --git a/crypto/shash.c b/crypto/shash.c -index f426330f..929058a 100644 ---- a/crypto/shash.c -+++ b/crypto/shash.c -@@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) - struct crypto_report_hash rhash; - struct shash_alg *salg = __crypto_shash_alg(alg); - -- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash"); -+ strncpy(rhash.type, "shash", sizeof(rhash.type)); -+ - rhash.blocksize = alg->cra_blocksize; - rhash.digestsize = salg->digestsize; - --- -1.8.1.2 - diff --git a/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch b/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch deleted file mode 100644 index f105a7e6a..000000000 --- a/dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch +++ /dev/null @@ -1,47 +0,0 @@ -From: Ben Hutchings -Subject: dmi_scan: fix missing check for _DMI_ signature in smbios_present() - -Commit 9f9c9cbb6057 ('drivers/firmware/dmi_scan.c: fetch dmi version from -SMBIOS if it exists') hoisted the check for "_DMI_" into -dmi_scan_machine(), which means that we don't bother to check for "_DMI_" -at offset 16 in an SMBIOS entry. smbios_present() may also call -dmi_present() for an address where we found "_SM_", if it failed further -validation. - -Check for "_DMI_" in smbios_present() before calling dmi_present(). - -Signed-off-by: Ben Hutchings -Reported-by: Tim McGrath -Tested-by: Tim Mcgrath -Cc: Zhenzhong Duan -Cc: -Signed-off-by: Andrew Morton ---- - - drivers/firmware/dmi_scan.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff -puN drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present drivers/firmware/dmi_scan.c ---- a/drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present -+++ a/drivers/firmware/dmi_scan.c -@@ -442,7 +442,6 @@ static int __init dmi_present(const char - static int __init smbios_present(const char __iomem *p) - { - u8 buf[32]; -- int offset = 0; - - memcpy_fromio(buf, p, 32); - if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { -@@ -461,9 +460,9 @@ static int __init smbios_present(const c - dmi_ver = 0x0206; - break; - } -- offset = 16; -+ return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); - } -- return dmi_present(buf + offset); -+ return 1; - } - - void __init dmi_scan_machine(void) -_ diff --git a/efi-fixes-3.8.patch b/efi-fixes-3.8.patch deleted file mode 100644 index f53dac078..000000000 --- a/efi-fixes-3.8.patch +++ /dev/null @@ -1,736 +0,0 @@ -From 27857f8a3240e35c61dedb88cbdbfbaabbd8ad2b Mon Sep 17 00:00:00 2001 -From: Seiji Aguchi -Date: Tue, 12 Feb 2013 12:59:07 -0800 -Subject: [PATCH 1/4] efivars: Disable external interrupt while holding - efivars->lock - -[Problem] -There is a scenario which efi_pstore fails to log messages in a panic case. - - - CPUA holds an efi_var->lock in either efivarfs parts - or efi_pstore with interrupt enabled. - - CPUB panics and sends IPI to CPUA in smp_send_stop(). - - CPUA stops with holding the lock. - - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC) - but it returns without logging messages. - -[Patch Description] -This patch disables an external interruption while holding efivars->lock -as follows. - -In efi_pstore_write() and get_var_data(), spin_lock/spin_unlock is -replaced by spin_lock_irqsave/spin_unlock_irqrestore because they may -be called in an interrupt context. - -In other functions, they are replaced by spin_lock_irq/spin_unlock_irq. -because they are all called from a process context. - -By applying this patch, we can avoid the problem above with -a following senario. - - - CPUA holds an efi_var->lock with interrupt disabled. - - CPUB panics and sends IPI to CPUA in smp_send_stop(). - - CPUA receives the IPI after releasing the lock because it is - disabling interrupt while holding the lock. - - CPUB waits for one sec until CPUA releases the lock. - - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC) - And it can hold the lock successfully. - -Signed-off-by: Seiji Aguchi -Acked-by: Mike Waychison -Acked-by: Matt Fleming -Signed-off-by: Tony Luck ---- - drivers/firmware/efivars.c | 84 ++++++++++++++++++++++++---------------------- - 1 file changed, 43 insertions(+), 41 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index bcb201c..a9277cc 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -406,10 +406,11 @@ static efi_status_t - get_var_data(struct efivars *efivars, struct efi_variable *var) - { - efi_status_t status; -+ unsigned long flags; - -- spin_lock(&efivars->lock); -+ spin_lock_irqsave(&efivars->lock, flags); - status = get_var_data_locked(efivars, var); -- spin_unlock(&efivars->lock); -+ spin_unlock_irqrestore(&efivars->lock, flags); - - if (status != EFI_SUCCESS) { - printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", -@@ -538,14 +539,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) - return -EINVAL; - } - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - status = efivars->ops->set_variable(new_var->VariableName, - &new_var->VendorGuid, - new_var->Attributes, - new_var->DataSize, - new_var->Data); - -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - if (status != EFI_SUCCESS) { - printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", -@@ -714,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file, - * amounts of memory. Pick a default size of 64K if - * QueryVariableInfo() isn't supported by the firmware. - */ -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - if (!efivars->ops->query_variable_info) - status = EFI_UNSUPPORTED; -@@ -724,7 +725,7 @@ static ssize_t efivarfs_file_write(struct file *file, - &remaining_size, &max_size); - } - -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - if (status != EFI_SUCCESS) { - if (status != EFI_UNSUPPORTED) -@@ -755,7 +756,7 @@ static ssize_t efivarfs_file_write(struct file *file, - * set_variable call, and removal of the variable from the efivars - * list (in the case of an authenticated delete). - */ -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - status = efivars->ops->set_variable(var->var.VariableName, - &var->var.VendorGuid, -@@ -763,7 +764,7 @@ static ssize_t efivarfs_file_write(struct file *file, - data); - - if (status != EFI_SUCCESS) { -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - kfree(data); - - return efi_status_to_err(status); -@@ -784,21 +785,21 @@ static ssize_t efivarfs_file_write(struct file *file, - NULL); - - if (status == EFI_BUFFER_TOO_SMALL) { -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - mutex_lock(&inode->i_mutex); - i_size_write(inode, newdatasize + sizeof(attributes)); - mutex_unlock(&inode->i_mutex); - - } else if (status == EFI_NOT_FOUND) { - list_del(&var->list); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - efivar_unregister(var); - drop_nlink(inode); - d_delete(file->f_dentry); - dput(file->f_dentry); - - } else { -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - pr_warn("efivarfs: inconsistent EFI variable implementation? " - "status = %lx\n", status); - } -@@ -820,11 +821,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - void *data; - ssize_t size = 0; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, - &attributes, &datasize, NULL); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - if (status != EFI_BUFFER_TOO_SMALL) - return efi_status_to_err(status); -@@ -834,12 +835,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, - if (!data) - return -ENOMEM; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - status = efivars->ops->get_variable(var->var.VariableName, - &var->var.VendorGuid, - &attributes, &datasize, - (data + sizeof(attributes))); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - if (status != EFI_SUCCESS) { - size = efi_status_to_err(status); -@@ -1005,9 +1006,9 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, - goto out; - - kobject_uevent(&var->kobj, KOBJ_ADD); -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - list_add(&var->list, &efivars->list); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - d_instantiate(dentry, inode); - dget(dentry); - out: -@@ -1024,7 +1025,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) - struct efivars *efivars = var->efivars; - efi_status_t status; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - status = efivars->ops->set_variable(var->var.VariableName, - &var->var.VendorGuid, -@@ -1032,14 +1033,14 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) - - if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { - list_del(&var->list); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - efivar_unregister(var); - drop_nlink(dentry->d_inode); - dput(dentry); - return 0; - } - -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return -EINVAL; - }; - -@@ -1184,13 +1185,13 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - /* copied by the above to local storage in the dentry. */ - kfree(name); - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - efivars->ops->get_variable(entry->var.VariableName, - &entry->var.VendorGuid, - &entry->var.Attributes, - &size, - NULL); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - mutex_lock(&inode->i_mutex); - inode->i_private = entry; -@@ -1253,7 +1254,7 @@ static int efi_pstore_open(struct pstore_info *psi) - { - struct efivars *efivars = psi->data; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - efivars->walk_entry = list_first_entry(&efivars->list, - struct efivar_entry, list); - return 0; -@@ -1263,7 +1264,7 @@ static int efi_pstore_close(struct pstore_info *psi) - { - struct efivars *efivars = psi->data; - -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return 0; - } - -@@ -1339,8 +1340,9 @@ static int efi_pstore_write(enum pstore_type_id type, - int i, ret = 0; - u64 storage_space, remaining_space, max_variable_size; - efi_status_t status = EFI_NOT_FOUND; -+ unsigned long flags; - -- spin_lock(&efivars->lock); -+ spin_lock_irqsave(&efivars->lock, flags); - - /* - * Check if there is a space enough to log. -@@ -1352,7 +1354,7 @@ static int efi_pstore_write(enum pstore_type_id type, - &remaining_space, - &max_variable_size); - if (status || remaining_space < size + DUMP_NAME_LEN * 2) { -- spin_unlock(&efivars->lock); -+ spin_unlock_irqrestore(&efivars->lock, flags); - *id = part; - return -ENOSPC; - } -@@ -1366,7 +1368,7 @@ static int efi_pstore_write(enum pstore_type_id type, - efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, - size, psi->buf); - -- spin_unlock(&efivars->lock); -+ spin_unlock_irqrestore(&efivars->lock, flags); - - if (size) - ret = efivar_create_sysfs_entry(efivars, -@@ -1393,7 +1395,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, - sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count, - time.tv_sec); - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - for (i = 0; i < DUMP_NAME_LEN; i++) - efi_name[i] = name[i]; -@@ -1437,7 +1439,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, - if (found) - list_del(&found->list); - -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - if (found) - efivar_unregister(found); -@@ -1507,7 +1509,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, - return -EINVAL; - } - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - /* - * Does this variable already exist? -@@ -1525,7 +1527,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, - } - } - if (found) { -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return -EINVAL; - } - -@@ -1539,10 +1541,10 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, - if (status != EFI_SUCCESS) { - printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", - status); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return -EIO; - } -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - /* Create the entry in sysfs. Locking is not required here */ - status = efivar_create_sysfs_entry(efivars, -@@ -1570,7 +1572,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - - /* - * Does this variable already exist? -@@ -1588,7 +1590,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, - } - } - if (!found) { -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return -EINVAL; - } - /* force the Attributes/DataSize to 0 to ensure deletion */ -@@ -1604,12 +1606,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, - if (status != EFI_SUCCESS) { - printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", - status); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - return -EIO; - } - list_del(&search_efivar->list); - /* We need to release this lock before unregistering. */ -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - efivar_unregister(search_efivar); - - /* It's dead Jim.... */ -@@ -1724,9 +1726,9 @@ efivar_create_sysfs_entry(struct efivars *efivars, - kfree(short_name); - short_name = NULL; - -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - list_add(&new_efivar->list, &efivars->list); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - - return 0; - } -@@ -1795,9 +1797,9 @@ void unregister_efivars(struct efivars *efivars) - struct efivar_entry *entry, *n; - - list_for_each_entry_safe(entry, n, &efivars->list, list) { -- spin_lock(&efivars->lock); -+ spin_lock_irq(&efivars->lock); - list_del(&entry->list); -- spin_unlock(&efivars->lock); -+ spin_unlock_irq(&efivars->lock); - efivar_unregister(entry); - } - if (efivars->new_var) --- -1.8.1.2 - - -From 19adc04301476eaa15e035b66e92cb333223c352 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Sat, 2 Mar 2013 19:40:17 -0500 -Subject: [PATCH 2/4] efi: be more paranoid about available space when creating - variables - -UEFI variables are typically stored in flash. For various reasons, avaiable -space is typically not reclaimed immediately upon the deletion of a -variable - instead, the system will garbage collect during initialisation -after a reboot. - -Some systems appear to handle this garbage collection extremely poorly, -failing if more than 50% of the system flash is in use. This can result in -the machine refusing to boot. The safest thing to do for the moment is to -forbid writes if they'd end up using more than half of the storage space. -We can make this more finegrained later if we come up with a method for -identifying the broken machines. - -Signed-off-by: Matthew Garrett -Cc: -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 106 +++++++++++++++++++++++++++++++++------------ - 1 file changed, 79 insertions(+), 27 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index a9277cc..919862b 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -419,6 +419,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var) - return status; - } - -+static efi_status_t -+check_var_size_locked(struct efivars *efivars, u32 attributes, -+ unsigned long size) -+{ -+ u64 storage_size, remaining_size, max_size; -+ efi_status_t status; -+ const struct efivar_operations *fops = efivars->ops; -+ -+ if (!efivars->ops->query_variable_info) -+ return EFI_UNSUPPORTED; -+ -+ status = fops->query_variable_info(attributes, &storage_size, -+ &remaining_size, &max_size); -+ -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ if (!storage_size || size > remaining_size || size > max_size || -+ (remaining_size - size) < (storage_size / 2)) -+ return EFI_OUT_OF_RESOURCES; -+ -+ return status; -+} -+ -+ -+static efi_status_t -+check_var_size(struct efivars *efivars, u32 attributes, unsigned long size) -+{ -+ efi_status_t status; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&efivars->lock, flags); -+ status = check_var_size_locked(efivars, attributes, size); -+ spin_unlock_irqrestore(&efivars->lock, flags); -+ -+ return status; -+} -+ - static ssize_t - efivar_guid_read(struct efivar_entry *entry, char *buf) - { -@@ -540,11 +578,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) - } - - spin_lock_irq(&efivars->lock); -- status = efivars->ops->set_variable(new_var->VariableName, -- &new_var->VendorGuid, -- new_var->Attributes, -- new_var->DataSize, -- new_var->Data); -+ -+ status = check_var_size_locked(efivars, new_var->Attributes, -+ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); -+ -+ if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) -+ status = efivars->ops->set_variable(new_var->VariableName, -+ &new_var->VendorGuid, -+ new_var->Attributes, -+ new_var->DataSize, -+ new_var->Data); - - spin_unlock_irq(&efivars->lock); - -@@ -695,8 +738,7 @@ static ssize_t efivarfs_file_write(struct file *file, - u32 attributes; - struct inode *inode = file->f_mapping->host; - unsigned long datasize = count - sizeof(attributes); -- unsigned long newdatasize; -- u64 storage_size, remaining_size, max_size; -+ unsigned long newdatasize, varsize; - ssize_t bytes = 0; - - if (count < sizeof(attributes)) -@@ -715,28 +757,18 @@ static ssize_t efivarfs_file_write(struct file *file, - * amounts of memory. Pick a default size of 64K if - * QueryVariableInfo() isn't supported by the firmware. - */ -- spin_lock_irq(&efivars->lock); - -- if (!efivars->ops->query_variable_info) -- status = EFI_UNSUPPORTED; -- else { -- const struct efivar_operations *fops = efivars->ops; -- status = fops->query_variable_info(attributes, &storage_size, -- &remaining_size, &max_size); -- } -- -- spin_unlock_irq(&efivars->lock); -+ varsize = datasize + utf16_strsize(var->var.VariableName, 1024); -+ status = check_var_size(efivars, attributes, varsize); - - if (status != EFI_SUCCESS) { - if (status != EFI_UNSUPPORTED) - return efi_status_to_err(status); - -- remaining_size = 65536; -+ if (datasize > 65536) -+ return -ENOSPC; - } - -- if (datasize > remaining_size) -- return -ENOSPC; -- - data = kmalloc(datasize, GFP_KERNEL); - if (!data) - return -ENOMEM; -@@ -758,6 +790,19 @@ static ssize_t efivarfs_file_write(struct file *file, - */ - spin_lock_irq(&efivars->lock); - -+ /* -+ * Ensure that the available space hasn't shrunk below the safe level -+ */ -+ -+ status = check_var_size_locked(efivars, attributes, varsize); -+ -+ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) { -+ spin_unlock_irq(&efivars->lock); -+ kfree(data); -+ -+ return efi_status_to_err(status); -+ } -+ - status = efivars->ops->set_variable(var->var.VariableName, - &var->var.VendorGuid, - attributes, datasize, -@@ -1338,7 +1383,6 @@ static int efi_pstore_write(enum pstore_type_id type, - efi_guid_t vendor = LINUX_EFI_CRASH_GUID; - struct efivars *efivars = psi->data; - int i, ret = 0; -- u64 storage_space, remaining_space, max_variable_size; - efi_status_t status = EFI_NOT_FOUND; - unsigned long flags; - -@@ -1349,11 +1393,11 @@ static int efi_pstore_write(enum pstore_type_id type, - * size: a size of logging data - * DUMP_NAME_LEN * 2: a maximum size of variable name - */ -- status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES, -- &storage_space, -- &remaining_space, -- &max_variable_size); -- if (status || remaining_space < size + DUMP_NAME_LEN * 2) { -+ -+ status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES, -+ size + DUMP_NAME_LEN * 2); -+ -+ if (status) { - spin_unlock_irqrestore(&efivars->lock, flags); - *id = part; - return -ENOSPC; -@@ -1531,6 +1575,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, - return -EINVAL; - } - -+ status = check_var_size_locked(efivars, new_var->Attributes, -+ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); -+ -+ if (status && status != EFI_UNSUPPORTED) { -+ spin_unlock_irq(&efivars->lock); -+ return efi_status_to_err(status); -+ } -+ - /* now *really* create the variable via EFI */ - status = efivars->ops->set_variable(new_var->VariableName, - &new_var->VendorGuid, --- -1.8.1.2 - - -From 46b6e1db3a81203deaf4615637616a0266a2e6e6 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Tue, 5 Mar 2013 07:40:16 +0000 -Subject: [PATCH 3/4] efivars: efivarfs_valid_name() should handle pstore - syntax - -Stricter validation was introduced with commit da27a24383b2b -("efivarfs: guid part of filenames are case-insensitive") and commit -47f531e8ba3b ("efivarfs: Validate filenames much more aggressively"), -which is necessary for the guid portion of efivarfs filenames, but we -don't need to be so strict with the first part, the variable name. The -UEFI specification doesn't impose any constraints on variable names -other than they be a NULL-terminated string. - -The above commits caused a regression that resulted in users seeing -the following message, - - $ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory - -whenever pstore EFI variables were present in the variable store, -since their variable names failed to pass the following check, - - /* GUID should be right after the first '-' */ - if (s - 1 != strchr(str, '-')) - -as a typical pstore filename is of the form, dump-type0-10-1-. -The fix is trivial since the guid portion of the filename is GUID_LEN -bytes, we can use (len - GUID_LEN) to ensure the '-' character is -where we expect it to be. - -(The bogus ENOMEM error value will be fixed in a separate patch.) - -Reported-by: Joseph Yasi -Reported-by: Lingzhu Xiang -Cc: Josh Boyer -Cc: Jeremy Kerr -Cc: Matthew Garrett -Cc: -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index 919862b..fc54ddd 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -967,8 +967,8 @@ static bool efivarfs_valid_name(const char *str, int len) - if (len < GUID_LEN + 2) - return false; - -- /* GUID should be right after the first '-' */ -- if (s - 1 != strchr(str, '-')) -+ /* GUID must be preceded by a '-' */ -+ if (*(s - 1) != '-') - return false; - - /* --- -1.8.1.2 - - -From f751b6c973fe5a480ff12c97df4b8ac4e9a666a7 Mon Sep 17 00:00:00 2001 -From: Matt Fleming -Date: Tue, 5 Mar 2013 12:46:30 +0000 -Subject: [PATCH 4/4] efivarfs: return accurate error code in - efivarfs_fill_super() - -Joseph was hitting a failure case when mounting efivarfs which -resulted in an incorrect error message, - - $ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory - -triggered when efivarfs_valid_name() returned -EINVAL. - -Make sure we pass accurate return values up the stack if -efivarfs_fill_super() fails to build inodes for EFI variables. - -Reported-by: Joseph Yasi -Reported-by: Lingzhu Xiang -Cc: Josh Boyer -Cc: Jeremy Kerr -Cc: Matthew Garrett -Cc: -Signed-off-by: Matt Fleming ---- - drivers/firmware/efivars.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c -index fc54ddd..2a2e145 100644 ---- a/drivers/firmware/efivars.c -+++ b/drivers/firmware/efivars.c -@@ -1156,15 +1156,22 @@ static struct dentry_operations efivarfs_d_ops = { - - static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) - { -+ struct dentry *d; - struct qstr q; -+ int err; - - q.name = name; - q.len = strlen(name); - -- if (efivarfs_d_hash(NULL, NULL, &q)) -- return NULL; -+ err = efivarfs_d_hash(NULL, NULL, &q); -+ if (err) -+ return ERR_PTR(err); -+ -+ d = d_alloc(parent, &q); -+ if (d) -+ return d; - -- return d_alloc(parent, &q); -+ return ERR_PTR(-ENOMEM); - } - - static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) -@@ -1174,6 +1181,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - struct efivar_entry *entry, *n; - struct efivars *efivars = &__efivars; - char *name; -+ int err = -ENOMEM; - - efivarfs_sb = sb; - -@@ -1224,8 +1232,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) - goto fail_name; - - dentry = efivarfs_alloc_dentry(root, name); -- if (!dentry) -+ if (IS_ERR(dentry)) { -+ err = PTR_ERR(dentry); - goto fail_inode; -+ } - - /* copied by the above to local storage in the dentry. */ - kfree(name); -@@ -1252,7 +1262,7 @@ fail_inode: - fail_name: - kfree(name); - fail: -- return -ENOMEM; -+ return err; - } - - static struct dentry *efivarfs_mount(struct file_system_type *fs_type, --- -1.8.1.2 - diff --git a/kernel.spec b/kernel.spec index d1021bdfa..c3b96b02a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 210 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -95,7 +95,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 0 # The git snapshot level -%define gitrev 0 +%define gitrev 100 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -718,8 +718,6 @@ Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM -# http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/137164.html -Patch21002: arm-alignment-faults.patch # ARM tegra Patch21004: arm-tegra-nvec-kconfig.patch @@ -756,21 +754,6 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch -#rhbz 917984 -Patch22264: efi-fixes-3.8.patch - -#rhbz 918512 918521 -Patch22265: crypto-user-fix-info-leaks-in-report-API.patch - -# CVE-2013-1792 rhbz 916646,919021 -Patch22266: keys-fix-race-with-concurrent-install_user_keyrings.patch - -#rhbz 840391 -Patch22267: logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch - -#rhbz 916444 -Patch22268: dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch - #CVE-2013-1828 rhbz 919315 919316 Patch22269: net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch @@ -804,7 +787,6 @@ Patch24108: signal-always-clear-sa_restorer-on-execve.patch Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch #rhbz 856863 892599 -Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch @@ -1380,7 +1362,6 @@ ApplyPatch vmbugon-warnon.patch #ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch #ApplyPatch arm-tegra-sdhci-module-fix.patch -ApplyPatch arm-alignment-faults.patch # # bugfixes to drivers and filesystems @@ -1522,26 +1503,11 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #rhbz 916544 ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch -#rhbz 917984 -ApplyPatch efi-fixes-3.8.patch - -#rhbz 918512 918521 -ApplyPatch crypto-user-fix-info-leaks-in-report-API.patch - ApplyPatch userns-avoid-recursion-in-put_user_ns.patch #rhbz 859346 ApplyPatch fix-destroy_conntrack-GPF.patch -# CVE-2013-1792 rhbz 916646,919021 -ApplyPatch keys-fix-race-with-concurrent-install_user_keyrings.patch - -#rhbz 840391 -ApplyPatch logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch - -#rhbz 916444 -ApplyPatch dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch - #CVE-2013-1828 rhbz 919315 919316 ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch @@ -1576,7 +1542,6 @@ ApplyPatch signal-always-clear-sa_restorer-on-execve.patch ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch #rhbz 856863 892599 -ApplyPatch mac80211-Fix-crash-due-to-un-canceled-work-items.patch ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch @@ -2440,6 +2405,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 14 2013 Justin M. Forbes 3.8.3-201 +- Linux v3.8.3 + * Thu Mar 14 2013 Josh Boyer - Fix divide by zero on host TSC calibration failure (rhbz 859282) diff --git a/keys-fix-race-with-concurrent-install_user_keyrings.patch b/keys-fix-race-with-concurrent-install_user_keyrings.patch deleted file mode 100644 index ba7b30a6d..000000000 --- a/keys-fix-race-with-concurrent-install_user_keyrings.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index 58dfe08..c5ec083 100644 ---- a/security/keys/process_keys.c -+++ b/security/keys/process_keys.c -@@ -57,7 +57,7 @@ int install_user_keyrings(void) - - kenter("%p{%u}", user, uid); - -- if (user->uid_keyring) { -+ if (user->uid_keyring && user->session_keyring) { - kleave(" = 0 [exist]"); - return 0; - } - - \ No newline at end of file diff --git a/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch b/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch deleted file mode 100644 index 68a524a94..000000000 --- a/logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch +++ /dev/null @@ -1,66 +0,0 @@ -From dcd9006b1b053c7b1cebe81333261d4fd492ffeb Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Tue, 05 Mar 2013 16:09:00 +0000 -Subject: HID: logitech-dj: do not directly call hid_output_raw_report() during probe - -hid_output_raw_report() makes a direct call to usb_control_msg(). However, -some USB3 boards have shown that the usb device is not ready during the -.probe(). This blocks the entire usb device, and the paired mice, keyboards -are not functional. The dmesg output is the following: - -[ 11.912287] logitech-djreceiver 0003:046D:C52B.0003: hiddev0,hidraw0: USB HID v1.11 Device [Logitech USB Receiver] on usb-0000:00:14.0-2/input2 -[ 11.912537] logitech-djreceiver 0003:046D:C52B.0003: logi_dj_probe:logi_dj_recv_query_paired_devices error:-32 -[ 11.912636] logitech-djreceiver: probe of 0003:046D:C52B.0003 failed with error -32 - -Relying on the scheduled call to usbhid_submit_report() fixes the problem. - -related bugs: -https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1072082 -https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1039143 -https://bugzilla.redhat.com/show_bug.cgi?id=840391 -https://bugzilla.kernel.org/show_bug.cgi?id=49781 - -Reported-and-tested-by: Bob Bowles -Signed-off-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina ---- -diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c -index 9500f2f..8758f38c 100644 ---- a/drivers/hid/hid-logitech-dj.c -+++ b/drivers/hid/hid-logitech-dj.c -@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) - { - struct hid_device *hdev = djrcv_dev->hdev; -- int sent_bytes; -+ struct hid_report *report; -+ struct hid_report_enum *output_report_enum; -+ u8 *data = (u8 *)(&dj_report->device_index); -+ int i; - -- if (!hdev->hid_output_raw_report) { -- dev_err(&hdev->dev, "%s:" -- "hid_output_raw_report is null\n", __func__); -+ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; -+ report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; -+ -+ if (!report) { -+ dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__); - return -ENODEV; - } - -- sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report, -- sizeof(struct dj_report), -- HID_OUTPUT_REPORT); -+ for (i = 0; i < report->field[0]->report_count; i++) -+ report->field[0]->value[i] = data[i]; -+ -+ usbhid_submit_report(hdev, report, USB_DIR_OUT); - -- return (sent_bytes < 0) ? sent_bytes : 0; -+ return 0; - } - - static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) --- -cgit v0.9.1 diff --git a/mac80211-Fix-crash-due-to-un-canceled-work-items.patch b/mac80211-Fix-crash-due-to-un-canceled-work-items.patch deleted file mode 100644 index 71fd5963b..000000000 --- a/mac80211-Fix-crash-due-to-un-canceled-work-items.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 499218595a2e8296b7492af32fcca141b7b8184a Mon Sep 17 00:00:00 2001 -From: Ben Greear -Date: Wed, 20 Feb 2013 09:41:09 -0800 -Subject: [PATCH] mac80211: Fix crash due to un-canceled work-items - -Some mlme work structs are not cancelled on disassociation -nor interface deletion, which leads to them running after -the memory has been freed - -There is not a clean way to cancel these in the disassociation -logic because they must be canceled outside of the ifmgd->mtx -lock, so just cancel them in mgd_stop logic that tears down -the station. - -This fixes the crashes we see in 3.7.9+. The crash stack -trace itself isn't so helpful, but this warning gives -more useful info: - -WARNING: at /home/greearb/git/linux-3.7.dev.y/lib/debugobjects.c:261 debug_print_object+0x7c/0x8d() -ODEBUG: free active (active state 0) object type: work_struct hint: ieee80211_sta_monitor_work+0x0/0x14 [mac80211] -Modules linked in: [...] -Pid: 14743, comm: iw Tainted: G C O 3.7.9+ #11 -Call Trace: - [] warn_slowpath_common+0x80/0x98 - [] warn_slowpath_fmt+0x41/0x43 - [] debug_print_object+0x7c/0x8d - [] debug_check_no_obj_freed+0x95/0x1c3 - [] slab_free_hook+0x70/0x79 - [] kfree+0x62/0xb7 - [] netdev_release+0x39/0x3e - [] device_release+0x52/0x8a - [] kobject_release+0x121/0x158 - [] kobject_put+0x4c/0x50 - [] netdev_run_todo+0x25c/0x27e - -Cc: stable@vger.kernel.org -Signed-off-by: Ben Greear -Signed-off-by: Johannes Berg ---- - net/mac80211/mlme.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 6044c6d..b756d29 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -4319,6 +4319,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) - { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - -+ /* -+ * Make sure some work items will not run after this, -+ * they will not do anything but might not have been -+ * cancelled when disconnecting. -+ */ -+ cancel_work_sync(&ifmgd->monitor_work); -+ cancel_work_sync(&ifmgd->beacon_connection_loss_work); -+ cancel_work_sync(&ifmgd->request_smps_work); -+ cancel_work_sync(&ifmgd->csa_connection_drop_work); -+ cancel_work_sync(&ifmgd->chswitch_work); -+ - mutex_lock(&ifmgd->mtx); - if (ifmgd->assoc_data) - ieee80211_destroy_assoc_data(sdata, false); --- -1.8.1.2 - diff --git a/sources b/sources index 9ada6af78..499b47a52 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -e282fcff76e975e121e0636018e31a56 patch-3.8.2.xz +ba18b5d27ed303f5e5a9cda32a451031 patch-3.8.3.xz From c47f090f17160da0b193c055479db1dcb1b85580 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 15 Mar 2013 07:53:08 -0400 Subject: [PATCH 251/492] CVE-2013-1860 usb: cdc-wdm buf overflow triggered by dev (rhbz 921970 922004) --- USB-cdc-wdm-fix-buffer-overflow.patch | 88 +++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 USB-cdc-wdm-fix-buffer-overflow.patch diff --git a/USB-cdc-wdm-fix-buffer-overflow.patch b/USB-cdc-wdm-fix-buffer-overflow.patch new file mode 100644 index 000000000..2b1ed4254 --- /dev/null +++ b/USB-cdc-wdm-fix-buffer-overflow.patch @@ -0,0 +1,88 @@ +From c0f5ecee4e741667b2493c742b60b6218d40b3aa Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 12 Mar 2013 14:52:42 +0100 +Subject: [PATCH] USB: cdc-wdm: fix buffer overflow + +The buffer for responses must not overflow. +If this would happen, set a flag, drop the data and return +an error after user space has read all remaining data. + +Signed-off-by: Oliver Neukum +CC: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/cdc-wdm.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c +index 5f0cb41..122d056 100644 +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); + #define WDM_RESPONDING 7 + #define WDM_SUSPENDING 8 + #define WDM_RESETTING 9 ++#define WDM_OVERFLOW 10 + + #define WDM_MAX 16 + +@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb) + { + struct wdm_device *desc = urb->context; + int status = urb->status; ++ int length = urb->actual_length; + + spin_lock(&desc->iuspin); + clear_bit(WDM_RESPONDING, &desc->flags); +@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb) + } + + desc->rerr = status; +- desc->reslength = urb->actual_length; +- memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); +- desc->length += desc->reslength; ++ if (length + desc->length > desc->wMaxCommand) { ++ /* The buffer would overflow */ ++ set_bit(WDM_OVERFLOW, &desc->flags); ++ } else { ++ /* we may already be in overflow */ ++ if (!test_bit(WDM_OVERFLOW, &desc->flags)) { ++ memmove(desc->ubuf + desc->length, desc->inbuf, length); ++ desc->length += length; ++ desc->reslength = length; ++ } ++ } + skip_error: + wake_up(&desc->wait); + +@@ -435,6 +445,11 @@ retry: + rv = -ENODEV; + goto err; + } ++ if (test_bit(WDM_OVERFLOW, &desc->flags)) { ++ clear_bit(WDM_OVERFLOW, &desc->flags); ++ rv = -ENOBUFS; ++ goto err; ++ } + i++; + if (file->f_flags & O_NONBLOCK) { + if (!test_bit(WDM_READ, &desc->flags)) { +@@ -478,6 +493,7 @@ retry: + spin_unlock_irq(&desc->iuspin); + goto retry; + } ++ + if (!desc->reslength) { /* zero length read */ + dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); + clear_bit(WDM_READ, &desc->flags); +@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf) + struct wdm_device *desc = wdm_find_device(intf); + int rv; + ++ clear_bit(WDM_OVERFLOW, &desc->flags); + clear_bit(WDM_RESETTING, &desc->flags); + rv = recover_from_urb_loss(desc); + mutex_unlock(&desc->wlock); +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index c3b96b02a..823bb976e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -793,6 +793,9 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch +#CVE-2013-1860 rhbz 921970 922004 +Patch24114: USB-cdc-wdm-fix-buffer-overflow.patch + #rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch @@ -1548,6 +1551,9 @@ ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch +#CVE-2013-1860 rhbz 921970 922004 +ApplyPatch USB-cdc-wdm-fix-buffer-overflow.patch + # END OF PATCH APPLICATIONS %endif @@ -2405,6 +2411,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 15 2013 Josh Boyer +- CVE-2013-1860 usb: cdc-wdm buf overflow triggered by dev (rhbz 921970 922004) + * Thu Mar 14 2013 Justin M. Forbes 3.8.3-201 - Linux v3.8.3 From ffee9661d347ae7676b14d214ae46c315872f349 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 18 Mar 2013 09:09:13 +0000 Subject: [PATCH 252/492] Enable OMAP RNG and mvebu dove configs --- config-arm-omap | 1 + config-armv7 | 25 +++++++++++++++++++------ kernel.spec | 3 +++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/config-arm-omap b/config-arm-omap index 38a73b4b1..6c854036a 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -346,6 +346,7 @@ CONFIG_PWM_TWL_LED=m CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m +CONFIG_HW_RANDOM_OMAP=m # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_MTD_NAND_OMAP_BCH is not set diff --git a/config-armv7 b/config-armv7 index fa0ea0ff1..6a5972d5d 100644 --- a/config-armv7 +++ b/config-armv7 @@ -18,10 +18,6 @@ CONFIG_ARCH_VEXPRESS_DT=y # not enabling first round # CONFIG_ARCH_ZYNQ is not set -CONFIG_MACH_ARMADA_370_XP=y -CONFIG_MACH_ARMADA_370=y -CONFIG_MACH_ARMADA_XP=y - # generic ARM config options CONFIG_CMDLINE="" CONFIG_ARM_ARCH_TIMER=y @@ -42,6 +38,8 @@ CONFIG_SWP_EMULATE=y CONFIG_CPU_BPREDICT_DISABLE=y CONFIG_CACHE_L2X0=y CONFIG_HIGHPTE=y +CONFIG_AUTO_ZRELADDR=y +# CONFIG_XIP_KERNEL is not set # CONFIG_OABI_COMPAT is not set # CONFIG_ATAGS is not set # CONFIG_ATAGS_PROC is not set @@ -68,9 +66,11 @@ CONFIG_HIGHPTE=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set # Cortex-A9 +CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_742230=y CONFIG_ARM_ERRATA_742231=y CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_751472=y CONFIG_ARM_ERRATA_754322=y CONFIG_ARM_ERRATA_754327=y CONFIG_ARM_ERRATA_764369=y @@ -139,6 +139,8 @@ CONFIG_LBDAF=y CONFIG_COMMON_CLK=y CONFIG_REGULATOR=y +CONFIG_THERMAL=y +CONFIG_PERF_EVENTS=y # Versatile and highbank CONFIG_VEXPRESS_CONFIG=y @@ -185,6 +187,15 @@ CONFIG_REGULATOR_VEXPRESS=m CONFIG_ARM_AMBA=y # mvebu +CONFIG_MACH_ARMADA_370_XP=y +CONFIG_MACH_ARMADA_370=y +CONFIG_MACH_ARMADA_XP=y +CONFIG_ARCH_DOVE=y +# CONFIG_MACH_DOVE_DB is not set +# CONFIG_MACH_CM_A510 is not set +CONFIG_MACH_DOVE_DT=y + +CONFIG_CACHE_TAUROS2=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m CONFIG_MV643XX_ETH=m @@ -204,6 +215,7 @@ CONFIG_MVNETA=m CONFIG_GPIO_MVEBU=y CONFIG_MVEBU_CLK_CORE=y CONFIG_MVEBU_CLK_GATING=y +CONFIG_MMC_SDHCI_DOVE=m # Allwinner a1x # CONFIG_SUNXI_RFKILL=y @@ -374,6 +386,7 @@ CONFIG_MTD_OF_PARTS=y CONFIG_FB_SSD1307=m # Regulator drivers +CONFIG_REGULATOR_FIXED_VOLTAGE=m CONFIG_REGULATOR_FAN53555=m # CONFIG_CHARGER_MANAGER is not set # CONFIG_REGULATOR_DUMMY is not set @@ -421,9 +434,9 @@ CONFIG_REGULATOR_TPS6507X=m CONFIG_ETHERNET=y # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CIRRUS is not set -CONFIG_THERMAL=y # CONFIG_PATA_PLATFORM is not set -CONFIG_PERF_EVENTS=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_SGI_IOC4 is not set # Defined config options we don't use yet # CONFIG_PINCTRL_IMX35 is not set diff --git a/kernel.spec b/kernel.spec index 823bb976e..4fc3a1316 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2411,6 +2411,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 18 2013 Peter Robinson +- Enable OMAP RNG and mvebu dove configs + * Fri Mar 15 2013 Josh Boyer - CVE-2013-1860 usb: cdc-wdm buf overflow triggered by dev (rhbz 921970 922004) From 7e393f7df6a2c9505150e2827dbddd507566a38d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 18 Mar 2013 07:38:29 -0500 Subject: [PATCH 253/492] Revert rc6 ilk changes from 3.8.3 stable (rhbz 922304) --- drm-ilk-rc6-reverts.patch | 206 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 drm-ilk-rc6-reverts.patch diff --git a/drm-ilk-rc6-reverts.patch b/drm-ilk-rc6-reverts.patch new file mode 100644 index 000000000..211ffa81a --- /dev/null +++ b/drm-ilk-rc6-reverts.patch @@ -0,0 +1,206 @@ +From 52d7ecedac3f96fb562cb482c139015372728638 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sat, 1 Dec 2012 21:03:22 +0100 +Subject: drm/i915: reorder setup sequence to have irqs for output setup + +From: Daniel Vetter + +commit 52d7ecedac3f96fb562cb482c139015372728638 upstream. + +Otherwise the new&shiny irq-driven gmbus and dp aux code won't work that +well. Noticed since the dp aux code doesn't have an automatic fallback +with a timeout (since the hw provides for that already). + +v2: Simple move drm_irq_install before intel_modeset_gem_init, as +suggested by Ben Widawsky. + +v3: Now that interrupts are enabled before all connectors are fully +set up, we might fall over serving a HPD interrupt while things are +still being set up. Instead of jumping through massive hoops and +complicating the code with a separate hpd irq enable step, simply +block out the hotplug work item from doing anything until things are +in place. + +v4: Actually, we can enable hotplug processing only after the fbdev is +fully set up, since we call down into the fbdev from the hotplug work +functions. So stick the hpd enabling right next to the poll helper +initialization. + +v5: We need to enable irqs before intel_modeset_init, since that +function sets up the outputs. + +v6: Fixup cleanup sequence, too. + +Reviewed-by: Imre Deak +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_dma.c | 23 ++++++++++++++--------- + drivers/gpu/drm/i915/i915_drv.h | 1 + + drivers/gpu/drm/i915/i915_irq.c | 4 ++++ + 3 files changed, 19 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_dma.c ++++ b/drivers/gpu/drm/i915/i915_dma.c +@@ -1297,19 +1297,21 @@ static int i915_load_modeset_init(struct + if (ret) + goto cleanup_vga_switcheroo; + ++ ret = drm_irq_install(dev); ++ if (ret) ++ goto cleanup_gem_stolen; ++ ++ /* Important: The output setup functions called by modeset_init need ++ * working irqs for e.g. gmbus and dp aux transfers. */ + intel_modeset_init(dev); + + ret = i915_gem_init(dev); + if (ret) +- goto cleanup_gem_stolen; +- +- intel_modeset_gem_init(dev); ++ goto cleanup_irq; + + INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); + +- ret = drm_irq_install(dev); +- if (ret) +- goto cleanup_gem; ++ intel_modeset_gem_init(dev); + + /* Always safe in the mode setting case. */ + /* FIXME: do pre/post-mode set stuff in core KMS code */ +@@ -1317,7 +1319,10 @@ static int i915_load_modeset_init(struct + + ret = intel_fbdev_init(dev); + if (ret) +- goto cleanup_irq; ++ goto cleanup_gem; ++ ++ /* Only enable hotplug handling once the fbdev is fully set up. */ ++ dev_priv->enable_hotplug_processing = true; + + drm_kms_helper_poll_init(dev); + +@@ -1326,13 +1331,13 @@ static int i915_load_modeset_init(struct + + return 0; + +-cleanup_irq: +- drm_irq_uninstall(dev); + cleanup_gem: + mutex_lock(&dev->struct_mutex); + i915_gem_cleanup_ringbuffer(dev); + mutex_unlock(&dev->struct_mutex); + i915_gem_cleanup_aliasing_ppgtt(dev); ++cleanup_irq: ++ drm_irq_uninstall(dev); + cleanup_gem_stolen: + i915_gem_cleanup_stolen(dev); + cleanup_vga_switcheroo: +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -672,6 +672,7 @@ typedef struct drm_i915_private { + + u32 hotplug_supported_mask; + struct work_struct hotplug_work; ++ bool enable_hotplug_processing; + + int num_pipe; + int num_pch_pll; +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -287,6 +287,10 @@ static void i915_hotplug_work_func(struc + struct drm_mode_config *mode_config = &dev->mode_config; + struct intel_encoder *encoder; + ++ /* HPD irq before everything is fully set up. */ ++ if (!dev_priv->enable_hotplug_processing) ++ return; ++ + mutex_lock(&mode_config->mutex); + DRM_DEBUG_KMS("running encoder hotplug functions\n"); + +From 15239099d7a7a9ecdc1ccb5b187ae4cda5488ff9 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Tue, 5 Mar 2013 09:50:58 +0100 +Subject: drm/i915: enable irqs earlier when resuming + +From: Daniel Vetter + +commit 15239099d7a7a9ecdc1ccb5b187ae4cda5488ff9 upstream. + +We need it to restore the ilk rc6 context, since the gpu wait no +requires interrupts. But in general having interrupts around should +help in code sanity, since more and more stuff is interrupt driven. + +This regression has been introduced in + +commit 3e9605018ab3e333d51cc90fccfde2031886763b +Author: Chris Wilson +Date: Tue Nov 27 16:22:54 2012 +0000 + + drm/i915: Rearrange code to only have a single method for waiting upon the ring + +Like in the driver load code we need to make sure that hotplug +interrupts don't cause havoc with our modeset state, hence block them +with the existing infrastructure. Again we ignore races where we might +loose hotplug interrupts ... + +Note that the driver load part of the regression has already been +fixed in + +commit 52d7ecedac3f96fb562cb482c139015372728638 +Author: Daniel Vetter +Date: Sat Dec 1 21:03:22 2012 +0100 + + drm/i915: reorder setup sequence to have irqs for output setup + +v2: Add a note to the commit message about which patch fixed the +driver load part of the regression. Stable kernels need to backport +both patches. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54691 +Cc: Chris Wilson +Cc: Mika Kuoppala +Reported-and-Tested-by: Ilya Tumaykin +Reviewed-by: Chris wilson (v1) +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_drv.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -486,6 +486,7 @@ static int i915_drm_freeze(struct drm_de + intel_modeset_disable(dev); + + drm_irq_uninstall(dev); ++ dev_priv->enable_hotplug_processing = false; + } + + i915_save_state(dev); +@@ -562,9 +563,19 @@ static int __i915_drm_thaw(struct drm_de + error = i915_gem_init_hw(dev); + mutex_unlock(&dev->struct_mutex); + ++ /* We need working interrupts for modeset enabling ... */ ++ drm_irq_install(dev); ++ + intel_modeset_init_hw(dev); + intel_modeset_setup_hw_state(dev, false); +- drm_irq_install(dev); ++ ++ /* ++ * ... but also need to make sure that hotplug processing ++ * doesn't cause havoc. Like in the driver load code we don't ++ * bother with the tiny race here where we might loose hotplug ++ * notifications. ++ * */ ++ dev_priv->enable_hotplug_processing = true; + } + + intel_opregion_init(dev); diff --git a/kernel.spec b/kernel.spec index 4fc3a1316..25519b806 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -802,6 +802,9 @@ Patch25000: amd64_edac_fix_rank_count.patch #rhbz 921500 Patch25001: i7300_edac_single_mode_fixup.patch +#rhbz 922304 +Patch25002: drm-ilk-rc6-reverts.patch + # END OF PATCH DEFINITIONS %endif @@ -1554,6 +1557,9 @@ ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch #CVE-2013-1860 rhbz 921970 922004 ApplyPatch USB-cdc-wdm-fix-buffer-overflow.patch +#rhbz 922304 +ApplyPatch drm-ilk-rc6-reverts.patch -R + # END OF PATCH APPLICATIONS %endif @@ -2411,6 +2417,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 18 2013 Justin M. Forbes +- Revert rc6 ilk changes from 3.8.3 stable (rhbz 922304) + * Mon Mar 18 2013 Peter Robinson - Enable OMAP RNG and mvebu dove configs From dcfb7ac98d593cbdc549163efc37e44bb80189f3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Mar 2013 16:12:06 -0400 Subject: [PATCH 254/492] CVE-2013-1796 kvm: buffer overflow in handling of MSR_KVM_SYSTEM_TIME (rhbz 917012 923966) - CVE-2013-1797 kvm: after free issue with the handling of MSR_KVM_SYSTEM_TIME (rhbz 917013 923967) - CVE-2013-1798 kvm: out-of-bounds access in ioapic indirect register reads (rhbz 917017 923968) --- ...hecking-in-ioapic-indirect-register-.patch | 44 +++++ ...buffer-overflow-in-handling-of-MSR_K.patch | 41 +++++ ...MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch | 163 ++++++++++++++++++ kernel.spec | 28 ++- 4 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch create mode 100644 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch create mode 100644 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch diff --git a/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch b/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch new file mode 100644 index 000000000..7583f74c2 --- /dev/null +++ b/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch @@ -0,0 +1,44 @@ +From a2c118bfab8bc6b8bb213abfc35201e441693d55 Mon Sep 17 00:00:00 2001 +From: Andy Honig +Date: Wed, 20 Feb 2013 14:49:16 -0800 +Subject: [PATCH] KVM: Fix bounds checking in ioapic indirect register reads + (CVE-2013-1798) + +If the guest specifies a IOAPIC_REG_SELECT with an invalid value and follows +that with a read of the IOAPIC_REG_WINDOW KVM does not properly validate +that request. ioapic_read_indirect contains an +ASSERT(redir_index < IOAPIC_NUM_PINS), but the ASSERT has no effect in +non-debug builds. In recent kernels this allows a guest to cause a kernel +oops by reading invalid memory. In older kernels (pre-3.3) this allows a +guest to read from large ranges of host memory. + +Tested: tested against apic unit tests. + +Signed-off-by: Andrew Honig +Signed-off-by: Marcelo Tosatti +--- + virt/kvm/ioapic.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c +index ce82b94..5ba005c 100644 +--- a/virt/kvm/ioapic.c ++++ b/virt/kvm/ioapic.c +@@ -74,9 +74,12 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, + u32 redir_index = (ioapic->ioregsel - 0x10) >> 1; + u64 redir_content; + +- ASSERT(redir_index < IOAPIC_NUM_PINS); ++ if (redir_index < IOAPIC_NUM_PINS) ++ redir_content = ++ ioapic->redirtbl[redir_index].bits; ++ else ++ redir_content = ~0ULL; + +- redir_content = ioapic->redirtbl[redir_index].bits; + result = (ioapic->ioregsel & 0x1) ? + (redir_content >> 32) & 0xffffffff : + redir_content & 0xffffffff; +-- +1.8.1.4 + diff --git a/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch b/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch new file mode 100644 index 000000000..a4516e43e --- /dev/null +++ b/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch @@ -0,0 +1,41 @@ +From c300aa64ddf57d9c5d9c898a64b36877345dd4a9 Mon Sep 17 00:00:00 2001 +From: Andy Honig +Date: Mon, 11 Mar 2013 09:34:52 -0700 +Subject: [PATCH 2/3] KVM: x86: fix for buffer overflow in handling of + MSR_KVM_SYSTEM_TIME (CVE-2013-1796) + +If the guest sets the GPA of the time_page so that the request to update the +time straddles a page then KVM will write onto an incorrect page. The +write is done byusing kmap atomic to get a pointer to the page for the time +structure and then performing a memcpy to that page starting at an offset +that the guest controls. Well behaved guests always provide a 32-byte aligned +address, however a malicious guest could use this to corrupt host kernel +memory. + +Tested: Tested against kvmclock unit test. + +Signed-off-by: Andrew Honig +Signed-off-by: Marcelo Tosatti +--- + arch/x86/kvm/x86.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index f7c850b..2ade60c 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1959,6 +1959,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + /* ...but clean it before doing the actual write */ + vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); + ++ /* Check that the address is 32-byte aligned. */ ++ if (vcpu->arch.time_offset & ++ (sizeof(struct pvclock_vcpu_time_info) - 1)) ++ break; ++ + vcpu->arch.time_page = + gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT); + +-- +1.8.1.4 + diff --git a/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch b/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch new file mode 100644 index 000000000..7a2fe6547 --- /dev/null +++ b/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch @@ -0,0 +1,163 @@ +From 0b79459b482e85cb7426aa7da683a9f2c97aeae1 Mon Sep 17 00:00:00 2001 +From: Andy Honig +Date: Wed, 20 Feb 2013 14:48:10 -0800 +Subject: [PATCH 3/3] KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use + gfn_to_hva_cache functions (CVE-2013-1797) + +There is a potential use after free issue with the handling of +MSR_KVM_SYSTEM_TIME. If the guest specifies a GPA in a movable or removable +memory such as frame buffers then KVM might continue to write to that +address even after it's removed via KVM_SET_USER_MEMORY_REGION. KVM pins +the page in memory so it's unlikely to cause an issue, but if the user +space component re-purposes the memory previously used for the guest, then +the guest will be able to corrupt that memory. + +Tested: Tested against kvmclock unit test + +Signed-off-by: Andrew Honig +Signed-off-by: Marcelo Tosatti +--- + arch/x86/include/asm/kvm_host.h | 4 ++-- + arch/x86/kvm/x86.c | 47 ++++++++++++++++++----------------------- + 2 files changed, 22 insertions(+), 29 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 635a74d..4979778 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -414,8 +414,8 @@ struct kvm_vcpu_arch { + gpa_t time; + struct pvclock_vcpu_time_info hv_clock; + unsigned int hw_tsc_khz; +- unsigned int time_offset; +- struct page *time_page; ++ struct gfn_to_hva_cache pv_time; ++ bool pv_time_enabled; + /* set guest stopped flag in pvclock flags field */ + bool pvclock_set_guest_stopped_request; + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 2ade60c..f19ac0a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1406,10 +1406,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) + unsigned long flags, this_tsc_khz; + struct kvm_vcpu_arch *vcpu = &v->arch; + struct kvm_arch *ka = &v->kvm->arch; +- void *shared_kaddr; + s64 kernel_ns, max_kernel_ns; + u64 tsc_timestamp, host_tsc; +- struct pvclock_vcpu_time_info *guest_hv_clock; ++ struct pvclock_vcpu_time_info guest_hv_clock; + u8 pvclock_flags; + bool use_master_clock; + +@@ -1463,7 +1462,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) + + local_irq_restore(flags); + +- if (!vcpu->time_page) ++ if (!vcpu->pv_time_enabled) + return 0; + + /* +@@ -1525,12 +1524,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) + */ + vcpu->hv_clock.version += 2; + +- shared_kaddr = kmap_atomic(vcpu->time_page); +- +- guest_hv_clock = shared_kaddr + vcpu->time_offset; ++ if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time, ++ &guest_hv_clock, sizeof(guest_hv_clock)))) ++ return 0; + + /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */ +- pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED); ++ pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED); + + if (vcpu->pvclock_set_guest_stopped_request) { + pvclock_flags |= PVCLOCK_GUEST_STOPPED; +@@ -1543,12 +1542,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) + + vcpu->hv_clock.flags = pvclock_flags; + +- memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock, +- sizeof(vcpu->hv_clock)); +- +- kunmap_atomic(shared_kaddr); +- +- mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); ++ kvm_write_guest_cached(v->kvm, &vcpu->pv_time, ++ &vcpu->hv_clock, ++ sizeof(vcpu->hv_clock)); + return 0; + } + +@@ -1837,10 +1833,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) + + static void kvmclock_reset(struct kvm_vcpu *vcpu) + { +- if (vcpu->arch.time_page) { +- kvm_release_page_dirty(vcpu->arch.time_page); +- vcpu->arch.time_page = NULL; +- } ++ vcpu->arch.pv_time_enabled = false; + } + + static void accumulate_steal_time(struct kvm_vcpu *vcpu) +@@ -1947,6 +1940,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + break; + case MSR_KVM_SYSTEM_TIME_NEW: + case MSR_KVM_SYSTEM_TIME: { ++ u64 gpa_offset; + kvmclock_reset(vcpu); + + vcpu->arch.time = data; +@@ -1956,19 +1950,17 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + if (!(data & 1)) + break; + +- /* ...but clean it before doing the actual write */ +- vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); ++ gpa_offset = data & ~(PAGE_MASK | 1); + + /* Check that the address is 32-byte aligned. */ +- if (vcpu->arch.time_offset & +- (sizeof(struct pvclock_vcpu_time_info) - 1)) ++ if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1)) + break; + +- vcpu->arch.time_page = +- gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT); +- +- if (is_error_page(vcpu->arch.time_page)) +- vcpu->arch.time_page = NULL; ++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ++ &vcpu->arch.pv_time, data & ~1ULL)) ++ vcpu->arch.pv_time_enabled = false; ++ else ++ vcpu->arch.pv_time_enabled = true; + + break; + } +@@ -2972,7 +2964,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu, + */ + static int kvm_set_guest_paused(struct kvm_vcpu *vcpu) + { +- if (!vcpu->arch.time_page) ++ if (!vcpu->arch.pv_time_enabled) + return -EINVAL; + vcpu->arch.pvclock_set_guest_stopped_request = true; + kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); +@@ -6723,6 +6715,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + goto fail_free_wbinvd_dirty_mask; + + vcpu->arch.ia32_tsc_adjust_msr = 0x0; ++ vcpu->arch.pv_time_enabled = false; + kvm_async_pf_hash_reset(vcpu); + kvm_pmu_init(vcpu); + +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 25519b806..46563ed2f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -805,6 +805,15 @@ Patch25001: i7300_edac_single_mode_fixup.patch #rhbz 922304 Patch25002: drm-ilk-rc6-reverts.patch +#CVE-2013-1798 rhbz 917017 923968 +Patch25003: 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch + +#CVE-2013-1796 rhbz 917012 923966 +Patch25004: 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch + +#CVE-2013-1797 rhbz 917013 923967 +Patch25005: 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch + # END OF PATCH DEFINITIONS %endif @@ -1560,6 +1569,15 @@ ApplyPatch USB-cdc-wdm-fix-buffer-overflow.patch #rhbz 922304 ApplyPatch drm-ilk-rc6-reverts.patch -R +#CVE-2013-1798 rhbz 917017 923968 +ApplyPatch 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch + +#CVE-2013-1796 rhbz 917012 923966 +ApplyPatch 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch + +#CVE-2013-1797 rhbz 917013 923967 +ApplyPatch 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch + # END OF PATCH APPLICATIONS %endif @@ -2417,6 +2435,14 @@ fi # ||----w | # || || %changelog +* Wed Mar 20 2013 Josh Boyer +- CVE-2013-1796 kvm: buffer overflow in handling of MSR_KVM_SYSTEM_TIME + (rhbz 917012 923966) +- CVE-2013-1797 kvm: after free issue with the handling of MSR_KVM_SYSTEM_TIME + (rhbz 917013 923967) +- CVE-2013-1798 kvm: out-of-bounds access in ioapic indirect register reads + (rhbz 917017 923968) + * Mon Mar 18 2013 Justin M. Forbes - Revert rc6 ilk changes from 3.8.3 stable (rhbz 922304) From 03f3e5ade73c88016cfe33e3e583ed2e1d4c242b Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 20 Mar 2013 22:11:45 -0500 Subject: [PATCH 255/492] Linux v3.8.4 --- TTY-do-not-reset-master-s-packet-mode.patch | 63 ------ USB-cdc-wdm-fix-buffer-overflow.patch | 88 -------- drm-ilk-rc6-reverts.patch | 206 ------------------ fix-destroy_conntrack-GPF.patch | 92 -------- kernel.spec | 58 +---- ...e-parameter-size-for-SCTP_GET_ASSOC_.patch | 54 ----- ...-8250.-xxxx-module-options-functiona.patch | 63 ------ ...l-always-clear-sa_restorer-on-execve.patch | 113 ---------- silence-tty-null.patch | 13 -- sources | 2 +- ...x-oops-when-w1_search-is-called-from.patch | 111 ---------- 11 files changed, 7 insertions(+), 856 deletions(-) delete mode 100644 TTY-do-not-reset-master-s-packet-mode.patch delete mode 100644 USB-cdc-wdm-fix-buffer-overflow.patch delete mode 100644 drm-ilk-rc6-reverts.patch delete mode 100644 fix-destroy_conntrack-GPF.patch delete mode 100644 net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch delete mode 100644 serial-8250-Keep-8250.-xxxx-module-options-functiona.patch delete mode 100644 signal-always-clear-sa_restorer-on-execve.patch delete mode 100644 silence-tty-null.patch delete mode 100644 w1-fix-oops-when-w1_search-is-called-from.patch diff --git a/TTY-do-not-reset-master-s-packet-mode.patch b/TTY-do-not-reset-master-s-packet-mode.patch deleted file mode 100644 index 633bfcf46..000000000 --- a/TTY-do-not-reset-master-s-packet-mode.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b81273a132177edd806476b953f6afeb17b786d5 Mon Sep 17 00:00:00 2001 -From: Jiri Slaby -Date: Tue, 15 Jan 2013 23:26:22 +0100 -Subject: [PATCH] TTY: do not reset master's packet mode - -Now that login from util-linux is forced to drop all references to a -TTY which it wants to hangup (to reach reference count 1) we are -seeing issues with telnet. When login closes its last reference to the -slave PTY, it also resets packet mode on the *master* side. And we -have a race here. - -What telnet does is fork+exec of `login'. Then there are two -scenarios: -* `login' closes the slave TTY and resets thus master's packet mode, - but even now telnet properly sets the mode, or -* `telnetd' sets packet mode on the master, `login' closes the slave - TTY and resets master's packet mode. - -The former case is OK. However the latter happens in much more cases, -by the order of magnitude to be precise. So when one tries to login to -such a messed telnet setup, they see the following: -inux login: - ogin incorrect - -Note the missing first letters -- telnet thinks it is still in the -packet mode, so when it receives "linux login" from `login', it -considers "l" as the type of the packet and strips it. - -SuS does not mention how the implementation should behave. Both BSDs I -checked (Free and Net) do not reset the flag upon the last close. - -By this I am resurrecting an old bug, see References. We are hitting -it regularly now, i.e. with updated util-linux, ergo login. - -Here, I am changing a behavior introduced back in 2.1 times. It would -better have a long time testing before goes upstream. - -Signed-off-by: Jiri Slaby -Cc: Mauro Carvalho Chehab -Cc: Bryan Mason -References: https://lkml.org/lkml/2009/11/11/223 -References: https://bugzilla.redhat.com/show_bug.cgi?id=504703 -References: https://bugzilla.novell.com/show_bug.cgi?id=797042 -Signed-off-by: Greg Kroah-Hartman ---- - drivers/tty/pty.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c -index 4ec11f3..40ff2bf 100644 ---- a/drivers/tty/pty.c -+++ b/drivers/tty/pty.c -@@ -47,7 +47,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) - /* Review - krefs on tty_link ?? */ - if (!tty->link) - return; -- tty->link->packet = 0; - set_bit(TTY_OTHER_CLOSED, &tty->link->flags); - wake_up_interruptible(&tty->link->read_wait); - wake_up_interruptible(&tty->link->write_wait); --- -1.8.1.2 - diff --git a/USB-cdc-wdm-fix-buffer-overflow.patch b/USB-cdc-wdm-fix-buffer-overflow.patch deleted file mode 100644 index 2b1ed4254..000000000 --- a/USB-cdc-wdm-fix-buffer-overflow.patch +++ /dev/null @@ -1,88 +0,0 @@ -From c0f5ecee4e741667b2493c742b60b6218d40b3aa Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Tue, 12 Mar 2013 14:52:42 +0100 -Subject: [PATCH] USB: cdc-wdm: fix buffer overflow - -The buffer for responses must not overflow. -If this would happen, set a flag, drop the data and return -an error after user space has read all remaining data. - -Signed-off-by: Oliver Neukum -CC: stable@kernel.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/usb/class/cdc-wdm.c | 23 ++++++++++++++++++++--- - 1 file changed, 20 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c -index 5f0cb41..122d056 100644 ---- a/drivers/usb/class/cdc-wdm.c -+++ b/drivers/usb/class/cdc-wdm.c -@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); - #define WDM_RESPONDING 7 - #define WDM_SUSPENDING 8 - #define WDM_RESETTING 9 -+#define WDM_OVERFLOW 10 - - #define WDM_MAX 16 - -@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb) - { - struct wdm_device *desc = urb->context; - int status = urb->status; -+ int length = urb->actual_length; - - spin_lock(&desc->iuspin); - clear_bit(WDM_RESPONDING, &desc->flags); -@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb) - } - - desc->rerr = status; -- desc->reslength = urb->actual_length; -- memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); -- desc->length += desc->reslength; -+ if (length + desc->length > desc->wMaxCommand) { -+ /* The buffer would overflow */ -+ set_bit(WDM_OVERFLOW, &desc->flags); -+ } else { -+ /* we may already be in overflow */ -+ if (!test_bit(WDM_OVERFLOW, &desc->flags)) { -+ memmove(desc->ubuf + desc->length, desc->inbuf, length); -+ desc->length += length; -+ desc->reslength = length; -+ } -+ } - skip_error: - wake_up(&desc->wait); - -@@ -435,6 +445,11 @@ retry: - rv = -ENODEV; - goto err; - } -+ if (test_bit(WDM_OVERFLOW, &desc->flags)) { -+ clear_bit(WDM_OVERFLOW, &desc->flags); -+ rv = -ENOBUFS; -+ goto err; -+ } - i++; - if (file->f_flags & O_NONBLOCK) { - if (!test_bit(WDM_READ, &desc->flags)) { -@@ -478,6 +493,7 @@ retry: - spin_unlock_irq(&desc->iuspin); - goto retry; - } -+ - if (!desc->reslength) { /* zero length read */ - dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); - clear_bit(WDM_READ, &desc->flags); -@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf) - struct wdm_device *desc = wdm_find_device(intf); - int rv; - -+ clear_bit(WDM_OVERFLOW, &desc->flags); - clear_bit(WDM_RESETTING, &desc->flags); - rv = recover_from_urb_loss(desc); - mutex_unlock(&desc->wlock); --- -1.8.1.2 - diff --git a/drm-ilk-rc6-reverts.patch b/drm-ilk-rc6-reverts.patch deleted file mode 100644 index 211ffa81a..000000000 --- a/drm-ilk-rc6-reverts.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 52d7ecedac3f96fb562cb482c139015372728638 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Sat, 1 Dec 2012 21:03:22 +0100 -Subject: drm/i915: reorder setup sequence to have irqs for output setup - -From: Daniel Vetter - -commit 52d7ecedac3f96fb562cb482c139015372728638 upstream. - -Otherwise the new&shiny irq-driven gmbus and dp aux code won't work that -well. Noticed since the dp aux code doesn't have an automatic fallback -with a timeout (since the hw provides for that already). - -v2: Simple move drm_irq_install before intel_modeset_gem_init, as -suggested by Ben Widawsky. - -v3: Now that interrupts are enabled before all connectors are fully -set up, we might fall over serving a HPD interrupt while things are -still being set up. Instead of jumping through massive hoops and -complicating the code with a separate hpd irq enable step, simply -block out the hotplug work item from doing anything until things are -in place. - -v4: Actually, we can enable hotplug processing only after the fbdev is -fully set up, since we call down into the fbdev from the hotplug work -functions. So stick the hpd enabling right next to the poll helper -initialization. - -v5: We need to enable irqs before intel_modeset_init, since that -function sets up the outputs. - -v6: Fixup cleanup sequence, too. - -Reviewed-by: Imre Deak -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_dma.c | 23 ++++++++++++++--------- - drivers/gpu/drm/i915/i915_drv.h | 1 + - drivers/gpu/drm/i915/i915_irq.c | 4 ++++ - 3 files changed, 19 insertions(+), 9 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -1297,19 +1297,21 @@ static int i915_load_modeset_init(struct - if (ret) - goto cleanup_vga_switcheroo; - -+ ret = drm_irq_install(dev); -+ if (ret) -+ goto cleanup_gem_stolen; -+ -+ /* Important: The output setup functions called by modeset_init need -+ * working irqs for e.g. gmbus and dp aux transfers. */ - intel_modeset_init(dev); - - ret = i915_gem_init(dev); - if (ret) -- goto cleanup_gem_stolen; -- -- intel_modeset_gem_init(dev); -+ goto cleanup_irq; - - INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); - -- ret = drm_irq_install(dev); -- if (ret) -- goto cleanup_gem; -+ intel_modeset_gem_init(dev); - - /* Always safe in the mode setting case. */ - /* FIXME: do pre/post-mode set stuff in core KMS code */ -@@ -1317,7 +1319,10 @@ static int i915_load_modeset_init(struct - - ret = intel_fbdev_init(dev); - if (ret) -- goto cleanup_irq; -+ goto cleanup_gem; -+ -+ /* Only enable hotplug handling once the fbdev is fully set up. */ -+ dev_priv->enable_hotplug_processing = true; - - drm_kms_helper_poll_init(dev); - -@@ -1326,13 +1331,13 @@ static int i915_load_modeset_init(struct - - return 0; - --cleanup_irq: -- drm_irq_uninstall(dev); - cleanup_gem: - mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); - mutex_unlock(&dev->struct_mutex); - i915_gem_cleanup_aliasing_ppgtt(dev); -+cleanup_irq: -+ drm_irq_uninstall(dev); - cleanup_gem_stolen: - i915_gem_cleanup_stolen(dev); - cleanup_vga_switcheroo: ---- a/drivers/gpu/drm/i915/i915_drv.h -+++ b/drivers/gpu/drm/i915/i915_drv.h -@@ -672,6 +672,7 @@ typedef struct drm_i915_private { - - u32 hotplug_supported_mask; - struct work_struct hotplug_work; -+ bool enable_hotplug_processing; - - int num_pipe; - int num_pch_pll; ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -287,6 +287,10 @@ static void i915_hotplug_work_func(struc - struct drm_mode_config *mode_config = &dev->mode_config; - struct intel_encoder *encoder; - -+ /* HPD irq before everything is fully set up. */ -+ if (!dev_priv->enable_hotplug_processing) -+ return; -+ - mutex_lock(&mode_config->mutex); - DRM_DEBUG_KMS("running encoder hotplug functions\n"); - -From 15239099d7a7a9ecdc1ccb5b187ae4cda5488ff9 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Tue, 5 Mar 2013 09:50:58 +0100 -Subject: drm/i915: enable irqs earlier when resuming - -From: Daniel Vetter - -commit 15239099d7a7a9ecdc1ccb5b187ae4cda5488ff9 upstream. - -We need it to restore the ilk rc6 context, since the gpu wait no -requires interrupts. But in general having interrupts around should -help in code sanity, since more and more stuff is interrupt driven. - -This regression has been introduced in - -commit 3e9605018ab3e333d51cc90fccfde2031886763b -Author: Chris Wilson -Date: Tue Nov 27 16:22:54 2012 +0000 - - drm/i915: Rearrange code to only have a single method for waiting upon the ring - -Like in the driver load code we need to make sure that hotplug -interrupts don't cause havoc with our modeset state, hence block them -with the existing infrastructure. Again we ignore races where we might -loose hotplug interrupts ... - -Note that the driver load part of the regression has already been -fixed in - -commit 52d7ecedac3f96fb562cb482c139015372728638 -Author: Daniel Vetter -Date: Sat Dec 1 21:03:22 2012 +0100 - - drm/i915: reorder setup sequence to have irqs for output setup - -v2: Add a note to the commit message about which patch fixed the -driver load part of the regression. Stable kernels need to backport -both patches. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54691 -Cc: Chris Wilson -Cc: Mika Kuoppala -Reported-and-Tested-by: Ilya Tumaykin -Reviewed-by: Chris wilson (v1) -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_drv.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -486,6 +486,7 @@ static int i915_drm_freeze(struct drm_de - intel_modeset_disable(dev); - - drm_irq_uninstall(dev); -+ dev_priv->enable_hotplug_processing = false; - } - - i915_save_state(dev); -@@ -562,9 +563,19 @@ static int __i915_drm_thaw(struct drm_de - error = i915_gem_init_hw(dev); - mutex_unlock(&dev->struct_mutex); - -+ /* We need working interrupts for modeset enabling ... */ -+ drm_irq_install(dev); -+ - intel_modeset_init_hw(dev); - intel_modeset_setup_hw_state(dev, false); -- drm_irq_install(dev); -+ -+ /* -+ * ... but also need to make sure that hotplug processing -+ * doesn't cause havoc. Like in the driver load code we don't -+ * bother with the tiny race here where we might loose hotplug -+ * notifications. -+ * */ -+ dev_priv->enable_hotplug_processing = true; - } - - intel_opregion_init(dev); diff --git a/fix-destroy_conntrack-GPF.patch b/fix-destroy_conntrack-GPF.patch deleted file mode 100644 index 35ffa581d..000000000 --- a/fix-destroy_conntrack-GPF.patch +++ /dev/null @@ -1,92 +0,0 @@ -On Wed, 2013-03-06 at 10:59 -0500, Dave Jones wrote: -> I know 3.7.9 is EOL, but this code doesn't look like it's changed in current. -> (unless the cause/fix was in code unrelated to these paths) -> -> A user reported the following GPF.. -> -> general protection fault: 0000 [#1] SMP -> Modules linked in: ipheth fuse ebtable_nat xt_CHECKSUM bridge stp llc ip6t_REJECT iptable_mangle nf_conntrack(-) ebtable_filter ebtables snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc hp_wmi snd_timer coretemp iTCO_wdt tg3 snd sparse_keymap rfkill soundcore iTCO_vendor_support lpc_ich i7core_edac edac_core serio_raw microcode mfd_core vhost_net tun macvtap macvlan kvm_intel kvm binfmt_misc uinput nouveau mxm_wmi crc32c_intel video i2c_algo_bit drm_kms_helper ttm firewire_ohci firewire_core drm crc_itu_t i2c_core wmi [last unloaded: xt_conntrack] -> CPU 2 -> Pid: 25407, comm: qemu-kvm Not tainted 3.7.9-205.fc18.x86_64 #1 Hewlett-Packard HP Z400 Workstation/0B4Ch -> RIP: 0010:[] [] destroy_conntrack+0x35/0x120 [nf_conntrack] -> RSP: 0018:ffff880276913d78 EFLAGS: 00010206 -> RAX: 50626b6b7876376c RBX: ffff88026e530d68 RCX: ffff88028d158e00 -> RDX: ffff88026d0d5470 RSI: 0000000000000011 RDI: 0000000000000002 -> RBP: ffff880276913d88 R08: 0000000000000000 R09: ffff880295002900 -> R10: 0000000000000000 R11: 0000000000000003 R12: ffffffff81ca3b40 -> R13: ffffffff8151a8e0 R14: ffff880270875000 R15: 0000000000000002 -> FS: 00007ff3bce38a00(0000) GS:ffff88029fc40000(0000) knlGS:0000000000000000 -> CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b -> CR2: 00007fd1430bd000 CR3: 000000027042b000 CR4: 00000000000027e0 -> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 -> Process qemu-kvm (pid: 25407, threadinfo ffff880276912000, task ffff88028c369720) -> Stack: -> ffff880156f59100 ffff880156f59100 ffff880276913d98 ffffffff815534f7 -> ffff880276913db8 ffffffff8151a74b ffff880270875000 ffff880156f59100 -> ffff880276913dd8 ffffffff8151a5a6 ffff880276913dd8 ffff88026d0d5470 -> Call Trace: -> [] nf_conntrack_destroy+0x17/0x20 -> [] skb_release_head_state+0x7b/0x100 -> [] __kfree_skb+0x16/0xa0 -> [] kfree_skb+0x36/0xa0 -> [] skb_queue_purge+0x20/0x40 -> [] __tun_detach+0x117/0x140 [tun] -> [] tun_chr_close+0x3c/0xd0 [tun] -> [] __fput+0xec/0x240 -> [] ____fput+0xe/0x10 -> [] task_work_run+0xa7/0xe0 -> [] do_notify_resume+0x71/0xb0 -> [] int_signal+0x12/0x17 -> Code: 00 00 04 48 89 e5 41 54 53 48 89 fb 4c 8b a7 e8 00 00 00 0f 85 de 00 00 00 0f b6 73 3e 0f b7 7b 2a e8 10 40 00 00 48 85 c0 74 0e <48> 8b 40 28 48 85 c0 74 05 48 89 df ff d0 48 c7 c7 08 6a 3a a0 -> RIP [] destroy_conntrack+0x35/0x120 [nf_conntrack] -> RSP -> -> -> -> /* To make sure we don't get any weird locking issues here: -> * destroy_conntrack() MUST NOT be called with a write lock -> * to nf_conntrack_lock!!! -HW */ -> rcu_read_lock(); -> l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); -> 1378: 0f b6 b3 86 00 00 00 movzbl 0x86(%rbx),%esi -> 137f: 0f b7 7b 72 movzwl 0x72(%rbx),%edi -> 1383: e8 00 00 00 00 callq 1388 -> if (l4proto && l4proto->destroy) -> 1388: 48 85 c0 test %rax,%rax -> 138b: 74 0e je 139b -> 138d: 48 8b 40 28 mov 0x28(%rax),%rax <----- HERE -> 1391: 48 85 c0 test %rax,%rax -> 1394: 74 05 je 139b -> l4proto->destroy(ct); -> 1396: 48 89 df mov %rbx,%rdi -> 1399: ff d0 callq *%rax -> -> -> l4proto (%rax) is garbage (0x50626b6b7876376c) which looks a little like ascii, -> but P>kkxv7l doesn't mean much to me. -> -> https://bugzilla.redhat.com/show_bug.cgi?id=917792 is the original report, but -> there aren't any further details yet. -> -> Dave -> - -tun driver lacks a nf_reset(skb) call - -I would try : - -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index 2c6a22e..b7c457a 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -747,6 +747,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) - goto drop; - skb_orphan(skb); - -+ nf_reset(skb); -+ - /* Enqueue packet */ - skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); - - diff --git a/kernel.spec b/kernel.spec index 46563ed2f..ea5de280f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -666,7 +666,6 @@ Patch510: silence-noise.patch Patch520: quiet-apm.patch Patch530: silence-fbcon-logo.patch Patch540: silence-empty-ipi-mask-warning.patch -Patch541: silence-tty-null.patch Patch800: crash-driver.patch @@ -754,35 +753,17 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch -#CVE-2013-1828 rhbz 919315 919316 -Patch22269: net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch - #rhbz 812111 Patch24000: alps.patch Patch24100: userns-avoid-recursion-in-put_user_ns.patch -#rhbz 859346 -Patch24101: fix-destroy_conntrack-GPF.patch - #rhbz 917353 Patch24102: backlight_revert.patch -#rhbz 904182 -Patch24103: TTY-do-not-reset-master-s-packet-mode.patch - -#rhbz 857954 -Patch24105: w1-fix-oops-when-w1_search-is-called-from.patch - -#rhbz 911771 -Patch24106: serial-8250-Keep-8250.-xxxx-module-options-functiona.patch - #rhbz 879462 Patch24107: uvcvideo-suspend-fix.patch -#CVE-2013-0914 rhbz 920499 920510 -Patch24108: signal-always-clear-sa_restorer-on-execve.patch - #CVE-2013-0913 rhbz 920471 920529 Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch @@ -793,18 +774,12 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch -#CVE-2013-1860 rhbz 921970 922004 -Patch24114: USB-cdc-wdm-fix-buffer-overflow.patch - #rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch #rhbz 921500 Patch25001: i7300_edac_single_mode_fixup.patch -#rhbz 922304 -Patch25002: drm-ilk-rc6-reverts.patch - #CVE-2013-1798 rhbz 917017 923968 Patch25003: 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch @@ -1436,7 +1411,6 @@ ApplyPatch silence-fbcon-logo.patch # no-one cares about these warnings. ApplyPatch silence-empty-ipi-mask-warning.patch -ApplyPatch silence-tty-null.patch # Changes to upstream defaults. @@ -1520,12 +1494,6 @@ ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch ApplyPatch userns-avoid-recursion-in-put_user_ns.patch -#rhbz 859346 -ApplyPatch fix-destroy_conntrack-GPF.patch - -#CVE-2013-1828 rhbz 919315 919316 -ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch - #rhbz 917353 ApplyPatch backlight_revert.patch -R @@ -1538,21 +1506,9 @@ ApplyPatch i7300_edac_single_mode_fixup.patch #Team Driver update ApplyPatch team-net-next-update-20130307.patch -#rhbz 904182 -ApplyPatch TTY-do-not-reset-master-s-packet-mode.patch - -#rhbz 857954 -ApplyPatch w1-fix-oops-when-w1_search-is-called-from.patch - -#rhbz 911771 -ApplyPatch serial-8250-Keep-8250.-xxxx-module-options-functiona.patch - #rhbz 879462 ApplyPatch uvcvideo-suspend-fix.patch -#CVE-2013-0914 rhbz 920499 920510 -ApplyPatch signal-always-clear-sa_restorer-on-execve.patch - #CVE-2013-0913 rhbz 920471 920529 ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch @@ -1563,12 +1519,6 @@ ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch -#CVE-2013-1860 rhbz 921970 922004 -ApplyPatch USB-cdc-wdm-fix-buffer-overflow.patch - -#rhbz 922304 -ApplyPatch drm-ilk-rc6-reverts.patch -R - #CVE-2013-1798 rhbz 917017 923968 ApplyPatch 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch @@ -2435,6 +2385,10 @@ fi # ||----w | # || || %changelog +* Wed Mar 20 2013 Justin M. Forbes 3.8.4-201 +- Linux v3.8.4 +- CVE-2013-1873 information leaks via netlink interface (rhbz 923652 923662) + * Wed Mar 20 2013 Josh Boyer - CVE-2013-1796 kvm: buffer overflow in handling of MSR_KVM_SYSTEM_TIME (rhbz 917012 923966) diff --git a/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch b/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch deleted file mode 100644 index bb976c593..000000000 --- a/net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 726bc6b092da4c093eb74d13c07184b18c1af0f1 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Wed, 27 Feb 2013 10:57:31 +0000 -Subject: [PATCH] net/sctp: Validate parameter size for SCTP_GET_ASSOC_STATS -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Building sctp may fail with: - -In function ‘copy_from_user’, - inlined from ‘sctp_getsockopt_assoc_stats’ at - net/sctp/socket.c:5656:20: -arch/x86/include/asm/uaccess_32.h:211:26: error: call to - ‘copy_from_user_overflow’ declared with attribute error: copy_from_user() - buffer size is not provably correct - -if built with W=1 due to a missing parameter size validation -before the call to copy_from_user. - -Signed-off-by: Guenter Roeck -Acked-by: Vlad Yasevich -Signed-off-by: David S. Miller ---- - net/sctp/socket.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index cedd9bf..9ef5c73 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, - if (len < sizeof(sctp_assoc_t)) - return -EINVAL; - -+ /* Allow the struct to grow and fill in as much as possible */ -+ len = min_t(size_t, len, sizeof(sas)); -+ - if (copy_from_user(&sas, optval, len)) - return -EFAULT; - -@@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, - /* Mark beginning of a new observation period */ - asoc->stats.max_obs_rto = asoc->rto_min; - -- /* Allow the struct to grow and fill in as much as possible */ -- len = min_t(size_t, len, sizeof(sas)); -- - if (put_user(len, optlen)) - return -EFAULT; - --- -1.8.1.2 - diff --git a/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch b/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch deleted file mode 100644 index b16be4417..000000000 --- a/serial-8250-Keep-8250.-xxxx-module-options-functiona.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e94256528a988231ccc7a2a0b6b206a1131cb358 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 8 Mar 2013 21:13:52 -0500 -Subject: [PATCH] serial: 8250: Keep 8250. module options functional - after driver rename - -With commit 835d844d1 (8250_pnp: do pnp probe before legacy probe), the -8250 driver was renamed to 8250_core. This means any existing usage of -the 8259. module parameters or as a kernel command line switch is -now broken, as the 8250_core driver doesn't parse options belonging to -something called "8250". - -To solve this, we redefine the module options in a dummy function using -a redefined MODULE_PARAM_PREFX when built into the kernel. In the case -where we're building as a module, we provide an alias to the old 8250 -name. The dummy function prevents compiler errors due to global variable -redefinitions that happen as part of the module_param_ macro expansions. - -Signed-off-by: Josh Boyer ---- - drivers/tty/serial/8250/8250.c | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c -index 0efc815..f982633 100644 ---- a/drivers/tty/serial/8250/8250.c -+++ b/drivers/tty/serial/8250/8250.c -@@ -3396,3 +3396,32 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); - MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); - #endif - MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); -+ -+#ifndef MODULE -+/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name -+ * working as well for the module options so we don't break people. We -+ * need to keep the names identical and the convenient macros will happily -+ * refuse to let us do that by failing the build with redefinition errors -+ * of global variables. So we stick them inside a dummy function to avoid -+ * those conflicts. The options still get parsed, and the redefined -+ * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. -+ * -+ * This is hacky. I'm sorry. -+ */ -+static void __used s8250_options(void) -+{ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX "8250." -+ -+ module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644); -+ module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644); -+ module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644); -+#ifdef CONFIG_SERIAL_8250_RSA -+ __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, -+ ¶m_array_ops, .arr = &__param_arr_probe_rsa, -+ 0444, -1); -+#endif -+} -+#else -+MODULE_ALIAS("8250"); -+#endif --- -1.8.1.2 - diff --git a/signal-always-clear-sa_restorer-on-execve.patch b/signal-always-clear-sa_restorer-on-execve.patch deleted file mode 100644 index 658f97a96..000000000 --- a/signal-always-clear-sa_restorer-on-execve.patch +++ /dev/null @@ -1,113 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.169.233 with SMTP id ah9csp99159oac; - Mon, 11 Mar 2013 13:14:17 -0700 (PDT) -X-Received: by 10.68.179.1 with SMTP id dc1mr24297029pbc.128.1363032856671; - Mon, 11 Mar 2013 13:14:16 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id tx10si24737165pbc.272.2013.03.11.13.14.10; - Mon, 11 Mar 2013 13:14:16 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754069Ab3CKUN4 (ORCPT + 99 others); - Mon, 11 Mar 2013 16:13:56 -0400 -Received: from smtp.outflux.net ([198.145.64.163]:59839 "EHLO smtp.outflux.net" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1753913Ab3CKUN4 (ORCPT ); - Mon, 11 Mar 2013 16:13:56 -0400 -Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) - by vinyl.outflux.net (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id r2BKDgjn022201; - Mon, 11 Mar 2013 13:13:43 -0700 -Date: Mon, 11 Mar 2013 13:13:42 -0700 -From: Kees Cook -To: linux-kernel@vger.kernel.org -Cc: Al Viro , Oleg Nesterov , - Andrew Morton , - "Eric W. Biederman" , - Serge Hallyn , - Emese Revfy , - PaX Team , jln@google.com -Subject: [PATCH v2] signal: always clear sa_restorer on execve -Message-ID: <20130311201342.GA19824@www.outflux.net> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -X-MIMEDefang-Filter: outflux$Revision: 1.316 $ -X-HELO: www.outflux.net -X-Scanned-By: MIMEDefang 2.71 on 10.2.0.1 -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org - -When the new signal handlers are set up, the location of sa_restorer -is not cleared, leaking a parent process's address space location to -children. This allows for a potential bypass of the parent's ASLR by -examining the sa_restorer value returned when calling sigaction(). - -Based on what should be considered "secret" about addresses, it only -matters across the exec not the fork (since the VMAs haven't changed -until the exec). But since exec sets SIG_DFL and keeps sa_restorer, -this is where it should be fixed. - -Given the few uses of sa_restorer, a "set" function was not written -since this would be the only use. Instead, we use __ARCH_HAS_SA_RESTORER, -as already done in other places. - -Example of the leak before applying this patch: - -$ cat /proc/$$/maps -... -7fb9f3083000-7fb9f3238000 r-xp 00000000 fd:01 404469 .../libc-2.15.so -... -$ ./leak -... -7f278bc74000-7f278be29000 r-xp 00000000 fd:01 404469 .../libc-2.15.so -... -1 0 (nil) 0x7fb9f30b94a0 -2 4000000 (nil) 0x7f278bcaa4a0 -3 4000000 (nil) 0x7f278bcaa4a0 -4 0 (nil) 0x7fb9f30b94a0 -... - -Signed-off-by: Kees Cook -Reported-by: Emese Revfy -Cc: Emese Revfy -Cc: PaX Team -Cc: stable@vger.kernel.org ---- -v2: - - clarify commit, explain use of #ifdef. ---- - kernel/signal.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/kernel/signal.c b/kernel/signal.c -index 2ec870a..8c8e3ca 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct *t, int force_default) - if (force_default || ka->sa.sa_handler != SIG_IGN) - ka->sa.sa_handler = SIG_DFL; - ka->sa.sa_flags = 0; -+#ifdef SA_RESTORER -+ ka->sa.sa_restorer = NULL; -+#endif - sigemptyset(&ka->sa.sa_mask); - ka++; - } --- -1.7.9.5 - - --- -Kees Cook -Chrome OS Security --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ diff --git a/silence-tty-null.patch b/silence-tty-null.patch deleted file mode 100644 index 00f64239b..000000000 --- a/silence-tty-null.patch +++ /dev/null @@ -1,13 +0,0 @@ -This should be fixed in 3.9, but is unlikely to be backported. - ---- linux-3.8.1-201.fc18.x86_64/drivers/tty/tty_buffer.c~ 2013-03-01 11:07:37.498291384 -0500 -+++ linux-3.8.1-201.fc18.x86_64/drivers/tty/tty_buffer.c 2013-03-01 11:08:11.088250537 -0500 -@@ -473,7 +473,7 @@ static void flush_to_ldisc(struct work_s - struct tty_ldisc *disc; - - tty = port->itty; -- if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n")) -+ if (tty == NULL) - return; - - disc = tty_ldisc_ref(tty); diff --git a/sources b/sources index 499b47a52..2d46829f1 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -ba18b5d27ed303f5e5a9cda32a451031 patch-3.8.3.xz +40ab82996ff4b49ad3f4e19cf729dcab patch-3.8.4.xz diff --git a/w1-fix-oops-when-w1_search-is-called-from.patch b/w1-fix-oops-when-w1_search-is-called-from.patch deleted file mode 100644 index 0a54eff17..000000000 --- a/w1-fix-oops-when-w1_search-is-called-from.patch +++ /dev/null @@ -1,111 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.101.212.35 with SMTP id o35csp6769anq; - Sat, 2 Mar 2013 05:50:51 -0800 (PST) -X-Received: by 10.68.137.42 with SMTP id qf10mr19122124pbb.80.1362232251119; - Sat, 02 Mar 2013 05:50:51 -0800 (PST) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id pu7si8560937pbc.232.2013.03.02.05.50.50; - Sat, 02 Mar 2013 05:50:51 -0800 (PST) -Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org; - dkim=neutral (body hash did not verify) header.i=@gmail.com -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1752198Ab3CBNuU (ORCPT - + 99 others); Sat, 2 Mar 2013 08:50:20 -0500 -Received: from mail-ee0-f48.google.com ([74.125.83.48]:46431 "EHLO - mail-ee0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1752038Ab3CBNuT (ORCPT - ); - Sat, 2 Mar 2013 08:50:19 -0500 -Received: by mail-ee0-f48.google.com with SMTP id t10so2921534eei.7 - for ; Sat, 02 Mar 2013 05:50:18 -0800 (PST) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20120113; - h=x-received:date:from:to:cc:subject:message-id:references - :mime-version:content-type:content-disposition:in-reply-to - :user-agent; - bh=8ABPYEMGQsyhtGtpdGpnD1kQchBrqYm9rJ3sEUcIQOc=; - b=hx/4GjbvaME9C3c+WOrfUkkwnJ5jJXefsOhCKmPCE8kmswk3Tvm11198r4+y1jM/Bl - 1wtIYby6sFgA08JUldm09fPpsKfbdeDnFAI5WmUAGJjahFXXRrQPocI6E0+s2BcM+t3H - Ii8g8ZvYJ+YMgbbSmp7mwMv98aa0+qdY6TIF4P/wNwAWrsjFh5TBgc/QyB0MzyQQ2tMp - LfA7n/2sH11vofS6FLSaWhtwGIIexPZ+oxWpvwBcCIYX+gTrSHPZqnLQkvhQ5oZDx7WF - 6QlNEqlmL+usW1ApRCAwcL4jOaORDAC2MytGH4jdZNic0PqdzonfbJTRE6YmZ45FHtNG - l+6w== -X-Received: by 10.15.101.204 with SMTP id bp52mr38431150eeb.31.1362232218031; - Sat, 02 Mar 2013 05:50:18 -0800 (PST) -Received: from gmail.com (aek101.neoplus.adsl.tpnet.pl. [83.25.114.101]) - by mx.google.com with ESMTPS id o3sm22363368eem.15.2013.03.02.05.50.16 - (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); - Sat, 02 Mar 2013 05:50:17 -0800 (PST) -Date: Sat, 2 Mar 2013 14:50:15 +0100 -From: Marcin Jurkowski -To: Sven Geggus -Cc: Evgeniy Polyakov , linux-kernel@vger.kernel.org -Subject: [PATCH 1/1] w1: fix oops when w1_search is called from netlink - connector -Message-ID: <20130302135015.GA21448@gmail.com> -References: <20130116141627.GA23638@ioremap.net> - <20130302001103.GB18026@gmail.com> - <20130302094510.GA4695@geggus.net> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20130302094510.GA4695@geggus.net> -User-Agent: Mutt/1.5.21 (2010-09-15) -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org - -On Sat, Mar 02, 2013 at 10:45:10AM +0100, Sven Geggus wrote: -> This is the bad commit I found doing git bisect: -> 04f482faf50535229a5a5c8d629cf963899f857c is the first bad commit -> commit 04f482faf50535229a5a5c8d629cf963899f857c -> Author: Patrick McHardy -> Date: Mon Mar 28 08:39:36 2011 +0000 - -Good job. I was too lazy to bisect for bad commit;) - -Reading the code I found problematic kthread_should_stop call from netlink -connector which causes the oops. After applying a patch, I've been testing -owfs+w1 setup for nearly two days and it seems to work very reliable (no -hangs, no memleaks etc). -More detailed description and possible fix is given below: - -Function w1_search can be called from either kthread or netlink callback. -While the former works fine, the latter causes oops due to kthread_should_stop -invocation. - -This patch adds a check if w1_search is serving netlink command, skipping -kthread_should_stop invocation if so. - -Signed-off-by: Marcin Jurkowski ---- - drivers/w1/w1.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c -index 7994d933..7e2220d 100644 ---- a/drivers/w1/w1.c -+++ b/drivers/w1/w1.c -@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb - tmp64 = (triplet_ret >> 2); - rn |= (tmp64 << i); - -- if (kthread_should_stop()) { -+ /* ensure we're called from kthread and not by netlink callback */ -+ if (!dev->priv && kthread_should_stop()) { - mutex_unlock(&dev->bus_mutex); - dev_dbg(&dev->dev, "Abort w1_search\n"); - return; --- -1.7.12.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ From 0bbf13e93722ae6d3a845515288bc4ef2cbde1c6 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 21 Mar 2013 12:57:49 +0000 Subject: [PATCH 256/492] Minor ARM config updates --- config-armv7 | 16 ++++++++++++++++ kernel.spec | 3 +++ 2 files changed, 19 insertions(+) diff --git a/config-armv7 b/config-armv7 index 6a5972d5d..8eb6dafa4 100644 --- a/config-armv7 +++ b/config-armv7 @@ -466,6 +466,22 @@ CONFIG_ETHERNET=y # CONFIG_PANEL_TAAL is not set # CONFIG_SND_OMAP_SOC_OMAP_TWL4030 is not set +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SFC is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set + # CONFIG_DVB_USB_PCTV452E is not set # We need to fix these as they should be either generic includes or kconfig fixes # drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] diff --git a/kernel.spec b/kernel.spec index ea5de280f..8f4fdb8c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2385,6 +2385,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 21 2013 Peter Robinson +- Minor ARM config updates + * Wed Mar 20 2013 Justin M. Forbes 3.8.4-201 - Linux v3.8.4 - CVE-2013-1873 information leaks via netlink interface (rhbz 923652 923662) From bf0fa1e0bc5cf81d0eba48419606ff87f6b116e5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 21 Mar 2013 09:04:30 -0400 Subject: [PATCH 257/492] Fix workqueue crash in mac80211 (rhbz 920218) --- kernel.spec | 11 +++- ...ont-restart-sta-timer-if-not-running.patch | 55 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 mac80211-Dont-restart-sta-timer-if-not-running.patch diff --git a/kernel.spec b/kernel.spec index 8f4fdb8c6..7118f86d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -789,6 +789,9 @@ Patch25004: 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch #CVE-2013-1797 rhbz 917013 923967 Patch25005: 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch +#rhbz 920218 +Patch25006: mac80211-Dont-restart-sta-timer-if-not-running.patch + # END OF PATCH DEFINITIONS %endif @@ -1528,6 +1531,9 @@ ApplyPatch 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch #CVE-2013-1797 rhbz 917013 923967 ApplyPatch 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch +#rhbz 920218 +ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch + # END OF PATCH APPLICATIONS %endif @@ -2385,6 +2391,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 21 2013 Josh Boyer +- Fix workqueue crash in mac80211 (rhbz 920218) + * Thu Mar 21 2013 Peter Robinson - Minor ARM config updates diff --git a/mac80211-Dont-restart-sta-timer-if-not-running.patch b/mac80211-Dont-restart-sta-timer-if-not-running.patch new file mode 100644 index 000000000..7727ad8f2 --- /dev/null +++ b/mac80211-Dont-restart-sta-timer-if-not-running.patch @@ -0,0 +1,55 @@ +From: Ben Greear + +I found another crash when deleting lots of virtual stations +in a congested environment. I think the problem is that +the ieee80211_mlme_notify_scan_completed could call +ieee80211_restart_sta_timer for a stopped interface +that was about to be deleted. Fix similar problem for +mesh interfaces as well. + +Signed-off-by: Ben Greear +--- +v4: Fix up mesh as well, add check in calling code instead of + in the methods that mucks iwth the timers. + +:100644 100644 67fcfdf... 02e3d75... M net/mac80211/mesh.c +:100644 100644 aec786d... 1d237e9... M net/mac80211/mlme.c + net/mac80211/mesh.c | 3 ++- + net/mac80211/mlme.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 67fcfdf..02e3d75 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -779,7 +779,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) +- if (ieee80211_vif_is_mesh(&sdata->vif)) ++ if (ieee80211_sdata_running(sdata) ++ && ieee80211_vif_is_mesh(&sdata->vif)) + ieee80211_queue_work(&local->hw, &sdata->work); + rcu_read_unlock(); + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index aec786d..1d237e9 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3054,7 +3054,8 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) + /* Restart STA timers */ + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) +- ieee80211_restart_sta_timer(sdata); ++ if (ieee80211_sdata_running(sdata)) ++ ieee80211_restart_sta_timer(sdata); + rcu_read_unlock(); + } + +-- +1.7.3.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From d70d5dbf6eb5fd1df50ba3fafd5af3dec378cffc Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sat, 23 Mar 2013 18:39:43 +0000 Subject: [PATCH 258/492] Disable Marvell Dove support for the moment as it breaks other SoCs --- config-armv7 | 6 ------ kernel.spec | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/config-armv7 b/config-armv7 index 8eb6dafa4..eea4d33ff 100644 --- a/config-armv7 +++ b/config-armv7 @@ -190,10 +190,6 @@ CONFIG_ARM_AMBA=y CONFIG_MACH_ARMADA_370_XP=y CONFIG_MACH_ARMADA_370=y CONFIG_MACH_ARMADA_XP=y -CONFIG_ARCH_DOVE=y -# CONFIG_MACH_DOVE_DB is not set -# CONFIG_MACH_CM_A510 is not set -CONFIG_MACH_DOVE_DT=y CONFIG_CACHE_TAUROS2=y CONFIG_MV_XOR=y @@ -203,7 +199,6 @@ CONFIG_I2C_MV64XXX=m CONFIG_PINCTRL_MVEBU=y CONFIG_PINCTRL_ARMADA_370=y CONFIG_PINCTRL_ARMADA_XP=y -CONFIG_PINCTRL_DOVE=y CONFIG_EDAC_MV64X60=m CONFIG_SATA_MV=m CONFIG_MARVELL_PHY=m @@ -215,7 +210,6 @@ CONFIG_MVNETA=m CONFIG_GPIO_MVEBU=y CONFIG_MVEBU_CLK_CORE=y CONFIG_MVEBU_CLK_GATING=y -CONFIG_MMC_SDHCI_DOVE=m # Allwinner a1x # CONFIG_SUNXI_RFKILL=y diff --git a/kernel.spec b/kernel.spec index 7118f86d4..0c28e5045 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2391,6 +2391,9 @@ fi # ||----w | # || || %changelog +* Sat Mar 23 2013 Peter Robinson +- Disable Marvell Dove support for the moment as it breaks other SoCs + * Thu Mar 21 2013 Josh Boyer - Fix workqueue crash in mac80211 (rhbz 920218) From 0d7b2212f7b2add8f38aa06debc462749aded700 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 25 Mar 2013 12:28:12 -0500 Subject: [PATCH 259/492] enable CONFIG_DRM_VMWGFX_FBCON (rhbz 927022) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 69d546064..1f1cd0022 100644 --- a/config-generic +++ b/config-generic @@ -2552,7 +2552,7 @@ CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_UDL=m CONFIG_DRM_VMWGFX=m -# CONFIG_DRM_VMWGFX_FBCON is not set +CONFIG_DRM_VMWGFX_FBCON=y CONFIG_DRM_VGEM=m # diff --git a/kernel.spec b/kernel.spec index 0c28e5045..ec91a01b6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2391,6 +2391,9 @@ fi # ||----w | # || || %changelog +* Mon Mar 25 2013 Justin M. Forbes +- enable CONFIG_DRM_VMWGFX_FBCON (rhbz 927022) + * Sat Mar 23 2013 Peter Robinson - Disable Marvell Dove support for the moment as it breaks other SoCs From b13c8c241f6a25874543f2724ef02861aa6e0df3 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 25 Mar 2013 13:30:23 -0500 Subject: [PATCH 260/492] disable whci-hcd since it doesnt seem to have users (rhbz 919289) --- config-generic | 2 +- kernel.spec | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 1f1cd0022..3337d2b34 100644 --- a/config-generic +++ b/config-generic @@ -4408,7 +4408,7 @@ CONFIG_WM8350_POWER=m CONFIG_USB_WUSB=m CONFIG_USB_WUSB_CBAF=m # CONFIG_USB_WUSB_CBAF_DEBUG is not set -CONFIG_USB_WHCI_HCD=m +# CONFIG_USB_WHCI_HCD is not set CONFIG_USB_HWA_HCD=m # CONFIG_USB_HCD_BCMA is not set # CONFIG_USB_HCD_SSB is not set diff --git a/kernel.spec b/kernel.spec index ec91a01b6..6361d5be7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2393,6 +2393,7 @@ fi %changelog * Mon Mar 25 2013 Justin M. Forbes - enable CONFIG_DRM_VMWGFX_FBCON (rhbz 927022) +- disable whci-hcd since it doesnt seem to have users (rhbz 919289) * Sat Mar 23 2013 Peter Robinson - Disable Marvell Dove support for the moment as it breaks other SoCs From c6c6a44cac384822af2b6a9e2188f4dcb8a07d8f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Mar 2013 07:47:37 -0400 Subject: [PATCH 261/492] Add quirk for MSI keyboard backlight to avoid 10 sec boot delay (rhbz 907221) --- ...sbhid-quirk-for-MSI-GX680R-led-panel.patch | 45 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch diff --git a/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch b/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch new file mode 100644 index 000000000..66e529d72 --- /dev/null +++ b/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch @@ -0,0 +1,45 @@ +From 565bd59e8f55b82eb49b58b0972ac41f4448ef06 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 15 Mar 2013 10:31:31 -0400 +Subject: [PATCH] HID: usbhid: quirk for MSI GX680R led panel + +This keyboard backlight device causes a 10 second delay to boot. Add it +to the quirk list with HID_QUIRK_NO_INIT_REPORTS. + +This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=907221 + +Signed-off-by: Josh Boyer +--- + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/usbhid/hid-quirks.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index d1063e9..c438877 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -590,6 +590,9 @@ + #define USB_VENDOR_ID_MONTEREY 0x0566 + #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 + ++#define USB_VENDOR_ID_MSI 0x1770 ++#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00 ++ + #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 + #define USB_DEVICE_ID_N_S_HARMONY 0xc359 + +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index e991d81..476c984 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -73,6 +73,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 6361d5be7..680530eaf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -774,6 +774,9 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch +#rhbz 907221 +Patch24116: HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch + #rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch @@ -1534,6 +1537,9 @@ ApplyPatch 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch #rhbz 920218 ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch +#rhbz 907221 +ApplyPatch HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch + # END OF PATCH APPLICATIONS %endif @@ -2391,6 +2397,9 @@ fi # ||----w | # || || %changelog +* Tue Mar 26 2013 Josh Boyer +- Add quirk for MSI keyboard backlight to avoid 10 sec boot delay (rhbz 907221) + * Mon Mar 25 2013 Justin M. Forbes - enable CONFIG_DRM_VMWGFX_FBCON (rhbz 927022) - disable whci-hcd since it doesnt seem to have users (rhbz 919289) From 892fd041916cb2c2fae51b9bf549a7261115a5a3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Mar 2013 07:52:06 -0400 Subject: [PATCH 262/492] Add quirk for Realtek card reader to avoid 10 sec boot delay (rhbz 806587) --- ...-quirk-for-Realtek-Multi-card-reader.patch | 45 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch diff --git a/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch b/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch new file mode 100644 index 000000000..6bccd6cd1 --- /dev/null +++ b/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch @@ -0,0 +1,45 @@ +From 926bb9deb21046248d01e2f6fc86fdbb149b514c Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 15 Mar 2013 10:27:36 -0400 +Subject: [PATCH 1/2] HID: usbhid: quirk for Realtek Multi-card reader + +This device has an odd HID entry and causes a 10 second delay in boot. +Add this device to the quirks list with HID_QUIRK_NO_INIT_REPORTS. + +This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=806587 + +Signed-off-by: Josh Boyer +--- + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/usbhid/hid-quirks.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 92e47e5..d1063e9 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -684,6 +684,9 @@ + #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 + #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 + ++#define USB_VENDOR_ID_REALTEK 0x0bda ++#define USB_DEVICE_ID_REALTEK_READER 0x0152 ++ + #define USB_VENDOR_ID_ROCCAT 0x1e7d + #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 + #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index e0e6abf..e991d81 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -80,6 +80,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 680530eaf..5f3ac035b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -774,6 +774,9 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch +#rhbz 806587 +Patch24115: HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch + #rhbz 907221 Patch24116: HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch @@ -1540,6 +1543,9 @@ ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch #rhbz 907221 ApplyPatch HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch +#rhbz 806587 +ApplyPatch HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch + # END OF PATCH APPLICATIONS %endif @@ -2398,6 +2404,7 @@ fi # || || %changelog * Tue Mar 26 2013 Josh Boyer +- Add quirk for Realtek card reader to avoid 10 sec boot delay (rhbz 806587) - Add quirk for MSI keyboard backlight to avoid 10 sec boot delay (rhbz 907221) * Mon Mar 25 2013 Justin M. Forbes From 030685dae1c79b7edc26d524e9f2fcafd8a687d7 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 26 Mar 2013 15:03:42 -0500 Subject: [PATCH 263/492] Fix child thread introspection of of /proc/self/exe (rhbz 927469) --- fix-child-thread-introspection.patch | 76 ++++++++++++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 85 insertions(+) create mode 100644 fix-child-thread-introspection.patch diff --git a/fix-child-thread-introspection.patch b/fix-child-thread-introspection.patch new file mode 100644 index 000000000..4c0bad1a6 --- /dev/null +++ b/fix-child-thread-introspection.patch @@ -0,0 +1,76 @@ +Allow threads other than the main thread to do introspection of files in +proc without relying on read permissions. proc_pid_follow_link() calls +proc_fd_access_allowed() which ultimately calls __ptrace_may_access(). + +Though this allows additional access to some proc files, we do not +believe that this has any unintended security implications. However it +probably needs to be looked at carefully. + +The original problem was a thread of a process whose permissions were +111 couldn't open its own /proc/self/exe This was interfering with a +special purpose debugging tool. A simple reproducer is below.: + +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 2048 + +void *thread_main(void *arg){ + char *str=(char*)arg; + char buf[BUFSIZE]; + ssize_t len=readlink("/proc/self/exe", buf, BUFSIZE); + if(len==-1) + printf("/proc/self/exe in %s: %s\n", str,sys_errlist[errno]); + else + printf("/proc/self/exe in %s: OK\n", str); + + return 0; +} + +int main(){ + pthread_t thread; + + int retval=pthread_create( &thread, NULL, thread_main, "thread"); + if(retval!=0) + exit(1); + + thread_main("main"); + pthread_join(thread, NULL); + + exit(0); +} + +Signed-off-by: Ben Woodard +Signed-off-by: Mark Grondona +--- + kernel/ptrace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index acbd284..347c4c7 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +diff -ruNp linux-3.8.4-103.fc17.noarch/kernel/ptrace.c linux-3.8.4-103.fc17.ptrace/kernel/ptrace.c +--- linux-3.8.4-103.fc17.noarch/kernel/ptrace.c 2013-02-18 17:58:34.000000000 -0600 ++++ linux-3.8.4-103.fc17.ptrace/kernel/ptrace.c 2013-03-26 14:59:01.939396346 -0500 +@@ -234,7 +234,7 @@ static int __ptrace_may_access(struct ta + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ +- if (task == current) ++ if (same_thread_group(task, current)) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); +-- +1.8.1.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/kernel.spec b/kernel.spec index 5f3ac035b..1ed37910e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -798,6 +798,9 @@ Patch25005: 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch #rhbz 920218 Patch25006: mac80211-Dont-restart-sta-timer-if-not-running.patch +#rhbz 927469 +Patch25007: fix-child-thread-introspection.patch + # END OF PATCH DEFINITIONS %endif @@ -1546,6 +1549,9 @@ ApplyPatch HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch #rhbz 806587 ApplyPatch HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch +#rhbz 927469 +ApplyPatch fix-child-thread-introspection.patch + # END OF PATCH APPLICATIONS %endif @@ -2403,6 +2409,9 @@ fi # ||----w | # || || %changelog +* Tue Mar 26 2013 Justin M. Forbes +- Fix child thread introspection of of /proc/self/exe (rhbz 927469) + * Tue Mar 26 2013 Josh Boyer - Add quirk for Realtek card reader to avoid 10 sec boot delay (rhbz 806587) - Add quirk for MSI keyboard backlight to avoid 10 sec boot delay (rhbz 907221) From 245cd7a89cbce02de904fcd498e7f9e94f6218e3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 28 Mar 2013 16:22:57 -0400 Subject: [PATCH 264/492] Linux v3.8.5 --- backlight_revert.patch | 61 ------------------- config-x86-generic | 2 + ...ds-check-execbuffer-relocation-count.patch | 51 ---------------- kernel.spec | 19 ++---- sources | 2 +- 5 files changed, 8 insertions(+), 127 deletions(-) delete mode 100644 backlight_revert.patch delete mode 100644 drm-i915-bounds-check-execbuffer-relocation-count.patch diff --git a/backlight_revert.patch b/backlight_revert.patch deleted file mode 100644 index 6d2957c2a..000000000 --- a/backlight_revert.patch +++ /dev/null @@ -1,61 +0,0 @@ -commit cf0a6584aa6d382f802f2c3cacac23ccbccde0cd -Author: Daniel Vetter -Date: Wed Feb 6 11:24:41 2013 +0100 - - drm/i915: write backlight harder - - 770c12312ad617172b1a65b911d3e6564fc5aca8 is the first bad commit - commit 770c12312ad617172b1a65b911d3e6564fc5aca8 - Author: Takashi Iwai - Date: Sat Aug 11 08:56:42 2012 +0200 - - drm/i915: Fix blank panel at reopening lid - - changed the register write sequence for restoring the backlight, which - helped prevent non-working backlights on some machines. Turns out that - the original sequence was the right thing to do for a different set of - machines. Worse, setting the backlight level _after_ enabling it seems - to reset it somehow. So we need to make that one conditional upon the - backlight having been reset to zero, and add the old one back. - - Cargo-culting at it's best, but it seems to work. - - Cc: stable@vger.kernel.org - Cc: Takashi Iwai - Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47941 - Reviewed-by: Jani Nikula - Acked-by: Takashi Iwai - Signed-off-by: Daniel Vetter - -diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c -index bee8cb6..a3730e0 100644 ---- a/drivers/gpu/drm/i915/intel_panel.c -+++ b/drivers/gpu/drm/i915/intel_panel.c -@@ -321,6 +321,9 @@ void intel_panel_enable_backlight(struct drm_device *dev, - if (dev_priv->backlight_level == 0) - dev_priv->backlight_level = intel_panel_get_max_backlight(dev); - -+ dev_priv->backlight_enabled = true; -+ intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); -+ - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; - -@@ -356,12 +359,12 @@ void intel_panel_enable_backlight(struct drm_device *dev, - } - - set_level: -- /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. -- * BLC_PWM_CPU_CTL may be cleared to zero automatically when these -- * registers are set. -+ /* Check the current backlight level and try to set again if it's zero. -+ * On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically -+ * when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written. - */ -- dev_priv->backlight_enabled = true; -- intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); -+ if (!intel_panel_get_backlight(dev)) -+ intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); - } - - static void intel_panel_init_backlight(struct drm_device *dev) diff --git a/config-x86-generic b/config-x86-generic index e8335a2f0..8c4609db6 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -36,6 +36,8 @@ CONFIG_X86_PM_TIMER=y CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_EFI_VARS=y +CONFIG_EFI_VARS_PSTORE=y +# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set CONFIG_EFI_PCDP=y CONFIG_FB_EFI=y diff --git a/drm-i915-bounds-check-execbuffer-relocation-count.patch b/drm-i915-bounds-check-execbuffer-relocation-count.patch deleted file mode 100644 index a6c9d4b12..000000000 --- a/drm-i915-bounds-check-execbuffer-relocation-count.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e896e9dde50fd9a44cbbed205cc0beb869e2193b Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Mon, 11 Mar 2013 17:31:45 -0700 -Subject: [PATCH] drm/i915: bounds check execbuffer relocation count - -It is possible to wrap the counter used to allocate the buffer for -relocation copies. This could lead to heap writing overflows. - -CVE-2013-0913 - -v3: collapse test, improve comment -v2: move check into validate_exec_list - -Signed-off-by: Kees Cook -Reported-by: Pinkie Pie -Cc: stable@vger.kernel.org ---- - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -index 26d08bb..7adf5a7 100644 ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -706,15 +706,20 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, - int count) - { - int i; -+ int relocs_total = 0; -+ int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); - - for (i = 0; i < count; i++) { - char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; - int length; /* limited by fault_in_pages_readable() */ - -- /* First check for malicious input causing overflow */ -- if (exec[i].relocation_count > -- INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) -+ /* First check for malicious input causing overflow in -+ * the worst case where we need to allocate the entire -+ * relocation tree as a single array. -+ */ -+ if (exec[i].relocation_count > relocs_max - relocs_total) - return -EINVAL; -+ relocs_total += exec[i].relocation_count; - - length = exec[i].relocation_count * - sizeof(struct drm_i915_gem_relocation_entry); --- -1.8.1.2 - diff --git a/kernel.spec b/kernel.spec index 1ed37910e..bb663e863 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -758,15 +758,9 @@ Patch24000: alps.patch Patch24100: userns-avoid-recursion-in-put_user_ns.patch -#rhbz 917353 -Patch24102: backlight_revert.patch - #rhbz 879462 Patch24107: uvcvideo-suspend-fix.patch -#CVE-2013-0913 rhbz 920471 920529 -Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch - #rhbz 856863 892599 Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch @@ -1506,9 +1500,6 @@ ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch ApplyPatch userns-avoid-recursion-in-put_user_ns.patch -#rhbz 917353 -ApplyPatch backlight_revert.patch -R - #rhbz 920586 ApplyPatch amd64_edac_fix_rank_count.patch @@ -1521,9 +1512,6 @@ ApplyPatch team-net-next-update-20130307.patch #rhbz 879462 ApplyPatch uvcvideo-suspend-fix.patch -#CVE-2013-0913 rhbz 920471 920529 -ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch - #rhbz 856863 892599 ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch @@ -2409,6 +2397,9 @@ fi # ||----w | # || || %changelog +* Thu Mar 28 2013 Josh Boyer - 3.8.5-201 +- Linux v3.8.5 + * Tue Mar 26 2013 Justin M. Forbes - Fix child thread introspection of of /proc/self/exe (rhbz 927469) diff --git a/sources b/sources index 2d46829f1..046b4ea88 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -40ab82996ff4b49ad3f4e19cf729dcab patch-3.8.4.xz +3ac9864bcf512fd71a7ecdd8c9c96d6c patch-3.8.5.xz From 5fab95dc2e30d1b0962b1f00dc513980f8de2efc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 1 Apr 2013 12:43:09 -0400 Subject: [PATCH 265/492] Enable CONFIG_MCE_INJECT (rhbz 927353) --- config-x86-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-x86-generic b/config-x86-generic index 8c4609db6..761e1da3f 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -348,7 +348,7 @@ CONFIG_PERF_EVENTS=y CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y CONFIG_X86_MCE_AMD=y -# CONFIG_X86_MCE_INJECT is not set +CONFIG_X86_MCE_INJECT=m CONFIG_SFI=y diff --git a/kernel.spec b/kernel.spec index bb663e863..e9be00407 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2397,6 +2397,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 01 2013 Josh Boyer +- Enable CONFIG_MCE_INJECT (rhbz 927353) + * Thu Mar 28 2013 Josh Boyer - 3.8.5-201 - Linux v3.8.5 From a44dd01fceca53532fde94f5284467ae381208d3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 1 Apr 2013 12:49:38 -0400 Subject: [PATCH 266/492] Enable the rtl8192e driver (rhbz 913753) --- config-generic | 7 ++++++- kernel.spec | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 3337d2b34..ea4e25f84 100644 --- a/config-generic +++ b/config-generic @@ -4448,7 +4448,12 @@ CONFIG_USB_ATMEL=m # CONFIG_RAR_REGISTER is not set # CONFIG_VT6656 is not set # CONFIG_USB_SERIAL_QUATECH_USB2 is not set -# CONFIG_RTL8192E is not set +# Larry Finger maintains these (rhbz 913753) +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_RTL8192E=m # CONFIG_INPUT_GPIO is not set # CONFIG_VIDEO_CX25821 is not set # CONFIG_R8187SE is not set diff --git a/kernel.spec b/kernel.spec index e9be00407..c22039e58 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2398,6 +2398,7 @@ fi # || || %changelog * Mon Apr 01 2013 Josh Boyer +- Enable the rtl8192e driver (rhbz 913753) - Enable CONFIG_MCE_INJECT (rhbz 927353) * Thu Mar 28 2013 Josh Boyer - 3.8.5-201 From aa6f8c0eefbf32af775c4d2672b0c2391029cc06 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Apr 2013 12:00:46 -0400 Subject: [PATCH 267/492] Enable CONFIG_SCSI_DMX3191D (rhbz 919874) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index ea4e25f84..e9c7f33bd 100644 --- a/config-generic +++ b/config-generic @@ -450,7 +450,7 @@ CONFIG_SCSI_ARCMSR=m CONFIG_SCSI_BUSLOGIC=m CONFIG_SCSI_INITIO=m CONFIG_SCSI_FLASHPOINT=y -# CONFIG_SCSI_DMX3191D is not set +CONFIG_SCSI_DMX3191D=m # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set diff --git a/kernel.spec b/kernel.spec index c22039e58..7542205ee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2397,6 +2397,9 @@ fi # ||----w | # || || %changelog +* Tue Apr 02 2013 Josh Boyer +- Enable CONFIG_SCSI_DMX3191D (rhbz 919874) + * Mon Apr 01 2013 Josh Boyer - Enable the rtl8192e driver (rhbz 913753) - Enable CONFIG_MCE_INJECT (rhbz 927353) From fd87540dd99f27b983a73fb9cb582dcf85b5ea9b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Apr 2013 14:23:58 -0400 Subject: [PATCH 268/492] Add support for Atheros 04ca:3004 bluetooth devices (again) (rhbz 844750) --- ...pport-for-atheros-04ca-3004-device-t.patch | 62 +++++++++++++++++++ kernel.spec | 6 ++ 2 files changed, 68 insertions(+) create mode 100644 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch diff --git a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch new file mode 100644 index 000000000..8d34a68f3 --- /dev/null +++ b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch @@ -0,0 +1,62 @@ +From 017de1136ff304ab401dbfee4eca2e796c61797f Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 19 Feb 2013 11:54:16 -0500 +Subject: [PATCH] Bluetooth: Add support for atheros 04ca:3004 device to ath3k + +Yet another version of the atheros bluetooth chipset + +T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=04ca ProdID=3004 Rev=00.01 +S: Manufacturer=Atheros Communications +S: Product=Bluetooth USB Host Controller +S: SerialNumber=Alaska Day 2006 +C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb + +This resolves https://bugzilla.redhat.com/show_bug.cgi?id=844750 + +Reported-by: niktr@mail.ru +Signed-off-by: Josh Boyer +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/ath3k.c | 2 ++ + drivers/bluetooth/btusb.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 33c9a44..b9908dd 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0x3004) }, + { USB_DEVICE(0x0CF3, 0x311D) }, + { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x04CA, 0x3004) }, + { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3008) }, +@@ -108,6 +109,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 7e351e3..59cde8e 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 7542205ee..95b00f78d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -795,6 +795,9 @@ Patch25006: mac80211-Dont-restart-sta-timer-if-not-running.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch +#rhbz 844750 +Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + # END OF PATCH DEFINITIONS %endif @@ -1540,6 +1543,8 @@ ApplyPatch HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch +ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + # END OF PATCH APPLICATIONS %endif @@ -2398,6 +2403,7 @@ fi # || || %changelog * Tue Apr 02 2013 Josh Boyer +- Add support for Atheros 04ca:3004 bluetooth devices (again) (rhbz 844750) - Enable CONFIG_SCSI_DMX3191D (rhbz 919874) * Mon Apr 01 2013 Josh Boyer From 1d4383241f6a755909ee8f244e998d0cbd8087f3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Apr 2013 16:21:07 -0400 Subject: [PATCH 269/492] Enable CONFIG_FB_MATROX_G on powerpc --- config-powerpc-generic | 1 + kernel.spec | 1 + 2 files changed, 2 insertions(+) diff --git a/config-powerpc-generic b/config-powerpc-generic index 902dccdee..03341c818 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -39,6 +39,7 @@ CONFIG_FB_OF=y # CONFIG_FB_CONTROL is not set CONFIG_FB_IBM_GXT4500=y CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_G=y # CONFIG_FB_VGA16 is not set CONFIG_FB_ATY128_BACKLIGHT=y CONFIG_FB_ATY_BACKLIGHT=y diff --git a/kernel.spec b/kernel.spec index 95b00f78d..8532a6d6e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2403,6 +2403,7 @@ fi # || || %changelog * Tue Apr 02 2013 Josh Boyer +- Enable CONFIG_FB_MATROX_G on powerpc - Add support for Atheros 04ca:3004 bluetooth devices (again) (rhbz 844750) - Enable CONFIG_SCSI_DMX3191D (rhbz 919874) From 58d2019abdba1e9ea87abe76579ee80fc00244ab Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Apr 2013 14:48:46 -0400 Subject: [PATCH 270/492] Enable MTD_CHAR/MTD_BLOCK (Needed for SFC) Enable 10gigE on 64-bit only. --- config-generic | 12 +++--------- config-x86_64-generic | 15 +++++++++++++++ kernel.spec | 4 ++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/config-generic b/config-generic index e9c7f33bd..5c137e66d 100644 --- a/config-generic +++ b/config-generic @@ -1426,16 +1426,10 @@ CONFIG_JME=m # # Ethernet (10000 Mbit) # -CONFIG_IP1000=m -CONFIG_MLX4_EN=m -CONFIG_MLX4_EN_DCB=y +# CONFIG_IP1000 is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_DEBUG is not set -CONFIG_SFC=m -CONFIG_SFC_MCDI_MON=y -CONFIG_SFC_SRIOV=y -CONFIG_SFC_PTP=y - -# CONFIG_SFC_MTD is not set +# CONFIG_SFC is not set # CONFIG_FDDI is not set # CONFIG_DEFXX is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index bcea67e2a..f4fc09d98 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -130,3 +130,18 @@ CONFIG_BPF_JIT=y # Should be 32bit only, but lacks KConfig depends # CONFIG_XO15_EBOOK is not set +# 10GigE +# +CONFIG_IP1000=m +CONFIG_MLX4_EN=m +CONFIG_MLX4_EN_DCB=y +# CONFIG_MLX4_DEBUG is not set +CONFIG_SFC=m +CONFIG_SFC_MCDI_MON=y +CONFIG_SFC_SRIOV=y +CONFIG_SFC_PTP=y +CONFIG_SFC_MTD=y +# Override MTD stuff because SFC_MTD needs it +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m + diff --git a/kernel.spec b/kernel.spec index 8532a6d6e..9be42500a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2402,6 +2402,10 @@ fi # ||----w | # || || %changelog +* Wed Apr 03 2013 Dave Jones +- Enable MTD_CHAR/MTD_BLOCK (Needed for SFC) + Enable 10gigE on 64-bit only. + * Tue Apr 02 2013 Josh Boyer - Enable CONFIG_FB_MATROX_G on powerpc - Add support for Atheros 04ca:3004 bluetooth devices (again) (rhbz 844750) From 14ff3d827a7916f82be9a28394dbd420c9c3a7f1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 5 Apr 2013 13:16:32 -0500 Subject: [PATCH 271/492] Linux v3.8.6 --- ...pport-for-atheros-04ca-3004-device-t.patch | 6 +-- ...sbhid-quirk-for-MSI-GX680R-led-panel.patch | 45 ------------------- ...-quirk-for-Realtek-Multi-card-reader.patch | 45 ------------------- kernel.spec | 19 +++----- sources | 2 +- 5 files changed, 9 insertions(+), 108 deletions(-) delete mode 100644 HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch delete mode 100644 HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch diff --git a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch index 8d34a68f3..a15d00b6a 100644 --- a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +++ b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch @@ -30,16 +30,16 @@ index 33c9a44..b9908dd 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = { - { USB_DEVICE(0x0CF3, 0x3004) }, { USB_DEVICE(0x0CF3, 0x311D) }, + { USB_DEVICE(0x0CF3, 0x817a) }, { USB_DEVICE(0x13d3, 0x3375) }, + { USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3006) }, { USB_DEVICE(0x04CA, 0x3008) }, @@ -108,6 +109,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, @@ -50,8 +50,8 @@ index 7e351e3..59cde8e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, diff --git a/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch b/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch deleted file mode 100644 index 66e529d72..000000000 --- a/HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 565bd59e8f55b82eb49b58b0972ac41f4448ef06 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 15 Mar 2013 10:31:31 -0400 -Subject: [PATCH] HID: usbhid: quirk for MSI GX680R led panel - -This keyboard backlight device causes a 10 second delay to boot. Add it -to the quirk list with HID_QUIRK_NO_INIT_REPORTS. - -This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=907221 - -Signed-off-by: Josh Boyer ---- - drivers/hid/hid-ids.h | 3 +++ - drivers/hid/usbhid/hid-quirks.c | 1 + - 2 files changed, 4 insertions(+) - -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index d1063e9..c438877 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -590,6 +590,9 @@ - #define USB_VENDOR_ID_MONTEREY 0x0566 - #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 - -+#define USB_VENDOR_ID_MSI 0x1770 -+#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00 -+ - #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 - #define USB_DEVICE_ID_N_S_HARMONY 0xc359 - -diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c -index e991d81..476c984 100644 ---- a/drivers/hid/usbhid/hid-quirks.c -+++ b/drivers/hid/usbhid/hid-quirks.c -@@ -73,6 +73,7 @@ static const struct hid_blacklist { - { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, -+ { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, --- -1.8.1.2 - diff --git a/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch b/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch deleted file mode 100644 index 6bccd6cd1..000000000 --- a/HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 926bb9deb21046248d01e2f6fc86fdbb149b514c Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 15 Mar 2013 10:27:36 -0400 -Subject: [PATCH 1/2] HID: usbhid: quirk for Realtek Multi-card reader - -This device has an odd HID entry and causes a 10 second delay in boot. -Add this device to the quirks list with HID_QUIRK_NO_INIT_REPORTS. - -This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=806587 - -Signed-off-by: Josh Boyer ---- - drivers/hid/hid-ids.h | 3 +++ - drivers/hid/usbhid/hid-quirks.c | 1 + - 2 files changed, 4 insertions(+) - -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 92e47e5..d1063e9 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -684,6 +684,9 @@ - #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 - #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 - -+#define USB_VENDOR_ID_REALTEK 0x0bda -+#define USB_DEVICE_ID_REALTEK_READER 0x0152 -+ - #define USB_VENDOR_ID_ROCCAT 0x1e7d - #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 - #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c -diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c -index e0e6abf..e991d81 100644 ---- a/drivers/hid/usbhid/hid-quirks.c -+++ b/drivers/hid/usbhid/hid-quirks.c -@@ -80,6 +80,7 @@ static const struct hid_blacklist { - { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, -+ { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, --- -1.8.1.2 - diff --git a/kernel.spec b/kernel.spec index 9be42500a..e68c16129 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -768,12 +768,6 @@ Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch -#rhbz 806587 -Patch24115: HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch - -#rhbz 907221 -Patch24116: HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch - #rhbz 920586 Patch25000: amd64_edac_fix_rank_count.patch @@ -1534,12 +1528,6 @@ ApplyPatch 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch #rhbz 920218 ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch -#rhbz 907221 -ApplyPatch HID-usbhid-quirk-for-MSI-GX680R-led-panel.patch - -#rhbz 806587 -ApplyPatch HID-usbhid-quirk-for-Realtek-Multi-card-reader.patch - #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch @@ -2402,6 +2390,9 @@ fi # ||----w | # || || %changelog +* Fri Apr 05 2013 Justin M. Forbes +- Linux v3.8.6 + * Wed Apr 03 2013 Dave Jones - Enable MTD_CHAR/MTD_BLOCK (Needed for SFC) Enable 10gigE on 64-bit only. diff --git a/sources b/sources index 046b4ea88..14c34d719 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -3ac9864bcf512fd71a7ecdd8c9c96d6c patch-3.8.5.xz +f11748a53d4ec0e2dcbfbb64526d6434 patch-3.8.6.xz From 97aee9cc43be1a577160125c70788580fe44ac60 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 8 Apr 2013 09:25:52 -0400 Subject: [PATCH 272/492] Add patch from Benjamin Tissoires to fix race in HID magicmouse (rhbz 908604) --- ...ace-between-input_register-and-probe.patch | 83 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 HID-magicmouse-fix-race-between-input_register-and-probe.patch diff --git a/HID-magicmouse-fix-race-between-input_register-and-probe.patch b/HID-magicmouse-fix-race-between-input_register-and-probe.patch new file mode 100644 index 000000000..87f0ccb1e --- /dev/null +++ b/HID-magicmouse-fix-race-between-input_register-and-probe.patch @@ -0,0 +1,83 @@ +From f1a9a149abc86903e81dd1b2e720f3f89874384b Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Tue, 2 Apr 2013 11:11:52 +0200 +Subject: HID: magicmouse: fix race between input_register() and probe() + +From: Benjamin Tissoires + +commit f1a9a149abc86903e81dd1b2e720f3f89874384b upstream. + +Since kernel 3.7, it appears that the input registration occured before +the end of magicmouse_setup_input(). This is shown by receiving a lot of +"EV_SYN SYN_REPORT 1" instead of normal "EV_SYN SYN_REPORT 0". +This value means that the output buffer is full, and the user space +is loosing events. + +Using .input_configured guarantees that the race is not occuring, and that +the call of "input_set_events_per_packet(input, 60)" is taken into account +by input_register(). + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=908604 + +Reported-and-Tested-By: Clarke Wixon +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-magicmouse.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(stru + return 0; + } + ++static void magicmouse_input_configured(struct hid_device *hdev, ++ struct hid_input *hi) ++ ++{ ++ struct magicmouse_sc *msc = hid_get_drvdata(hdev); ++ ++ int ret = magicmouse_setup_input(msc->input, hdev); ++ if (ret) { ++ hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); ++ /* clean msc->input to notify probe() of the failure */ ++ msc->input = NULL; ++ } ++} ++ ++ + static int magicmouse_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_d + goto err_free; + } + +- /* We do this after hid-input is done parsing reports so that +- * hid-input uses the most natural button and axis IDs. +- */ +- if (msc->input) { +- ret = magicmouse_setup_input(msc->input, hdev); +- if (ret) { +- hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); +- goto err_stop_hw; +- } ++ if (!msc->input) { ++ hid_err(hdev, "magicmouse input not registered\n"); ++ ret = -ENOMEM; ++ goto err_stop_hw; + } + + if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) +@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driv + .remove = magicmouse_remove, + .raw_event = magicmouse_raw_event, + .input_mapping = magicmouse_input_mapping, ++ .input_configured = magicmouse_input_configured, + }; + + static int __init magicmouse_init(void) diff --git a/kernel.spec b/kernel.spec index e68c16129..b6bd13041 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -792,6 +792,9 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 844750 Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#rhbz 908604 +Patch25009: HID-magicmouse-fix-race-between-input_register-and-probe.patch + # END OF PATCH DEFINITIONS %endif @@ -1533,6 +1536,9 @@ ApplyPatch fix-child-thread-introspection.patch ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#rhbz 908604 +ApplyPatch HID-magicmouse-fix-race-between-input_register-and-probe.patch + # END OF PATCH APPLICATIONS %endif @@ -2390,6 +2396,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 08 2013 Josh Boyer +- Add patch from Benjamin Tissoires to fix race in HID magicmouse (rhbz 908604) + * Fri Apr 05 2013 Justin M. Forbes - Linux v3.8.6 From fbcca03d1b93afbced552a2d8f6d6e4b900ff072 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 8 Apr 2013 16:29:39 +0100 Subject: [PATCH 273/492] Enable CMA on ARM tegra, Minor tweeks to ARM OMAP --- config-arm-omap | 15 ++++++++------- config-arm-tegra | 10 ++++++++++ kernel.spec | 4 ++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/config-arm-omap b/config-arm-omap index 6c854036a..cbffc64d5 100644 --- a/config-arm-omap +++ b/config-arm-omap @@ -192,6 +192,9 @@ CONFIG_TWL6030_PWM=m CONFIG_TWL6040_CORE=y CONFIG_SENSORS_TWL4030_MADC=m CONFIG_SENSORS_LIS3_I2C=m +CONFIG_RTC_DRV_OMAP=m +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_TPS65910=m CONFIG_TI_DAVINCI_EMAC=m CONFIG_TI_DAVINCI_MDIO=m CONFIG_TI_DAVINCI_CPDMA=m @@ -295,9 +298,12 @@ CONFIG_RADIO_WL128X=m CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD_OMAP=y -CONFIG_USB_MUSB_OMAP2PLUS=y -CONFIG_USB_MUSB_HDRC=y CONFIG_USB_OHCI_HCD_OMAP3=y +CONFIG_USB_MUSB_OMAP2PLUS=m +CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_GADGET_MUSB_HDRC=m +CONFIG_TWL4030_USB=m +CONFIG_TWL6030_USB=m # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_MUSB_PIO_ONLY is not set @@ -317,11 +323,6 @@ CONFIG_MMC_SPI=y CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y -CONFIG_TWL4030_USB=y -CONFIG_TWL6030_USB=y -CONFIG_RTC_DRV_OMAP=m -CONFIG_RTC_DRV_TWL4030=y -CONFIG_RTC_DRV_TPS65910=m CONFIG_PWM_TIECAP=m CONFIG_PWM_TIEHRPWM=m diff --git a/config-arm-tegra b/config-arm-tegra index 80a15dda4..8b62dedf5 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -94,6 +94,16 @@ CONFIG_NVEC_PAZ00=y CONFIG_PWM_TEGRA=m +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 + CONFIG_DRM_TEGRA=m CONFIG_CPU_PM=y diff --git a/kernel.spec b/kernel.spec index b6bd13041..6bde24e53 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2396,6 +2396,10 @@ fi # ||----w | # || || %changelog +* Mon Apr 8 2013 Peter Robinson +- Enable CMA on ARM tegra +- Minor tweeks to ARM OMAP + * Mon Apr 08 2013 Josh Boyer - Add patch from Benjamin Tissoires to fix race in HID magicmouse (rhbz 908604) From d79c154aba1f91198e89aa5fe8db475a19628c83 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Apr 2013 08:43:44 -0400 Subject: [PATCH 274/492] Backport intel brightness quirk for emachines (rhbz 871932) --- ...rk-to-invert-brightness-on-eMachines.patch | 36 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch diff --git a/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch b/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch new file mode 100644 index 000000000..22e2ac7ae --- /dev/null +++ b/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch @@ -0,0 +1,36 @@ +From 0bc8d69a3bbbb261fdaadd759adbd8e60da72e36 Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Tue, 22 Jan 2013 12:50:35 +0200 +Subject: [PATCH] drm/i915: add quirk to invert brightness on eMachines e725 + +Upstream commit 01e3a8feb40e54b962a20fa7eb595c5efef5e109 + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=31522#c35 +[Note: There are more than one broken setups in the bug. This fixes one.] +Reported-by: Martins +Signed-off-by: Jani Nikula +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_display.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index e6e4df7..6292677 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -8899,6 +8899,12 @@ static struct intel_quirk intel_quirks[] = { + /* Acer Aspire 5734Z must invert backlight brightness */ + { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, + ++ /* Acer/eMachines G725 */ ++ { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, ++ ++ /* Acer/eMachines e725 */ ++ { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, ++ + /* Acer Aspire 4736Z */ + { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, + }; +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 6bde24e53..329d99ecf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -795,6 +795,9 @@ Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #rhbz 908604 Patch25009: HID-magicmouse-fix-race-between-input_register-and-probe.patch +#rhbz 871932 +Patch25010: 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch + # END OF PATCH DEFINITIONS %endif @@ -1539,6 +1542,9 @@ ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #rhbz 908604 ApplyPatch HID-magicmouse-fix-race-between-input_register-and-probe.patch +#rhbz 871932 +ApplyPatch 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch + # END OF PATCH APPLICATIONS %endif @@ -2396,6 +2402,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 09 2013 Josh Boyer +- Backport intel brightness quirk for emachines (rhbz 871932) + * Mon Apr 8 2013 Peter Robinson - Enable CMA on ARM tegra - Minor tweeks to ARM OMAP From e72a53b739897c71f263714a90df601e061c3ccc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Apr 2013 08:56:31 -0400 Subject: [PATCH 275/492] Note CVE-2013-1929 is fixed with 3.8.6 in changelog --- kernel.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel.spec b/kernel.spec index 329d99ecf..4722302b7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2403,6 +2403,7 @@ fi # || || %changelog * Mon Apr 09 2013 Josh Boyer +- CVE-2013-1929 tg3: len overflow in VPD firmware parsing (rhbz 949932 949946) - Backport intel brightness quirk for emachines (rhbz 871932) * Mon Apr 8 2013 Peter Robinson From 7a6889fefdfb020289cb1916041621a8ff869ec1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Apr 2013 13:27:49 -0400 Subject: [PATCH 276/492] Update dmesg_restrict patch to v2 --- ...or-dmesg_restrict-sysctl-on-dev-kmsg.patch | 166 +++++++++++++++--- 1 file changed, 141 insertions(+), 25 deletions(-) diff --git a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch index acaf5f881..c42c8c4f1 100644 --- a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch +++ b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch @@ -1,46 +1,162 @@ -From feaf4959c30d0640093a607c577940d3e9351076 Mon Sep 17 00:00:00 2001 +From ce10d1b72b4da3c98bbbcb1b945687d964c31923 Mon Sep 17 00:00:00 2001 From: Josh Boyer -Date: Fri, 22 Feb 2013 11:47:37 -0500 +Date: Tue, 9 Apr 2013 11:08:13 -0400 Subject: [PATCH] kmsg: Honor dmesg_restrict sysctl on /dev/kmsg -Originally, the addition of the dmesg_restrict covered both the syslog -method of accessing dmesg, as well as /dev/kmsg itself. This was done -indirectly by security_syslog calling cap_syslog before doing any LSM -checks. +The dmesg_restrict sysctl currently covers the syslog method for access +dmesg, however /dev/kmsg isn't covered by the same protections. Most +people haven't noticed because util-linux dmesg(1) defaults to using the +syslog method for access in older versions. With util-linux dmesg(1) +defaults to reading directly from /dev/kmsg. -However, commit 12b3052c3ee (capabilities/syslog: open code cap_syslog -logic to fix build failure) moved the code around and pushed the checks -into the caller itself. That seems to have inadvertently dropped the -checks for dmesg_restrict on /dev/kmsg. Most people haven't noticed -because util-linux dmesg(1) defaults to using the syslog method for -access in older versions. With util-linux 2.22 and a kernel newer than -3.5, dmesg(1) defaults to reading directly from /dev/kmsg. - -Fix this by making an explicit check in the devkmsg_open function. +Fix this by reworking all of the access methods to use the +check_syslog_permissions function and adding checks to devkmsg_open and +devkmsg_read. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=903192 Reported-by: Christian Kujau CC: stable@vger.kernel.org +Signed-off-by: Eric Paris Signed-off-by: Josh Boyer --- - kernel/printk.c | 3 +++ - 1 file changed, 3 insertions(+) + kernel/printk.c | 91 +++++++++++++++++++++++++++++---------------------------- + 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c -index f24633a..398ef9a 100644 +index abbdd9e..5541095 100644 --- a/kernel/printk.c +++ b/kernel/printk.c -@@ -615,6 +615,9 @@ static int devkmsg_open(struct inode *inode, struct file *file) - struct devkmsg_user *user; - int err; +@@ -368,6 +368,46 @@ static void log_store(int facility, int level, + log_next_seq++; + } -+ if (dmesg_restrict && !capable(CAP_SYSLOG)) -+ return -EACCES; ++#ifdef CONFIG_SECURITY_DMESG_RESTRICT ++int dmesg_restrict = 1; ++#else ++int dmesg_restrict; ++#endif + - /* write-only does not need any file context */ ++static int syslog_action_restricted(int type) ++{ ++ if (dmesg_restrict) ++ return 1; ++ /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ ++ return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; ++} ++ ++static int check_syslog_permissions(int type, bool from_file) ++{ ++ /* ++ * If this is from /proc/kmsg and we've already opened it, then we've ++ * already done the capabilities checks at open time. ++ */ ++ if (from_file && type != SYSLOG_ACTION_OPEN) ++ goto ok; ++ ++ if (syslog_action_restricted(type)) { ++ if (capable(CAP_SYSLOG)) ++ goto ok; ++ /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ ++ if (capable(CAP_SYS_ADMIN)) { ++ printk_once(KERN_WARNING "%s (%d): " ++ "Attempt to access syslog with CAP_SYS_ADMIN " ++ "but no CAP_SYSLOG (deprecated).\n", ++ current->comm, task_pid_nr(current)); ++ goto ok; ++ } ++ return -EPERM; ++ } ++ok: ++ return security_syslog(type); ++} ++ + /* /dev/kmsg - userspace message inject/listen interface */ + struct devkmsg_user { + u64 seq; +@@ -443,10 +483,16 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, + char cont = '-'; + size_t len; + ssize_t ret; ++ int err; + + if (!user) + return -EBADF; + ++ err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, ++ SYSLOG_FROM_FILE); ++ if (err) ++ return err; ++ + ret = mutex_lock_interruptible(&user->lock); + if (ret) + return ret; +@@ -624,7 +670,7 @@ static int devkmsg_open(struct inode *inode, struct file *file) if ((file->f_flags & O_ACCMODE) == O_WRONLY) return 0; + +- err = security_syslog(SYSLOG_ACTION_READ_ALL); ++ err = check_syslog_permissions(SYSLOG_ACTION_OPEN, SYSLOG_FROM_FILE); + if (err) + return err; + +@@ -817,45 +863,6 @@ static inline void boot_delay_msec(int level) + } + #endif + +-#ifdef CONFIG_SECURITY_DMESG_RESTRICT +-int dmesg_restrict = 1; +-#else +-int dmesg_restrict; +-#endif +- +-static int syslog_action_restricted(int type) +-{ +- if (dmesg_restrict) +- return 1; +- /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ +- return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; +-} +- +-static int check_syslog_permissions(int type, bool from_file) +-{ +- /* +- * If this is from /proc/kmsg and we've already opened it, then we've +- * already done the capabilities checks at open time. +- */ +- if (from_file && type != SYSLOG_ACTION_OPEN) +- return 0; +- +- if (syslog_action_restricted(type)) { +- if (capable(CAP_SYSLOG)) +- return 0; +- /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ +- if (capable(CAP_SYS_ADMIN)) { +- printk_once(KERN_WARNING "%s (%d): " +- "Attempt to access syslog with CAP_SYS_ADMIN " +- "but no CAP_SYSLOG (deprecated).\n", +- current->comm, task_pid_nr(current)); +- return 0; +- } +- return -EPERM; +- } +- return 0; +-} +- + #if defined(CONFIG_PRINTK_TIME) + static bool printk_time = 1; + #else +@@ -1131,10 +1138,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) + if (error) + goto out; + +- error = security_syslog(type); +- if (error) +- return error; +- + switch (type) { + case SYSLOG_ACTION_CLOSE: /* Close log */ + break; -- -1.8.1.2 +1.8.1.4 From 32c7b91b958eeb95426b48d7aeb682a1856229a3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Apr 2013 15:06:09 -0400 Subject: [PATCH 277/492] Temporarily work around pci device assignment issues (rhbz 908888) --- kernel.spec | 5 +- ...130219.patch => secure-boot-20130409.patch | 130 ++++++++++-------- 2 files changed, 76 insertions(+), 59 deletions(-) rename secure-boot-20130219.patch => secure-boot-20130409.patch (93%) diff --git a/kernel.spec b/kernel.spec index 4722302b7..39cfad646 100644 --- a/kernel.spec +++ b/kernel.spec @@ -670,7 +670,7 @@ Patch540: silence-empty-ipi-mask-warning.patch Patch800: crash-driver.patch # secure boot -Patch1000: secure-boot-20130219.patch +Patch1000: secure-boot-20130409.patch # virt + ksm patches @@ -1428,7 +1428,7 @@ ApplyPatch silence-empty-ipi-mask-warning.patch ApplyPatch crash-driver.patch # secure boot -ApplyPatch secure-boot-20130219.patch +ApplyPatch secure-boot-20130409.patch # Assorted Virt Fixes @@ -2403,6 +2403,7 @@ fi # || || %changelog * Mon Apr 09 2013 Josh Boyer +- Temporarily work around pci device assignment issues (rhbz 908888) - CVE-2013-1929 tg3: len overflow in VPD firmware parsing (rhbz 949932 949946) - Backport intel brightness quirk for emachines (rhbz 871932) diff --git a/secure-boot-20130219.patch b/secure-boot-20130409.patch similarity index 93% rename from secure-boot-20130219.patch rename to secure-boot-20130409.patch index 368cfed17..81b2561e0 100644 --- a/secure-boot-20130219.patch +++ b/secure-boot-20130409.patch @@ -1,4 +1,4 @@ -From 0c5837031a4e996877930fd023a5877dd1d615ba Mon Sep 17 00:00:00 2001 +From 21d9399006e65d7c7cf94c0f4d5378fd450e4d9a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 Subject: [PATCH 01/19] Secure boot: Add new capability @@ -32,10 +32,10 @@ index ba478fa..7109e65 100644 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) -- -1.8.1.2 +1.8.1.4 -From 87c8fddbcb3042fc4174b53763adbf66045a12be Mon Sep 17 00:00:00 2001 +From 2284c2baab55a3d1b70e579974b002ec255713e2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability @@ -65,10 +65,10 @@ index 14d04e6..ed99a2d 100644 { "tun_socket", { COMMON_SOCK_PERMS, "attach_queue", NULL } }, -- -1.8.1.2 +1.8.1.4 -From df14b5319bf3ed2110839e233ac61e6136745be8 Mon Sep 17 00:00:00 2001 +From ad44e5d0bff09944532508591d9eab77dc24455e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will @@ -85,10 +85,10 @@ Signed-off-by: Josh Boyer 2 files changed, 24 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 6c72381..7dffdd5 100644 +index 986614d..cd531ba 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -2654,6 +2654,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -2659,6 +2659,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Note: increases power consumption, thus should only be enabled if running jitter sensitive (HPC/RT) workloads. @@ -131,10 +131,10 @@ index e0573a4..c3f4e3e 100644 * prepare_kernel_cred - Prepare a set of credentials for a kernel service * @daemon: A userspace daemon to be used as a reference -- -1.8.1.2 +1.8.1.4 -From 49c76a665e8a09da48cbe271ea40266ca1a226c0 Mon Sep 17 00:00:00 2001 +From 829b1ec4f2102775b6d60d7ba85c17333e6d4cec Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when @@ -170,10 +170,10 @@ index 199f453..ff651d3 100644 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures 2D0/A00 ALL e820_map E820 memory map table diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index f8fa411..96bd86b 100644 +index c205035..96d859d 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -849,6 +849,36 @@ fail: +@@ -861,6 +861,36 @@ fail: return status; } @@ -210,7 +210,7 @@ index f8fa411..96bd86b 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1143,6 +1173,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1155,6 +1185,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -277,10 +277,10 @@ index 7a9498a..1ae16b6 100644 #ifdef CONFIG_EFI # ifdef CONFIG_X86 -- -1.8.1.2 +1.8.1.4 -From d4d1b3ad3e1a553c807b4ecafcbde4bf816e4db2 Mon Sep 17 00:00:00 2001 +From 980c3259cd54d71e8d20916453b3f90fd710d146 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 Subject: [PATCH 05/19] Add EFI signature data types @@ -332,10 +332,10 @@ index 1ae16b6..de7021d 100644 * All runtime access to EFI goes through this structure: */ -- -1.8.1.2 +1.8.1.4 -From 3cffca89eadf7e0f0a266c370f8034f33723831a Mon Sep 17 00:00:00 2001 +From e381c3c9b22585601a41b2eb616e03107f6bb677 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader. @@ -511,10 +511,10 @@ index de7021d..64b3e55 100644 * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- -1.8.1.2 +1.8.1.4 -From 89ea7424726ae4f7265ab84e703cf2da77acda57 Mon Sep 17 00:00:00 2001 +From 4a6aa76febc26971c3a49ce37d9cab6ed0ee410a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring @@ -620,10 +620,10 @@ index f2970bd..5423195 100644 &key_type_asymmetric, id); if (IS_ERR(key)) -- -1.8.1.2 +1.8.1.4 -From 733a5c25b896d8d5fa0051825a671911b50cb47d Mon Sep 17 00:00:00 2001 +From ffe139eb9b68b1997b25c12123962e5fc79a6666 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot @@ -805,10 +805,10 @@ index 0000000..b9237d7 +} +late_initcall(load_uefi_certs); -- -1.8.1.2 +1.8.1.4 -From 16027d676baed34a9de804dac68d48096a688b39 Mon Sep 17 00:00:00 2001 +From cf1c95fca2c16e4de7b0ae8786c234d48d4bae87 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments @@ -819,41 +819,57 @@ arbitrary kernel behaviour. Default to paranoid - in future we can potentially relax this for sufficiently IOMMU-isolated devices. Signed-off-by: Matthew Garrett + +jwb: Temporarily work around https://bugzilla.redhat.com/show_bug.cgi?id=908888 --- - drivers/pci/pci-sysfs.c | 9 +++++++++ - drivers/pci/proc.c | 8 +++++++- - drivers/pci/syscall.c | 2 +- - 3 files changed, 17 insertions(+), 2 deletions(-) + drivers/pci/pci-sysfs.c | 16 ++++++++++++++++ + drivers/pci/proc.c | 8 +++++++- + drivers/pci/syscall.c | 2 +- + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index 9c6e9bb..b966089 100644 +index 9c6e9bb..09c311e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c -@@ -622,6 +622,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include "pci.h" + + static int sysfs_initialized; /* = 0 */ +@@ -622,6 +623,11 @@ pci_write_config(struct file* filp, struct kobject *kobj, loff_t init_off = off; u8 *data = (u8*) buf; -+ if (!capable(CAP_COMPROMISE_KERNEL)) ++ /* Work around rhbz 908888 for now ++ if (!capable(CAP_COMPROMISE_KERNEL))*/ ++ if (efi_enabled(EFI_SECURE_BOOT)) + return -EPERM; + if (off > dev->cfg_size) return 0; if (off + count > dev->cfg_size) { -@@ -928,6 +931,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +@@ -928,6 +934,11 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, resource_size_t start, end; int i; -+ if (!capable(CAP_COMPROMISE_KERNEL)) ++ /* Work around rhbz 908888 for now ++ if (!capable(CAP_COMPROMISE_KERNEL)) */ ++ if (efi_enabled(EFI_SECURE_BOOT)) + return -EPERM; + for (i = 0; i < PCI_ROM_RESOURCE; i++) if (res == &pdev->resource[i]) break; -@@ -1035,6 +1041,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, +@@ -1035,6 +1046,11 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { -+ if (!capable(CAP_COMPROMISE_KERNEL)) ++ /* Work around rhbz 908888 for now ++ if (!capable(CAP_COMPROMISE_KERNEL)) */ ++ if (efi_enabled(EFI_SECURE_BOOT)) + return -EPERM; + return pci_resource_io(filp, kobj, attr, buf, off, count, true); @@ -906,10 +922,10 @@ index e1c1ec5..97e785f 100644 dev = pci_get_bus_and_slot(bus, dfn); -- -1.8.1.2 +1.8.1.4 -From 9ff1537bbe8c22bbf7f992027da43d4fe8da0860 Mon Sep 17 00:00:00 2001 +From c6ecf3e5233060dcfc972625ef6655c46ced7f71 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot @@ -963,10 +979,10 @@ index c6fa3bc..fc28099 100644 return -EFAULT; while (count-- > 0 && i < 65536) { -- -1.8.1.2 +1.8.1.4 -From 3b27408b1ced1ec83a3ce27f9d51161dbf7cea9a Mon Sep 17 00:00:00 2001 +From 083d92056bae5c74c99a7942deb33f5f59e608a6 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 Subject: [PATCH 11/19] ACPI: Limit access to custom_method @@ -995,10 +1011,10 @@ index 5d42c24..247d58b 100644 /* parse the table header to get the table length */ if (count <= sizeof(struct acpi_table_header)) -- -1.8.1.2 +1.8.1.4 -From fb618a04089d454b7ade68c00a2b9c7dbac013f9 Mon Sep 17 00:00:00 2001 +From 39ac07b200114ac8603388fa7d0eee3cc6e3d5ed Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface @@ -1048,10 +1064,10 @@ index f80ae4d..059195f 100644 1, asus->debug.method_id, &input, &output); -- -1.8.1.2 +1.8.1.4 -From e515bbd5410d00835390fd8981aa9029e7b22b73 Mon Sep 17 00:00:00 2001 +From c3726b30a361079f7121b438326d1c5252a4d805 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups @@ -1089,10 +1105,10 @@ index fc28099..b5df7a8 100644 unsigned long to_write = min_t(unsigned long, count, (unsigned long)high_memory - p); -- -1.8.1.2 +1.8.1.4 -From 19640bebdcabe48ce1789ce7a6a0d0d5b925f0b5 Mon Sep 17 00:00:00 2001 +From 1d9ea90d4d22bf8c5e029d4c31621d793e6f8d13 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -1124,10 +1140,10 @@ index bd22f86..d68c04f 100644 #endif -- -1.8.1.2 +1.8.1.4 -From b9ab9c0b3356d9cde36f3ef3a0719623df2ee2d3 Mon Sep 17 00:00:00 2001 +From 8b40ad15b16627302d4126aba2a6f2e0fb931504 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 15/19] kexec: Disable in a secure boot environment @@ -1156,10 +1172,10 @@ index 5e4bd78..dd464e0 100644 /* -- -1.8.1.2 +1.8.1.4 -From 23e0646e1df8a0b4c31333b71796294801355032 Mon Sep 17 00:00:00 2001 +From 4b01a77b889d37bee6a1e4f547b9bba0050f5e7c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot @@ -1218,10 +1234,10 @@ index eab0827..93a16dc 100644 static int param_set_bool_enable_only(const char *val, const struct kernel_param *kp) -- -1.8.1.2 +1.8.1.4 -From 833c54471c85e70e46d76f9f7ffa30197b9f135d Mon Sep 17 00:00:00 2001 +From f95db0134af575215a14e77f3a29f0037ea9149a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment @@ -1332,10 +1348,10 @@ index 4ed81e7..b11a0f4 100644 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -- -1.8.1.2 +1.8.1.4 -From 1a9afaa05489b817ebe84c61d22e958856aa0737 Mon Sep 17 00:00:00 2001 +From b9d7a7423b330552c89e32d10c9964e6447eadf2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Feb 2013 19:25:05 -0500 Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode @@ -1352,10 +1368,10 @@ Signed-off-by: Josh Boyer 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 96bd86b..6e1331c 100644 +index 96d859d..c9ffd2f 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -851,8 +851,9 @@ fail: +@@ -863,8 +863,9 @@ fail: static int get_secure_boot(efi_system_table_t *_table) { @@ -1366,7 +1382,7 @@ index 96bd86b..6e1331c 100644 efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_status_t status; -@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table) +@@ -888,6 +889,23 @@ static int get_secure_boot(efi_system_table_t *_table) if (setup == 1) return 0; @@ -1391,10 +1407,10 @@ index 96bd86b..6e1331c 100644 } -- -1.8.1.2 +1.8.1.4 -From 763f18d6a1e2d5f4d84ce3382ef91434240c80d6 Mon Sep 17 00:00:00 2001 +From 627b4ba6ba59f095aaea33b1374186506fe2561f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 8 Feb 2013 11:12:13 -0800 Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot @@ -1433,5 +1449,5 @@ index 4929502..adaab3d 100644 err = -EFAULT; break; -- -1.8.1.2 +1.8.1.4 From a9b6a2bb036d0a7ce102414b322207588f8d6645 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Apr 2013 15:19:16 -0400 Subject: [PATCH 278/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 39cfad646..a8a89d01b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2402,7 +2402,7 @@ fi # ||----w | # || || %changelog -* Mon Apr 09 2013 Josh Boyer +* Mon Apr 09 2013 Josh Boyer - 3.8.6-203 - Temporarily work around pci device assignment issues (rhbz 908888) - CVE-2013-1929 tg3: len overflow in VPD firmware parsing (rhbz 949932 949946) - Backport intel brightness quirk for emachines (rhbz 871932) From 3e53792876c05e6ca8b724f8f1bdf8c7ee9fc094 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 11 Apr 2013 08:58:53 -0400 Subject: [PATCH 279/492] Fix ALPS backport patch (rhbz 812111) --- alps.patch => alps-v2.patch | 2913 ++++++++++++++++++++++++----------- kernel.spec | 9 +- 2 files changed, 2007 insertions(+), 915 deletions(-) rename alps.patch => alps-v2.patch (51%) diff --git a/alps.patch b/alps-v2.patch similarity index 51% rename from alps.patch rename to alps-v2.patch index 83d3cfe0a..d394c4a92 100644 --- a/alps.patch +++ b/alps-v2.patch @@ -1,42 +1,139 @@ -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index e229fa3..7b99fc7 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -27,14 +27,11 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ --#define ALPS_V3_X_MAX 2000 --#define ALPS_V3_Y_MAX 1400 -- --#define ALPS_BITMAP_X_BITS 15 --#define ALPS_BITMAP_Y_BITS 11 -- - #define ALPS_CMD_NIBBLE_10 0x01f2 +From f822982515378982dc8d8e6058579288d0ee3cff Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:55:19 -0800 +Subject: [PATCH 01/15] Input: ALPS - document the alps.h data structures + +Add kernel-doc markup. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.h | 74 ++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 61 insertions(+), 13 deletions(-) + +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index ae1ac35..67be4e5 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -17,30 +17,78 @@ + #define ALPS_PROTO_V3 2 + #define ALPS_PROTO_V4 3 -+#define ALPS_REG_BASE_RUSHMORE 0xc2c0 -+#define ALPS_REG_BASE_PINNACLE 0x0000 -+ - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { - { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ - { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -@@ -109,11 +106,14 @@ static const struct alps_model_info alps_model_data[] = { - { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ - { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, ++/** ++ * struct alps_model_info - touchpad ID table ++ * @signature: E7 response string to match. ++ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response ++ * (aka command mode response) identifies the firmware minor version. This ++ * can be used to distinguish different hardware models which are not ++ * uniquely identifiable through their E7 responses. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * ++ * Many (but not all) ALPS touchpads can be identified by looking at the ++ * values returned in the "E7 report" and/or the "EC report." This table ++ * lists a number of such touchpads. ++ */ + struct alps_model_info { +- unsigned char signature[3]; +- unsigned char command_mode_resp; /* v3/v4 only */ ++ unsigned char signature[3]; ++ unsigned char command_mode_resp; + unsigned char proto_version; +- unsigned char byte0, mask0; +- unsigned char flags; ++ unsigned char byte0, mask0; ++ unsigned char flags; }; -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1); -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1); -+ - /* - * XXX - this entry is suspicious. First byte has zero lower nibble, - * which is what a normal mouse would report. Also, the value 0x0e ++/** ++ * struct alps_nibble_commands - encodings for register accesses ++ * @command: PS/2 command used for the nibble ++ * @data: Data supplied as an argument to the PS/2 command, if applicable ++ * ++ * The ALPS protocol uses magic sequences to transmit binary data to the ++ * touchpad, as it is generally not OK to send arbitrary bytes out the ++ * PS/2 port. Each of the sequences in this table sends one nibble of the ++ * register address or (write) data. Different versions of the ALPS protocol ++ * use slightly different encodings. ++ */ + struct alps_nibble_commands { + int command; + unsigned char data; + }; + ++/** ++ * struct alps_data - private data structure for the ALPS driver ++ * @dev2: "Relative" device used to report trackstick or mouse activity. ++ * @phys: Physical path for the relative device. ++ * @i: Information on the detected touchpad model. ++ * @nibble_commands: Command mapping used for touchpad register accesses. ++ * @addr_command: Command used to tell the touchpad that a register address ++ * follows. ++ * @prev_fin: Finger bit from previous packet. ++ * @multi_packet: Multi-packet data in progress. ++ * @multi_data: Saved multi-packet data. ++ * @x1: First X coordinate from last MT report. ++ * @x2: Second X coordinate from last MT report. ++ * @y1: First Y coordinate from last MT report. ++ * @y2: Second Y coordinate from last MT report. ++ * @fingers: Number of fingers from last MT report. ++ * @quirks: Bitmap of ALPS_QUIRK_*. ++ * @timer: Timer for flushing out the final report packet in the stream. ++ */ + struct alps_data { +- struct input_dev *dev2; /* Relative device */ +- char phys[32]; /* Phys */ +- const struct alps_model_info *i;/* Info */ ++ struct input_dev *dev2; ++ char phys[32]; ++ const struct alps_model_info *i; + const struct alps_nibble_commands *nibble_commands; +- int addr_command; /* Command to set register address */ +- int prev_fin; /* Finger bit from previous packet */ +- int multi_packet; /* Multi-packet data in progress */ +- unsigned char multi_data[6]; /* Saved multi-packet data */ +- int x1, x2, y1, y2; /* Coordinates from last MT report */ +- int fingers; /* Number of fingers from MT report */ ++ int addr_command; ++ int prev_fin; ++ int multi_packet; ++ unsigned char multi_data[6]; ++ int x1, x2, y1, y2; ++ int fingers; + u8 quirks; + struct timer_list timer; + }; +-- +1.8.1.2 + + +From 196069863604cb55061a02ad5f046c5e4054ba54 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:56:33 -0800 +Subject: [PATCH 02/15] Input: ALPS - copy "model" info into alps_data struct + +Not every type of ALPS touchpad is well-suited to table-based detection. +Start moving the various alps_model_data attributes into the alps_data +struct so that we don't need a unique table entry for every possible +permutation of protocol version, flags, byte0/mask0, etc. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 63 +++++++++++++++++++++++----------------------- + drivers/input/mouse/alps.h | 14 +++++++++-- + 2 files changed, 43 insertions(+), 34 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index e229fa3..33ee6e0 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c @@ -122,10 +122,10 @@ static const struct alps_model_info alps_model_data[] = { /* Packet formats are described in Documentation/input/alps.txt */ @@ -109,270 +206,18 @@ index e229fa3..7b99fc7 100644 input_report_key(dev, BTN_0, packet[2] & 4); input_report_key(dev, BTN_1, packet[0] & 0x10); input_report_key(dev, BTN_2, packet[3] & 4); -@@ -267,7 +266,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - * These points are returned in x1, y1, x2, and y2 when the return value - * is greater than 0. - */ --static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+static int alps_process_bitmap(struct alps_data *priv, -+ unsigned int x_map, unsigned int y_map, - int *x1, int *y1, int *x2, int *y2) - { - struct alps_bitmap_point { -@@ -309,7 +309,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - * y bitmap is reversed for what we need (lower positions are in - * higher bits), so we process from the top end. - */ -- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); - prev_bit = 0; - point = &y_low; - for (i = 0; y_map != 0; i++, y_map <<= 1) { -@@ -355,16 +355,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - } - } - -- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - - if (fingers > 1) { -- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x2 = (priv->x_max * -+ (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y2 = (priv->y_max * -+ (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - } - - return fingers; -@@ -448,17 +450,57 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - return; - } - -+static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) -+{ -+ f->left = !!(p[3] & 0x01); -+ f->right = !!(p[3] & 0x02); -+ f->middle = !!(p[3] & 0x04); -+ -+ f->ts_left = !!(p[3] & 0x10); -+ f->ts_right = !!(p[3] & 0x20); -+ f->ts_middle = !!(p[3] & 0x40); -+} -+ -+static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) -+{ -+ f->first_mp = !!(p[4] & 0x40); -+ f->is_mp = !!(p[0] & 0x40); -+ -+ f->fingers = (p[5] & 0x3) + 1; -+ f->x_map = ((p[4] & 0x7e) << 8) | -+ ((p[1] & 0x7f) << 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y_map = ((p[3] & 0x70) << 4) | -+ ((p[2] & 0x7f) << 1) | -+ (p[4] & 0x01); -+ -+ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); -+ f->z = p[5] & 0x7f; -+ -+ alps_decode_buttons_v3(f, p); -+} -+ -+static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) -+{ -+ alps_decode_pinnacle(f, p); -+ -+ f->x_map |= (p[5] & 0x10) << 11; -+ f->y_map |= (p[5] & 0x20) << 6; -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -699,9 +698,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + static void alps_process_packet(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; -- int x, y, z; -- int left, right, middle; - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - int fingers = 0, bmap_fingers; -- unsigned int x_bitmap, y_bitmap; -+ struct alps_fields f; -+ -+ priv->decode_fields(&f, packet); - - /* - * There's no single feature of touchpad position and bitmap packets -@@ -473,16 +515,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * packet. Check for this, and when it happens process the - * position packet as usual. - */ -- if (packet[0] & 0x40) { -- fingers = (packet[5] & 0x3) + 1; -- x_bitmap = ((packet[4] & 0x7e) << 8) | -- ((packet[1] & 0x7f) << 2) | -- ((packet[0] & 0x30) >> 4); -- y_bitmap = ((packet[3] & 0x70) << 4) | -- ((packet[2] & 0x7f) << 1) | -- (packet[4] & 0x01); -- -- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ if (f.is_mp) { -+ fingers = f.fingers; -+ bmap_fingers = alps_process_bitmap(priv, -+ f.x_map, f.y_map, - &x1, &y1, &x2, &y2); - - /* -@@ -493,7 +529,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - fingers = bmap_fingers; - - /* Now process position packet */ -- packet = priv->multi_data; -+ priv->decode_fields(&f, priv->multi_data); - } else { - priv->multi_packet = 0; - } -@@ -507,10 +543,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * out misidentified bitmap packets, we reject anything with this - * bit set. - */ -- if (packet[0] & 0x40) -+ if (f.is_mp) - return; - -- if (!priv->multi_packet && (packet[4] & 0x40)) { -+ if (!priv->multi_packet && f.first_mp) { - priv->multi_packet = 1; - memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); - return; -@@ -518,22 +554,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - priv->multi_packet = 0; - -- left = packet[3] & 0x01; -- right = packet[3] & 0x02; -- middle = packet[3] & 0x04; -- -- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -- ((packet[0] & 0x30) >> 4); -- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -- z = packet[5] & 0x7f; -- - /* - * Sometimes the hardware sends a single packet with z = 0 - * in the middle of a stream. Real releases generate packets - * with x, y, and z all zero, so these seem to be flukes. - * Ignore them. - */ -- if (x && y && !z) -+ if (f.x && f.y && !f.z) - return; - - /* -@@ -541,12 +568,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * to rely on ST data. - */ - if (!fingers) { -- x1 = x; -- y1 = y; -- fingers = z > 0 ? 1 : 0; -+ x1 = f.x; -+ y1 = f.y; -+ fingers = f.z > 0 ? 1 : 0; - } - -- if (z >= 64) -+ if (f.z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); -@@ -555,26 +582,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - input_mt_report_finger_count(dev, fingers); - -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -+ input_report_key(dev, BTN_LEFT, f.left); -+ input_report_key(dev, BTN_RIGHT, f.right); -+ input_report_key(dev, BTN_MIDDLE, f.middle); - -- if (z > 0) { -- input_report_abs(dev, ABS_X, x); -- input_report_abs(dev, ABS_Y, y); -+ if (f.z > 0) { -+ input_report_abs(dev, ABS_X, f.x); -+ input_report_abs(dev, ABS_Y, f.y); - } -- input_report_abs(dev, ABS_PRESSURE, z); -+ input_report_abs(dev, ABS_PRESSURE, f.z); - - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -- left = packet[3] & 0x10; -- right = packet[3] & 0x20; -- middle = packet[3] & 0x40; -- -- input_report_key(dev2, BTN_LEFT, left); -- input_report_key(dev2, BTN_RIGHT, right); -- input_report_key(dev2, BTN_MIDDLE, middle); -+ input_report_key(dev2, BTN_LEFT, f.ts_left); -+ input_report_key(dev2, BTN_RIGHT, f.ts_right); -+ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); - input_sync(dev2); - } - } -@@ -639,7 +662,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - ((priv->multi_data[3] & 0x1f) << 5) | - (priv->multi_data[1] & 0x1f); - -- fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* Store MT data.*/ -@@ -696,25 +719,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - input_sync(dev); - } - --static void alps_process_packet(struct psmouse *psmouse) --{ -- struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; -- + - switch (model->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- alps_process_packet_v1_v2(psmouse); -- break; -- case ALPS_PROTO_V3: -- alps_process_packet_v3(psmouse); -- break; -- case ALPS_PROTO_V4: -- alps_process_packet_v4(psmouse); -- break; -- } --} -- - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -765,14 +769,14 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + alps_process_packet_v1_v2(psmouse); +@@ -765,7 +763,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) if (((psmouse->packet[3] | psmouse->packet[4] | psmouse->packet[5]) & 0x80) || @@ -381,32 +226,7 @@ index e229fa3..7b99fc7 100644 psmouse_dbg(psmouse, "refusing packet %4ph (suspected interleaved ps/2)\n", psmouse->packet + 3); - return PSMOUSE_BAD_DATA; - } - -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - - /* Continue with the next packet */ - psmouse->packet[0] = psmouse->packet[6]; -@@ -816,6 +820,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - static void alps_flush_packet(unsigned long data) - { - struct psmouse *psmouse = (struct psmouse *)data; -+ struct alps_data *priv = psmouse->private; - - serio_pause_rx(psmouse->ps2dev.serio); - -@@ -833,7 +838,7 @@ static void alps_flush_packet(unsigned long data) - "refusing packet %3ph (suspected interleaved ps/2)\n", - psmouse->packet + 3); - } else { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - } - psmouse->pktcnt = 0; - } -@@ -844,7 +849,6 @@ static void alps_flush_packet(unsigned long data) +@@ -844,7 +842,6 @@ static void alps_flush_packet(unsigned long data) static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -414,7 +234,7 @@ index e229fa3..7b99fc7 100644 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ if (psmouse->pktcnt == 3) { -@@ -857,15 +861,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -857,15 +854,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ @@ -433,67 +253,181 @@ index e229fa3..7b99fc7 100644 return PSMOUSE_BAD_DATA; } -@@ -879,7 +883,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - } +@@ -1190,16 +1187,16 @@ static int alps_poll(struct psmouse *psmouse) + unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; - if (psmouse->pktcnt == psmouse->pktsize) { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, true); -@@ -967,24 +971,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, - return __alps_command_mode_write_reg(psmouse, value); - } + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; -+static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, -+ int repeated_command, unsigned char *param) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ param[0] = 0; -+ if (init_command && ps2_command(ps2dev, param, init_command)) -+ return -EIO; -+ -+ if (ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command)) -+ return -EIO; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -EIO; -+ -+ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", -+ repeated_command, param[0], param[1], param[2]); -+ return 0; -+} -+ - static int alps_enter_command_mode(struct psmouse *psmouse, - unsigned char *resp) +- if (priv->i->flags & ALPS_PASS) ++ if (priv->flags & ALPS_PASS) + alps_passthrough_mode_v2(psmouse, false); + +- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) ++ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) + return -1; + + if ((psmouse->badbyte & 0xc8) == 0x08) { +@@ -1217,9 +1214,8 @@ static int alps_poll(struct psmouse *psmouse) + static int alps_hw_init_v1_v2(struct psmouse *psmouse) { - unsigned char param[4]; -- struct ps2dev *ps2dev = &psmouse->ps2dev; + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { - psmouse_err(psmouse, "failed to enter command mode\n"); +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } +@@ -1234,7 +1230,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) return -1; } -- if (param[0] != 0x88 && param[1] != 0x07) { -+ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { - psmouse_dbg(psmouse, -- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -- param[0], param[1], param[2]); -+ "unknown response while entering command mode\n"); +- if ((model->flags & ALPS_PASS) && ++ if ((priv->flags & ALPS_PASS) && + alps_passthrough_mode_v2(psmouse, false)) { return -1; } +@@ -1520,10 +1516,9 @@ error: + static int alps_hw_init(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- const struct alps_model_info *model = priv->i; + int ret = -1; -@@ -1001,99 +1023,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + ret = alps_hw_init_v1_v2(psmouse); +@@ -1585,7 +1580,10 @@ int alps_init(struct psmouse *psmouse) + if (!model) + goto init_fail; + +- priv->i = model; ++ priv->proto_version = model->proto_version; ++ priv->byte0 = model->byte0; ++ priv->mask0 = model->mask0; ++ priv->flags = model->flags; + + if (alps_hw_init(psmouse)) + goto init_fail; +@@ -1609,7 +1607,7 @@ int alps_init(struct psmouse *psmouse) + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); + +- switch (model->proto_version) { ++ switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: + input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +@@ -1633,17 +1631,17 @@ int alps_init(struct psmouse *psmouse) + + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + +- if (model->flags & ALPS_WHEEL) { ++ if (priv->flags & ALPS_WHEEL) { + dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); + dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); + } + +- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { ++ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); + dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); + } + +- if (model->flags & ALPS_FOUR_BUTTONS) { ++ if (priv->flags & ALPS_FOUR_BUTTONS) { + dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); + dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); + dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); +@@ -1654,7 +1652,8 @@ int alps_init(struct psmouse *psmouse) + + snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); + dev2->phys = priv->phys; +- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; ++ dev2->name = (priv->flags & ALPS_DUALPOINT) ? ++ "DualPoint Stick" : "PS/2 Mouse"; + dev2->id.bustype = BUS_I8042; + dev2->id.vendor = 0x0002; + dev2->id.product = PSMOUSE_ALPS; +@@ -1673,7 +1672,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; ++ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 67be4e5..efd0eea 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -63,10 +63,15 @@ struct alps_nibble_commands { + * struct alps_data - private data structure for the ALPS driver + * @dev2: "Relative" device used to report trackstick or mouse activity. + * @phys: Physical path for the relative device. +- * @i: Information on the detected touchpad model. + * @nibble_commands: Command mapping used for touchpad register accesses. + * @addr_command: Command used to tell the touchpad that a register address + * follows. ++ * @proto_version: Indicates V1/V2/V3/... ++ * @byte0: Helps figure out whether a position report packet matches the ++ * known format for this model. The first byte of the report, ANDed with ++ * mask0, should match byte0. ++ * @mask0: The mask used to check the first byte of the report. ++ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. + * @multi_data: Saved multi-packet data. +@@ -81,9 +86,14 @@ struct alps_nibble_commands { + struct alps_data { + struct input_dev *dev2; + char phys[32]; +- const struct alps_model_info *i; ++ ++ /* these are autodetected when the device is identified */ + const struct alps_nibble_commands *nibble_commands; + int addr_command; ++ unsigned char proto_version; ++ unsigned char byte0, mask0; ++ unsigned char flags; ++ + int prev_fin; + int multi_packet; + unsigned char multi_data[6]; +-- +1.8.1.2 + + +From b856c913996a38ced60bdf41aeae4da00882bf1f Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 20:57:04 -0800 +Subject: [PATCH 03/15] Input: ALPS - move alps_get_model() down below hw_init + code + +This will minimize the number of forward declarations needed when +alps_get_model() starts assigning function pointers. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 186 ++++++++++++++++++++++----------------------- + 1 file changed, 93 insertions(+), 93 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 33ee6e0..c473549 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -998,99 +998,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) return 0; } @@ -593,7 +527,182 @@ index e229fa3..7b99fc7 100644 /* * For DualPoint devices select the device that should respond to * subsequent commands. It looks like glidepad is behind stickpointer, -@@ -1137,18 +1066,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) +@@ -1534,6 +1441,99 @@ static int alps_hw_init(struct psmouse *psmouse) + return ret; + } + ++static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; ++ unsigned char param[4]; ++ const struct alps_model_info *model = NULL; ++ int i; ++ ++ /* ++ * First try "E6 report". ++ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. ++ * The bits 0-2 of the first byte will be 1s if some buttons are ++ * pressed. ++ */ ++ param[0] = 0; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) ++ return NULL; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return NULL; ++ ++ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", ++ param[0], param[1], param[2]); ++ ++ if ((param[0] & 0xf8) != 0 || param[1] != 0 || ++ (param[2] != 10 && param[2] != 100)) ++ return NULL; ++ ++ /* ++ * Now try "E7 report". Allowed responses are in ++ * alps_model_data[].signature ++ */ ++ param[0] = 0; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) ++ return NULL; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return NULL; ++ ++ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", ++ param[0], param[1], param[2]); ++ ++ if (version) { ++ for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) ++ /* empty */; ++ *version = (param[0] << 8) | (param[1] << 4) | i; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (!memcmp(param, alps_model_data[i].signature, ++ sizeof(alps_model_data[i].signature))) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ ++ if (model && model->proto_version > ALPS_PROTO_V2) { ++ /* ++ * Need to check command mode response to identify ++ * model ++ */ ++ model = NULL; ++ if (alps_enter_command_mode(psmouse, param)) { ++ psmouse_warn(psmouse, ++ "touchpad failed to enter command mode\n"); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && ++ alps_model_data[i].command_mode_resp == param[0]) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ alps_exit_command_mode(psmouse); ++ ++ if (!model) ++ psmouse_dbg(psmouse, ++ "Unknown command mode response %2.2x\n", ++ param[0]); ++ } ++ } ++ ++ return model; ++} ++ + static int alps_reconnect(struct psmouse *psmouse) + { + const struct alps_model_info *model; +-- +1.8.1.2 + + +From b719d56d5743e2c338568f4edb6eab17ea9c9eec Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:19:01 -0800 +Subject: [PATCH 04/15] Input: ALPS - introduce helper function for repeated + commands + +Several ALPS driver init sequences repeat a command three times, then +issue PSMOUSE_CMD_GETINFO to read the result. Move this into a helper +function to simplify the code. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 71 ++++++++++++++++++++-------------------------- + 1 file changed, 30 insertions(+), 41 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index c473549..1ca854b 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -964,24 +964,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, + return __alps_command_mode_write_reg(psmouse, value); + } + ++static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, ++ int repeated_command, unsigned char *param) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ param[0] = 0; ++ if (init_command && ps2_command(ps2dev, param, init_command)) ++ return -EIO; ++ ++ if (ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command) || ++ ps2_command(ps2dev, NULL, repeated_command)) ++ return -EIO; ++ ++ param[0] = param[1] = param[2] = 0xff; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -EIO; ++ ++ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", ++ repeated_command, param[0], param[1], param[2]); ++ return 0; ++} ++ + static int alps_enter_command_mode(struct psmouse *psmouse, + unsigned char *resp) + { + unsigned char param[4]; +- struct ps2dev *ps2dev = &psmouse->ps2dev; + +- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || +- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { + psmouse_err(psmouse, "failed to enter command mode\n"); + return -1; + } + + if (param[0] != 0x88 && param[1] != 0x07) { + psmouse_dbg(psmouse, +- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", +- param[0], param[1], param[2]); ++ "unknown response while entering command mode\n"); + return -1; + } + +@@ -1041,18 +1059,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) static int alps_get_status(struct psmouse *psmouse, char *param) { @@ -613,47 +722,1273 @@ index e229fa3..7b99fc7 100644 return 0; } -@@ -1190,16 +1111,16 @@ static int alps_poll(struct psmouse *psmouse) - unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; +@@ -1443,7 +1453,6 @@ static int alps_hw_init(struct psmouse *psmouse) -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, true); + static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) + { +- struct ps2dev *ps2dev = &psmouse->ps2dev; + static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; + unsigned char param[4]; + const struct alps_model_info *model = NULL; +@@ -1455,20 +1464,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * The bits 0-2 of the first byte will be 1s if some buttons are + * pressed. + */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, ++ param)) + return NULL; - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; +- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- + if ((param[0] & 0xf8) != 0 || param[1] != 0 || + (param[2] != 10 && param[2] != 100)) + return NULL; +@@ -1477,20 +1476,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * Now try "E7 report". Allowed responses are in + * alps_model_data[].signature + */ +- param[0] = 0; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || +- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) +- return NULL; +- +- param[0] = param[1] = param[2] = 0xff; +- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, ++ param)) + return NULL; -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, false); +- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", +- param[0], param[1], param[2]); +- + if (version) { + for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) + /* empty */; +-- +1.8.1.2 + + +From c7fd5d0e90f577072ece70651aeecb37f62f5fdb Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:19:59 -0800 +Subject: [PATCH 05/15] Input: ALPS - rework detection sequence + +If the E6 report test passes, get the E7 and EC reports right away and +then try to match an entry in the table. + +Pass in the alps_data struct, so that the detection code will be able to +set operating parameters based on information found during detection. + +Change the version (psmouse->model) to report the protocol version only, +in preparation for supporting models that do not show up in the ID table. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 124 +++++++++++++++++++-------------------------- + drivers/input/mouse/alps.h | 8 +-- + 2 files changed, 56 insertions(+), 76 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 1ca854b..e6a27a5 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1451,86 +1451,76 @@ static int alps_hw_init(struct psmouse *psmouse) + return ret; + } -- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) -+ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) +-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) ++static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, ++ unsigned char *e7, unsigned char *ec) + { +- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; +- unsigned char param[4]; +- const struct alps_model_info *model = NULL; ++ const struct alps_model_info *model; + int i; + ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ model = &alps_model_data[i]; ++ ++ if (!memcmp(e7, model->signature, sizeof(model->signature)) && ++ (!model->command_mode_resp || ++ model->command_mode_resp == ec[2])) { ++ ++ priv->proto_version = model->proto_version; ++ priv->flags = model->flags; ++ priv->byte0 = model->byte0; ++ priv->mask0 = model->mask0; ++ ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ++{ ++ unsigned char e6[4], e7[4], ec[4]; ++ + /* + * First try "E6 report". + * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. + * The bits 0-2 of the first byte will be 1s if some buttons are + * pressed. + */ +- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, +- param)) +- return NULL; ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE11, e6)) ++ return -EIO; + +- if ((param[0] & 0xf8) != 0 || param[1] != 0 || +- (param[2] != 10 && param[2] != 100)) +- return NULL; ++ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) ++ return -EINVAL; + + /* +- * Now try "E7 report". Allowed responses are in +- * alps_model_data[].signature ++ * Now get the "E7" and "EC" reports. These will uniquely identify ++ * most ALPS touchpads. + */ +- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, +- param)) +- return NULL; +- +- if (version) { +- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) +- /* empty */; +- *version = (param[0] << 8) | (param[1] << 4) | i; +- } +- +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) { +- model = alps_model_data + i; +- break; +- } +- } ++ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_SETSCALE21, e7) || ++ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, ++ PSMOUSE_CMD_RESET_WRAP, ec) || ++ alps_exit_command_mode(psmouse)) ++ return -EIO; + +- if (model && model->proto_version > ALPS_PROTO_V2) { +- /* +- * Need to check command mode response to identify +- * model +- */ +- model = NULL; +- if (alps_enter_command_mode(psmouse, param)) { +- psmouse_warn(psmouse, +- "touchpad failed to enter command mode\n"); +- } else { +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { +- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && +- alps_model_data[i].command_mode_resp == param[0]) { +- model = alps_model_data + i; +- break; +- } +- } +- alps_exit_command_mode(psmouse); ++ if (alps_match_table(psmouse, priv, e7, ec) == 0) ++ return 0; + +- if (!model) +- psmouse_dbg(psmouse, +- "Unknown command mode response %2.2x\n", +- param[0]); +- } +- } ++ psmouse_info(psmouse, ++ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", ++ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); + +- return model; ++ return -EINVAL; + } + + static int alps_reconnect(struct psmouse *psmouse) + { +- const struct alps_model_info *model; ++ struct alps_data *priv = psmouse->private; + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, NULL); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) return -1; - if ((psmouse->badbyte & 0xc8) == 0x08) { -@@ -1217,9 +1138,8 @@ static int alps_poll(struct psmouse *psmouse) - static int alps_hw_init_v1_v2(struct psmouse *psmouse) + return alps_hw_init(psmouse); +@@ -1549,9 +1539,7 @@ static void alps_disconnect(struct psmouse *psmouse) + int alps_init(struct psmouse *psmouse) + { + struct alps_data *priv; +- const struct alps_model_info *model; + struct input_dev *dev1 = psmouse->dev, *dev2; +- int version; + + priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + dev2 = input_allocate_device(); +@@ -1565,15 +1553,9 @@ int alps_init(struct psmouse *psmouse) + + psmouse_reset(psmouse); + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, priv) < 0) + goto init_fail; + +- priv->proto_version = model->proto_version; +- priv->byte0 = model->byte0; +- priv->mask0 = model->mask0; +- priv->flags = model->flags; +- + if (alps_hw_init(psmouse)) + goto init_fail; + +@@ -1678,18 +1660,16 @@ init_fail: + + int alps_detect(struct psmouse *psmouse, bool set_properties) + { +- int version; +- const struct alps_model_info *model; ++ struct alps_data dummy; + +- model = alps_get_model(psmouse, &version); +- if (!model) ++ if (alps_identify(psmouse, &dummy) < 0) + return -1; + + if (set_properties) { + psmouse->vendor = "ALPS"; +- psmouse->name = model->flags & ALPS_DUALPOINT ? ++ psmouse->name = dummy.flags & ALPS_DUALPOINT ? + "DualPoint TouchPad" : "GlidePoint"; +- psmouse->model = version; ++ psmouse->model = dummy.proto_version << 8; + } + return 0; + } +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index efd0eea..a81b318 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -12,10 +12,10 @@ + #ifndef _ALPS_H + #define _ALPS_H + +-#define ALPS_PROTO_V1 0 +-#define ALPS_PROTO_V2 1 +-#define ALPS_PROTO_V3 2 +-#define ALPS_PROTO_V4 3 ++#define ALPS_PROTO_V1 1 ++#define ALPS_PROTO_V2 2 ++#define ALPS_PROTO_V3 3 ++#define ALPS_PROTO_V4 4 + + /** + * struct alps_model_info - touchpad ID table +-- +1.8.1.2 + + +From c7fb8a63ba1257e2ee829425ef7197c7cbe893a1 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:22:08 -0800 +Subject: [PATCH 06/15] Input: ALPS - use function pointers for different + protocol handlers + +In anticipation of adding more ALPS protocols and more per-device quirks, +use function pointers instead of switch statements to call functions that +differ from one device to the next. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 101 +++++++++++++++++++++------------------------ + drivers/input/mouse/alps.h | 7 ++++ + 2 files changed, 54 insertions(+), 54 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index e6a27a5..fe45687 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -114,6 +114,11 @@ static const struct alps_model_info alps_model_data[] = { + { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1); ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1); ++ + /* + * XXX - this entry is suspicious. First byte has zero lower nibble, + * which is what a normal mouse would report. Also, the value 0x0e +@@ -695,24 +700,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + input_sync(dev); + } + +-static void alps_process_packet(struct psmouse *psmouse) +-{ +- struct alps_data *priv = psmouse->private; +- +- switch (priv->proto_version) { +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- alps_process_packet_v1_v2(psmouse); +- break; +- case ALPS_PROTO_V3: +- alps_process_packet_v3(psmouse); +- break; +- case ALPS_PROTO_V4: +- alps_process_packet_v4(psmouse); +- break; +- } +-} +- + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -770,7 +757,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + + /* Continue with the next packet */ + psmouse->packet[0] = psmouse->packet[6]; +@@ -814,6 +801,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) + static void alps_flush_packet(unsigned long data) + { + struct psmouse *psmouse = (struct psmouse *)data; ++ struct alps_data *priv = psmouse->private; + + serio_pause_rx(psmouse->ps2dev.serio); + +@@ -831,7 +819,7 @@ static void alps_flush_packet(unsigned long data) + "refusing packet %3ph (suspected interleaved ps/2)\n", + psmouse->packet + 3); + } else { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + } + psmouse->pktcnt = 0; + } +@@ -876,7 +864,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + if (psmouse->pktcnt == psmouse->pktsize) { +- alps_process_packet(psmouse); ++ priv->process_packet(psmouse); + return PSMOUSE_FULL_PACKET; + } + +@@ -1430,25 +1418,26 @@ error: + return -1; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static void alps_set_defaults(struct alps_data *priv) + { +- struct alps_data *priv = psmouse->private; +- int ret = -1; +- + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +- ret = alps_hw_init_v1_v2(psmouse); ++ priv->hw_init = alps_hw_init_v1_v2; ++ priv->process_packet = alps_process_packet_v1_v2; ++ priv->set_abs_params = alps_set_abs_params_st; + break; + case ALPS_PROTO_V3: +- ret = alps_hw_init_v3(psmouse); ++ priv->hw_init = alps_hw_init_v3; ++ priv->process_packet = alps_process_packet_v3; ++ priv->set_abs_params = alps_set_abs_params_mt; + break; + case ALPS_PROTO_V4: +- ret = alps_hw_init_v4(psmouse); ++ priv->hw_init = alps_hw_init_v4; ++ priv->process_packet = alps_process_packet_v4; ++ priv->set_abs_params = alps_set_abs_params_mt; + break; + } +- +- return ret; + } + + static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, +@@ -1465,6 +1454,8 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, + model->command_mode_resp == ec[2])) { + + priv->proto_version = model->proto_version; ++ alps_set_defaults(priv); ++ + priv->flags = model->flags; + priv->byte0 = model->byte0; + priv->mask0 = model->mask0; +@@ -1523,7 +1514,7 @@ static int alps_reconnect(struct psmouse *psmouse) + if (alps_identify(psmouse, priv) < 0) + return -1; + +- return alps_hw_init(psmouse); ++ return priv->hw_init(psmouse); + } + + static void alps_disconnect(struct psmouse *psmouse) +@@ -1536,6 +1527,29 @@ static void alps_disconnect(struct psmouse *psmouse) + kfree(priv); + } + ++static void alps_set_abs_params_st(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++} ++ ++static void alps_set_abs_params_mt(struct alps_data *priv, ++ struct input_dev *dev1) ++{ ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ ++ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++} ++ + int alps_init(struct psmouse *psmouse) + { + struct alps_data *priv; +@@ -1556,7 +1570,7 @@ int alps_init(struct psmouse *psmouse) + if (alps_identify(psmouse, priv) < 0) + goto init_fail; + +- if (alps_hw_init(psmouse)) ++ if (priv->hw_init(psmouse)) + goto init_fail; + + /* +@@ -1578,28 +1592,7 @@ int alps_init(struct psmouse *psmouse) + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); + +- switch (priv->proto_version) { +- case ALPS_PROTO_V1: +- case ALPS_PROTO_V2: +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); +- break; +- case ALPS_PROTO_V3: +- case ALPS_PROTO_V4: +- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); +- input_mt_init_slots(dev1, 2, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- +- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); +- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); +- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); +- +- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); +- break; +- } +- ++ priv->set_abs_params(priv, dev1); + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + + if (priv->flags & ALPS_WHEEL) { +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index a81b318..0934f8b 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -72,6 +72,9 @@ struct alps_nibble_commands { + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * @hw_init: Protocol-specific hardware init function. ++ * @process_packet: Protocol-specific function to process a report packet. ++ * @set_abs_params: Protocol-specific function to configure the input_dev. + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. + * @multi_data: Saved multi-packet data. +@@ -94,6 +97,10 @@ struct alps_data { + unsigned char byte0, mask0; + unsigned char flags; + ++ int (*hw_init)(struct psmouse *psmouse); ++ void (*process_packet)(struct psmouse *psmouse); ++ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); ++ + int prev_fin; + int multi_packet; + unsigned char multi_data[6]; +-- +1.8.1.2 + + +From e2600c708bef8e1c8126ca9b8d4ce1f83c002688 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:23:04 -0800 +Subject: [PATCH 07/15] Input: ALPS - move {addr,nibble}_command settings into + alps_set_defaults() + +This allows alps_identify() to override these settings based on the +device characteristics, if it is ever necessary. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index fe45687..2221a00 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1190,14 +1190,10 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) + + static int alps_hw_init_v3(struct psmouse *psmouse) + { +- struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val; + unsigned char param[4]; + +- priv->nibble_commands = alps_v3_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; +- + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +@@ -1343,13 +1339,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) + + static int alps_hw_init_v4(struct psmouse *psmouse) + { +- struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + +- priv->nibble_commands = alps_v4_nibble_commands; +- priv->addr_command = PSMOUSE_CMD_DISABLE; +- + if (alps_enter_command_mode(psmouse, NULL)) + goto error; + +@@ -1431,11 +1423,15 @@ static void alps_set_defaults(struct alps_data *priv) + priv->hw_init = alps_hw_init_v3; + priv->process_packet = alps_process_packet_v3; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + break; + case ALPS_PROTO_V4: + priv->hw_init = alps_hw_init_v4; + priv->process_packet = alps_process_packet_v4; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; + break; + } + } +-- +1.8.1.2 + + +From df0bf385112a7b38c5c3d307bb9399f9f3b3bba2 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:23:34 -0800 +Subject: [PATCH 08/15] Input: ALPS - rework detection of Pinnacle AGx + touchpads + +The official ALPS driver uses the EC report, not the E7 report, to detect +these devices. Also, they check for a range of values; the original +table-based code only checked for two specific ones. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 2221a00..eafeae2 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -109,8 +109,6 @@ static const struct alps_model_info alps_model_data[] = { + { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ +- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, +- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, + { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + +@@ -1412,6 +1410,10 @@ error: + + static void alps_set_defaults(struct alps_data *priv) + { ++ priv->byte0 = 0x8f; ++ priv->mask0 = 0x8f; ++ priv->flags = ALPS_DUALPOINT; ++ + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +@@ -1491,8 +1493,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + alps_exit_command_mode(psmouse)) + return -EIO; + +- if (alps_match_table(psmouse, priv, e7, ec) == 0) ++ if (alps_match_table(psmouse, priv, e7, ec) == 0) { ++ return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x07 && ++ ec[2] >= 0x90 && ec[2] <= 0x9d) { ++ priv->proto_version = ALPS_PROTO_V3; ++ alps_set_defaults(priv); ++ + return 0; ++ } + + psmouse_info(psmouse, + "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", +-- +1.8.1.2 + + +From 8e6493f800dc08a28abd59dfe63790aaade0c700 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:24:22 -0800 +Subject: [PATCH 09/15] Input: ALPS - fix command mode check + +Pinnacle class devices should return "88 07 xx" or "88 08 xx" when +entering command mode. If either the first byte or the second byte is +invalid, return an error. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index eafeae2..bfc1938 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -983,7 +983,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + return -1; + } + +- if (param[0] != 0x88 && param[1] != 0x07) { ++ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { + psmouse_dbg(psmouse, + "unknown response while entering command mode\n"); + return -1; +-- +1.8.1.2 + + +From 0302b4c4a1b4201bf82a45c46084f3ccd0ee696f Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:24:55 -0800 +Subject: [PATCH 10/15] Input: ALPS - move pixel and bitmap info into alps_data + struct + +Newer touchpads use different constants, so make them runtime- +configurable. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 47 ++++++++++++++++++++++++---------------------- + drivers/input/mouse/alps.h | 8 ++++++++ + 2 files changed, 33 insertions(+), 22 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index bfc1938..2cd8be7 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -27,12 +27,6 @@ + /* + * Definitions for ALPS version 3 and 4 command mode protocol + */ +-#define ALPS_V3_X_MAX 2000 +-#define ALPS_V3_Y_MAX 1400 +- +-#define ALPS_BITMAP_X_BITS 15 +-#define ALPS_BITMAP_Y_BITS 11 +- + #define ALPS_CMD_NIBBLE_10 0x01f2 + + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { +@@ -269,7 +263,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + * These points are returned in x1, y1, x2, and y2 when the return value + * is greater than 0. + */ +-static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++static int alps_process_bitmap(struct alps_data *priv, ++ unsigned int x_map, unsigned int y_map, + int *x1, int *y1, int *x2, int *y2) + { + struct alps_bitmap_point { +@@ -311,7 +306,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + * y bitmap is reversed for what we need (lower positions are in + * higher bits), so we process from the top end. + */ +- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); + prev_bit = 0; + point = &y_low; + for (i = 0; y_map != 0; i++, y_map <<= 1) { +@@ -357,16 +352,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, + } + } + +- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + + if (fingers > 1) { +- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_X_BITS - 1)); +- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / +- (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ *x2 = (priv->x_max * ++ (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (priv->x_bits - 1)); ++ *y2 = (priv->y_max * ++ (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (priv->y_bits - 1)); + } + + return fingers; +@@ -484,7 +481,8 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + ((packet[2] & 0x7f) << 1) | + (packet[4] & 0x01); + +- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ bmap_fingers = alps_process_bitmap(priv, ++ x_bitmap, y_bitmap, + &x1, &y1, &x2, &y2); + + /* +@@ -641,7 +639,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) + ((priv->multi_data[3] & 0x1f) << 5) | + (priv->multi_data[1] & 0x1f); + +- fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, + &x1, &y1, &x2, &y2); + + /* Store MT data.*/ +@@ -1414,6 +1412,11 @@ static void alps_set_defaults(struct alps_data *priv) + priv->mask0 = 0x8f; + priv->flags = ALPS_DUALPOINT; + ++ priv->x_max = 2000; ++ priv->y_max = 1400; ++ priv->x_bits = 15; ++ priv->y_bits = 11; ++ + switch (priv->proto_version) { + case ALPS_PROTO_V1: + case ALPS_PROTO_V2: +@@ -1544,15 +1547,15 @@ static void alps_set_abs_params_mt(struct alps_data *priv, + { + set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); + input_mt_init_slots(dev1, 2, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); + + set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); + set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); + set_bit(BTN_TOOL_QUADTAP, dev1->keybit); + +- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); + } + + int alps_init(struct psmouse *psmouse) +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 0934f8b..5e638be 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -72,6 +72,10 @@ struct alps_nibble_commands { + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). ++ * @x_max: Largest possible X position value. ++ * @y_max: Largest possible Y position value. ++ * @x_bits: Number of X bits in the MT bitmap. ++ * @y_bits: Number of Y bits in the MT bitmap. + * @hw_init: Protocol-specific hardware init function. + * @process_packet: Protocol-specific function to process a report packet. + * @set_abs_params: Protocol-specific function to configure the input_dev. +@@ -96,6 +100,10 @@ struct alps_data { + unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; ++ int x_max; ++ int y_max; ++ int x_bits; ++ int y_bits; + + int (*hw_init)(struct psmouse *psmouse); + void (*process_packet)(struct psmouse *psmouse); +-- +1.8.1.2 + + +From 3c9d054fef84ccc967445b330ab6012c6b6bd85b Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:26:11 -0800 +Subject: [PATCH 11/15] Input: ALPS - make the V3 packet field decoder + "pluggable" + +A number of different ALPS touchpad protocols can reuse +alps_process_touchpad_packet_v3() with small tweaks to the bitfield +decoding. Create a new priv->decode_fields() callback that handles the +per-model differences. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 101 +++++++++++++++++++++++++-------------------- + drivers/input/mouse/alps.h | 38 +++++++++++++++++ + 2 files changed, 95 insertions(+), 44 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 2cd8be7..270b7de 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -447,17 +447,49 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + return; + } + ++static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) ++{ ++ f->left = !!(p[3] & 0x01); ++ f->right = !!(p[3] & 0x02); ++ f->middle = !!(p[3] & 0x04); ++ ++ f->ts_left = !!(p[3] & 0x10); ++ f->ts_right = !!(p[3] & 0x20); ++ f->ts_middle = !!(p[3] & 0x40); ++} ++ ++static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) ++{ ++ f->first_mp = !!(p[4] & 0x40); ++ f->is_mp = !!(p[0] & 0x40); ++ ++ f->fingers = (p[5] & 0x3) + 1; ++ f->x_map = ((p[4] & 0x7e) << 8) | ++ ((p[1] & 0x7f) << 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y_map = ((p[3] & 0x70) << 4) | ++ ((p[2] & 0x7f) << 1) | ++ (p[4] & 0x01); ++ ++ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | ++ ((p[0] & 0x30) >> 4); ++ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); ++ f->z = p[5] & 0x7f; ++ ++ alps_decode_buttons_v3(f, p); ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + struct input_dev *dev2 = priv->dev2; +- int x, y, z; +- int left, right, middle; + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + int fingers = 0, bmap_fingers; +- unsigned int x_bitmap, y_bitmap; ++ struct alps_fields f; ++ ++ priv->decode_fields(&f, packet); -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } -@@ -1234,7 +1154,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) - return -1; + /* + * There's no single feature of touchpad position and bitmap packets +@@ -472,17 +504,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * packet. Check for this, and when it happens process the + * position packet as usual. + */ +- if (packet[0] & 0x40) { +- fingers = (packet[5] & 0x3) + 1; +- x_bitmap = ((packet[4] & 0x7e) << 8) | +- ((packet[1] & 0x7f) << 2) | +- ((packet[0] & 0x30) >> 4); +- y_bitmap = ((packet[3] & 0x70) << 4) | +- ((packet[2] & 0x7f) << 1) | +- (packet[4] & 0x01); +- ++ if (f.is_mp) { ++ fingers = f.fingers; + bmap_fingers = alps_process_bitmap(priv, +- x_bitmap, y_bitmap, ++ f.x_map, f.y_map, + &x1, &y1, &x2, &y2); + + /* +@@ -493,7 +518,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + fingers = bmap_fingers; + + /* Now process position packet */ +- packet = priv->multi_data; ++ priv->decode_fields(&f, priv->multi_data); + } else { + priv->multi_packet = 0; + } +@@ -507,10 +532,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * out misidentified bitmap packets, we reject anything with this + * bit set. + */ +- if (packet[0] & 0x40) ++ if (f.is_mp) + return; + +- if (!priv->multi_packet && (packet[4] & 0x40)) { ++ if (!priv->multi_packet && f.first_mp) { + priv->multi_packet = 1; + memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); + return; +@@ -518,22 +543,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + priv->multi_packet = 0; + +- left = packet[3] & 0x01; +- right = packet[3] & 0x02; +- middle = packet[3] & 0x04; +- +- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | +- ((packet[0] & 0x30) >> 4); +- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); +- z = packet[5] & 0x7f; +- + /* + * Sometimes the hardware sends a single packet with z = 0 + * in the middle of a stream. Real releases generate packets + * with x, y, and z all zero, so these seem to be flukes. + * Ignore them. + */ +- if (x && y && !z) ++ if (f.x && f.y && !f.z) + return; + + /* +@@ -541,12 +557,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * to rely on ST data. + */ + if (!fingers) { +- x1 = x; +- y1 = y; +- fingers = z > 0 ? 1 : 0; ++ x1 = f.x; ++ y1 = f.y; ++ fingers = f.z > 0 ? 1 : 0; } -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, false)) { - return -1; +- if (z >= 64) ++ if (f.z >= 64) + input_report_key(dev, BTN_TOUCH, 1); + else + input_report_key(dev, BTN_TOUCH, 0); +@@ -555,26 +571,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + + input_mt_report_finger_count(dev, fingers); + +- input_report_key(dev, BTN_LEFT, left); +- input_report_key(dev, BTN_RIGHT, right); +- input_report_key(dev, BTN_MIDDLE, middle); ++ input_report_key(dev, BTN_LEFT, f.left); ++ input_report_key(dev, BTN_RIGHT, f.right); ++ input_report_key(dev, BTN_MIDDLE, f.middle); + +- if (z > 0) { +- input_report_abs(dev, ABS_X, x); +- input_report_abs(dev, ABS_Y, y); ++ if (f.z > 0) { ++ input_report_abs(dev, ABS_X, f.x); ++ input_report_abs(dev, ABS_Y, f.y); } -@@ -1249,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) +- input_report_abs(dev, ABS_PRESSURE, z); ++ input_report_abs(dev, ABS_PRESSURE, f.z); + + input_sync(dev); + + if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { +- left = packet[3] & 0x10; +- right = packet[3] & 0x20; +- middle = packet[3] & 0x40; +- +- input_report_key(dev2, BTN_LEFT, left); +- input_report_key(dev2, BTN_RIGHT, right); +- input_report_key(dev2, BTN_MIDDLE, middle); ++ input_report_key(dev2, BTN_LEFT, f.ts_left); ++ input_report_key(dev2, BTN_RIGHT, f.ts_right); ++ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); + input_sync(dev2); + } + } +@@ -1428,6 +1440,7 @@ static void alps_set_defaults(struct alps_data *priv) + priv->hw_init = alps_hw_init_v3; + priv->process_packet = alps_process_packet_v3; + priv->set_abs_params = alps_set_abs_params_mt; ++ priv->decode_fields = alps_decode_pinnacle; + priv->nibble_commands = alps_v3_nibble_commands; + priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + break; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 5e638be..9704805 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -60,6 +60,42 @@ struct alps_nibble_commands { + }; + + /** ++ * struct alps_fields - decoded version of the report packet ++ * @x_map: Bitmap of active X positions for MT. ++ * @y_map: Bitmap of active Y positions for MT. ++ * @fingers: Number of fingers for MT. ++ * @x: X position for ST. ++ * @y: Y position for ST. ++ * @z: Z position for ST. ++ * @first_mp: Packet is the first of a multi-packet report. ++ * @is_mp: Packet is part of a multi-packet report. ++ * @left: Left touchpad button is active. ++ * @right: Right touchpad button is active. ++ * @middle: Middle touchpad button is active. ++ * @ts_left: Left trackstick button is active. ++ * @ts_right: Right trackstick button is active. ++ * @ts_middle: Middle trackstick button is active. ++ */ ++struct alps_fields { ++ unsigned int x_map; ++ unsigned int y_map; ++ unsigned int fingers; ++ unsigned int x; ++ unsigned int y; ++ unsigned int z; ++ unsigned int first_mp:1; ++ unsigned int is_mp:1; ++ ++ unsigned int left:1; ++ unsigned int right:1; ++ unsigned int middle:1; ++ ++ unsigned int ts_left:1; ++ unsigned int ts_right:1; ++ unsigned int ts_middle:1; ++}; ++ ++/** + * struct alps_data - private data structure for the ALPS driver + * @dev2: "Relative" device used to report trackstick or mouse activity. + * @phys: Physical path for the relative device. +@@ -78,6 +114,7 @@ struct alps_nibble_commands { + * @y_bits: Number of Y bits in the MT bitmap. + * @hw_init: Protocol-specific hardware init function. + * @process_packet: Protocol-specific function to process a report packet. ++ * @decode_fields: Protocol-specific function to read packet bitfields. + * @set_abs_params: Protocol-specific function to configure the input_dev. + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. +@@ -107,6 +144,7 @@ struct alps_data { + + int (*hw_init)(struct psmouse *psmouse); + void (*process_packet)(struct psmouse *psmouse); ++ void (*decode_fields)(struct alps_fields *f, unsigned char *p); + void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); + + int prev_fin; +-- +1.8.1.2 + + +From 9e7c99b6c125653f53ef0999a176c3a79de21be8 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:27:08 -0800 +Subject: [PATCH 12/15] Input: ALPS - add support for "Rushmore" touchpads + +Rushmore touchpads are found on Dell E6230/E6430/E6530. They use the V3 +protocol with slightly tweaked init sequences and report formats. + +The E7 report is 73 03 0a, and the EC report is 88 08 1d + +Credits: Emmanuel Thome reported the MT bitmap changes. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 270b7de..bf2fa51 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -479,6 +479,14 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) + alps_decode_buttons_v3(f, p); + } + ++static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) ++{ ++ alps_decode_pinnacle(f, p); ++ ++ f->x_map |= (p[5] & 0x10) << 11; ++ f->y_map |= (p[5] & 0x20) << 6; ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -1329,6 +1337,40 @@ error: + return -1; + } + ++static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val, ret = -1; ++ ++ if (alps_enter_command_mode(psmouse, NULL) || ++ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || ++ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) ++ goto error; ++ ++ /* enter absolute mode */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); ++ ++error: ++ alps_exit_command_mode(psmouse); ++ return ret; ++} ++ + /* Must be in command mode when calling this function */ + static int alps_absolute_mode_v4(struct psmouse *psmouse) + { +@@ -1511,6 +1553,16 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + + if (alps_match_table(psmouse, priv, e7, ec) == 0) { + return 0; ++ } else if (ec[0] == 0x88 && ec[1] == 0x08) { ++ priv->proto_version = ALPS_PROTO_V3; ++ alps_set_defaults(priv); ++ ++ priv->hw_init = alps_hw_init_rushmore_v3; ++ priv->decode_fields = alps_decode_rushmore; ++ priv->x_bits = 16; ++ priv->y_bits = 12; ++ ++ return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x07 && + ec[2] >= 0x90 && ec[2] <= 0x9d) { + priv->proto_version = ALPS_PROTO_V3; +-- +1.8.1.2 + + +From e5ca58dc506fb7f64760b483ecd407593b764f3b Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Wed, 13 Feb 2013 22:28:07 -0800 +Subject: [PATCH 13/15] Input: ALPS - enable trackstick on Rushmore touchpads + +Separate out the common trackstick probe/setup sequences, then call them +from each of the v3 init functions. + +Credits: Emmanual Thome furnished the information on the trackstick init +and how it affected the report format. + +Signed-off-by: Kevin Cernekee +Tested-by: Dave Turvene +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 185 ++++++++++++++++++++++++++++----------------- + 1 file changed, 115 insertions(+), 70 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index bf2fa51..7b99fc7 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -29,6 +29,9 @@ + */ + #define ALPS_CMD_NIBBLE_10 0x01f2 + ++#define ALPS_REG_BASE_RUSHMORE 0xc2c0 ++#define ALPS_REG_BASE_PINNACLE 0x0000 ++ + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { + { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ + { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ +@@ -1166,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) } /* @@ -694,20 +2029,16 @@ index e229fa3..7b99fc7 100644 } /* Must be in command mode when calling this function */ -@@ -1287,73 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) +@@ -1204,69 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) return 0; } -static int alps_hw_init_v3(struct psmouse *psmouse) +static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; -- -- priv->nibble_commands = alps_v3_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + int ret = -EIO, reg_val; if (alps_enter_command_mode(psmouse, NULL)) @@ -850,7 +2181,7 @@ index e229fa3..7b99fc7 100644 psmouse_err(psmouse, "Failed to enter absolute mode\n"); goto error; } -@@ -1390,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) +@@ -1303,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) goto error; @@ -865,7 +2196,7 @@ index e229fa3..7b99fc7 100644 alps_exit_command_mode(psmouse); /* Set rate and enable data reporting */ -@@ -1410,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) +@@ -1323,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) return 0; @@ -876,16 +2207,14 @@ index e229fa3..7b99fc7 100644 error: /* * Leaving the touchpad in command mode will essentially render -@@ -1424,6 +1366,50 @@ error: - return -1; - } +@@ -1339,9 +1368,19 @@ error: -+static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) -+{ + static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val, ret = -1; -+ + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val, ret = -1; + + if (priv->flags & ALPS_DUALPOINT) { + reg_val = alps_setup_trackstick_v3(psmouse, + ALPS_REG_BASE_RUSHMORE); @@ -895,511 +2224,271 @@ index e229fa3..7b99fc7 100644 + priv->flags &= ~ALPS_DUALPOINT; + } + -+ if (alps_enter_command_mode(psmouse, NULL) || -+ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || -+ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) -+ goto error; -+ -+ /* enter absolute mode */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); -+ -+error: -+ alps_exit_command_mode(psmouse); -+ return ret; -+} -+ - /* Must be in command mode when calling this function */ - static int alps_absolute_mode_v4(struct psmouse *psmouse) - { -@@ -1442,13 +1428,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) + if (alps_enter_command_mode(psmouse, NULL) || + alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || + alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) +@@ -1562,6 +1601,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + priv->x_bits = 16; + priv->y_bits = 12; - static int alps_hw_init_v4(struct psmouse *psmouse) - { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - -- priv->nibble_commands = alps_v4_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_DISABLE; -- - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -@@ -1517,39 +1499,140 @@ error: - return -1; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static void alps_set_defaults(struct alps_data *priv) - { -- struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; -- int ret = -1; -+ priv->byte0 = 0x8f; -+ priv->mask0 = 0x8f; -+ priv->flags = ALPS_DUALPOINT; -+ -+ priv->x_max = 2000; -+ priv->y_max = 1400; -+ priv->x_bits = 15; -+ priv->y_bits = 11; - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -- ret = alps_hw_init_v1_v2(psmouse); -+ priv->hw_init = alps_hw_init_v1_v2; -+ priv->process_packet = alps_process_packet_v1_v2; -+ priv->set_abs_params = alps_set_abs_params_st; - break; - case ALPS_PROTO_V3: -- ret = alps_hw_init_v3(psmouse); -+ priv->hw_init = alps_hw_init_v3; -+ priv->process_packet = alps_process_packet_v3; -+ priv->set_abs_params = alps_set_abs_params_mt; -+ priv->decode_fields = alps_decode_pinnacle; -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - break; - case ALPS_PROTO_V4: -- ret = alps_hw_init_v4(psmouse); -+ priv->hw_init = alps_hw_init_v4; -+ priv->process_packet = alps_process_packet_v4; -+ priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; - break; - } -+} - -- return ret; -+static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, -+ unsigned char *e7, unsigned char *ec) -+{ -+ const struct alps_model_info *model; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ model = &alps_model_data[i]; -+ -+ if (!memcmp(e7, model->signature, sizeof(model->signature)) && -+ (!model->command_mode_resp || -+ model->command_mode_resp == ec[2])) { -+ -+ priv->proto_version = model->proto_version; -+ alps_set_defaults(priv); -+ -+ priv->flags = model->flags; -+ priv->byte0 = model->byte0; -+ priv->mask0 = model->mask0; -+ -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) -+{ -+ unsigned char e6[4], e7[4], ec[4]; -+ -+ /* -+ * First try "E6 report". -+ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. -+ * The bits 0-2 of the first byte will be 1s if some buttons are -+ * pressed. -+ */ -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE11, e6)) -+ return -EIO; -+ -+ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) -+ return -EINVAL; -+ -+ /* -+ * Now get the "E7" and "EC" reports. These will uniquely identify -+ * most ALPS touchpads. -+ */ -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE21, e7) || -+ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_RESET_WRAP, ec) || -+ alps_exit_command_mode(psmouse)) -+ return -EIO; -+ -+ if (alps_match_table(psmouse, priv, e7, ec) == 0) { -+ return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x08) { -+ priv->proto_version = ALPS_PROTO_V3; -+ alps_set_defaults(priv); -+ -+ priv->hw_init = alps_hw_init_rushmore_v3; -+ priv->decode_fields = alps_decode_rushmore; -+ priv->x_bits = 16; -+ priv->y_bits = 12; -+ + /* hack to make addr_command, nibble_command available */ + psmouse->private = priv; + + if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) + priv->flags &= ~ALPS_DUALPOINT; + -+ return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x07 && -+ ec[2] >= 0x90 && ec[2] <= 0x9d) { -+ priv->proto_version = ALPS_PROTO_V3; + return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x07 && + ec[2] >= 0x90 && ec[2] <= 0x9d) { +-- +1.8.1.2 + + +From db7192fa07fa5c70c9849d8f658a7ff696cff99d Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Sat, 16 Feb 2013 22:40:03 -0800 +Subject: [PATCH 14/15] Input: ALPS - Remove unused argument to + alps_enter_command_mode() + +Now that alps_identify() explicitly issues an EC report using +alps_rpt_cmd(), we no longer need to look at the magic numbers returned +by alps_enter_command_mode(). + +Signed-off-by: Kevin Cernekee +--- + drivers/input/mouse/alps.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 7b99fc7..9c97531 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -994,8 +994,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, + return 0; + } + +-static int alps_enter_command_mode(struct psmouse *psmouse, +- unsigned char *resp) ++static int alps_enter_command_mode(struct psmouse *psmouse) + { + unsigned char param[4]; + +@@ -1009,9 +1008,6 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + "unknown response while entering command mode\n"); + return -1; + } +- +- if (resp) +- *resp = param[2]; + return 0; + } + +@@ -1176,7 +1172,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, + { + int reg_val, ret = -1; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + return -1; + + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); +@@ -1216,7 +1212,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) + { + int ret = -EIO, reg_val; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + goto error; + + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); +@@ -1279,7 +1275,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) + * supported by this driver. If bit 1 isn't set the packet + * format is different. + */ +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_command_mode_write_reg(psmouse, + reg_base + 0x08, 0x82) || + alps_exit_command_mode(psmouse)) +@@ -1306,7 +1302,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) + goto error; + +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_absolute_mode_v3(psmouse)) { + psmouse_err(psmouse, "Failed to enter absolute mode\n"); + goto error; +@@ -1381,7 +1377,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) + priv->flags &= ~ALPS_DUALPOINT; + } + +- if (alps_enter_command_mode(psmouse, NULL) || ++ if (alps_enter_command_mode(psmouse) || + alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || + alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) + goto error; +@@ -1431,7 +1427,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + +- if (alps_enter_command_mode(psmouse, NULL)) ++ if (alps_enter_command_mode(psmouse)) + goto error; + + if (alps_absolute_mode_v4(psmouse)) { +-- +1.8.1.2 + + +From 10740a25bb3b895b5de7773f926a978416b38409 Mon Sep 17 00:00:00 2001 +From: Dave Turvene +Date: Sat, 16 Feb 2013 22:40:04 -0800 +Subject: [PATCH 15/15] Input: ALPS - Add "Dolphin V1" touchpad support + +These touchpads use a different protocol; they have been seen on Dell +N5110, Dell 17R SE, and others. + +The official ALPS driver identifies them by looking for an exact match +on the E7 report: 73 03 50. Dolphin V1 returns an EC report of +73 01 xx (02 and 0d have been seen); Dolphin V2 returns an EC report of +73 02 xx (02 has been seen). + +Dolphin V2 probably needs a different initialization sequence and/or +report parser, so it is left for a future commit. + +Signed-off-by: Dave Turvene +Signed-off-by: Kevin Cernekee +--- + drivers/input/mouse/alps.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.h | 1 + + 2 files changed, 66 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 9c97531..0238e0e 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) + f->y_map |= (p[5] & 0x20) << 6; + } + ++static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) ++{ ++ f->first_mp = !!(p[0] & 0x02); ++ f->is_mp = !!(p[0] & 0x20); ++ ++ f->fingers = ((p[0] & 0x6) >> 1 | ++ (p[0] & 0x10) >> 2); ++ f->x_map = ((p[2] & 0x60) >> 5) | ++ ((p[4] & 0x7f) << 2) | ++ ((p[5] & 0x7f) << 9) | ++ ((p[3] & 0x07) << 16) | ++ ((p[3] & 0x70) << 15) | ++ ((p[0] & 0x01) << 22); ++ f->y_map = (p[1] & 0x7f) | ++ ((p[2] & 0x1f) << 7); ++ ++ f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); ++ f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); ++ f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; ++ ++ alps_decode_buttons_v3(f, p); ++} ++ + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + /* Bytes 2 - pktsize should have 0 in the highest bit */ +- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && ++ if (priv->proto_version != ALPS_PROTO_V5 && ++ psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, +@@ -1003,7 +1027,8 @@ static int alps_enter_command_mode(struct psmouse *psmouse) + return -1; + } + +- if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { ++ if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && ++ param[0] != 0x73) { + psmouse_dbg(psmouse, + "unknown response while entering command mode\n"); + return -1; +@@ -1495,6 +1520,23 @@ error: + return -1; + } + ++static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[2]; ++ ++ /* This is dolphin "v1" as empirically defined by florin9doi */ ++ param[0] = 0x64; ++ param[1] = 0x28; ++ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || ++ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) ++ return -1; ++ ++ return 0; ++} ++ + static void alps_set_defaults(struct alps_data *priv) + { + priv->byte0 = 0x8f; +@@ -1528,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) + priv->nibble_commands = alps_v4_nibble_commands; + priv->addr_command = PSMOUSE_CMD_DISABLE; + break; ++ case ALPS_PROTO_V5: ++ priv->hw_init = alps_hw_init_dolphin_v1; ++ priv->process_packet = alps_process_packet_v3; ++ priv->decode_fields = alps_decode_dolphin; ++ priv->set_abs_params = alps_set_abs_params_mt; ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; ++ priv->byte0 = 0xc8; ++ priv->mask0 = 0xc8; ++ priv->flags = 0; ++ priv->x_max = 1360; ++ priv->y_max = 660; ++ priv->x_bits = 23; ++ priv->y_bits = 12; ++ break; + } + } + +@@ -1588,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) + + if (alps_match_table(psmouse, priv, e7, ec) == 0) { + return 0; ++ } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && ++ ec[0] == 0x73 && ec[1] == 0x01) { ++ priv->proto_version = ALPS_PROTO_V5; + alps_set_defaults(priv); + + return 0; -+ } -+ -+ psmouse_info(psmouse, -+ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", -+ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); -+ -+ return -EINVAL; - } - - static int alps_reconnect(struct psmouse *psmouse) - { -- const struct alps_model_info *model; -+ struct alps_data *priv = psmouse->private; - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, NULL); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) - return -1; - -- return alps_hw_init(psmouse); -+ return priv->hw_init(psmouse); - } - - static void alps_disconnect(struct psmouse *psmouse) -@@ -1562,12 +1645,33 @@ static void alps_disconnect(struct psmouse *psmouse) - kfree(priv); - } - -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+} -+ -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ -+ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); -+} -+ - int alps_init(struct psmouse *psmouse) - { - struct alps_data *priv; -- const struct alps_model_info *model; - struct input_dev *dev1 = psmouse->dev, *dev2; -- int version; - - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); - dev2 = input_allocate_device(); -@@ -1581,13 +1685,10 @@ int alps_init(struct psmouse *psmouse) - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) - goto init_fail; - -- priv->i = model; -- -- if (alps_hw_init(psmouse)) -+ if (priv->hw_init(psmouse)) - goto init_fail; - - /* -@@ -1609,41 +1710,20 @@ int alps_init(struct psmouse *psmouse) - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - -- switch (model->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -- break; -- case ALPS_PROTO_V3: -- case ALPS_PROTO_V4: -- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -- input_mt_init_slots(dev1, 2, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- -- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -- -- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- break; -- } -- -+ priv->set_abs_params(priv, dev1); - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - -- if (model->flags & ALPS_WHEEL) { -+ if (priv->flags & ALPS_WHEEL) { - dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); - dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); - } - -- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { -+ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); - dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); - } - -- if (model->flags & ALPS_FOUR_BUTTONS) { -+ if (priv->flags & ALPS_FOUR_BUTTONS) { - dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); - dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); - dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); -@@ -1654,7 +1734,8 @@ int alps_init(struct psmouse *psmouse) - - snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys; -- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; -+ dev2->name = (priv->flags & ALPS_DUALPOINT) ? -+ "DualPoint Stick" : "PS/2 Mouse"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_ALPS; -@@ -1673,7 +1754,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; -+ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -@@ -1690,18 +1771,16 @@ init_fail: - - int alps_detect(struct psmouse *psmouse, bool set_properties) - { -- int version; -- const struct alps_model_info *model; -+ struct alps_data dummy; - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, &dummy) < 0) - return -1; - - if (set_properties) { - psmouse->vendor = "ALPS"; -- psmouse->name = model->flags & ALPS_DUALPOINT ? -+ psmouse->name = dummy.flags & ALPS_DUALPOINT ? - "DualPoint TouchPad" : "GlidePoint"; -- psmouse->model = version; -+ psmouse->model = dummy.proto_version << 8; - } - return 0; - } + } else if (ec[0] == 0x88 && ec[1] == 0x08) { + priv->proto_version = ALPS_PROTO_V3; + alps_set_defaults(priv); diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index ae1ac35..9704805 100644 +index 9704805..eee5985 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h -@@ -12,35 +12,146 @@ - #ifndef _ALPS_H - #define _ALPS_H +@@ -16,6 +16,7 @@ + #define ALPS_PROTO_V2 2 + #define ALPS_PROTO_V3 3 + #define ALPS_PROTO_V4 4 ++#define ALPS_PROTO_V5 5 --#define ALPS_PROTO_V1 0 --#define ALPS_PROTO_V2 1 --#define ALPS_PROTO_V3 2 --#define ALPS_PROTO_V4 3 -+#define ALPS_PROTO_V1 1 -+#define ALPS_PROTO_V2 2 -+#define ALPS_PROTO_V3 3 -+#define ALPS_PROTO_V4 4 - -+/** -+ * struct alps_model_info - touchpad ID table -+ * @signature: E7 response string to match. -+ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response -+ * (aka command mode response) identifies the firmware minor version. This -+ * can be used to distinguish different hardware models which are not -+ * uniquely identifiable through their E7 responses. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * -+ * Many (but not all) ALPS touchpads can be identified by looking at the -+ * values returned in the "E7 report" and/or the "EC report." This table -+ * lists a number of such touchpads. -+ */ - struct alps_model_info { -- unsigned char signature[3]; -- unsigned char command_mode_resp; /* v3/v4 only */ -+ unsigned char signature[3]; -+ unsigned char command_mode_resp; - unsigned char proto_version; -- unsigned char byte0, mask0; -- unsigned char flags; -+ unsigned char byte0, mask0; -+ unsigned char flags; - }; - -+/** -+ * struct alps_nibble_commands - encodings for register accesses -+ * @command: PS/2 command used for the nibble -+ * @data: Data supplied as an argument to the PS/2 command, if applicable -+ * -+ * The ALPS protocol uses magic sequences to transmit binary data to the -+ * touchpad, as it is generally not OK to send arbitrary bytes out the -+ * PS/2 port. Each of the sequences in this table sends one nibble of the -+ * register address or (write) data. Different versions of the ALPS protocol -+ * use slightly different encodings. -+ */ - struct alps_nibble_commands { - int command; - unsigned char data; - }; - -+/** -+ * struct alps_fields - decoded version of the report packet -+ * @x_map: Bitmap of active X positions for MT. -+ * @y_map: Bitmap of active Y positions for MT. -+ * @fingers: Number of fingers for MT. -+ * @x: X position for ST. -+ * @y: Y position for ST. -+ * @z: Z position for ST. -+ * @first_mp: Packet is the first of a multi-packet report. -+ * @is_mp: Packet is part of a multi-packet report. -+ * @left: Left touchpad button is active. -+ * @right: Right touchpad button is active. -+ * @middle: Middle touchpad button is active. -+ * @ts_left: Left trackstick button is active. -+ * @ts_right: Right trackstick button is active. -+ * @ts_middle: Middle trackstick button is active. -+ */ -+struct alps_fields { -+ unsigned int x_map; -+ unsigned int y_map; -+ unsigned int fingers; -+ unsigned int x; -+ unsigned int y; -+ unsigned int z; -+ unsigned int first_mp:1; -+ unsigned int is_mp:1; -+ -+ unsigned int left:1; -+ unsigned int right:1; -+ unsigned int middle:1; -+ -+ unsigned int ts_left:1; -+ unsigned int ts_right:1; -+ unsigned int ts_middle:1; -+}; -+ -+/** -+ * struct alps_data - private data structure for the ALPS driver -+ * @dev2: "Relative" device used to report trackstick or mouse activity. -+ * @phys: Physical path for the relative device. -+ * @nibble_commands: Command mapping used for touchpad register accesses. -+ * @addr_command: Command used to tell the touchpad that a register address -+ * follows. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * @x_max: Largest possible X position value. -+ * @y_max: Largest possible Y position value. -+ * @x_bits: Number of X bits in the MT bitmap. -+ * @y_bits: Number of Y bits in the MT bitmap. -+ * @hw_init: Protocol-specific hardware init function. -+ * @process_packet: Protocol-specific function to process a report packet. -+ * @decode_fields: Protocol-specific function to read packet bitfields. -+ * @set_abs_params: Protocol-specific function to configure the input_dev. -+ * @prev_fin: Finger bit from previous packet. -+ * @multi_packet: Multi-packet data in progress. -+ * @multi_data: Saved multi-packet data. -+ * @x1: First X coordinate from last MT report. -+ * @x2: Second X coordinate from last MT report. -+ * @y1: First Y coordinate from last MT report. -+ * @y2: Second Y coordinate from last MT report. -+ * @fingers: Number of fingers from last MT report. -+ * @quirks: Bitmap of ALPS_QUIRK_*. -+ * @timer: Timer for flushing out the final report packet in the stream. -+ */ - struct alps_data { -- struct input_dev *dev2; /* Relative device */ -- char phys[32]; /* Phys */ -- const struct alps_model_info *i;/* Info */ -+ struct input_dev *dev2; -+ char phys[32]; -+ -+ /* these are autodetected when the device is identified */ - const struct alps_nibble_commands *nibble_commands; -- int addr_command; /* Command to set register address */ -- int prev_fin; /* Finger bit from previous packet */ -- int multi_packet; /* Multi-packet data in progress */ -- unsigned char multi_data[6]; /* Saved multi-packet data */ -- int x1, x2, y1, y2; /* Coordinates from last MT report */ -- int fingers; /* Number of fingers from MT report */ -+ int addr_command; -+ unsigned char proto_version; -+ unsigned char byte0, mask0; -+ unsigned char flags; -+ int x_max; -+ int y_max; -+ int x_bits; -+ int y_bits; -+ -+ int (*hw_init)(struct psmouse *psmouse); -+ void (*process_packet)(struct psmouse *psmouse); -+ void (*decode_fields)(struct alps_fields *f, unsigned char *p); -+ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); -+ -+ int prev_fin; -+ int multi_packet; -+ unsigned char multi_data[6]; -+ int x1, x2, y1, y2; -+ int fingers; - u8 quirks; - struct timer_list timer; - }; + /** + * struct alps_model_info - touchpad ID table +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index a8a89d01b..5c3cd9895 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 204 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -754,7 +754,7 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch #rhbz 812111 -Patch24000: alps.patch +Patch24000: alps-v2.patch Patch24100: userns-avoid-recursion-in-put_user_ns.patch @@ -1490,7 +1490,7 @@ ApplyPatch Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch ApplyPatch ath9k_rx_dma_stop_check.patch #rhbz 812111 -ApplyPatch alps.patch +ApplyPatch alps-v2.patch #rhbz 903192 ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch @@ -2402,6 +2402,9 @@ fi # ||----w | # || || %changelog +* Thu Apr 11 2013 Josh Boyer +- Fix ALPS backport patch (rhbz 812111) + * Mon Apr 09 2013 Josh Boyer - 3.8.6-203 - Temporarily work around pci device assignment issues (rhbz 908888) - CVE-2013-1929 tg3: len overflow in VPD firmware parsing (rhbz 949932 949946) From ee5b1741369abee4a5ca5963b848e6fde0c3c0de Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 11 Apr 2013 11:53:05 -0400 Subject: [PATCH 280/492] Print out some extra debug information when we hit bad page tables. --- debug-bad-pte-dmi.patch | 64 +++++++++++++++++++++++++++++++++++++ debug-bad-pte-modules.patch | 21 ++++++++++++ kernel.spec | 10 ++++++ 3 files changed, 95 insertions(+) create mode 100644 debug-bad-pte-dmi.patch create mode 100644 debug-bad-pte-modules.patch diff --git a/debug-bad-pte-dmi.patch b/debug-bad-pte-dmi.patch new file mode 100644 index 000000000..0552cb34f --- /dev/null +++ b/debug-bad-pte-dmi.patch @@ -0,0 +1,64 @@ +diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/include/asm-generic/bug.h linux-dj/include/asm-generic/bug.h +--- /home/davej/src/kernel/git-trees/linux/include/asm-generic/bug.h 2013-01-04 18:57:12.604282214 -0500 ++++ linux-dj/include/asm-generic/bug.h 2013-02-28 20:04:37.649304147 -0500 +@@ -55,6 +55,8 @@ struct bug_entry { + #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) + #endif + ++void print_hardware_dmi_name(void); ++ + /* + * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report + * significant issues that need prompt attention if they should ever +diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/kernel/panic.c linux-dj/kernel/panic.c +--- /home/davej/src/kernel/git-trees/linux/kernel/panic.c 2013-02-26 14:41:18.544116674 -0500 ++++ linux-dj/kernel/panic.c 2013-02-28 20:04:37.666304115 -0500 +@@ -397,16 +397,22 @@ struct slowpath_args { + va_list args; + }; + +-static void warn_slowpath_common(const char *file, int line, void *caller, +- unsigned taint, struct slowpath_args *args) ++void print_hardware_dmi_name(void) + { + const char *board; + +- printk(KERN_WARNING "------------[ cut here ]------------\n"); +- printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); + board = dmi_get_system_info(DMI_PRODUCT_NAME); + if (board) + printk(KERN_WARNING "Hardware name: %s\n", board); ++} ++ ++static void warn_slowpath_common(const char *file, int line, void *caller, ++ unsigned taint, struct slowpath_args *args) ++{ ++ printk(KERN_WARNING "------------[ cut here ]------------\n"); ++ printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); ++ ++ print_hardware_dmi_name(); + + if (args) + vprintk(args->fmt, args->args); +diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/mm/memory.c linux-dj/mm/memory.c +--- /home/davej/src/kernel/git-trees/linux/mm/memory.c 2013-02-26 14:41:18.591116577 -0500 ++++ linux-dj/mm/memory.c 2013-02-28 20:04:37.678304092 -0500 +@@ -705,6 +706,8 @@ static void print_bad_pte(struct vm_area + "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", + current->comm, + (long long)pte_val(pte), (long long)pmd_val(*pmd)); ++ print_hardware_dmi_name(); ++ + if (page) + dump_page(page); + printk(KERN_ALERT +--- linux-dj/mm/page_alloc.c~ 2013-04-11 11:47:12.536675503 -0400 ++++ linux-dj/mm/page_alloc.c 2013-04-11 11:47:16.416667806 -0400 +@@ -321,6 +321,7 @@ static void bad_page(struct page *page) + current->comm, page_to_pfn(page)); + dump_page(page); + ++ print_hardware_dmi_name(); + print_modules(); + dump_stack(); + out: diff --git a/debug-bad-pte-modules.patch b/debug-bad-pte-modules.patch new file mode 100644 index 000000000..bcf328667 --- /dev/null +++ b/debug-bad-pte-modules.patch @@ -0,0 +1,21 @@ +diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/mm/memory.c linux-dj/mm/memory.c +--- /home/davej/src/kernel/git-trees/linux/mm/memory.c 2013-02-26 14:41:18.591116577 -0500 ++++ linux-dj/mm/memory.c 2013-02-28 20:04:37.678304092 -0500 +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + #include + #include + +--- linux-3.8.6-104.fc17.noarch/mm/memory.c~ 2013-04-11 11:48:54.024470277 -0400 ++++ linux-3.8.6-104.fc17.noarch/mm/memory.c 2013-04-11 11:49:15.770425274 -0400 +@@ -718,6 +718,7 @@ static void print_bad_pte(struct vm_area + if (vma->vm_file && vma->vm_file->f_op) + print_symbol(KERN_ALERT "vma->vm_file->f_op->mmap: %s\n", + (unsigned long)vma->vm_file->f_op->mmap); ++ print_modules(); + dump_stack(); + add_taint(TAINT_BAD_PAGE); + } diff --git a/kernel.spec b/kernel.spec index 5c3cd9895..3c1cfb764 100644 --- a/kernel.spec +++ b/kernel.spec @@ -650,6 +650,9 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch +Patch200: debug-bad-pte-dmi.patch +Patch201: debug-bad-pte-modules.patch + Patch390: defaults-acpi-video.patch Patch391: acpi-video-dos.patch Patch394: acpi-debug-infinite-loop.patch @@ -1351,6 +1354,10 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch +ApplyPatch debug-bad-pte-dmi.patch +ApplyPatch debug-bad-pte-modules.patch + + # Architecture patches # x86(-64) @@ -2402,6 +2409,9 @@ fi # ||----w | # || || %changelog +* Thu Apr 11 2013 Dave Jones +- Print out some extra debug information when we hit bad page tables. + * Thu Apr 11 2013 Josh Boyer - Fix ALPS backport patch (rhbz 812111) From 8924cb541f969c40b817a88fc2418809f9ae2d33 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 12 Apr 2013 11:52:38 -0400 Subject: [PATCH 281/492] Enable CONFIG_LDM_PARTITION (rhbz 948636) --- config-generic | 3 ++- kernel.spec | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config-generic b/config-generic index 5c137e66d..6550abbbb 100644 --- a/config-generic +++ b/config-generic @@ -3778,7 +3778,8 @@ CONFIG_AMIGA_PARTITION=y CONFIG_BSD_DISKLABEL=y CONFIG_EFI_PARTITION=y CONFIG_KARMA_PARTITION=y -# CONFIG_LDM_PARTITION is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y CONFIG_MINIX_SUBPARTITION=y diff --git a/kernel.spec b/kernel.spec index 3c1cfb764..de4d6a20e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 204 +%global baserelease 205 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2409,6 +2409,9 @@ fi # ||----w | # || || %changelog +* Fri Apr 12 2013 Josh Boyer +- Enable CONFIG_LDM_PARTITION (rhbz 948636) + * Thu Apr 11 2013 Dave Jones - Print out some extra debug information when we hit bad page tables. From 1eac3cd5133bd39a6160a78fa3b253c3136db576 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 12 Apr 2013 13:53:01 -0400 Subject: [PATCH 282/492] Linux v3.8.7 Also drop some tegra patches that aren't being applied at all --- ...rk-to-invert-brightness-on-eMachines.patch | 36 -------- ...ace-between-input_register-and-probe.patch | 83 ------------------- arm-tegra-nvec-kconfig.patch | 10 --- arm-tegra-sdhci-module-fix.patch | 11 --- kernel.spec | 23 +---- sources | 2 +- 6 files changed, 5 insertions(+), 160 deletions(-) delete mode 100644 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch delete mode 100644 HID-magicmouse-fix-race-between-input_register-and-probe.patch delete mode 100644 arm-tegra-nvec-kconfig.patch delete mode 100644 arm-tegra-sdhci-module-fix.patch diff --git a/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch b/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch deleted file mode 100644 index 22e2ac7ae..000000000 --- a/0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0bc8d69a3bbbb261fdaadd759adbd8e60da72e36 Mon Sep 17 00:00:00 2001 -From: Jani Nikula -Date: Tue, 22 Jan 2013 12:50:35 +0200 -Subject: [PATCH] drm/i915: add quirk to invert brightness on eMachines e725 - -Upstream commit 01e3a8feb40e54b962a20fa7eb595c5efef5e109 - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=31522#c35 -[Note: There are more than one broken setups in the bug. This fixes one.] -Reported-by: Martins -Signed-off-by: Jani Nikula -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_display.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index e6e4df7..6292677 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -8899,6 +8899,12 @@ static struct intel_quirk intel_quirks[] = { - /* Acer Aspire 5734Z must invert backlight brightness */ - { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, - -+ /* Acer/eMachines G725 */ -+ { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, -+ -+ /* Acer/eMachines e725 */ -+ { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, -+ - /* Acer Aspire 4736Z */ - { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, - }; --- -1.8.1.4 - diff --git a/HID-magicmouse-fix-race-between-input_register-and-probe.patch b/HID-magicmouse-fix-race-between-input_register-and-probe.patch deleted file mode 100644 index 87f0ccb1e..000000000 --- a/HID-magicmouse-fix-race-between-input_register-and-probe.patch +++ /dev/null @@ -1,83 +0,0 @@ -From f1a9a149abc86903e81dd1b2e720f3f89874384b Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Tue, 2 Apr 2013 11:11:52 +0200 -Subject: HID: magicmouse: fix race between input_register() and probe() - -From: Benjamin Tissoires - -commit f1a9a149abc86903e81dd1b2e720f3f89874384b upstream. - -Since kernel 3.7, it appears that the input registration occured before -the end of magicmouse_setup_input(). This is shown by receiving a lot of -"EV_SYN SYN_REPORT 1" instead of normal "EV_SYN SYN_REPORT 0". -This value means that the output buffer is full, and the user space -is loosing events. - -Using .input_configured guarantees that the race is not occuring, and that -the call of "input_set_events_per_packet(input, 60)" is taken into account -by input_register(). - -Fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=908604 - -Reported-and-Tested-By: Clarke Wixon -Signed-off-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hid/hid-magicmouse.c | 29 ++++++++++++++++++++--------- - 1 file changed, 20 insertions(+), 9 deletions(-) - ---- a/drivers/hid/hid-magicmouse.c -+++ b/drivers/hid/hid-magicmouse.c -@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(stru - return 0; - } - -+static void magicmouse_input_configured(struct hid_device *hdev, -+ struct hid_input *hi) -+ -+{ -+ struct magicmouse_sc *msc = hid_get_drvdata(hdev); -+ -+ int ret = magicmouse_setup_input(msc->input, hdev); -+ if (ret) { -+ hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); -+ /* clean msc->input to notify probe() of the failure */ -+ msc->input = NULL; -+ } -+} -+ -+ - static int magicmouse_probe(struct hid_device *hdev, - const struct hid_device_id *id) - { -@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_d - goto err_free; - } - -- /* We do this after hid-input is done parsing reports so that -- * hid-input uses the most natural button and axis IDs. -- */ -- if (msc->input) { -- ret = magicmouse_setup_input(msc->input, hdev); -- if (ret) { -- hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); -- goto err_stop_hw; -- } -+ if (!msc->input) { -+ hid_err(hdev, "magicmouse input not registered\n"); -+ ret = -ENOMEM; -+ goto err_stop_hw; - } - - if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) -@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driv - .remove = magicmouse_remove, - .raw_event = magicmouse_raw_event, - .input_mapping = magicmouse_input_mapping, -+ .input_configured = magicmouse_input_configured, - }; - - static int __init magicmouse_init(void) diff --git a/arm-tegra-nvec-kconfig.patch b/arm-tegra-nvec-kconfig.patch deleted file mode 100644 index a3f568cd5..000000000 --- a/arm-tegra-nvec-kconfig.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- linux-2.6.42.noarch/drivers/staging/nvec/Kconfig.orig 2012-02-02 08:16:12.512727480 -0600 -+++ linux-2.6.42.noarch/drivers/staging/nvec/Kconfig 2012-02-01 18:44:56.674990109 -0600 -@@ -1,6 +1,6 @@ - config MFD_NVEC - bool "NV Tegra Embedded Controller SMBus Interface" -- depends on I2C && GPIOLIB && ARCH_TEGRA -+ depends on I2C && GPIOLIB && ARCH_TEGRA && MFD_CORE=y - help - Say Y here to enable support for a nVidia compliant embedded - controller. diff --git a/arm-tegra-sdhci-module-fix.patch b/arm-tegra-sdhci-module-fix.patch deleted file mode 100644 index 0c5d2448f..000000000 --- a/arm-tegra-sdhci-module-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-3.5.0-0.rc0.git3.1.fc18.armv7hl/drivers/mmc/host/sdhci-tegra.c.orig 2012-05-23 06:59:19.797302757 -0500 -+++ linux-3.5.0-0.rc0.git3.1.fc18.armv7hl/drivers/mmc/host/sdhci-tegra.c 2012-05-22 15:26:07.154823359 -0500 -@@ -190,7 +190,7 @@ - #endif - {} - }; --MODULE_DEVICE_TABLE(of, sdhci_dt_ids); -+MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); - - static struct tegra_sdhci_platform_data * sdhci_tegra_dt_parse_pdata( - struct platform_device *pdev) diff --git a/kernel.spec b/kernel.spec index de4d6a20e..3e724b84b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 205 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -722,9 +722,7 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM # ARM tegra -Patch21004: arm-tegra-nvec-kconfig.patch Patch21005: arm-tegra-usb-no-reset-linux33.patch -Patch21006: arm-tegra-sdhci-module-fix.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -795,12 +793,6 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 844750 Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch -#rhbz 908604 -Patch25009: HID-magicmouse-fix-race-between-input_register-and-probe.patch - -#rhbz 871932 -Patch25010: 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch - # END OF PATCH DEFINITIONS %endif @@ -1365,9 +1357,7 @@ ApplyPatch debug-bad-pte-modules.patch # ARM # -#ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch -#ApplyPatch arm-tegra-sdhci-module-fix.patch # # bugfixes to drivers and filesystems @@ -1546,12 +1536,6 @@ ApplyPatch fix-child-thread-introspection.patch ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch -#rhbz 908604 -ApplyPatch HID-magicmouse-fix-race-between-input_register-and-probe.patch - -#rhbz 871932 -ApplyPatch 0001-drm-i915-add-quirk-to-invert-brightness-on-eMachines.patch - # END OF PATCH APPLICATIONS %endif @@ -2409,7 +2393,8 @@ fi # ||----w | # || || %changelog -* Fri Apr 12 2013 Josh Boyer +* Fri Apr 12 2013 Josh Boyer - 3.8.7-201 +- Linux v3.8.7 - Enable CONFIG_LDM_PARTITION (rhbz 948636) * Thu Apr 11 2013 Dave Jones diff --git a/sources b/sources index 14c34d719..54f3c6b34 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -f11748a53d4ec0e2dcbfbb64526d6434 patch-3.8.6.xz +d166692330220c425d69db82c9d693b6 patch-3.8.7.xz From 5117b24b10839b5a1dc2a52c418ebe2fe814818d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 15 Apr 2013 08:27:47 -0400 Subject: [PATCH 283/492] tracing: NULL pointer dereference (rhbz 952197 952217) --- kernel.spec | 9 ++ ...x-possible-NULL-pointer-dereferences.patch | 111 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tracing-Fix-possible-NULL-pointer-dereferences.patch diff --git a/kernel.spec b/kernel.spec index 3e724b84b..4e54479ee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -793,6 +793,9 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 844750 Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#CVE-xxxx-xxxx rhbz 952197 952217 +Patch25009: tracing-Fix-possible-NULL-pointer-dereferences.patch + # END OF PATCH DEFINITIONS %endif @@ -1536,6 +1539,9 @@ ApplyPatch fix-child-thread-introspection.patch ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +#CVE-xxxx-xxxx rhbz 952197 952217 +ApplyPatch tracing-Fix-possible-NULL-pointer-dereferences.patch + # END OF PATCH APPLICATIONS %endif @@ -2393,6 +2399,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 15 2013 Josh Boyer +- tracing: NULL pointer dereference (rhbz 952197 952217) + * Fri Apr 12 2013 Josh Boyer - 3.8.7-201 - Linux v3.8.7 - Enable CONFIG_LDM_PARTITION (rhbz 948636) diff --git a/tracing-Fix-possible-NULL-pointer-dereferences.patch b/tracing-Fix-possible-NULL-pointer-dereferences.patch new file mode 100644 index 000000000..71af4ddc6 --- /dev/null +++ b/tracing-Fix-possible-NULL-pointer-dereferences.patch @@ -0,0 +1,111 @@ +From 6a76f8c0ab19f215af2a3442870eeb5f0e81998d Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Thu, 11 Apr 2013 15:55:01 +0900 +Subject: [PATCH] tracing: Fix possible NULL pointer dereferences + +Currently set_ftrace_pid and set_graph_function files use seq_lseek +for their fops. However seq_open() is called only for FMODE_READ in +the fops->open() so that if an user tries to seek one of those file +when she open it for writing, it sees NULL seq_file and then panic. + +It can be easily reproduced with following command: + + $ cd /sys/kernel/debug/tracing + $ echo 1234 | sudo tee -a set_ftrace_pid + +In this example, GNU coreutils' tee opens the file with fopen(, "a") +and then the fopen() internally calls lseek(). + +Link: http://lkml.kernel.org/r/1365663302-2170-1-git-send-email-namhyung@kernel.org + +Cc: Frederic Weisbecker +Cc: Ingo Molnar +Cc: Namhyung Kim +Cc: stable@vger.kernel.org +Signed-off-by: Namhyung Kim +Signed-off-by: Steven Rostedt +--- + include/linux/ftrace.h | 2 +- + kernel/trace/ftrace.c | 10 +++++----- + kernel/trace/trace_stack.c | 2 +- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h +index 167abf9..eb3ce32 100644 +--- a/include/linux/ftrace.h ++++ b/include/linux/ftrace.h +@@ -396,7 +396,7 @@ ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf, + size_t cnt, loff_t *ppos); + ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, + size_t cnt, loff_t *ppos); +-loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence); ++loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence); + int ftrace_regex_release(struct inode *inode, struct file *file); + + void __init +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 926ebfb..affc35d 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -2697,7 +2697,7 @@ ftrace_notrace_open(struct inode *inode, struct file *file) + } + + loff_t +-ftrace_regex_lseek(struct file *file, loff_t offset, int whence) ++ftrace_filter_lseek(struct file *file, loff_t offset, int whence) + { + loff_t ret; + +@@ -3570,7 +3570,7 @@ static const struct file_operations ftrace_filter_fops = { + .open = ftrace_filter_open, + .read = seq_read, + .write = ftrace_filter_write, +- .llseek = ftrace_regex_lseek, ++ .llseek = ftrace_filter_lseek, + .release = ftrace_regex_release, + }; + +@@ -3578,7 +3578,7 @@ static const struct file_operations ftrace_notrace_fops = { + .open = ftrace_notrace_open, + .read = seq_read, + .write = ftrace_notrace_write, +- .llseek = ftrace_regex_lseek, ++ .llseek = ftrace_filter_lseek, + .release = ftrace_regex_release, + }; + +@@ -3783,8 +3783,8 @@ static const struct file_operations ftrace_graph_fops = { + .open = ftrace_graph_open, + .read = seq_read, + .write = ftrace_graph_write, ++ .llseek = ftrace_filter_lseek, + .release = ftrace_graph_release, +- .llseek = seq_lseek, + }; + #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +@@ -4439,7 +4439,7 @@ static const struct file_operations ftrace_pid_fops = { + .open = ftrace_pid_open, + .write = ftrace_pid_write, + .read = seq_read, +- .llseek = seq_lseek, ++ .llseek = ftrace_filter_lseek, + .release = ftrace_pid_release, + }; + +diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c +index 42ca822..83a8b5b 100644 +--- a/kernel/trace/trace_stack.c ++++ b/kernel/trace/trace_stack.c +@@ -322,7 +322,7 @@ static const struct file_operations stack_trace_filter_fops = { + .open = stack_trace_filter_open, + .read = seq_read, + .write = ftrace_filter_write, +- .llseek = ftrace_regex_lseek, ++ .llseek = ftrace_filter_lseek, + .release = ftrace_regex_release, + }; + +-- +1.8.1.4 + From 5df5912517b49a0a051ef88d1b2c0c9e463f7cfa Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 15 Apr 2013 20:36:23 -0400 Subject: [PATCH 284/492] Fix debug patches to build on s390x/ppc --- debug-bad-pte-dmi.patch | 62 +++++++++++++++++++++-------------------- kernel.spec | 3 +- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/debug-bad-pte-dmi.patch b/debug-bad-pte-dmi.patch index 0552cb34f..eddd595b0 100644 --- a/debug-bad-pte-dmi.patch +++ b/debug-bad-pte-dmi.patch @@ -1,6 +1,5 @@ -diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/include/asm-generic/bug.h linux-dj/include/asm-generic/bug.h ---- /home/davej/src/kernel/git-trees/linux/include/asm-generic/bug.h 2013-01-04 18:57:12.604282214 -0500 -+++ linux-dj/include/asm-generic/bug.h 2013-02-28 20:04:37.649304147 -0500 +--- linux.orig/include/asm-generic/bug.h ++++ linux/include/asm-generic/bug.h @@ -55,6 +55,8 @@ struct bug_entry { #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) #endif @@ -10,40 +9,43 @@ diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-tre /* * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report * significant issues that need prompt attention if they should ever -diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/kernel/panic.c linux-dj/kernel/panic.c ---- /home/davej/src/kernel/git-trees/linux/kernel/panic.c 2013-02-26 14:41:18.544116674 -0500 -+++ linux-dj/kernel/panic.c 2013-02-28 20:04:37.666304115 -0500 -@@ -397,16 +397,22 @@ struct slowpath_args { - va_list args; - }; +--- linux.orig/kernel/panic.c ++++ linux/kernel/panic.c +@@ -391,6 +391,15 @@ void oops_exit(void) + kmsg_dump(KMSG_DUMP_OOPS); + } --static void warn_slowpath_common(const char *file, int line, void *caller, -- unsigned taint, struct slowpath_args *args) +void print_hardware_dmi_name(void) - { - const char *board; - -- printk(KERN_WARNING "------------[ cut here ]------------\n"); -- printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); - board = dmi_get_system_info(DMI_PRODUCT_NAME); - if (board) - printk(KERN_WARNING "Hardware name: %s\n", board); ++{ ++ const char *board; ++ ++ board = dmi_get_system_info(DMI_PRODUCT_NAME); ++ if (board) ++ printk(KERN_WARNING "Hardware name: %s\n", board); +} + -+static void warn_slowpath_common(const char *file, int line, void *caller, -+ unsigned taint, struct slowpath_args *args) -+{ -+ printk(KERN_WARNING "------------[ cut here ]------------\n"); -+ printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); + #ifdef WANT_WARN_ON_SLOWPATH + struct slowpath_args { + const char *fmt; +@@ -400,13 +409,10 @@ struct slowpath_args { + static void warn_slowpath_common(const char *file, int line, void *caller, + unsigned taint, struct slowpath_args *args) + { +- const char *board; +- + printk(KERN_WARNING "------------[ cut here ]------------\n"); + printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); +- board = dmi_get_system_info(DMI_PRODUCT_NAME); +- if (board) +- printk(KERN_WARNING "Hardware name: %s\n", board); + + print_hardware_dmi_name(); if (args) vprintk(args->fmt, args->args); -diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/mm/memory.c linux-dj/mm/memory.c ---- /home/davej/src/kernel/git-trees/linux/mm/memory.c 2013-02-26 14:41:18.591116577 -0500 -+++ linux-dj/mm/memory.c 2013-02-28 20:04:37.678304092 -0500 -@@ -705,6 +706,8 @@ static void print_bad_pte(struct vm_area +--- linux.orig/mm/memory.c ++++ linux/mm/memory.c +@@ -706,6 +706,8 @@ static void print_bad_pte(struct vm_area "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", current->comm, (long long)pte_val(pte), (long long)pmd_val(*pmd)); @@ -52,8 +54,8 @@ diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-tre if (page) dump_page(page); printk(KERN_ALERT ---- linux-dj/mm/page_alloc.c~ 2013-04-11 11:47:12.536675503 -0400 -+++ linux-dj/mm/page_alloc.c 2013-04-11 11:47:16.416667806 -0400 +--- linux.orig/mm/page_alloc.c ++++ linux/mm/page_alloc.c @@ -321,6 +321,7 @@ static void bad_page(struct page *page) current->comm, page_to_pfn(page)); dump_page(page); diff --git a/kernel.spec b/kernel.spec index 4e54479ee..9faf55cc4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2401,6 +2401,7 @@ fi %changelog * Mon Apr 15 2013 Josh Boyer - tracing: NULL pointer dereference (rhbz 952197 952217) +- Fix debug patches to build on s390x/ppc * Fri Apr 12 2013 Josh Boyer - 3.8.7-201 - Linux v3.8.7 From 9266085284f58b427587e18f833d02dec93bfa99 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 16 Apr 2013 10:36:56 -0400 Subject: [PATCH 285/492] Fix race in regulatory code (rhbz 919176) --- kernel.spec | 9 +++++ ...fix-channel-disabling-race-condition.patch | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 wireless-regulatory-fix-channel-disabling-race-condition.patch diff --git a/kernel.spec b/kernel.spec index 9faf55cc4..2986903f6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -796,6 +796,9 @@ Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #CVE-xxxx-xxxx rhbz 952197 952217 Patch25009: tracing-Fix-possible-NULL-pointer-dereferences.patch +#rhbz 919176 +Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch + # END OF PATCH DEFINITIONS %endif @@ -1542,6 +1545,9 @@ ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch #CVE-xxxx-xxxx rhbz 952197 952217 ApplyPatch tracing-Fix-possible-NULL-pointer-dereferences.patch +#rhbz 919176 +ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch + # END OF PATCH APPLICATIONS %endif @@ -2399,6 +2405,9 @@ fi # ||----w | # || || %changelog +* Tue Apr 16 2013 Josh Boyer +- Fix race in regulatory code (rhbz 919176) + * Mon Apr 15 2013 Josh Boyer - tracing: NULL pointer dereference (rhbz 952197 952217) - Fix debug patches to build on s390x/ppc diff --git a/wireless-regulatory-fix-channel-disabling-race-condition.patch b/wireless-regulatory-fix-channel-disabling-race-condition.patch new file mode 100644 index 000000000..313735377 --- /dev/null +++ b/wireless-regulatory-fix-channel-disabling-race-condition.patch @@ -0,0 +1,40 @@ +From: Johannes Berg + +When a full scan 2.4 and 5 GHz scan is scheduled, but then the 2.4 GHz +part of the scan disables a 5.2 GHz channel due to, e.g. receiving +country or frequency information, that 5.2 GHz channel might already +be in the list of channels to scan next. Then, when the driver checks +if it should do a passive scan, that will return false and attempt an +active scan. This is not only wrong but can also lead to the iwlwifi +device firmware crashing since it checks regulatory as well. + +Fix this by not setting the channel flags to just disabled but rather +OR'ing in the disabled flag. That way, even if the race happens, the +channel will be scanned passively which is still (mostly) correct. + +Cc: stable@vger.kernel.org +Signed-off-by: Johannes Berg +--- + net/wireless/reg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 93ab840..507c28e 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy, + return; + + REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); +- chan->flags = IEEE80211_CHAN_DISABLED; ++ chan->flags |= IEEE80211_CHAN_DISABLED; + return; + } + +-- +1.8.0 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From f6772cc35beff4cb7b50642d527894135f1b0aac Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 16 Apr 2013 10:39:20 -0400 Subject: [PATCH 286/492] Fix uninitialized variable free in iwlwifi (rhbz 951241) --- ...fi-fix-freeing-uninitialized-pointer.patch | 51 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 58 insertions(+) create mode 100644 iwlwifi-fix-freeing-uninitialized-pointer.patch diff --git a/iwlwifi-fix-freeing-uninitialized-pointer.patch b/iwlwifi-fix-freeing-uninitialized-pointer.patch new file mode 100644 index 000000000..90e6b6f64 --- /dev/null +++ b/iwlwifi-fix-freeing-uninitialized-pointer.patch @@ -0,0 +1,51 @@ +If on iwl_dump_nic_event_log() error occurs before that function +initialize buf, we process uninitiated pointer in +iwl_dbgfs_log_event_read() and can hit "BUG at mm/slub.c:3409" + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=951241 + +Reported-by: ian.odette@eprize.com +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- +Patch is only compile tested, but I'm sure it fixes the problem. + + drivers/net/wireless/iwlwifi/dvm/debugfs.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c +index 7b8178b..cb6dd58 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c ++++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c +@@ -2237,15 +2237,15 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, + size_t count, loff_t *ppos) + { + struct iwl_priv *priv = file->private_data; +- char *buf; +- int pos = 0; +- ssize_t ret = -ENOMEM; ++ char *buf = NULL; ++ ssize_t ret; + +- ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); +- if (buf) { +- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +- kfree(buf); +- } ++ ret = iwl_dump_nic_event_log(priv, true, &buf, true); ++ if (ret < 0) ++ goto err; ++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); ++err: ++ kfree(buf); + return ret; + } + +-- +1.7.11.7 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 2986903f6..32e4a1cdd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -799,6 +799,9 @@ Patch25009: tracing-Fix-possible-NULL-pointer-dereferences.patch #rhbz 919176 Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch +#rhbz 951241 +Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch + # END OF PATCH DEFINITIONS %endif @@ -1548,6 +1551,9 @@ ApplyPatch tracing-Fix-possible-NULL-pointer-dereferences.patch #rhbz 919176 ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch +#rhbz 951241 +ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch + # END OF PATCH APPLICATIONS %endif @@ -2406,6 +2412,7 @@ fi # || || %changelog * Tue Apr 16 2013 Josh Boyer +- Fix uninitialized variable free in iwlwifi (rhbz 951241) - Fix race in regulatory code (rhbz 919176) * Mon Apr 15 2013 Josh Boyer From c000c59d21408d9e3342936e69e4cb908c8feafc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 17 Apr 2013 08:25:31 -0400 Subject: [PATCH 287/492] Linux v3.8.8 --- kernel.spec | 19 +-- sources | 2 +- ...x-possible-NULL-pointer-dereferences.patch | 111 ------------------ ...c_fault-oops-during-lazy-MMU-updates.patch | 48 -------- 4 files changed, 6 insertions(+), 174 deletions(-) delete mode 100644 tracing-Fix-possible-NULL-pointer-dereferences.patch delete mode 100644 x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch diff --git a/kernel.spec b/kernel.spec index 32e4a1cdd..d602d1167 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -748,9 +748,6 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 903192 Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch -#rhbz 914737 -Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch - #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch @@ -793,9 +790,6 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 844750 Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch -#CVE-xxxx-xxxx rhbz 952197 952217 -Patch25009: tracing-Fix-possible-NULL-pointer-dereferences.patch - #rhbz 919176 Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch @@ -1501,9 +1495,6 @@ ApplyPatch alps-v2.patch #rhbz 903192 ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch -#rhbz 914737 -ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch - #rhbz 916544 ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch @@ -1545,9 +1536,6 @@ ApplyPatch fix-child-thread-introspection.patch ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch -#CVE-xxxx-xxxx rhbz 952197 952217 -ApplyPatch tracing-Fix-possible-NULL-pointer-dereferences.patch - #rhbz 919176 ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch @@ -2411,6 +2399,9 @@ fi # ||----w | # || || %changelog +* Wed Apr 17 2013 Josh Boyer - 3.8.8-201 +- Linux v3.8.8 + * Tue Apr 16 2013 Josh Boyer - Fix uninitialized variable free in iwlwifi (rhbz 951241) - Fix race in regulatory code (rhbz 919176) diff --git a/sources b/sources index 54f3c6b34..7c8f0e1f6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -d166692330220c425d69db82c9d693b6 patch-3.8.7.xz +08cdcef928c2ca402adf1c444a3c43ac patch-3.8.8.xz diff --git a/tracing-Fix-possible-NULL-pointer-dereferences.patch b/tracing-Fix-possible-NULL-pointer-dereferences.patch deleted file mode 100644 index 71af4ddc6..000000000 --- a/tracing-Fix-possible-NULL-pointer-dereferences.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 6a76f8c0ab19f215af2a3442870eeb5f0e81998d Mon Sep 17 00:00:00 2001 -From: Namhyung Kim -Date: Thu, 11 Apr 2013 15:55:01 +0900 -Subject: [PATCH] tracing: Fix possible NULL pointer dereferences - -Currently set_ftrace_pid and set_graph_function files use seq_lseek -for their fops. However seq_open() is called only for FMODE_READ in -the fops->open() so that if an user tries to seek one of those file -when she open it for writing, it sees NULL seq_file and then panic. - -It can be easily reproduced with following command: - - $ cd /sys/kernel/debug/tracing - $ echo 1234 | sudo tee -a set_ftrace_pid - -In this example, GNU coreutils' tee opens the file with fopen(, "a") -and then the fopen() internally calls lseek(). - -Link: http://lkml.kernel.org/r/1365663302-2170-1-git-send-email-namhyung@kernel.org - -Cc: Frederic Weisbecker -Cc: Ingo Molnar -Cc: Namhyung Kim -Cc: stable@vger.kernel.org -Signed-off-by: Namhyung Kim -Signed-off-by: Steven Rostedt ---- - include/linux/ftrace.h | 2 +- - kernel/trace/ftrace.c | 10 +++++----- - kernel/trace/trace_stack.c | 2 +- - 3 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h -index 167abf9..eb3ce32 100644 ---- a/include/linux/ftrace.h -+++ b/include/linux/ftrace.h -@@ -396,7 +396,7 @@ ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf, - size_t cnt, loff_t *ppos); - ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, - size_t cnt, loff_t *ppos); --loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence); -+loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence); - int ftrace_regex_release(struct inode *inode, struct file *file); - - void __init -diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index 926ebfb..affc35d 100644 ---- a/kernel/trace/ftrace.c -+++ b/kernel/trace/ftrace.c -@@ -2697,7 +2697,7 @@ ftrace_notrace_open(struct inode *inode, struct file *file) - } - - loff_t --ftrace_regex_lseek(struct file *file, loff_t offset, int whence) -+ftrace_filter_lseek(struct file *file, loff_t offset, int whence) - { - loff_t ret; - -@@ -3570,7 +3570,7 @@ static const struct file_operations ftrace_filter_fops = { - .open = ftrace_filter_open, - .read = seq_read, - .write = ftrace_filter_write, -- .llseek = ftrace_regex_lseek, -+ .llseek = ftrace_filter_lseek, - .release = ftrace_regex_release, - }; - -@@ -3578,7 +3578,7 @@ static const struct file_operations ftrace_notrace_fops = { - .open = ftrace_notrace_open, - .read = seq_read, - .write = ftrace_notrace_write, -- .llseek = ftrace_regex_lseek, -+ .llseek = ftrace_filter_lseek, - .release = ftrace_regex_release, - }; - -@@ -3783,8 +3783,8 @@ static const struct file_operations ftrace_graph_fops = { - .open = ftrace_graph_open, - .read = seq_read, - .write = ftrace_graph_write, -+ .llseek = ftrace_filter_lseek, - .release = ftrace_graph_release, -- .llseek = seq_lseek, - }; - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ - -@@ -4439,7 +4439,7 @@ static const struct file_operations ftrace_pid_fops = { - .open = ftrace_pid_open, - .write = ftrace_pid_write, - .read = seq_read, -- .llseek = seq_lseek, -+ .llseek = ftrace_filter_lseek, - .release = ftrace_pid_release, - }; - -diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c -index 42ca822..83a8b5b 100644 ---- a/kernel/trace/trace_stack.c -+++ b/kernel/trace/trace_stack.c -@@ -322,7 +322,7 @@ static const struct file_operations stack_trace_filter_fops = { - .open = stack_trace_filter_open, - .read = seq_read, - .write = ftrace_filter_write, -- .llseek = ftrace_regex_lseek, -+ .llseek = ftrace_filter_lseek, - .release = ftrace_regex_release, - }; - --- -1.8.1.4 - diff --git a/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch b/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch deleted file mode 100644 index 31b0de8fb..000000000 --- a/x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Samu Kallio <> -Subject: [PATCH] x86: mm: Fix vmalloc_fault oops during lazy MMU updates. -Date: Sun, 17 Feb 2013 04:35:52 +0200 - -In paravirtualized x86_64 kernels, vmalloc_fault may cause an oops -when lazy MMU updates are enabled, because set_pgd effects are being -deferred. - -One instance of this problem is during process mm cleanup with memory -cgroups enabled. The chain of events is as follows: - -- zap_pte_range enables lazy MMU updates -- zap_pte_range eventually calls mem_cgroup_charge_statistics, - which accesses the vmalloc'd mem_cgroup per-cpu stat area -- vmalloc_fault is triggered which tries to sync the corresponding - PGD entry with set_pgd, but the update is deferred -- vmalloc_fault oopses due to a mismatch in the PUD entries - -Calling arch_flush_lazy_mmu_mode immediately after set_pgd makes the -changes visible to the consistency checks. - -Signed-off-by: Samu Kallio ---- - arch/x86/mm/fault.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) -diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c -index 8e13ecb..0a45298 100644 ---- a/arch/x86/mm/fault.c -+++ b/arch/x86/mm/fault.c -@@ -378,10 +378,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) - if (pgd_none(*pgd_ref)) - return -1; - -- if (pgd_none(*pgd)) -+ if (pgd_none(*pgd)) { - set_pgd(pgd, *pgd_ref); -- else -+ arch_flush_lazy_mmu_mode(); -+ } else { - BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); -+ } - - /* - * Below here mismatches are bugs because these lower tables --- -1.8.1.3 - - From e299ee3af9daacd9f70a0f7278bbd6776a9911c9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 17 Apr 2013 16:11:05 -0400 Subject: [PATCH 288/492] Fix missing raid REQ_WRITE_SAME flag commit (rhbz 947539) --- kernel.spec | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index d602d1167..a4d6d1312 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -796,6 +796,9 @@ Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch +#rhbz 947539 +Patch25013: md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch + # END OF PATCH DEFINITIONS %endif @@ -1542,6 +1545,9 @@ ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch +#rhbz 947539 +ApplyPatch md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch + # END OF PATCH APPLICATIONS %endif @@ -2399,6 +2405,9 @@ fi # ||----w | # || || %changelog +* Wed Apr 17 2013 Josh Boyer - 3.8.8-202 +- Fix missing raid REQ_WRITE_SAME flag commit (rhbz 947539) + * Wed Apr 17 2013 Josh Boyer - 3.8.8-201 - Linux v3.8.8 From 7be76a42257fda33c97db70334f6f419e28f747a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 17 Apr 2013 19:11:03 -0400 Subject: [PATCH 289/492] Actually add patch from last commit. Sigh and stuff. --- ...le-REQ_WRITE_SAME-flag-in-write-bios.patch | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch diff --git a/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch b/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch new file mode 100644 index 000000000..d9d66e22a --- /dev/null +++ b/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch @@ -0,0 +1,95 @@ +From c8dc9c654794a765ca61baed07f84ed8aaa7ca8c Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Thu, 21 Feb 2013 13:28:09 +1100 +Subject: [PATCH] md: raid1,10: Handle REQ_WRITE_SAME flag in write bios + +Set mddev queue's max_write_same_sectors to its chunk_sector value (before +disk_stack_limits merges the underlying disk limits.) With that in place, +be sure to handle writes coming down from the block layer that have the +REQ_WRITE_SAME flag set. That flag needs to be copied into any newly cloned +write bio. + +Signed-off-by: Joe Lawrence +Acked-by: "Martin K. Petersen" +Signed-off-by: NeilBrown +--- + drivers/md/raid1.c | 7 ++++++- + drivers/md/raid10.c | 9 +++++++-- + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index d5bddfc..6e5d5a5 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1000,6 +1000,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) + const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); + const unsigned long do_discard = (bio->bi_rw + & (REQ_DISCARD | REQ_SECURE)); ++ const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); + struct md_rdev *blocked_rdev; + struct blk_plug_cb *cb; + struct raid1_plug_cb *plug = NULL; +@@ -1301,7 +1302,8 @@ read_again: + conf->mirrors[i].rdev->data_offset); + mbio->bi_bdev = conf->mirrors[i].rdev->bdev; + mbio->bi_end_io = raid1_end_write_request; +- mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard; ++ mbio->bi_rw = ++ WRITE | do_flush_fua | do_sync | do_discard | do_same; + mbio->bi_private = r1_bio; + + atomic_inc(&r1_bio->remaining); +@@ -2818,6 +2820,9 @@ static int run(struct mddev *mddev) + if (IS_ERR(conf)) + return PTR_ERR(conf); + ++ if (mddev->queue) ++ blk_queue_max_write_same_sectors(mddev->queue, ++ mddev->chunk_sectors); + rdev_for_each(rdev, mddev) { + if (!mddev->gendisk) + continue; +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 64d4824..1a74c12 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1105,6 +1105,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) + const unsigned long do_fua = (bio->bi_rw & REQ_FUA); + const unsigned long do_discard = (bio->bi_rw + & (REQ_DISCARD | REQ_SECURE)); ++ const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); + unsigned long flags; + struct md_rdev *blocked_rdev; + struct blk_plug_cb *cb; +@@ -1460,7 +1461,8 @@ retry_write: + rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; +- mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; ++ mbio->bi_rw = ++ WRITE | do_sync | do_fua | do_discard | do_same; + mbio->bi_private = r10_bio; + + atomic_inc(&r10_bio->remaining); +@@ -1502,7 +1504,8 @@ retry_write: + r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; +- mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; ++ mbio->bi_rw = ++ WRITE | do_sync | do_fua | do_discard | do_same; + mbio->bi_private = r10_bio; + + atomic_inc(&r10_bio->remaining); +@@ -3569,6 +3572,8 @@ static int run(struct mddev *mddev) + if (mddev->queue) { + blk_queue_max_discard_sectors(mddev->queue, + mddev->chunk_sectors); ++ blk_queue_max_write_same_sectors(mddev->queue, ++ mddev->chunk_sectors); + blk_queue_io_min(mddev->queue, chunk_size); + if (conf->geo.raid_disks % conf->geo.near_copies) + blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); +-- +1.8.1.4 + From 811fc75c6ee6320da7f6718013ebb8d87c35fd52 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Apr 2013 14:07:48 -0400 Subject: [PATCH 290/492] CVE-2013-3222 atm: update msg_namelen in vcc_recvmsg (rhbz 955216 955228) --- atm-update-msg_namelen-in-vcc_recvmsg.patch | 35 +++++++++++++++++++++ kernel.spec | 11 ++++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 atm-update-msg_namelen-in-vcc_recvmsg.patch diff --git a/atm-update-msg_namelen-in-vcc_recvmsg.patch b/atm-update-msg_namelen-in-vcc_recvmsg.patch new file mode 100644 index 000000000..a22ef9c73 --- /dev/null +++ b/atm-update-msg_namelen-in-vcc_recvmsg.patch @@ -0,0 +1,35 @@ +From 9b3e617f3df53822345a8573b6d358f6b9e5ed87 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:47 +0000 +Subject: [PATCH] atm: update msg_namelen in vcc_recvmsg() + +The current code does not fill the msg_name member in case it is set. +It also does not set the msg_namelen member to 0 and therefore makes +net/socket.c leak the local, uninitialized sockaddr_storage variable +to userland -- 128 bytes of kernel stack memory. + +Fix that by simply setting msg_namelen to 0 as obviously nobody cared +about vcc_recvmsg() not filling the msg_name in case it was set. + +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/atm/common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/atm/common.c b/net/atm/common.c +index 7b49100..737bef5 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -531,6 +531,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + struct sk_buff *skb; + int copied, error = -EINVAL; + ++ msg->msg_namelen = 0; ++ + if (sock->state != SS_CONNECTED) + return -ENOTCONN; + +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index a4d6d1312..fe363c9e2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -799,6 +799,9 @@ Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch #rhbz 947539 Patch25013: md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch +#CVE-2013-3222 rhbz 955216 955228 +Patch25014: atm-update-msg_namelen-in-vcc_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1548,6 +1551,9 @@ ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch #rhbz 947539 ApplyPatch md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch +#CVE-2013-3222 rhbz 955216 955228 +ApplyPatch atm-update-msg_namelen-in-vcc_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2405,6 +2411,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 22 2013 Josh Boyer +- CVE-2013-3222 atm: update msg_namelen in vcc_recvmsg (rhbz 955216 955228) + * Wed Apr 17 2013 Josh Boyer - 3.8.8-202 - Fix missing raid REQ_WRITE_SAME flag commit (rhbz 947539) From 875e72cb7d9779ff47fde477c195fe4277d48d81 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 23 Apr 2013 08:15:52 -0400 Subject: [PATCH 291/492] CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) --- kernel.spec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel.spec b/kernel.spec index fe363c9e2..1b07f6cd6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,6 +802,9 @@ Patch25013: md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch #CVE-2013-3222 rhbz 955216 955228 Patch25014: atm-update-msg_namelen-in-vcc_recvmsg.patch +#CVE-2013-3224 rhbz 955599 955607 +Patch25015: Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1554,6 +1557,9 @@ ApplyPatch md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch #CVE-2013-3222 rhbz 955216 955228 ApplyPatch atm-update-msg_namelen-in-vcc_recvmsg.patch +#CVE-2013-3224 rhbz 955599 955607 +ApplyPatch Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2411,6 +2417,9 @@ fi # ||----w | # || || %changelog +* Tue Apr 23 2013 Josh Boyer +- CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) + * Mon Apr 22 2013 Josh Boyer - CVE-2013-3222 atm: update msg_namelen in vcc_recvmsg (rhbz 955216 955228) From 66a9977428716cea919b53fe565221ed3f21fda8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 23 Apr 2013 09:09:12 -0400 Subject: [PATCH 292/492] CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) - CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) --- kernel.spec | 7 ++++ net-fix-incorrect-credentials-passing.patch | 45 +++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 net-fix-incorrect-credentials-passing.patch diff --git a/kernel.spec b/kernel.spec index 1b07f6cd6..ac63caa13 100644 --- a/kernel.spec +++ b/kernel.spec @@ -805,6 +805,9 @@ Patch25014: atm-update-msg_namelen-in-vcc_recvmsg.patch #CVE-2013-3224 rhbz 955599 955607 Patch25015: Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch +#CVE-2013-1979 rhbz 955629 955647 +Patch25016: net-fix-incorrect-credentials-passing.patch + # END OF PATCH DEFINITIONS %endif @@ -1560,6 +1563,9 @@ ApplyPatch atm-update-msg_namelen-in-vcc_recvmsg.patch #CVE-2013-3224 rhbz 955599 955607 ApplyPatch Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch +#CVE-2013-1979 rhbz 955629 955647 +ApplyPatch net-fix-incorrect-credentials-passing.patch + # END OF PATCH APPLICATIONS %endif @@ -2418,6 +2424,7 @@ fi # || || %changelog * Tue Apr 23 2013 Josh Boyer +- CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) - CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) * Mon Apr 22 2013 Josh Boyer diff --git a/net-fix-incorrect-credentials-passing.patch b/net-fix-incorrect-credentials-passing.patch new file mode 100644 index 000000000..639faba6e --- /dev/null +++ b/net-fix-incorrect-credentials-passing.patch @@ -0,0 +1,45 @@ +From 83f1b4ba917db5dc5a061a44b3403ddb6e783494 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 19 Apr 2013 15:32:32 +0000 +Subject: [PATCH] net: fix incorrect credentials passing + +Commit 257b5358b32f ("scm: Capture the full credentials of the scm +sender") changed the credentials passing code to pass in the effective +uid/gid instead of the real uid/gid. + +Obviously this doesn't matter most of the time (since normally they are +the same), but it results in differences for suid binaries when the wrong +uid/gid ends up being used. + +This just undoes that (presumably unintentional) part of the commit. + +Reported-by: Andy Lutomirski +Cc: Eric W. Biederman +Cc: Serge E. Hallyn +Cc: David S. Miller +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +Acked-by: "Eric W. Biederman" +Signed-off-by: David S. Miller +--- + include/net/scm.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/net/scm.h b/include/net/scm.h +index 975cca0..b117081 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -56,8 +56,8 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, + scm->pid = get_pid(pid); + scm->cred = cred ? get_cred(cred) : NULL; + scm->creds.pid = pid_vnr(pid); +- scm->creds.uid = cred ? cred->euid : INVALID_UID; +- scm->creds.gid = cred ? cred->egid : INVALID_GID; ++ scm->creds.uid = cred ? cred->uid : INVALID_UID; ++ scm->creds.gid = cred ? cred->gid : INVALID_GID; + } + + static __inline__ void scm_destroy_cred(struct scm_cookie *scm) +-- +1.8.1.4 + From 8addbb8acf627db8672440936d478d4a0060421c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 23 Apr 2013 09:31:51 -0400 Subject: [PATCH 293/492] CVE-2013-3225 Bluetooth: RFCOMM missing msg_namelen update in rfcomm_sock_recvmsg (rhbz 955649 955658) --- ...-Fix-missing-msg_namelen-update-in-r.patch | 37 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 44 insertions(+) create mode 100644 Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch diff --git a/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch b/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch new file mode 100644 index 000000000..a4db050a6 --- /dev/null +++ b/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch @@ -0,0 +1,37 @@ +From e11e0455c0d7d3d62276a0c55d9dfbc16779d691 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:50 +0000 +Subject: [PATCH] Bluetooth: RFCOMM - Fix missing msg_namelen update in + rfcomm_sock_recvmsg() + +If RFCOMM_DEFER_SETUP is set in the flags, rfcomm_sock_recvmsg() returns +early with 0 without updating the possibly set msg_namelen member. This, +in turn, leads to a 128 byte kernel stack leak in net/socket.c. + +Fix this by updating msg_namelen in this case. For all other cases it +will be handled in bt_sock_stream_recvmsg(). + +Cc: Marcel Holtmann +Cc: Gustavo Padovan +Cc: Johan Hedberg +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/bluetooth/rfcomm/sock.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index c23bae8..7c9224b 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -608,6 +608,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { + rfcomm_dlc_accept(d); ++ msg->msg_namelen = 0; + return 0; + } + +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index ac63caa13..d867c0776 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,6 +808,9 @@ Patch25015: Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch #CVE-2013-1979 rhbz 955629 955647 Patch25016: net-fix-incorrect-credentials-passing.patch +#CVE-2013-3225 rhbz 955649 955658 +Patch25017: Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch + # END OF PATCH DEFINITIONS %endif @@ -1566,6 +1569,9 @@ ApplyPatch Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch #CVE-2013-1979 rhbz 955629 955647 ApplyPatch net-fix-incorrect-credentials-passing.patch +#CVE-2013-3225 rhbz 955649 955658 +ApplyPatch Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch + # END OF PATCH APPLICATIONS %endif @@ -2424,6 +2430,7 @@ fi # || || %changelog * Tue Apr 23 2013 Josh Boyer +- CVE-2013-3225 Bluetooth: RFCOMM missing msg_namelen update in rfcomm_sock_recvmsg (rhbz 955649 955658) - CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) - CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) From f300ffd10060c33a0d5cb1faac830ca95e324d98 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 23 Apr 2013 09:44:42 -0400 Subject: [PATCH 294/492] CVE-2013-3223 ax25: information leak via msg_name in ax25_recvmsg (rhbz 955662 955666) --- ...fo-leak-via-msg_name-in-ax25_recvmsg.patch | 38 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 45 insertions(+) create mode 100644 ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch diff --git a/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch b/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch new file mode 100644 index 000000000..818e2d9c4 --- /dev/null +++ b/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch @@ -0,0 +1,38 @@ +From ef3313e84acbf349caecae942ab3ab731471f1a1 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:48 +0000 +Subject: [PATCH] ax25: fix info leak via msg_name in ax25_recvmsg() + +When msg_namelen is non-zero the sockaddr info gets filled out, as +requested, but the code fails to initialize the padding bytes of struct +sockaddr_ax25 inserted by the compiler for alignment. Additionally the +msg_namelen value is updated to sizeof(struct full_sockaddr_ax25) but is +not always filled up to this size. + +Both issues lead to the fact that the code will leak uninitialized +kernel stack bytes in net/socket.c. + +Fix both issues by initializing the memory with memset(0). + +Cc: Ralf Baechle +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/ax25/af_ax25.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 7b11f8b..e277e38 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, + ax25_address src; + const unsigned char *mac = skb_mac_header(skb); + ++ memset(sax, 0, sizeof(struct full_sockaddr_ax25)); + ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, + &digi, NULL, NULL); + sax->sax25_family = AF_AX25; +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index d867c0776..dcdd6daec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -811,6 +811,9 @@ Patch25016: net-fix-incorrect-credentials-passing.patch #CVE-2013-3225 rhbz 955649 955658 Patch25017: Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch +#CVE-2013-3223 rhbz 955662 955666 +Patch25018: ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1572,6 +1575,9 @@ ApplyPatch net-fix-incorrect-credentials-passing.patch #CVE-2013-3225 rhbz 955649 955658 ApplyPatch Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch +#CVE-2013-3223 rhbz 955662 955666 +ApplyPatch ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2430,6 +2436,7 @@ fi # || || %changelog * Tue Apr 23 2013 Josh Boyer +- CVE-2013-3223 ax25: information leak via msg_name in ax25_recvmsg (rhbz 955662 955666) - CVE-2013-3225 Bluetooth: RFCOMM missing msg_namelen update in rfcomm_sock_recvmsg (rhbz 955649 955658) - CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) - CVE-2013-3224 Bluetooth: possible info leak in bt_sock_recvmsg (rhbz 955599 955607) From 6340edec3c2b8454f3277e47d218b046528631d0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 23 Apr 2013 18:15:00 -0400 Subject: [PATCH 295/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index dcdd6daec..2578948f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2435,7 +2435,7 @@ fi # ||----w | # || || %changelog -* Tue Apr 23 2013 Josh Boyer +* Tue Apr 23 2013 Josh Boyer - 3.8.8-203 - CVE-2013-3223 ax25: information leak via msg_name in ax25_recvmsg (rhbz 955662 955666) - CVE-2013-3225 Bluetooth: RFCOMM missing msg_namelen update in rfcomm_sock_recvmsg (rhbz 955649 955658) - CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) From a3cfd271ffac535324ad2b46db8337997b371c24 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:16:03 -0400 Subject: [PATCH 296/492] Actually add Bluetooth fix. Sigh. --- ...ossible-info-leak-in-bt_sock_recvmsg.patch | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch diff --git a/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch b/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch new file mode 100644 index 000000000..e68092ddd --- /dev/null +++ b/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch @@ -0,0 +1,47 @@ +From 4683f42fde3977bdb4e8a09622788cc8b5313778 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:49 +0000 +Subject: [PATCH] Bluetooth: fix possible info leak in bt_sock_recvmsg() + +In case the socket is already shutting down, bt_sock_recvmsg() returns +with 0 without updating msg_namelen leading to net/socket.c leaking the +local, uninitialized sockaddr_storage variable to userland -- 128 bytes +of kernel stack memory. + +Fix this by moving the msg_namelen assignment in front of the shutdown +test. + +Cc: Marcel Holtmann +Cc: Gustavo Padovan +Cc: Johan Hedberg +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/bluetooth/af_bluetooth.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c +index d3ee69b..0d1b08c 100644 +--- a/net/bluetooth/af_bluetooth.c ++++ b/net/bluetooth/af_bluetooth.c +@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags & (MSG_OOB)) + return -EOPNOTSUPP; + ++ msg->msg_namelen = 0; ++ + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) { + if (sk->sk_shutdown & RCV_SHUTDOWN) +@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + return err; + } + +- msg->msg_namelen = 0; +- + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +-- +1.8.1.4 + From d698a1000aec362787733e1d19655f9ee3f0294b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:23:22 -0400 Subject: [PATCH 297/492] CVE-2013-3076 crypto: algif suppress sending src addr info in recvmsg (rhbz 956162 956168) --- ...press-sending-source-address-informa.patch | 46 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 crypto-algif-suppress-sending-source-address-informa.patch diff --git a/crypto-algif-suppress-sending-source-address-informa.patch b/crypto-algif-suppress-sending-source-address-informa.patch new file mode 100644 index 000000000..3484c258c --- /dev/null +++ b/crypto-algif-suppress-sending-source-address-informa.patch @@ -0,0 +1,46 @@ +From 72a763d805a48ac8c0bf48fdb510e84c12de51fe Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 14:05:39 +0200 +Subject: [PATCH] crypto: algif - suppress sending source address information + in recvmsg + +The current code does not set the msg_namelen member to 0 and therefore +makes net/socket.c leak the local sockaddr_storage variable to userland +-- 128 bytes of kernel stack memory. Fix that. + +Cc: # 2.6.38 +Signed-off-by: Mathias Krause +Signed-off-by: Herbert Xu +--- + crypto/algif_hash.c | 2 ++ + crypto/algif_skcipher.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index ef5356c..0262210 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -161,6 +161,8 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, + else if (len < ds) + msg->msg_flags |= MSG_TRUNC; + ++ msg->msg_namelen = 0; ++ + lock_sock(sk); + if (ctx->more) { + ctx->more = 0; +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index 6a6dfc0..a1c4f0a 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -432,6 +432,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, + long copied = 0; + + lock_sock(sk); ++ msg->msg_namelen = 0; + for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; + iovlen--, iov++) { + unsigned long seglen = iov->iov_len; +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 2578948f9..83c0d7c63 100644 --- a/kernel.spec +++ b/kernel.spec @@ -814,6 +814,9 @@ Patch25017: Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch #CVE-2013-3223 rhbz 955662 955666 Patch25018: ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch +#CVE-2013-3076 956162 956168 +Patch25019: crypto-algif-suppress-sending-source-address-informa.patch + # END OF PATCH DEFINITIONS %endif @@ -1578,6 +1581,9 @@ ApplyPatch Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch #CVE-2013-3223 rhbz 955662 955666 ApplyPatch ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch +#CVE-2013-3076 956162 956168 +ApplyPatch crypto-algif-suppress-sending-source-address-informa.patch + # END OF PATCH APPLICATIONS %endif @@ -2435,7 +2441,10 @@ fi # ||----w | # || || %changelog -* Tue Apr 23 2013 Josh Boyer - 3.8.8-203 +* Wed Apr 24 2013 Josh Boyer +- CVE-2013-3076 crypto: algif suppress sending src addr info in recvmsg (rhbz 956162 956168) + +* Tue Apr 23 2013 Josh Boyer - CVE-2013-3223 ax25: information leak via msg_name in ax25_recvmsg (rhbz 955662 955666) - CVE-2013-3225 Bluetooth: RFCOMM missing msg_namelen update in rfcomm_sock_recvmsg (rhbz 955649 955658) - CVE-2013-1979 net: incorrect SCM_CREDENTIALS passing (rhbz 955629 955647) From eaa7646216e59d45c37980bb70f5bb330b790ca2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:26:33 -0400 Subject: [PATCH 298/492] CVE-2013-3234 rose: info leak via msg_name in rose_recvmsg (rhbz 956135 956139) --- kernel.spec | 7 ++++ ...fo-leak-via-msg_name-in-rose_recvmsg.patch | 36 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch diff --git a/kernel.spec b/kernel.spec index 83c0d7c63..5109dc75c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -817,6 +817,9 @@ Patch25018: ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch #CVE-2013-3076 956162 956168 Patch25019: crypto-algif-suppress-sending-source-address-informa.patch +#CVE-2013-3234 956135 956139 +Patch25020: rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1584,6 +1587,9 @@ ApplyPatch ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch #CVE-2013-3076 956162 956168 ApplyPatch crypto-algif-suppress-sending-source-address-informa.patch +#CVE-2013-3234 956135 956139 +ApplyPatch rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2442,6 +2448,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3234 rose: info leak via msg_name in rose_recvmsg (rhbz 956135 956139) - CVE-2013-3076 crypto: algif suppress sending src addr info in recvmsg (rhbz 956162 956168) * Tue Apr 23 2013 Josh Boyer diff --git a/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch b/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch new file mode 100644 index 000000000..81f423f65 --- /dev/null +++ b/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch @@ -0,0 +1,36 @@ +From 4a184233f21645cf0b719366210ed445d1024d72 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:59 +0000 +Subject: [PATCH] rose: fix info leak via msg_name in rose_recvmsg() + +The code in rose_recvmsg() does not initialize all of the members of +struct sockaddr_rose/full_sockaddr_rose when filling the sockaddr info. +Nor does it initialize the padding bytes of the structure inserted by +the compiler for alignment. This will lead to leaking uninitialized +kernel stack bytes in net/socket.c. + +Fix the issue by initializing the memory used for sockaddr info with +memset(0). + +Cc: Ralf Baechle +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/rose/af_rose.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index cf68e6e..9c83474 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + + if (srose != NULL) { ++ memset(srose, 0, msg->msg_namelen); + srose->srose_family = AF_ROSE; + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; +-- +1.8.1.4 + From 8499d94486ec0b6bfa496aa4d02de6da54fd57ca Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:34:57 -0400 Subject: [PATCH 299/492] CVE-2013-3233 NFC: llcp: info leaks via msg_name in llcp_sock_recvmsg (rhbz 956125 956129) --- ...o-leaks-via-msg_name-in-llcp_sock_re.patch | 61 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 68 insertions(+) create mode 100644 NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch diff --git a/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch b/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch new file mode 100644 index 000000000..e518cca51 --- /dev/null +++ b/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch @@ -0,0 +1,61 @@ +From 4a3ad999af6c1b9a872fb70f19842784779383ee Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:58 +0000 +Subject: [PATCH] NFC: llcp: fix info leaks via msg_name in llcp_sock_recvmsg() + +Upstream d26d6504f23e803824e8ebd14e52d4fc0a0b09cb + +The code in llcp_sock_recvmsg() does not initialize all the members of +struct sockaddr_nfc_llcp when filling the sockaddr info. Nor does it +initialize the padding bytes of the structure inserted by the compiler +for alignment. + +Also, if the socket is in state LLCP_CLOSED or is shutting down during +receive the msg_namelen member is not updated to 0 while otherwise +returning with 0, i.e. "success". The msg_namelen update is also +missing for stream and seqpacket sockets which don't fill the sockaddr +info. + +Both issues lead to the fact that the code will leak uninitialized +kernel stack bytes in net/socket.c. + +Fix the first issue by initializing the memory used for sockaddr info +with memset(0). Fix the second one by setting msg_namelen to 0 early. +It will be updated later if we're going to fill the msg_name member. + +Cc: Lauro Ramos Venancio +Cc: Aloisio Almeida Jr +Cc: Samuel Ortiz +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller + +Conflicts: + net/nfc/llcp/sock.c +--- + net/nfc/llcp/sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c +index fea22eb..48fb1de 100644 +--- a/net/nfc/llcp/sock.c ++++ b/net/nfc/llcp/sock.c +@@ -644,6 +644,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + pr_debug("%p %zu\n", sk, len); + ++ msg->msg_namelen = 0; ++ + lock_sock(sk); + + if (sk->sk_state == LLCP_CLOSED && +@@ -684,6 +686,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); + ++ memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sa_family = AF_NFC; + sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; + sockaddr.dsap = ui_cb->dsap; +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 5109dc75c..f7c6b84c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -820,6 +820,9 @@ Patch25019: crypto-algif-suppress-sending-source-address-informa.patch #CVE-2013-3234 956135 956139 Patch25020: rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch +#CVE-2013-3233 956125 956129 +Patch25021: NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch + # END OF PATCH DEFINITIONS %endif @@ -1590,6 +1593,9 @@ ApplyPatch crypto-algif-suppress-sending-source-address-informa.patch #CVE-2013-3234 956135 956139 ApplyPatch rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch +#CVE-2013-3233 956125 956129 +ApplyPatch NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch + # END OF PATCH APPLICATIONS %endif @@ -2448,6 +2454,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3233 NFC: llcp: info leaks via msg_name in llcp_sock_recvmsg (rhbz 956125 956129) - CVE-2013-3234 rose: info leak via msg_name in rose_recvmsg (rhbz 956135 956139) - CVE-2013-3076 crypto: algif suppress sending src addr info in recvmsg (rhbz 956162 956168) From 82eda85f498cc7527b124f73f3137c3f46127123 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:47:10 -0400 Subject: [PATCH 300/492] CVE-2013-3232 netrom: information leak via msg_name in nr_recvmsg (rhbz 956110 956113) --- kernel.spec | 7 ++++ ...-invalid-use-of-sizeof-in-nr_recvmsg.patch | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch diff --git a/kernel.spec b/kernel.spec index f7c6b84c0..7622f70a9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -823,6 +823,9 @@ Patch25020: rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch #CVE-2013-3233 956125 956129 Patch25021: NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch +#CVE-2013-3232 956110 956113 +Patch25022: netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1596,6 +1599,9 @@ ApplyPatch rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch #CVE-2013-3233 956125 956129 ApplyPatch NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch +#CVE-2013-3232 956110 956113 +ApplyPatch netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2454,6 +2460,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3232 netrom: information leak via msg_name in nr_recvmsg (rhbz 956110 956113) - CVE-2013-3233 NFC: llcp: info leaks via msg_name in llcp_sock_recvmsg (rhbz 956125 956129) - CVE-2013-3234 rose: info leak via msg_name in rose_recvmsg (rhbz 956135 956139) - CVE-2013-3076 crypto: algif suppress sending src addr info in recvmsg (rhbz 956162 956168) diff --git a/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch b/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch new file mode 100644 index 000000000..3881896f5 --- /dev/null +++ b/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch @@ -0,0 +1,35 @@ +From fdbf33caa22d6648227c39c48ae395fb36e4bd7f Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Tue, 9 Apr 2013 10:07:19 +0800 +Subject: [PATCH] netrom: fix invalid use of sizeof in nr_recvmsg() + +Upstream c802d759623acbd6e1ee9fbdabae89159a513913 + +sizeof() when applied to a pointer typed expression gives the size of the +pointer, not that of the pointed data. +Introduced by commit 3ce5ef(netrom: fix info leak via msg_name in nr_recvmsg) + +Signed-off-by: Wei Yongjun +Signed-off-by: David S. Miller + +Conflicts: + net/netrom/af_netrom.c +--- + net/netrom/af_netrom.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 7261eb8..f334fbd 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -1177,6 +1177,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, + } + + if (sax != NULL) { ++ memset(sax, 0, sizeof(*sax)); + sax->sax25_family = AF_NETROM; + skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, + AX25_ADDR_LEN); +-- +1.8.1.4 + From c416a99578ae1154e92c589ca49ca37e83427602 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:50:02 -0400 Subject: [PATCH 301/492] CVE-2013-3231 llc: Fix missing msg_namelen update in llc_ui_recvmsg (rhbz 956094 956104) --- kernel.spec | 7 ++++ ...msg_namelen-update-in-llc_ui_recvmsg.patch | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch diff --git a/kernel.spec b/kernel.spec index 7622f70a9..a3e1d2d60 100644 --- a/kernel.spec +++ b/kernel.spec @@ -826,6 +826,9 @@ Patch25021: NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch #CVE-2013-3232 956110 956113 Patch25022: netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch +#CVE-2013-3231 956094 956104 +Patch25023: llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1602,6 +1605,9 @@ ApplyPatch NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch #CVE-2013-3232 956110 956113 ApplyPatch netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch +#CVE-2013-3231 956094 956104 +ApplyPatch llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2460,6 +2466,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3231 llc: Fix missing msg_namelen update in llc_ui_recvmsg (rhbz 956094 956104) - CVE-2013-3232 netrom: information leak via msg_name in nr_recvmsg (rhbz 956110 956113) - CVE-2013-3233 NFC: llcp: info leaks via msg_name in llcp_sock_recvmsg (rhbz 956125 956129) - CVE-2013-3234 rose: info leak via msg_name in rose_recvmsg (rhbz 956135 956139) diff --git a/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch b/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch new file mode 100644 index 000000000..ef123b0f1 --- /dev/null +++ b/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch @@ -0,0 +1,37 @@ +From c77a4b9cffb6215a15196ec499490d116dfad181 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:56 +0000 +Subject: [PATCH] llc: Fix missing msg_namelen update in llc_ui_recvmsg() + +For stream sockets the code misses to update the msg_namelen member +to 0 and therefore makes net/socket.c leak the local, uninitialized +sockaddr_storage variable to userland -- 128 bytes of kernel stack +memory. The msg_namelen update is also missing for datagram sockets +in case the socket is shutting down during receive. + +Fix both issues by setting msg_namelen to 0 early. It will be +updated later if we're going to fill the msg_name member. + +Cc: Arnaldo Carvalho de Melo +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/llc/af_llc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 8870988..48aaa89 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, + int target; /* Read at least this many bytes */ + long timeo; + ++ msg->msg_namelen = 0; ++ + lock_sock(sk); + copied = -ENOTCONN; + if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) +-- +1.8.1.4 + From aba5c507e373e6a53b56f435b952a22c96c52807 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:52:41 -0400 Subject: [PATCH 302/492] CVE-2013-3230 l2tp: info leak in l2tp_ip6_recvmsg (rhbz 956088 956089) --- kernel.spec | 7 +++++ l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch | 32 ++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch diff --git a/kernel.spec b/kernel.spec index a3e1d2d60..8f056ce75 100644 --- a/kernel.spec +++ b/kernel.spec @@ -829,6 +829,9 @@ Patch25022: netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch #CVE-2013-3231 956094 956104 Patch25023: llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch +#CVE-2013-3230 956088 956089 +Patch25024: l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch + # END OF PATCH DEFINITIONS %endif @@ -1608,6 +1611,9 @@ ApplyPatch netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch #CVE-2013-3231 956094 956104 ApplyPatch llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch +#CVE-2013-3230 956088 956089 +ApplyPatch l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch + # END OF PATCH APPLICATIONS %endif @@ -2466,6 +2472,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3230 l2tp: info leak in l2tp_ip6_recvmsg (rhbz 956088 956089) - CVE-2013-3231 llc: Fix missing msg_namelen update in llc_ui_recvmsg (rhbz 956094 956104) - CVE-2013-3232 netrom: information leak via msg_name in nr_recvmsg (rhbz 956110 956113) - CVE-2013-3233 NFC: llcp: info leaks via msg_name in llcp_sock_recvmsg (rhbz 956125 956129) diff --git a/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch b/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch new file mode 100644 index 000000000..5ea7a7da6 --- /dev/null +++ b/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch @@ -0,0 +1,32 @@ +From b860d3cc62877fad02863e2a08efff69a19382d2 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:55 +0000 +Subject: [PATCH] l2tp: fix info leak in l2tp_ip6_recvmsg() + +The L2TP code for IPv6 fails to initialize the l2tp_conn_id member of +struct sockaddr_l2tpip6 and therefore leaks four bytes kernel stack +in l2tp_ip6_recvmsg() in case msg_name is set. + +Initialize l2tp_conn_id with 0 to avoid the info leak. + +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/l2tp/l2tp_ip6.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index c74f5a9..b8a6039 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, + lsa->l2tp_addr = ipv6_hdr(skb)->saddr; + lsa->l2tp_flowinfo = 0; + lsa->l2tp_scope_id = 0; ++ lsa->l2tp_conn_id = 0; + if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) + lsa->l2tp_scope_id = IP6CB(skb)->iif; + } +-- +1.8.1.4 + From 24030d84570e9f8b17889c8cde51bb193a4cca2f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:55:18 -0400 Subject: [PATCH 303/492] CVE-2013-3228 irda: missing msg_namelen update in irda_recvmsg_dgram (rhbz 956069 956071) --- ...-msg_namelen-update-in-irda_recvmsg_.patch | 37 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 44 insertions(+) create mode 100644 irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch diff --git a/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch b/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch new file mode 100644 index 000000000..074d2b48a --- /dev/null +++ b/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch @@ -0,0 +1,37 @@ +From 5ae94c0d2f0bed41d6718be743985d61b7f5c47d Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 7 Apr 2013 01:51:53 +0000 +Subject: [PATCH] irda: Fix missing msg_namelen update in irda_recvmsg_dgram() + +The current code does not fill the msg_name member in case it is set. +It also does not set the msg_namelen member to 0 and therefore makes +net/socket.c leak the local, uninitialized sockaddr_storage variable +to userland -- 128 bytes of kernel stack memory. + +Fix that by simply setting msg_namelen to 0 as obviously nobody cared +about irda_recvmsg_dgram() not filling the msg_name in case it was +set. + +Cc: Samuel Ortiz +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/irda/af_irda.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index d28e7f0..e493b33 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, + + IRDA_DEBUG(4, "%s()\n", __func__); + ++ msg->msg_namelen = 0; ++ + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); + if (!skb) +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 8f056ce75..d8dbe8699 100644 --- a/kernel.spec +++ b/kernel.spec @@ -832,6 +832,9 @@ Patch25023: llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch #CVE-2013-3230 956088 956089 Patch25024: l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch +#CVE-2013-3228 956069 956071 +Patch25025: irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch + # END OF PATCH DEFINITIONS %endif @@ -1614,6 +1617,9 @@ ApplyPatch llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch #CVE-2013-3230 956088 956089 ApplyPatch l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch +#CVE-2013-3228 956069 956071 +ApplyPatch irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch + # END OF PATCH APPLICATIONS %endif @@ -2472,6 +2478,7 @@ fi # || || %changelog * Wed Apr 24 2013 Josh Boyer +- CVE-2013-3228 irda: missing msg_namelen update in irda_recvmsg_dgram (rhbz 956069 956071) - CVE-2013-3230 l2tp: info leak in l2tp_ip6_recvmsg (rhbz 956088 956089) - CVE-2013-3231 llc: Fix missing msg_namelen update in llc_ui_recvmsg (rhbz 956094 956104) - CVE-2013-3232 netrom: information leak via msg_name in nr_recvmsg (rhbz 956110 956113) From 8f4049fe80c5bc6d916be108bce9e50ed4d5802a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Apr 2013 08:57:27 -0400 Subject: [PATCH 304/492] Add verrel for build. Let's try this again. --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index d8dbe8699..3ec719fdf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2477,7 +2477,7 @@ fi # ||----w | # || || %changelog -* Wed Apr 24 2013 Josh Boyer +* Wed Apr 24 2013 Josh Boyer - 3.8.8-203 - CVE-2013-3228 irda: missing msg_namelen update in irda_recvmsg_dgram (rhbz 956069 956071) - CVE-2013-3230 l2tp: info leak in l2tp_ip6_recvmsg (rhbz 956088 956089) - CVE-2013-3231 llc: Fix missing msg_namelen update in llc_ui_recvmsg (rhbz 956094 956104) From 9af76879a851e0a8be0d7dad3309534c07bac021 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 25 Apr 2013 15:20:40 +0100 Subject: [PATCH 305/492] minor ARM config fix --- config-armv7 | 1 + 1 file changed, 1 insertion(+) diff --git a/config-armv7 b/config-armv7 index eea4d33ff..d7d128571 100644 --- a/config-armv7 +++ b/config-armv7 @@ -151,6 +151,7 @@ CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_8250_DW=y CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y From a1255c4eb9805d4f0752b8ea25e57894095f7be9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Apr 2013 08:35:27 -0400 Subject: [PATCH 306/492] Linux v3.8.9 --- ...hecking-in-ioapic-indirect-register-.patch | 44 ----- ...buffer-overflow-in-handling-of-MSR_K.patch | 41 ----- ...MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch | 163 ------------------ ...press-sending-source-address-informa.patch | 46 ----- kernel.spec | 37 +--- ...le-REQ_WRITE_SAME-flag-in-write-bios.patch | 95 ---------- sources | 2 +- 7 files changed, 6 insertions(+), 422 deletions(-) delete mode 100644 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch delete mode 100644 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch delete mode 100644 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch delete mode 100644 crypto-algif-suppress-sending-source-address-informa.patch delete mode 100644 md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch diff --git a/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch b/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch deleted file mode 100644 index 7583f74c2..000000000 --- a/0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a2c118bfab8bc6b8bb213abfc35201e441693d55 Mon Sep 17 00:00:00 2001 -From: Andy Honig -Date: Wed, 20 Feb 2013 14:49:16 -0800 -Subject: [PATCH] KVM: Fix bounds checking in ioapic indirect register reads - (CVE-2013-1798) - -If the guest specifies a IOAPIC_REG_SELECT with an invalid value and follows -that with a read of the IOAPIC_REG_WINDOW KVM does not properly validate -that request. ioapic_read_indirect contains an -ASSERT(redir_index < IOAPIC_NUM_PINS), but the ASSERT has no effect in -non-debug builds. In recent kernels this allows a guest to cause a kernel -oops by reading invalid memory. In older kernels (pre-3.3) this allows a -guest to read from large ranges of host memory. - -Tested: tested against apic unit tests. - -Signed-off-by: Andrew Honig -Signed-off-by: Marcelo Tosatti ---- - virt/kvm/ioapic.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c -index ce82b94..5ba005c 100644 ---- a/virt/kvm/ioapic.c -+++ b/virt/kvm/ioapic.c -@@ -74,9 +74,12 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, - u32 redir_index = (ioapic->ioregsel - 0x10) >> 1; - u64 redir_content; - -- ASSERT(redir_index < IOAPIC_NUM_PINS); -+ if (redir_index < IOAPIC_NUM_PINS) -+ redir_content = -+ ioapic->redirtbl[redir_index].bits; -+ else -+ redir_content = ~0ULL; - -- redir_content = ioapic->redirtbl[redir_index].bits; - result = (ioapic->ioregsel & 0x1) ? - (redir_content >> 32) & 0xffffffff : - redir_content & 0xffffffff; --- -1.8.1.4 - diff --git a/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch b/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch deleted file mode 100644 index a4516e43e..000000000 --- a/0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch +++ /dev/null @@ -1,41 +0,0 @@ -From c300aa64ddf57d9c5d9c898a64b36877345dd4a9 Mon Sep 17 00:00:00 2001 -From: Andy Honig -Date: Mon, 11 Mar 2013 09:34:52 -0700 -Subject: [PATCH 2/3] KVM: x86: fix for buffer overflow in handling of - MSR_KVM_SYSTEM_TIME (CVE-2013-1796) - -If the guest sets the GPA of the time_page so that the request to update the -time straddles a page then KVM will write onto an incorrect page. The -write is done byusing kmap atomic to get a pointer to the page for the time -structure and then performing a memcpy to that page starting at an offset -that the guest controls. Well behaved guests always provide a 32-byte aligned -address, however a malicious guest could use this to corrupt host kernel -memory. - -Tested: Tested against kvmclock unit test. - -Signed-off-by: Andrew Honig -Signed-off-by: Marcelo Tosatti ---- - arch/x86/kvm/x86.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index f7c850b..2ade60c 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -1959,6 +1959,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - /* ...but clean it before doing the actual write */ - vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); - -+ /* Check that the address is 32-byte aligned. */ -+ if (vcpu->arch.time_offset & -+ (sizeof(struct pvclock_vcpu_time_info) - 1)) -+ break; -+ - vcpu->arch.time_page = - gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT); - --- -1.8.1.4 - diff --git a/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch b/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch deleted file mode 100644 index 7a2fe6547..000000000 --- a/0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 0b79459b482e85cb7426aa7da683a9f2c97aeae1 Mon Sep 17 00:00:00 2001 -From: Andy Honig -Date: Wed, 20 Feb 2013 14:48:10 -0800 -Subject: [PATCH 3/3] KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use - gfn_to_hva_cache functions (CVE-2013-1797) - -There is a potential use after free issue with the handling of -MSR_KVM_SYSTEM_TIME. If the guest specifies a GPA in a movable or removable -memory such as frame buffers then KVM might continue to write to that -address even after it's removed via KVM_SET_USER_MEMORY_REGION. KVM pins -the page in memory so it's unlikely to cause an issue, but if the user -space component re-purposes the memory previously used for the guest, then -the guest will be able to corrupt that memory. - -Tested: Tested against kvmclock unit test - -Signed-off-by: Andrew Honig -Signed-off-by: Marcelo Tosatti ---- - arch/x86/include/asm/kvm_host.h | 4 ++-- - arch/x86/kvm/x86.c | 47 ++++++++++++++++++----------------------- - 2 files changed, 22 insertions(+), 29 deletions(-) - -diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h -index 635a74d..4979778 100644 ---- a/arch/x86/include/asm/kvm_host.h -+++ b/arch/x86/include/asm/kvm_host.h -@@ -414,8 +414,8 @@ struct kvm_vcpu_arch { - gpa_t time; - struct pvclock_vcpu_time_info hv_clock; - unsigned int hw_tsc_khz; -- unsigned int time_offset; -- struct page *time_page; -+ struct gfn_to_hva_cache pv_time; -+ bool pv_time_enabled; - /* set guest stopped flag in pvclock flags field */ - bool pvclock_set_guest_stopped_request; - -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 2ade60c..f19ac0a 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -1406,10 +1406,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) - unsigned long flags, this_tsc_khz; - struct kvm_vcpu_arch *vcpu = &v->arch; - struct kvm_arch *ka = &v->kvm->arch; -- void *shared_kaddr; - s64 kernel_ns, max_kernel_ns; - u64 tsc_timestamp, host_tsc; -- struct pvclock_vcpu_time_info *guest_hv_clock; -+ struct pvclock_vcpu_time_info guest_hv_clock; - u8 pvclock_flags; - bool use_master_clock; - -@@ -1463,7 +1462,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) - - local_irq_restore(flags); - -- if (!vcpu->time_page) -+ if (!vcpu->pv_time_enabled) - return 0; - - /* -@@ -1525,12 +1524,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) - */ - vcpu->hv_clock.version += 2; - -- shared_kaddr = kmap_atomic(vcpu->time_page); -- -- guest_hv_clock = shared_kaddr + vcpu->time_offset; -+ if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time, -+ &guest_hv_clock, sizeof(guest_hv_clock)))) -+ return 0; - - /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */ -- pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED); -+ pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED); - - if (vcpu->pvclock_set_guest_stopped_request) { - pvclock_flags |= PVCLOCK_GUEST_STOPPED; -@@ -1543,12 +1542,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) - - vcpu->hv_clock.flags = pvclock_flags; - -- memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock, -- sizeof(vcpu->hv_clock)); -- -- kunmap_atomic(shared_kaddr); -- -- mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); -+ kvm_write_guest_cached(v->kvm, &vcpu->pv_time, -+ &vcpu->hv_clock, -+ sizeof(vcpu->hv_clock)); - return 0; - } - -@@ -1837,10 +1833,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) - - static void kvmclock_reset(struct kvm_vcpu *vcpu) - { -- if (vcpu->arch.time_page) { -- kvm_release_page_dirty(vcpu->arch.time_page); -- vcpu->arch.time_page = NULL; -- } -+ vcpu->arch.pv_time_enabled = false; - } - - static void accumulate_steal_time(struct kvm_vcpu *vcpu) -@@ -1947,6 +1940,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - break; - case MSR_KVM_SYSTEM_TIME_NEW: - case MSR_KVM_SYSTEM_TIME: { -+ u64 gpa_offset; - kvmclock_reset(vcpu); - - vcpu->arch.time = data; -@@ -1956,19 +1950,17 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - if (!(data & 1)) - break; - -- /* ...but clean it before doing the actual write */ -- vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); -+ gpa_offset = data & ~(PAGE_MASK | 1); - - /* Check that the address is 32-byte aligned. */ -- if (vcpu->arch.time_offset & -- (sizeof(struct pvclock_vcpu_time_info) - 1)) -+ if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1)) - break; - -- vcpu->arch.time_page = -- gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT); -- -- if (is_error_page(vcpu->arch.time_page)) -- vcpu->arch.time_page = NULL; -+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, -+ &vcpu->arch.pv_time, data & ~1ULL)) -+ vcpu->arch.pv_time_enabled = false; -+ else -+ vcpu->arch.pv_time_enabled = true; - - break; - } -@@ -2972,7 +2964,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu, - */ - static int kvm_set_guest_paused(struct kvm_vcpu *vcpu) - { -- if (!vcpu->arch.time_page) -+ if (!vcpu->arch.pv_time_enabled) - return -EINVAL; - vcpu->arch.pvclock_set_guest_stopped_request = true; - kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); -@@ -6723,6 +6715,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) - goto fail_free_wbinvd_dirty_mask; - - vcpu->arch.ia32_tsc_adjust_msr = 0x0; -+ vcpu->arch.pv_time_enabled = false; - kvm_async_pf_hash_reset(vcpu); - kvm_pmu_init(vcpu); - --- -1.8.1.4 - diff --git a/crypto-algif-suppress-sending-source-address-informa.patch b/crypto-algif-suppress-sending-source-address-informa.patch deleted file mode 100644 index 3484c258c..000000000 --- a/crypto-algif-suppress-sending-source-address-informa.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 72a763d805a48ac8c0bf48fdb510e84c12de51fe Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 14:05:39 +0200 -Subject: [PATCH] crypto: algif - suppress sending source address information - in recvmsg - -The current code does not set the msg_namelen member to 0 and therefore -makes net/socket.c leak the local sockaddr_storage variable to userland --- 128 bytes of kernel stack memory. Fix that. - -Cc: # 2.6.38 -Signed-off-by: Mathias Krause -Signed-off-by: Herbert Xu ---- - crypto/algif_hash.c | 2 ++ - crypto/algif_skcipher.c | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c -index ef5356c..0262210 100644 ---- a/crypto/algif_hash.c -+++ b/crypto/algif_hash.c -@@ -161,6 +161,8 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, - else if (len < ds) - msg->msg_flags |= MSG_TRUNC; - -+ msg->msg_namelen = 0; -+ - lock_sock(sk); - if (ctx->more) { - ctx->more = 0; -diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c -index 6a6dfc0..a1c4f0a 100644 ---- a/crypto/algif_skcipher.c -+++ b/crypto/algif_skcipher.c -@@ -432,6 +432,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, - long copied = 0; - - lock_sock(sk); -+ msg->msg_namelen = 0; - for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; - iovlen--, iov++) { - unsigned long seglen = iov->iov_len; --- -1.8.1.4 - diff --git a/kernel.spec b/kernel.spec index 3ec719fdf..5a9b7aad8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -772,15 +772,6 @@ Patch25000: amd64_edac_fix_rank_count.patch #rhbz 921500 Patch25001: i7300_edac_single_mode_fixup.patch -#CVE-2013-1798 rhbz 917017 923968 -Patch25003: 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch - -#CVE-2013-1796 rhbz 917012 923966 -Patch25004: 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch - -#CVE-2013-1797 rhbz 917013 923967 -Patch25005: 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch - #rhbz 920218 Patch25006: mac80211-Dont-restart-sta-timer-if-not-running.patch @@ -796,9 +787,6 @@ Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch -#rhbz 947539 -Patch25013: md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch - #CVE-2013-3222 rhbz 955216 955228 Patch25014: atm-update-msg_namelen-in-vcc_recvmsg.patch @@ -814,9 +802,6 @@ Patch25017: Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch #CVE-2013-3223 rhbz 955662 955666 Patch25018: ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch -#CVE-2013-3076 956162 956168 -Patch25019: crypto-algif-suppress-sending-source-address-informa.patch - #CVE-2013-3234 956135 956139 Patch25020: rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch @@ -1558,15 +1543,6 @@ ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch #rhbz 859282 ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch -#CVE-2013-1798 rhbz 917017 923968 -ApplyPatch 0001-KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch - -#CVE-2013-1796 rhbz 917012 923966 -ApplyPatch 0002-KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch - -#CVE-2013-1797 rhbz 917013 923967 -ApplyPatch 0003-KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch - #rhbz 920218 ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch @@ -1581,9 +1557,6 @@ ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch -#rhbz 947539 -ApplyPatch md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch - #CVE-2013-3222 rhbz 955216 955228 ApplyPatch atm-update-msg_namelen-in-vcc_recvmsg.patch @@ -1599,9 +1572,6 @@ ApplyPatch Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch #CVE-2013-3223 rhbz 955662 955666 ApplyPatch ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch -#CVE-2013-3076 956162 956168 -ApplyPatch crypto-algif-suppress-sending-source-address-informa.patch - #CVE-2013-3234 956135 956139 ApplyPatch rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch @@ -2477,6 +2447,9 @@ fi # ||----w | # || || %changelog +* Fri Apr 26 2013 Josh Boyer - 3.8.9-200 +- Linux v3.8.9 + * Wed Apr 24 2013 Josh Boyer - 3.8.8-203 - CVE-2013-3228 irda: missing msg_namelen update in irda_recvmsg_dgram (rhbz 956069 956071) - CVE-2013-3230 l2tp: info leak in l2tp_ip6_recvmsg (rhbz 956088 956089) diff --git a/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch b/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch deleted file mode 100644 index d9d66e22a..000000000 --- a/md-raid1-10-Handle-REQ_WRITE_SAME-flag-in-write-bios.patch +++ /dev/null @@ -1,95 +0,0 @@ -From c8dc9c654794a765ca61baed07f84ed8aaa7ca8c Mon Sep 17 00:00:00 2001 -From: Joe Lawrence -Date: Thu, 21 Feb 2013 13:28:09 +1100 -Subject: [PATCH] md: raid1,10: Handle REQ_WRITE_SAME flag in write bios - -Set mddev queue's max_write_same_sectors to its chunk_sector value (before -disk_stack_limits merges the underlying disk limits.) With that in place, -be sure to handle writes coming down from the block layer that have the -REQ_WRITE_SAME flag set. That flag needs to be copied into any newly cloned -write bio. - -Signed-off-by: Joe Lawrence -Acked-by: "Martin K. Petersen" -Signed-off-by: NeilBrown ---- - drivers/md/raid1.c | 7 ++++++- - drivers/md/raid10.c | 9 +++++++-- - 2 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c -index d5bddfc..6e5d5a5 100644 ---- a/drivers/md/raid1.c -+++ b/drivers/md/raid1.c -@@ -1000,6 +1000,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) - const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); - const unsigned long do_discard = (bio->bi_rw - & (REQ_DISCARD | REQ_SECURE)); -+ const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); - struct md_rdev *blocked_rdev; - struct blk_plug_cb *cb; - struct raid1_plug_cb *plug = NULL; -@@ -1301,7 +1302,8 @@ read_again: - conf->mirrors[i].rdev->data_offset); - mbio->bi_bdev = conf->mirrors[i].rdev->bdev; - mbio->bi_end_io = raid1_end_write_request; -- mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard; -+ mbio->bi_rw = -+ WRITE | do_flush_fua | do_sync | do_discard | do_same; - mbio->bi_private = r1_bio; - - atomic_inc(&r1_bio->remaining); -@@ -2818,6 +2820,9 @@ static int run(struct mddev *mddev) - if (IS_ERR(conf)) - return PTR_ERR(conf); - -+ if (mddev->queue) -+ blk_queue_max_write_same_sectors(mddev->queue, -+ mddev->chunk_sectors); - rdev_for_each(rdev, mddev) { - if (!mddev->gendisk) - continue; -diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c -index 64d4824..1a74c12 100644 ---- a/drivers/md/raid10.c -+++ b/drivers/md/raid10.c -@@ -1105,6 +1105,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) - const unsigned long do_fua = (bio->bi_rw & REQ_FUA); - const unsigned long do_discard = (bio->bi_rw - & (REQ_DISCARD | REQ_SECURE)); -+ const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); - unsigned long flags; - struct md_rdev *blocked_rdev; - struct blk_plug_cb *cb; -@@ -1460,7 +1461,8 @@ retry_write: - rdev)); - mbio->bi_bdev = rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; -- mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; -+ mbio->bi_rw = -+ WRITE | do_sync | do_fua | do_discard | do_same; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); -@@ -1502,7 +1504,8 @@ retry_write: - r10_bio, rdev)); - mbio->bi_bdev = rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; -- mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; -+ mbio->bi_rw = -+ WRITE | do_sync | do_fua | do_discard | do_same; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); -@@ -3569,6 +3572,8 @@ static int run(struct mddev *mddev) - if (mddev->queue) { - blk_queue_max_discard_sectors(mddev->queue, - mddev->chunk_sectors); -+ blk_queue_max_write_same_sectors(mddev->queue, -+ mddev->chunk_sectors); - blk_queue_io_min(mddev->queue, chunk_size); - if (conf->geo.raid_disks % conf->geo.near_copies) - blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); --- -1.8.1.4 - diff --git a/sources b/sources index 7c8f0e1f6..d9b883faa 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -08cdcef928c2ca402adf1c444a3c43ac patch-3.8.8.xz +b0c0861e8cb99273bfc4570535bbe076 patch-3.8.9.xz From 53d61ba1b1deb2be4a79a62707f37fbb25d76dab Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 29 Apr 2013 09:36:48 -0500 Subject: [PATCH 307/492] Linux v3.8.10 --- kernel.spec | 5 ++++- sources | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 5a9b7aad8..932e2fba2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2447,6 +2447,9 @@ fi # ||----w | # || || %changelog +* Mon Apr 29 2013 Justin M. Forbes - 3.8.10-200 +- Linux v3.8.10 + * Fri Apr 26 2013 Josh Boyer - 3.8.9-200 - Linux v3.8.9 diff --git a/sources b/sources index d9b883faa..9ca28ef9f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -b0c0861e8cb99273bfc4570535bbe076 patch-3.8.9.xz +973bc1c68bb5f082a66d20c94193d4ee patch-3.8.10.xz From a7a3b25626393893eeb3ed66dd9c4dd2f73a2c61 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 1 May 2013 14:15:53 -0500 Subject: [PATCH 308/492] Linux v3.8.11 --- ...-Fix-missing-msg_namelen-update-in-r.patch | 37 ---------- ...ossible-info-leak-in-bt_sock_recvmsg.patch | 47 ------------ ...o-leaks-via-msg_name-in-llcp_sock_re.patch | 61 ---------------- atm-update-msg_namelen-in-vcc_recvmsg.patch | 35 --------- ...fo-leak-via-msg_name-in-ax25_recvmsg.patch | 38 ---------- ...-msg_namelen-update-in-irda_recvmsg_.patch | 37 ---------- kernel.spec | 71 ++----------------- l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch | 32 --------- ...msg_namelen-update-in-llc_ui_recvmsg.patch | 37 ---------- net-fix-incorrect-credentials-passing.patch | 45 ------------ ...-invalid-use-of-sizeof-in-nr_recvmsg.patch | 35 --------- ...fo-leak-via-msg_name-in-rose_recvmsg.patch | 36 ---------- sources | 2 +- 13 files changed, 5 insertions(+), 508 deletions(-) delete mode 100644 Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch delete mode 100644 Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch delete mode 100644 NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch delete mode 100644 atm-update-msg_namelen-in-vcc_recvmsg.patch delete mode 100644 ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch delete mode 100644 irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch delete mode 100644 l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch delete mode 100644 llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch delete mode 100644 net-fix-incorrect-credentials-passing.patch delete mode 100644 netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch delete mode 100644 rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch diff --git a/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch b/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch deleted file mode 100644 index a4db050a6..000000000 --- a/Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e11e0455c0d7d3d62276a0c55d9dfbc16779d691 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:50 +0000 -Subject: [PATCH] Bluetooth: RFCOMM - Fix missing msg_namelen update in - rfcomm_sock_recvmsg() - -If RFCOMM_DEFER_SETUP is set in the flags, rfcomm_sock_recvmsg() returns -early with 0 without updating the possibly set msg_namelen member. This, -in turn, leads to a 128 byte kernel stack leak in net/socket.c. - -Fix this by updating msg_namelen in this case. For all other cases it -will be handled in bt_sock_stream_recvmsg(). - -Cc: Marcel Holtmann -Cc: Gustavo Padovan -Cc: Johan Hedberg -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/bluetooth/rfcomm/sock.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c -index c23bae8..7c9224b 100644 ---- a/net/bluetooth/rfcomm/sock.c -+++ b/net/bluetooth/rfcomm/sock.c -@@ -608,6 +608,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - - if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { - rfcomm_dlc_accept(d); -+ msg->msg_namelen = 0; - return 0; - } - --- -1.8.1.4 - diff --git a/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch b/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch deleted file mode 100644 index e68092ddd..000000000 --- a/Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4683f42fde3977bdb4e8a09622788cc8b5313778 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:49 +0000 -Subject: [PATCH] Bluetooth: fix possible info leak in bt_sock_recvmsg() - -In case the socket is already shutting down, bt_sock_recvmsg() returns -with 0 without updating msg_namelen leading to net/socket.c leaking the -local, uninitialized sockaddr_storage variable to userland -- 128 bytes -of kernel stack memory. - -Fix this by moving the msg_namelen assignment in front of the shutdown -test. - -Cc: Marcel Holtmann -Cc: Gustavo Padovan -Cc: Johan Hedberg -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/bluetooth/af_bluetooth.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c -index d3ee69b..0d1b08c 100644 ---- a/net/bluetooth/af_bluetooth.c -+++ b/net/bluetooth/af_bluetooth.c -@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - if (flags & (MSG_OOB)) - return -EOPNOTSUPP; - -+ msg->msg_namelen = 0; -+ - skb = skb_recv_datagram(sk, flags, noblock, &err); - if (!skb) { - if (sk->sk_shutdown & RCV_SHUTDOWN) -@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - return err; - } - -- msg->msg_namelen = 0; -- - copied = skb->len; - if (len < copied) { - msg->msg_flags |= MSG_TRUNC; --- -1.8.1.4 - diff --git a/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch b/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch deleted file mode 100644 index e518cca51..000000000 --- a/NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 4a3ad999af6c1b9a872fb70f19842784779383ee Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:58 +0000 -Subject: [PATCH] NFC: llcp: fix info leaks via msg_name in llcp_sock_recvmsg() - -Upstream d26d6504f23e803824e8ebd14e52d4fc0a0b09cb - -The code in llcp_sock_recvmsg() does not initialize all the members of -struct sockaddr_nfc_llcp when filling the sockaddr info. Nor does it -initialize the padding bytes of the structure inserted by the compiler -for alignment. - -Also, if the socket is in state LLCP_CLOSED or is shutting down during -receive the msg_namelen member is not updated to 0 while otherwise -returning with 0, i.e. "success". The msg_namelen update is also -missing for stream and seqpacket sockets which don't fill the sockaddr -info. - -Both issues lead to the fact that the code will leak uninitialized -kernel stack bytes in net/socket.c. - -Fix the first issue by initializing the memory used for sockaddr info -with memset(0). Fix the second one by setting msg_namelen to 0 early. -It will be updated later if we're going to fill the msg_name member. - -Cc: Lauro Ramos Venancio -Cc: Aloisio Almeida Jr -Cc: Samuel Ortiz -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller - -Conflicts: - net/nfc/llcp/sock.c ---- - net/nfc/llcp/sock.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c -index fea22eb..48fb1de 100644 ---- a/net/nfc/llcp/sock.c -+++ b/net/nfc/llcp/sock.c -@@ -644,6 +644,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - - pr_debug("%p %zu\n", sk, len); - -+ msg->msg_namelen = 0; -+ - lock_sock(sk); - - if (sk->sk_state == LLCP_CLOSED && -@@ -684,6 +686,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - - pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); - -+ memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sa_family = AF_NFC; - sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; - sockaddr.dsap = ui_cb->dsap; --- -1.8.1.4 - diff --git a/atm-update-msg_namelen-in-vcc_recvmsg.patch b/atm-update-msg_namelen-in-vcc_recvmsg.patch deleted file mode 100644 index a22ef9c73..000000000 --- a/atm-update-msg_namelen-in-vcc_recvmsg.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9b3e617f3df53822345a8573b6d358f6b9e5ed87 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:47 +0000 -Subject: [PATCH] atm: update msg_namelen in vcc_recvmsg() - -The current code does not fill the msg_name member in case it is set. -It also does not set the msg_namelen member to 0 and therefore makes -net/socket.c leak the local, uninitialized sockaddr_storage variable -to userland -- 128 bytes of kernel stack memory. - -Fix that by simply setting msg_namelen to 0 as obviously nobody cared -about vcc_recvmsg() not filling the msg_name in case it was set. - -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/atm/common.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/net/atm/common.c b/net/atm/common.c -index 7b49100..737bef5 100644 ---- a/net/atm/common.c -+++ b/net/atm/common.c -@@ -531,6 +531,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - struct sk_buff *skb; - int copied, error = -EINVAL; - -+ msg->msg_namelen = 0; -+ - if (sock->state != SS_CONNECTED) - return -ENOTCONN; - --- -1.8.1.4 - diff --git a/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch b/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch deleted file mode 100644 index 818e2d9c4..000000000 --- a/ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch +++ /dev/null @@ -1,38 +0,0 @@ -From ef3313e84acbf349caecae942ab3ab731471f1a1 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:48 +0000 -Subject: [PATCH] ax25: fix info leak via msg_name in ax25_recvmsg() - -When msg_namelen is non-zero the sockaddr info gets filled out, as -requested, but the code fails to initialize the padding bytes of struct -sockaddr_ax25 inserted by the compiler for alignment. Additionally the -msg_namelen value is updated to sizeof(struct full_sockaddr_ax25) but is -not always filled up to this size. - -Both issues lead to the fact that the code will leak uninitialized -kernel stack bytes in net/socket.c. - -Fix both issues by initializing the memory with memset(0). - -Cc: Ralf Baechle -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/ax25/af_ax25.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c -index 7b11f8b..e277e38 100644 ---- a/net/ax25/af_ax25.c -+++ b/net/ax25/af_ax25.c -@@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, - ax25_address src; - const unsigned char *mac = skb_mac_header(skb); - -+ memset(sax, 0, sizeof(struct full_sockaddr_ax25)); - ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, - &digi, NULL, NULL); - sax->sax25_family = AF_AX25; --- -1.8.1.4 - diff --git a/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch b/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch deleted file mode 100644 index 074d2b48a..000000000 --- a/irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 5ae94c0d2f0bed41d6718be743985d61b7f5c47d Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:53 +0000 -Subject: [PATCH] irda: Fix missing msg_namelen update in irda_recvmsg_dgram() - -The current code does not fill the msg_name member in case it is set. -It also does not set the msg_namelen member to 0 and therefore makes -net/socket.c leak the local, uninitialized sockaddr_storage variable -to userland -- 128 bytes of kernel stack memory. - -Fix that by simply setting msg_namelen to 0 as obviously nobody cared -about irda_recvmsg_dgram() not filling the msg_name in case it was -set. - -Cc: Samuel Ortiz -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/irda/af_irda.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c -index d28e7f0..e493b33 100644 ---- a/net/irda/af_irda.c -+++ b/net/irda/af_irda.c -@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, - - IRDA_DEBUG(4, "%s()\n", __func__); - -+ msg->msg_namelen = 0; -+ - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, - flags & MSG_DONTWAIT, &err); - if (!skb) --- -1.8.1.4 - diff --git a/kernel.spec b/kernel.spec index 932e2fba2..4344f9769 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -787,39 +787,6 @@ Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch -#CVE-2013-3222 rhbz 955216 955228 -Patch25014: atm-update-msg_namelen-in-vcc_recvmsg.patch - -#CVE-2013-3224 rhbz 955599 955607 -Patch25015: Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch - -#CVE-2013-1979 rhbz 955629 955647 -Patch25016: net-fix-incorrect-credentials-passing.patch - -#CVE-2013-3225 rhbz 955649 955658 -Patch25017: Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch - -#CVE-2013-3223 rhbz 955662 955666 -Patch25018: ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch - -#CVE-2013-3234 956135 956139 -Patch25020: rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch - -#CVE-2013-3233 956125 956129 -Patch25021: NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch - -#CVE-2013-3232 956110 956113 -Patch25022: netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch - -#CVE-2013-3231 956094 956104 -Patch25023: llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch - -#CVE-2013-3230 956088 956089 -Patch25024: l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch - -#CVE-2013-3228 956069 956071 -Patch25025: irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch - # END OF PATCH DEFINITIONS %endif @@ -1557,39 +1524,6 @@ ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch #rhbz 951241 ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch -#CVE-2013-3222 rhbz 955216 955228 -ApplyPatch atm-update-msg_namelen-in-vcc_recvmsg.patch - -#CVE-2013-3224 rhbz 955599 955607 -ApplyPatch Bluetooth-fix-possible-info-leak-in-bt_sock_recvmsg.patch - -#CVE-2013-1979 rhbz 955629 955647 -ApplyPatch net-fix-incorrect-credentials-passing.patch - -#CVE-2013-3225 rhbz 955649 955658 -ApplyPatch Bluetooth-RFCOMM-Fix-missing-msg_namelen-update-in-r.patch - -#CVE-2013-3223 rhbz 955662 955666 -ApplyPatch ax25-fix-info-leak-via-msg_name-in-ax25_recvmsg.patch - -#CVE-2013-3234 956135 956139 -ApplyPatch rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch - -#CVE-2013-3233 956125 956129 -ApplyPatch NFC-llcp-fix-info-leaks-via-msg_name-in-llcp_sock_re.patch - -#CVE-2013-3232 956110 956113 -ApplyPatch netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch - -#CVE-2013-3231 956094 956104 -ApplyPatch llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch - -#CVE-2013-3230 956088 956089 -ApplyPatch l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch - -#CVE-2013-3228 956069 956071 -ApplyPatch irda-Fix-missing-msg_namelen-update-in-irda_recvmsg_.patch - # END OF PATCH APPLICATIONS %endif @@ -2447,6 +2381,9 @@ fi # ||----w | # || || %changelog +* Wed May 01 2013 Justin M. Forbes - 3.8.11-200 +- Linux v3.8.11 + * Mon Apr 29 2013 Justin M. Forbes - 3.8.10-200 - Linux v3.8.10 diff --git a/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch b/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch deleted file mode 100644 index 5ea7a7da6..000000000 --- a/l2tp-fix-info-leak-in-l2tp_ip6_recvmsg.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b860d3cc62877fad02863e2a08efff69a19382d2 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:55 +0000 -Subject: [PATCH] l2tp: fix info leak in l2tp_ip6_recvmsg() - -The L2TP code for IPv6 fails to initialize the l2tp_conn_id member of -struct sockaddr_l2tpip6 and therefore leaks four bytes kernel stack -in l2tp_ip6_recvmsg() in case msg_name is set. - -Initialize l2tp_conn_id with 0 to avoid the info leak. - -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/l2tp/l2tp_ip6.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c -index c74f5a9..b8a6039 100644 ---- a/net/l2tp/l2tp_ip6.c -+++ b/net/l2tp/l2tp_ip6.c -@@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, - lsa->l2tp_addr = ipv6_hdr(skb)->saddr; - lsa->l2tp_flowinfo = 0; - lsa->l2tp_scope_id = 0; -+ lsa->l2tp_conn_id = 0; - if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) - lsa->l2tp_scope_id = IP6CB(skb)->iif; - } --- -1.8.1.4 - diff --git a/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch b/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch deleted file mode 100644 index ef123b0f1..000000000 --- a/llc-Fix-missing-msg_namelen-update-in-llc_ui_recvmsg.patch +++ /dev/null @@ -1,37 +0,0 @@ -From c77a4b9cffb6215a15196ec499490d116dfad181 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:56 +0000 -Subject: [PATCH] llc: Fix missing msg_namelen update in llc_ui_recvmsg() - -For stream sockets the code misses to update the msg_namelen member -to 0 and therefore makes net/socket.c leak the local, uninitialized -sockaddr_storage variable to userland -- 128 bytes of kernel stack -memory. The msg_namelen update is also missing for datagram sockets -in case the socket is shutting down during receive. - -Fix both issues by setting msg_namelen to 0 early. It will be -updated later if we're going to fill the msg_name member. - -Cc: Arnaldo Carvalho de Melo -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/llc/af_llc.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c -index 8870988..48aaa89 100644 ---- a/net/llc/af_llc.c -+++ b/net/llc/af_llc.c -@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, - int target; /* Read at least this many bytes */ - long timeo; - -+ msg->msg_namelen = 0; -+ - lock_sock(sk); - copied = -ENOTCONN; - if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) --- -1.8.1.4 - diff --git a/net-fix-incorrect-credentials-passing.patch b/net-fix-incorrect-credentials-passing.patch deleted file mode 100644 index 639faba6e..000000000 --- a/net-fix-incorrect-credentials-passing.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 83f1b4ba917db5dc5a061a44b3403ddb6e783494 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Fri, 19 Apr 2013 15:32:32 +0000 -Subject: [PATCH] net: fix incorrect credentials passing - -Commit 257b5358b32f ("scm: Capture the full credentials of the scm -sender") changed the credentials passing code to pass in the effective -uid/gid instead of the real uid/gid. - -Obviously this doesn't matter most of the time (since normally they are -the same), but it results in differences for suid binaries when the wrong -uid/gid ends up being used. - -This just undoes that (presumably unintentional) part of the commit. - -Reported-by: Andy Lutomirski -Cc: Eric W. Biederman -Cc: Serge E. Hallyn -Cc: David S. Miller -Cc: stable@vger.kernel.org -Signed-off-by: Linus Torvalds -Acked-by: "Eric W. Biederman" -Signed-off-by: David S. Miller ---- - include/net/scm.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/net/scm.h b/include/net/scm.h -index 975cca0..b117081 100644 ---- a/include/net/scm.h -+++ b/include/net/scm.h -@@ -56,8 +56,8 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, - scm->pid = get_pid(pid); - scm->cred = cred ? get_cred(cred) : NULL; - scm->creds.pid = pid_vnr(pid); -- scm->creds.uid = cred ? cred->euid : INVALID_UID; -- scm->creds.gid = cred ? cred->egid : INVALID_GID; -+ scm->creds.uid = cred ? cred->uid : INVALID_UID; -+ scm->creds.gid = cred ? cred->gid : INVALID_GID; - } - - static __inline__ void scm_destroy_cred(struct scm_cookie *scm) --- -1.8.1.4 - diff --git a/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch b/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch deleted file mode 100644 index 3881896f5..000000000 --- a/netrom-fix-invalid-use-of-sizeof-in-nr_recvmsg.patch +++ /dev/null @@ -1,35 +0,0 @@ -From fdbf33caa22d6648227c39c48ae395fb36e4bd7f Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Tue, 9 Apr 2013 10:07:19 +0800 -Subject: [PATCH] netrom: fix invalid use of sizeof in nr_recvmsg() - -Upstream c802d759623acbd6e1ee9fbdabae89159a513913 - -sizeof() when applied to a pointer typed expression gives the size of the -pointer, not that of the pointed data. -Introduced by commit 3ce5ef(netrom: fix info leak via msg_name in nr_recvmsg) - -Signed-off-by: Wei Yongjun -Signed-off-by: David S. Miller - -Conflicts: - net/netrom/af_netrom.c ---- - net/netrom/af_netrom.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c -index 7261eb8..f334fbd 100644 ---- a/net/netrom/af_netrom.c -+++ b/net/netrom/af_netrom.c -@@ -1177,6 +1177,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, - } - - if (sax != NULL) { -+ memset(sax, 0, sizeof(*sax)); - sax->sax25_family = AF_NETROM; - skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, - AX25_ADDR_LEN); --- -1.8.1.4 - diff --git a/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch b/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch deleted file mode 100644 index 81f423f65..000000000 --- a/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4a184233f21645cf0b719366210ed445d1024d72 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Sun, 7 Apr 2013 01:51:59 +0000 -Subject: [PATCH] rose: fix info leak via msg_name in rose_recvmsg() - -The code in rose_recvmsg() does not initialize all of the members of -struct sockaddr_rose/full_sockaddr_rose when filling the sockaddr info. -Nor does it initialize the padding bytes of the structure inserted by -the compiler for alignment. This will lead to leaking uninitialized -kernel stack bytes in net/socket.c. - -Fix the issue by initializing the memory used for sockaddr info with -memset(0). - -Cc: Ralf Baechle -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/rose/af_rose.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c -index cf68e6e..9c83474 100644 ---- a/net/rose/af_rose.c -+++ b/net/rose/af_rose.c -@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, - skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - - if (srose != NULL) { -+ memset(srose, 0, msg->msg_namelen); - srose->srose_family = AF_ROSE; - srose->srose_addr = rose->dest_addr; - srose->srose_call = rose->dest_call; --- -1.8.1.4 - diff --git a/sources b/sources index 9ca28ef9f..b1f904923 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -973bc1c68bb5f082a66d20c94193d4ee patch-3.8.10.xz +76ec67882ad94b8ab43c70a46befca13 patch-3.8.11.xz From 2123b28761b086bc0be17395cb8ec43cec461e90 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 6 May 2013 16:03:31 -0400 Subject: [PATCH 309/492] Rebase to Linux 3.9 merged: silence-empty-ipi-mask-warning.patch merged: quiet-apm.patch merged: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch merged: Input-add-support-for-Cypress-PS2-Trackpads.patch merged: Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch merged: alps-v2.patch merged: userns-avoid-recursion-in-put_user_ns.patch merged: amd64_edac_fix_rank_count.patch merged: team-net-next-update-20130307.patch merged: uvcvideo-suspend-fix.patch merged: cfg80211-mac80211-disconnect-on-suspend.patch merged: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch merged: mac80211-Dont-restart-sta-timer-if-not-running.patch merged: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch TODO: secure-boot TODO: ARM configs. --- ...pport-for-atheros-04ca-3004-device-t.patch | 62 - ...dd-support-for-Cypress-PS2-Trackpads.patch | 1063 ------- ...s2-fix-trackpadi-found-in-Dell-XPS12.patch | 71 - alps-v2.patch | 2494 ----------------- amd64_edac_fix_rank_count.patch | 182 -- cfg80211-mac80211-disconnect-on-suspend.patch | 227 -- config-debug | 1 + config-generic | 107 +- config-nodebug | 1 + config-powerpc-generic | 6 + config-powerpc64 | 4 +- config-powerpc64p7 | 3 +- config-x86-32-generic | 3 + config-x86-generic | 37 +- config-x86_64-generic | 3 + debug-bad-pte-modules.patch | 8 +- drm-i915-dp-stfu.patch | 6 +- kernel.spec | 96 +- ...ont-restart-sta-timer-if-not-running.patch | 55 - ...ieee80211_do_stop_while_suspend_v3.8.patch | 71 - quiet-apm.patch | 13 - serial-460800.patch | 4 +- silence-empty-ipi-mask-warning.patch | 11 - sources | 3 +- taint-vbox.patch | 14 +- team-net-next-update-20130307.patch | 608 ---- userns-avoid-recursion-in-put_user_ns.patch | 117 - uvcvideo-suspend-fix.patch | 38 - 28 files changed, 179 insertions(+), 5129 deletions(-) delete mode 100644 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch delete mode 100644 Input-add-support-for-Cypress-PS2-Trackpads.patch delete mode 100644 Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch delete mode 100644 alps-v2.patch delete mode 100644 amd64_edac_fix_rank_count.patch delete mode 100644 cfg80211-mac80211-disconnect-on-suspend.patch delete mode 100644 mac80211-Dont-restart-sta-timer-if-not-running.patch delete mode 100644 mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch delete mode 100644 quiet-apm.patch delete mode 100644 silence-empty-ipi-mask-warning.patch delete mode 100644 team-net-next-update-20130307.patch delete mode 100644 userns-avoid-recursion-in-put_user_ns.patch delete mode 100644 uvcvideo-suspend-fix.patch diff --git a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch b/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch deleted file mode 100644 index a15d00b6a..000000000 --- a/0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 017de1136ff304ab401dbfee4eca2e796c61797f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 19 Feb 2013 11:54:16 -0500 -Subject: [PATCH] Bluetooth: Add support for atheros 04ca:3004 device to ath3k - -Yet another version of the atheros bluetooth chipset - -T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 -D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=04ca ProdID=3004 Rev=00.01 -S: Manufacturer=Atheros Communications -S: Product=Bluetooth USB Host Controller -S: SerialNumber=Alaska Day 2006 -C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA -I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb -I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb - -This resolves https://bugzilla.redhat.com/show_bug.cgi?id=844750 - -Reported-by: niktr@mail.ru -Signed-off-by: Josh Boyer -Signed-off-by: Gustavo Padovan ---- - drivers/bluetooth/ath3k.c | 2 ++ - drivers/bluetooth/btusb.c | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index 33c9a44..b9908dd 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = { - { USB_DEVICE(0x0CF3, 0x311D) }, - { USB_DEVICE(0x0CF3, 0x817a) }, - { USB_DEVICE(0x13d3, 0x3375) }, -+ { USB_DEVICE(0x04CA, 0x3004) }, - { USB_DEVICE(0x04CA, 0x3005) }, - { USB_DEVICE(0x04CA, 0x3006) }, - { USB_DEVICE(0x04CA, 0x3008) }, -@@ -108,6 +109,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 7e351e3..59cde8e 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -134,6 +134,7 @@ static struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, --- -1.8.1.4 - diff --git a/Input-add-support-for-Cypress-PS2-Trackpads.patch b/Input-add-support-for-Cypress-PS2-Trackpads.patch deleted file mode 100644 index 8c5e569f9..000000000 --- a/Input-add-support-for-Cypress-PS2-Trackpads.patch +++ /dev/null @@ -1,1063 +0,0 @@ -From 0799a924bc93ba46a23e8e7e6b1431ab585fd2ea Mon Sep 17 00:00:00 2001 -From: Dudley Du -Date: Sat, 5 Jan 2013 00:14:22 -0800 -Subject: [PATCH] Input: add support for Cypress PS/2 Trackpads - -This driver, submitted on behalf of Cypress Semiconductor Corporation and -additional contributors, provides support for the Cypress PS/2 Trackpad. - -Original code contributed by Dudley Du (Cypress Semiconductor Corporation), -modified by Kamal Mostafa and Kyle Fazzari. - -BugLink: http://launchpad.net/bugs/978807 - -Signed-off-by: Dudley Du -Signed-off-by: Kamal Mostafa -Signed-off-by: Kyle Fazzari -Signed-off-by: Mario Limonciello -Signed-off-by: Tim Gardner -Acked-by: Herton Krzesinski -Reviewed-by: Henrik Rydberg -Reviewed-by: Dudley Du -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/Kconfig | 10 + - drivers/input/mouse/Makefile | 1 + - drivers/input/mouse/cypress_ps2.c | 725 ++++++++++++++++++++++++++++++++++++ - drivers/input/mouse/cypress_ps2.h | 191 ++++++++++ - drivers/input/mouse/psmouse-base.c | 32 ++ - drivers/input/mouse/psmouse.h | 1 + - 6 files changed, 960 insertions(+), 0 deletions(-) - create mode 100644 drivers/input/mouse/cypress_ps2.c - create mode 100644 drivers/input/mouse/cypress_ps2.h - -diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig -index cd6268c..88954dd 100644 ---- a/drivers/input/mouse/Kconfig -+++ b/drivers/input/mouse/Kconfig -@@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS - - If unsure, say Y. - -+config MOUSE_PS2_CYPRESS -+ bool "Cypress PS/2 mouse protocol extension" if EXPERT -+ default y -+ depends on MOUSE_PS2 -+ help -+ Say Y here if you have a Cypress PS/2 Trackpad connected to -+ your system. -+ -+ If unsure, say Y. -+ - config MOUSE_PS2_LIFEBOOK - bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT - default y -diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile -index 46ba755..323e352 100644 ---- a/drivers/input/mouse/Makefile -+++ b/drivers/input/mouse/Makefile -@@ -32,3 +32,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o - psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o - psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o - psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o -+psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o -diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c -new file mode 100644 -index 0000000..1673dc6 ---- /dev/null -+++ b/drivers/input/mouse/cypress_ps2.c -@@ -0,0 +1,725 @@ -+/* -+ * Cypress Trackpad PS/2 mouse driver -+ * -+ * Copyright (c) 2012 Cypress Semiconductor Corporation. -+ * -+ * Author: -+ * Dudley Du -+ * -+ * Additional contributors include: -+ * Kamal Mostafa -+ * Kyle Fazzari -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published by -+ * the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cypress_ps2.h" -+ -+#undef CYTP_DEBUG_VERBOSE /* define this and DEBUG for more verbose dump */ -+ -+static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ cytp->pkt_size = n; -+} -+ -+static const unsigned char cytp_rate[] = {10, 20, 40, 60, 100, 200}; -+static const unsigned char cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; -+ -+static int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { -+ psmouse_dbg(psmouse, -+ "sending command 0x%02x failed, resp 0x%02x\n", -+ value & 0xff, ps2dev->nak); -+ if (ps2dev->nak == CYTP_PS2_RETRY) -+ return CYTP_PS2_RETRY; -+ else -+ return CYTP_PS2_ERROR; -+ } -+ -+#ifdef CYTP_DEBUG_VERBOSE -+ psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", -+ value & 0xff); -+#endif -+ -+ return 0; -+} -+ -+static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, -+ unsigned char data) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int tries = CYTP_PS2_CMD_TRIES; -+ int rc; -+ -+ ps2_begin_command(ps2dev); -+ -+ do { -+ /* -+ * Send extension command byte (0xE8 or 0xF3). -+ * If sending the command fails, send recovery command -+ * to make the device return to the ready state. -+ */ -+ rc = cypress_ps2_sendbyte(psmouse, cmd & 0xff); -+ if (rc == CYTP_PS2_RETRY) { -+ rc = cypress_ps2_sendbyte(psmouse, 0x00); -+ if (rc == CYTP_PS2_RETRY) -+ rc = cypress_ps2_sendbyte(psmouse, 0x0a); -+ } -+ if (rc == CYTP_PS2_ERROR) -+ continue; -+ -+ rc = cypress_ps2_sendbyte(psmouse, data); -+ if (rc == CYTP_PS2_RETRY) -+ rc = cypress_ps2_sendbyte(psmouse, data); -+ if (rc == CYTP_PS2_ERROR) -+ continue; -+ else -+ break; -+ } while (--tries > 0); -+ -+ ps2_end_command(ps2dev); -+ -+ return rc; -+} -+ -+static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, -+ unsigned char cmd, -+ unsigned char *param) -+{ -+ int rc; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ enum psmouse_state old_state; -+ int pktsize; -+ -+ ps2_begin_command(&psmouse->ps2dev); -+ -+ old_state = psmouse->state; -+ psmouse->state = PSMOUSE_CMD_MODE; -+ psmouse->pktcnt = 0; -+ -+ pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3; -+ memset(param, 0, pktsize); -+ -+ rc = cypress_ps2_sendbyte(psmouse, 0xe9); -+ if (rc < 0) -+ goto out; -+ -+ wait_event_timeout(ps2dev->wait, -+ (psmouse->pktcnt >= pktsize), -+ msecs_to_jiffies(CYTP_CMD_TIMEOUT)); -+ -+ memcpy(param, psmouse->packet, pktsize); -+ -+ psmouse_dbg(psmouse, "Command 0x%02x response data (0x): %*ph\n", -+ cmd, pktsize, param); -+ -+out: -+ psmouse->state = old_state; -+ psmouse->pktcnt = 0; -+ -+ ps2_end_command(&psmouse->ps2dev); -+ -+ return rc; -+} -+ -+static bool cypress_verify_cmd_state(struct psmouse *psmouse, -+ unsigned char cmd, unsigned char *param) -+{ -+ bool rate_match = false; -+ bool resolution_match = false; -+ int i; -+ -+ /* callers will do further checking. */ -+ if (cmd == CYTP_CMD_READ_CYPRESS_ID || -+ cmd == CYTP_CMD_STANDARD_MODE || -+ cmd == CYTP_CMD_READ_TP_METRICS) -+ return true; -+ -+ if ((~param[0] & DFLT_RESP_BITS_VALID) == DFLT_RESP_BITS_VALID && -+ (param[0] & DFLT_RESP_BIT_MODE) == DFLT_RESP_STREAM_MODE) { -+ for (i = 0; i < sizeof(cytp_resolution); i++) -+ if (cytp_resolution[i] == param[1]) -+ resolution_match = true; -+ -+ for (i = 0; i < sizeof(cytp_rate); i++) -+ if (cytp_rate[i] == param[2]) -+ rate_match = true; -+ -+ if (resolution_match && rate_match) -+ return true; -+ } -+ -+ psmouse_dbg(psmouse, "verify cmd state failed.\n"); -+ return false; -+} -+ -+static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, -+ unsigned char *param) -+{ -+ int tries = CYTP_PS2_CMD_TRIES; -+ int rc; -+ -+ psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n", -+ cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd), -+ DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd)); -+ -+ do { -+ cypress_ps2_ext_cmd(psmouse, -+ PSMOUSE_CMD_SETRES, DECODE_CMD_DD(cmd)); -+ cypress_ps2_ext_cmd(psmouse, -+ PSMOUSE_CMD_SETRES, DECODE_CMD_CC(cmd)); -+ cypress_ps2_ext_cmd(psmouse, -+ PSMOUSE_CMD_SETRES, DECODE_CMD_BB(cmd)); -+ cypress_ps2_ext_cmd(psmouse, -+ PSMOUSE_CMD_SETRES, DECODE_CMD_AA(cmd)); -+ -+ rc = cypress_ps2_read_cmd_status(psmouse, cmd, param); -+ if (rc) -+ continue; -+ -+ if (cypress_verify_cmd_state(psmouse, cmd, param)) -+ return 0; -+ -+ } while (--tries > 0); -+ -+ return -EIO; -+} -+ -+int cypress_detect(struct psmouse *psmouse, bool set_properties) -+{ -+ unsigned char param[3]; -+ -+ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) -+ return -ENODEV; -+ -+ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ -+ if (param[0] != 0x33 || param[1] != 0xCC) -+ return -ENODEV; -+ -+ if (set_properties) { -+ psmouse->vendor = "Cypress"; -+ psmouse->name = "Trackpad"; -+ } -+ -+ return 0; -+} -+ -+static int cypress_read_fw_version(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ unsigned char param[3]; -+ -+ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) -+ return -ENODEV; -+ -+ /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ -+ if (param[0] != 0x33 || param[1] != 0xCC) -+ return -ENODEV; -+ -+ cytp->fw_version = param[2] & FW_VERSION_MASX; -+ cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; -+ -+ psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); -+ psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", -+ cytp->tp_metrics_supported); -+ -+ return 0; -+} -+ -+static int cypress_read_tp_metrics(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ unsigned char param[8]; -+ -+ /* set default values for tp metrics. */ -+ cytp->tp_width = CYTP_DEFAULT_WIDTH; -+ cytp->tp_high = CYTP_DEFAULT_HIGH; -+ cytp->tp_max_abs_x = CYTP_ABS_MAX_X; -+ cytp->tp_max_abs_y = CYTP_ABS_MAX_Y; -+ cytp->tp_min_pressure = CYTP_MIN_PRESSURE; -+ cytp->tp_max_pressure = CYTP_MAX_PRESSURE; -+ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; -+ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; -+ -+ memset(param, 0, sizeof(param)); -+ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { -+ /* Update trackpad parameters. */ -+ cytp->tp_max_abs_x = (param[1] << 8) | param[0]; -+ cytp->tp_max_abs_y = (param[3] << 8) | param[2]; -+ cytp->tp_min_pressure = param[4]; -+ cytp->tp_max_pressure = param[5]; -+ } -+ -+ if (!cytp->tp_max_pressure || -+ cytp->tp_max_pressure < cytp->tp_min_pressure || -+ !cytp->tp_width || !cytp->tp_high || -+ !cytp->tp_max_abs_x || -+ cytp->tp_max_abs_x < cytp->tp_width || -+ !cytp->tp_max_abs_y || -+ cytp->tp_max_abs_y < cytp->tp_high) -+ return -EINVAL; -+ -+ cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; -+ cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; -+ -+#ifdef CYTP_DEBUG_VERBOSE -+ psmouse_dbg(psmouse, "Dump trackpad hardware configuration as below:\n"); -+ psmouse_dbg(psmouse, "cytp->tp_width = %d\n", cytp->tp_width); -+ psmouse_dbg(psmouse, "cytp->tp_high = %d\n", cytp->tp_high); -+ psmouse_dbg(psmouse, "cytp->tp_max_abs_x = %d\n", cytp->tp_max_abs_x); -+ psmouse_dbg(psmouse, "cytp->tp_max_abs_y = %d\n", cytp->tp_max_abs_y); -+ psmouse_dbg(psmouse, "cytp->tp_min_pressure = %d\n", cytp->tp_min_pressure); -+ psmouse_dbg(psmouse, "cytp->tp_max_pressure = %d\n", cytp->tp_max_pressure); -+ psmouse_dbg(psmouse, "cytp->tp_res_x = %d\n", cytp->tp_res_x); -+ psmouse_dbg(psmouse, "cytp->tp_res_y = %d\n", cytp->tp_res_y); -+ -+ psmouse_dbg(psmouse, "tp_type_APA = %d\n", -+ (param[6] & TP_METRICS_BIT_APA) ? 1 : 0); -+ psmouse_dbg(psmouse, "tp_type_MTG = %d\n", -+ (param[6] & TP_METRICS_BIT_MTG) ? 1 : 0); -+ psmouse_dbg(psmouse, "tp_palm = %d\n", -+ (param[6] & TP_METRICS_BIT_PALM) ? 1 : 0); -+ psmouse_dbg(psmouse, "tp_stubborn = %d\n", -+ (param[6] & TP_METRICS_BIT_STUBBORN) ? 1 : 0); -+ psmouse_dbg(psmouse, "tp_1f_jitter = %d\n", -+ (param[6] & TP_METRICS_BIT_1F_JITTER) >> 2); -+ psmouse_dbg(psmouse, "tp_2f_jitter = %d\n", -+ (param[6] & TP_METRICS_BIT_2F_JITTER) >> 4); -+ psmouse_dbg(psmouse, "tp_1f_spike = %d\n", -+ param[7] & TP_METRICS_BIT_1F_SPIKE); -+ psmouse_dbg(psmouse, "tp_2f_spike = %d\n", -+ (param[7] & TP_METRICS_BIT_2F_SPIKE) >> 2); -+ psmouse_dbg(psmouse, "tp_abs_packet_format_set = %d\n", -+ (param[7] & TP_METRICS_BIT_ABS_PKT_FORMAT_SET) >> 4); -+#endif -+ -+ return 0; -+} -+ -+static int cypress_query_hardware(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ int ret; -+ -+ ret = cypress_read_fw_version(psmouse); -+ if (ret) -+ return ret; -+ -+ if (cytp->tp_metrics_supported) { -+ ret = cypress_read_tp_metrics(psmouse); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int cypress_set_absolute_mode(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ unsigned char param[3]; -+ -+ if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) -+ return -1; -+ -+ cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) -+ | CYTP_BIT_ABS_PRESSURE; -+ cypress_set_packet_size(psmouse, 5); -+ -+ return 0; -+} -+ -+/* -+ * Reset trackpad device. -+ * This is also the default mode when trackpad powered on. -+ */ -+static void cypress_reset(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ -+ cytp->mode = 0; -+ -+ psmouse_reset(psmouse); -+} -+ -+static int cypress_set_input_params(struct input_dev *input, -+ struct cytp_data *cytp) -+{ -+ int ret; -+ -+ if (!cytp->tp_res_x || !cytp->tp_res_y) -+ return -EINVAL; -+ -+ __set_bit(EV_ABS, input->evbit); -+ input_set_abs_params(input, ABS_X, 0, cytp->tp_max_abs_x, 0, 0); -+ input_set_abs_params(input, ABS_Y, 0, cytp->tp_max_abs_y, 0, 0); -+ input_set_abs_params(input, ABS_PRESSURE, -+ cytp->tp_min_pressure, cytp->tp_max_pressure, 0, 0); -+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); -+ -+ /* finger position */ -+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, cytp->tp_max_abs_x, 0, 0); -+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cytp->tp_max_abs_y, 0, 0); -+ input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); -+ -+ ret = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, -+ INPUT_MT_DROP_UNUSED|INPUT_MT_TRACK); -+ if (ret < 0) -+ return ret; -+ -+ __set_bit(INPUT_PROP_SEMI_MT, input->propbit); -+ -+ input_abs_set_res(input, ABS_X, cytp->tp_res_x); -+ input_abs_set_res(input, ABS_Y, cytp->tp_res_y); -+ -+ input_abs_set_res(input, ABS_MT_POSITION_X, cytp->tp_res_x); -+ input_abs_set_res(input, ABS_MT_POSITION_Y, cytp->tp_res_y); -+ -+ __set_bit(BTN_TOUCH, input->keybit); -+ __set_bit(BTN_TOOL_FINGER, input->keybit); -+ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); -+ __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); -+ __set_bit(BTN_TOOL_QUADTAP, input->keybit); -+ __set_bit(BTN_TOOL_QUINTTAP, input->keybit); -+ -+ __clear_bit(EV_REL, input->evbit); -+ __clear_bit(REL_X, input->relbit); -+ __clear_bit(REL_Y, input->relbit); -+ -+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); -+ __set_bit(EV_KEY, input->evbit); -+ __set_bit(BTN_LEFT, input->keybit); -+ __set_bit(BTN_RIGHT, input->keybit); -+ __set_bit(BTN_MIDDLE, input->keybit); -+ -+ input_set_drvdata(input, cytp); -+ -+ return 0; -+} -+ -+static int cypress_get_finger_count(unsigned char header_byte) -+{ -+ unsigned char bits6_7; -+ int finger_count; -+ -+ bits6_7 = header_byte >> 6; -+ finger_count = bits6_7 & 0x03; -+ -+ if (finger_count == 1) -+ return 1; -+ -+ if (header_byte & ABS_HSCROLL_BIT) { -+ /* HSCROLL gets added on to 0 finger count. */ -+ switch (finger_count) { -+ case 0: return 4; -+ case 2: return 5; -+ default: -+ /* Invalid contact (e.g. palm). Ignore it. */ -+ return -1; -+ } -+ } -+ -+ return finger_count; -+} -+ -+ -+static int cypress_parse_packet(struct psmouse *psmouse, -+ struct cytp_data *cytp, struct cytp_report_data *report_data) -+{ -+ unsigned char *packet = psmouse->packet; -+ unsigned char header_byte = packet[0]; -+ int contact_cnt; -+ -+ memset(report_data, 0, sizeof(struct cytp_report_data)); -+ -+ contact_cnt = cypress_get_finger_count(header_byte); -+ -+ if (contact_cnt < 0) /* e.g. palm detect */ -+ return -EINVAL; -+ -+ report_data->contact_cnt = contact_cnt; -+ -+ report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; -+ -+ if (report_data->contact_cnt == 1) { -+ report_data->contacts[0].x = -+ ((packet[1] & 0x70) << 4) | packet[2]; -+ report_data->contacts[0].y = -+ ((packet[1] & 0x07) << 8) | packet[3]; -+ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) -+ report_data->contacts[0].z = packet[4]; -+ -+ } else if (report_data->contact_cnt >= 2) { -+ report_data->contacts[0].x = -+ ((packet[1] & 0x70) << 4) | packet[2]; -+ report_data->contacts[0].y = -+ ((packet[1] & 0x07) << 8) | packet[3]; -+ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) -+ report_data->contacts[0].z = packet[4]; -+ -+ report_data->contacts[1].x = -+ ((packet[5] & 0xf0) << 4) | packet[6]; -+ report_data->contacts[1].y = -+ ((packet[5] & 0x0f) << 8) | packet[7]; -+ if (cytp->mode & CYTP_BIT_ABS_PRESSURE) -+ report_data->contacts[1].z = report_data->contacts[0].z; -+ } -+ -+ report_data->left = (header_byte & BTN_LEFT_BIT) ? 1 : 0; -+ report_data->right = (header_byte & BTN_RIGHT_BIT) ? 1 : 0; -+ -+ /* -+ * This is only true if one of the mouse buttons were tapped. Make -+ * sure it doesn't turn into a click. The regular tap-to-click -+ * functionality will handle that on its own. If we don't do this, -+ * disabling tap-to-click won't affect the mouse button zones. -+ */ -+ if (report_data->tap) -+ report_data->left = 0; -+ -+#ifdef CYTP_DEBUG_VERBOSE -+ { -+ int i; -+ int n = report_data->contact_cnt; -+ psmouse_dbg(psmouse, "Dump parsed report data as below:\n"); -+ psmouse_dbg(psmouse, "contact_cnt = %d\n", -+ report_data->contact_cnt); -+ if (n > CYTP_MAX_MT_SLOTS) -+ n = CYTP_MAX_MT_SLOTS; -+ for (i = 0; i < n; i++) -+ psmouse_dbg(psmouse, "contacts[%d] = {%d, %d, %d}\n", i, -+ report_data->contacts[i].x, -+ report_data->contacts[i].y, -+ report_data->contacts[i].z); -+ psmouse_dbg(psmouse, "left = %d\n", report_data->left); -+ psmouse_dbg(psmouse, "right = %d\n", report_data->right); -+ psmouse_dbg(psmouse, "middle = %d\n", report_data->middle); -+ } -+#endif -+ -+ return 0; -+} -+ -+static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) -+{ -+ int i; -+ struct input_dev *input = psmouse->dev; -+ struct cytp_data *cytp = psmouse->private; -+ struct cytp_report_data report_data; -+ struct cytp_contact *contact; -+ struct input_mt_pos pos[CYTP_MAX_MT_SLOTS]; -+ int slots[CYTP_MAX_MT_SLOTS]; -+ int n; -+ -+ if (cypress_parse_packet(psmouse, cytp, &report_data)) -+ return; -+ -+ n = report_data.contact_cnt; -+ -+ if (n > CYTP_MAX_MT_SLOTS) -+ n = CYTP_MAX_MT_SLOTS; -+ -+ for (i = 0; i < n; i++) { -+ contact = &report_data.contacts[i]; -+ pos[i].x = contact->x; -+ pos[i].y = contact->y; -+ } -+ -+ input_mt_assign_slots(input, slots, pos, n); -+ -+ for (i = 0; i < n; i++) { -+ contact = &report_data.contacts[i]; -+ input_mt_slot(input, slots[i]); -+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true); -+ input_report_abs(input, ABS_MT_POSITION_X, contact->x); -+ input_report_abs(input, ABS_MT_POSITION_Y, contact->y); -+ input_report_abs(input, ABS_MT_PRESSURE, contact->z); -+ } -+ -+ input_mt_sync_frame(input); -+ -+ input_mt_report_finger_count(input, report_data.contact_cnt); -+ -+ input_report_key(input, BTN_LEFT, report_data.left); -+ input_report_key(input, BTN_RIGHT, report_data.right); -+ input_report_key(input, BTN_MIDDLE, report_data.middle); -+ -+ input_sync(input); -+} -+ -+static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) -+{ -+ int contact_cnt; -+ int index = psmouse->pktcnt - 1; -+ unsigned char *packet = psmouse->packet; -+ struct cytp_data *cytp = psmouse->private; -+ -+ if (index < 0 || index > cytp->pkt_size) -+ return PSMOUSE_BAD_DATA; -+ -+ if (index == 0 && (packet[0] & 0xfc) == 0) { -+ /* call packet process for reporting finger leave. */ -+ cypress_process_packet(psmouse, 1); -+ return PSMOUSE_FULL_PACKET; -+ } -+ -+ /* -+ * Perform validation (and adjust packet size) based only on the -+ * first byte; allow all further bytes through. -+ */ -+ if (index != 0) -+ return PSMOUSE_GOOD_DATA; -+ -+ /* -+ * If absolute/relative mode bit has not been set yet, just pass -+ * the byte through. -+ */ -+ if ((cytp->mode & CYTP_BIT_ABS_REL_MASK) == 0) -+ return PSMOUSE_GOOD_DATA; -+ -+ if ((packet[0] & 0x08) == 0x08) -+ return PSMOUSE_BAD_DATA; -+ -+ contact_cnt = cypress_get_finger_count(packet[0]); -+ -+ if (contact_cnt < 0) -+ return PSMOUSE_BAD_DATA; -+ -+ if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) -+ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); -+ else -+ cypress_set_packet_size(psmouse, contact_cnt == 2 ? 8 : 5); -+ -+ return PSMOUSE_GOOD_DATA; -+} -+ -+static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ -+ if (psmouse->pktcnt >= cytp->pkt_size) { -+ cypress_process_packet(psmouse, 0); -+ return PSMOUSE_FULL_PACKET; -+ } -+ -+ return cypress_validate_byte(psmouse); -+} -+ -+static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) -+{ -+ struct cytp_data *cytp = psmouse->private; -+ -+ if (rate >= 80) { -+ psmouse->rate = 80; -+ cytp->mode |= CYTP_BIT_HIGH_RATE; -+ } else { -+ psmouse->rate = 40; -+ cytp->mode &= ~CYTP_BIT_HIGH_RATE; -+ } -+ -+ ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, -+ PSMOUSE_CMD_SETRATE); -+} -+ -+static void cypress_disconnect(struct psmouse *psmouse) -+{ -+ cypress_reset(psmouse); -+ kfree(psmouse->private); -+ psmouse->private = NULL; -+} -+ -+static int cypress_reconnect(struct psmouse *psmouse) -+{ -+ int tries = CYTP_PS2_CMD_TRIES; -+ int rc; -+ -+ do { -+ cypress_reset(psmouse); -+ rc = cypress_detect(psmouse, false); -+ } while (rc && (--tries > 0)); -+ -+ if (rc) { -+ psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); -+ return -1; -+ } -+ -+ if (cypress_set_absolute_mode(psmouse)) { -+ psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int cypress_init(struct psmouse *psmouse) -+{ -+ struct cytp_data *cytp; -+ -+ cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL); -+ psmouse->private = (void *)cytp; -+ if (cytp == NULL) -+ return -ENOMEM; -+ -+ cypress_reset(psmouse); -+ -+ psmouse->pktsize = 8; -+ -+ if (cypress_query_hardware(psmouse)) { -+ psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); -+ goto err_exit; -+ } -+ -+ if (cypress_set_absolute_mode(psmouse)) { -+ psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); -+ goto err_exit; -+ } -+ -+ if (cypress_set_input_params(psmouse->dev, cytp) < 0) { -+ psmouse_err(psmouse, "init: Unable to set input params.\n"); -+ goto err_exit; -+ } -+ -+ psmouse->model = 1; -+ psmouse->protocol_handler = cypress_protocol_handler; -+ psmouse->set_rate = cypress_set_rate; -+ psmouse->disconnect = cypress_disconnect; -+ psmouse->reconnect = cypress_reconnect; -+ psmouse->cleanup = cypress_reset; -+ psmouse->resync_time = 0; -+ -+ return 0; -+ -+err_exit: -+ /* -+ * Reset Cypress Trackpad as a standard mouse. Then -+ * let psmouse driver commmunicating with it as default PS2 mouse. -+ */ -+ cypress_reset(psmouse); -+ -+ psmouse->private = NULL; -+ kfree(cytp); -+ -+ return -1; -+} -+ -+bool cypress_supported(void) -+{ -+ return true; -+} -diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h -new file mode 100644 -index 0000000..4720f21 ---- /dev/null -+++ b/drivers/input/mouse/cypress_ps2.h -@@ -0,0 +1,191 @@ -+#ifndef _CYPRESS_PS2_H -+#define _CYPRESS_PS2_H -+ -+#include "psmouse.h" -+ -+#define CMD_BITS_MASK 0x03 -+#define COMPOSIT(x, s) (((x) & CMD_BITS_MASK) << (s)) -+ -+#define ENCODE_CMD(aa, bb, cc, dd) \ -+ (COMPOSIT((aa), 6) | COMPOSIT((bb), 4) | COMPOSIT((cc), 2) | COMPOSIT((dd), 0)) -+#define CYTP_CMD_ABS_NO_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 0) -+#define CYTP_CMD_ABS_WITH_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 1) -+#define CYTP_CMD_SMBUS_MODE ENCODE_CMD(0, 1, 1, 0) -+#define CYTP_CMD_STANDARD_MODE ENCODE_CMD(0, 2, 0, 0) /* not implemented yet. */ -+#define CYTP_CMD_CYPRESS_REL_MODE ENCODE_CMD(1, 1, 1, 1) /* not implemented yet. */ -+#define CYTP_CMD_READ_CYPRESS_ID ENCODE_CMD(0, 0, 0, 0) -+#define CYTP_CMD_READ_TP_METRICS ENCODE_CMD(0, 0, 0, 1) -+#define CYTP_CMD_SET_HSCROLL_WIDTH(w) ENCODE_CMD(1, 1, 0, (w)) -+#define CYTP_CMD_SET_HSCROLL_MASK ENCODE_CMD(1, 1, 0, 0) -+#define CYTP_CMD_SET_VSCROLL_WIDTH(w) ENCODE_CMD(1, 2, 0, (w)) -+#define CYTP_CMD_SET_VSCROLL_MASK ENCODE_CMD(1, 2, 0, 0) -+#define CYTP_CMD_SET_PALM_GEOMETRY(e) ENCODE_CMD(1, 2, 1, (e)) -+#define CYTP_CMD_PALM_GEMMETRY_MASK ENCODE_CMD(1, 2, 1, 0) -+#define CYTP_CMD_SET_PALM_SENSITIVITY(s) ENCODE_CMD(1, 2, 2, (s)) -+#define CYTP_CMD_PALM_SENSITIVITY_MASK ENCODE_CMD(1, 2, 2, 0) -+#define CYTP_CMD_SET_MOUSE_SENSITIVITY(s) ENCODE_CMD(1, 3, ((s) >> 2), (s)) -+#define CYTP_CMD_MOUSE_SENSITIVITY_MASK ENCODE_CMD(1, 3, 0, 0) -+#define CYTP_CMD_REQUEST_BASELINE_STATUS ENCODE_CMD(2, 0, 0, 1) -+#define CYTP_CMD_REQUEST_RECALIBRATION ENCODE_CMD(2, 0, 0, 3) -+ -+#define DECODE_CMD_AA(x) (((x) >> 6) & CMD_BITS_MASK) -+#define DECODE_CMD_BB(x) (((x) >> 4) & CMD_BITS_MASK) -+#define DECODE_CMD_CC(x) (((x) >> 2) & CMD_BITS_MASK) -+#define DECODE_CMD_DD(x) ((x) & CMD_BITS_MASK) -+ -+/* Cypress trackpad working mode. */ -+#define CYTP_BIT_ABS_PRESSURE (1 << 3) -+#define CYTP_BIT_ABS_NO_PRESSURE (1 << 2) -+#define CYTP_BIT_CYPRESS_REL (1 << 1) -+#define CYTP_BIT_STANDARD_REL (1 << 0) -+#define CYTP_BIT_REL_MASK (CYTP_BIT_CYPRESS_REL | CYTP_BIT_STANDARD_REL) -+#define CYTP_BIT_ABS_MASK (CYTP_BIT_ABS_PRESSURE | CYTP_BIT_ABS_NO_PRESSURE) -+#define CYTP_BIT_ABS_REL_MASK (CYTP_BIT_ABS_MASK | CYTP_BIT_REL_MASK) -+ -+#define CYTP_BIT_HIGH_RATE (1 << 4) -+/* -+ * report mode bit is set, firmware working in Remote Mode. -+ * report mode bit is cleared, firmware working in Stream Mode. -+ */ -+#define CYTP_BIT_REPORT_MODE (1 << 5) -+ -+/* scrolling width values for set HSCROLL and VSCROLL width command. */ -+#define SCROLL_WIDTH_NARROW 1 -+#define SCROLL_WIDTH_NORMAL 2 -+#define SCROLL_WIDTH_WIDE 3 -+ -+#define PALM_GEOMETRY_ENABLE 1 -+#define PALM_GEOMETRY_DISABLE 0 -+ -+#define TP_METRICS_MASK 0x80 -+#define FW_VERSION_MASX 0x7f -+#define FW_VER_HIGH_MASK 0x70 -+#define FW_VER_LOW_MASK 0x0f -+ -+/* Times to retry a ps2_command and millisecond delay between tries. */ -+#define CYTP_PS2_CMD_TRIES 3 -+#define CYTP_PS2_CMD_DELAY 500 -+ -+/* time out for PS/2 command only in milliseconds. */ -+#define CYTP_CMD_TIMEOUT 200 -+#define CYTP_DATA_TIMEOUT 30 -+ -+#define CYTP_EXT_CMD 0xe8 -+#define CYTP_PS2_RETRY 0xfe -+#define CYTP_PS2_ERROR 0xfc -+ -+#define CYTP_RESP_RETRY 0x01 -+#define CYTP_RESP_ERROR 0xfe -+ -+ -+#define CYTP_105001_WIDTH 97 /* Dell XPS 13 */ -+#define CYTP_105001_HIGH 59 -+#define CYTP_DEFAULT_WIDTH (CYTP_105001_WIDTH) -+#define CYTP_DEFAULT_HIGH (CYTP_105001_HIGH) -+ -+#define CYTP_ABS_MAX_X 1600 -+#define CYTP_ABS_MAX_Y 900 -+#define CYTP_MAX_PRESSURE 255 -+#define CYTP_MIN_PRESSURE 0 -+ -+/* header byte bits of relative package. */ -+#define BTN_LEFT_BIT 0x01 -+#define BTN_RIGHT_BIT 0x02 -+#define BTN_MIDDLE_BIT 0x04 -+#define REL_X_SIGN_BIT 0x10 -+#define REL_Y_SIGN_BIT 0x20 -+ -+/* header byte bits of absolute package. */ -+#define ABS_VSCROLL_BIT 0x10 -+#define ABS_HSCROLL_BIT 0x20 -+#define ABS_MULTIFINGER_TAP 0x04 -+#define ABS_EDGE_MOTION_MASK 0x80 -+ -+#define DFLT_RESP_BITS_VALID 0x88 /* SMBus bit should not be set. */ -+#define DFLT_RESP_SMBUS_BIT 0x80 -+#define DFLT_SMBUS_MODE 0x80 -+#define DFLT_PS2_MODE 0x00 -+#define DFLT_RESP_BIT_MODE 0x40 -+#define DFLT_RESP_REMOTE_MODE 0x40 -+#define DFLT_RESP_STREAM_MODE 0x00 -+#define DFLT_RESP_BIT_REPORTING 0x20 -+#define DFLT_RESP_BIT_SCALING 0x10 -+ -+#define TP_METRICS_BIT_PALM 0x80 -+#define TP_METRICS_BIT_STUBBORN 0x40 -+#define TP_METRICS_BIT_2F_JITTER 0x30 -+#define TP_METRICS_BIT_1F_JITTER 0x0c -+#define TP_METRICS_BIT_APA 0x02 -+#define TP_METRICS_BIT_MTG 0x01 -+#define TP_METRICS_BIT_ABS_PKT_FORMAT_SET 0xf0 -+#define TP_METRICS_BIT_2F_SPIKE 0x0c -+#define TP_METRICS_BIT_1F_SPIKE 0x03 -+ -+/* bits of first byte response of E9h-Status Request command. */ -+#define RESP_BTN_RIGHT_BIT 0x01 -+#define RESP_BTN_MIDDLE_BIT 0x02 -+#define RESP_BTN_LEFT_BIT 0x04 -+#define RESP_SCALING_BIT 0x10 -+#define RESP_ENABLE_BIT 0x20 -+#define RESP_REMOTE_BIT 0x40 -+#define RESP_SMBUS_BIT 0x80 -+ -+#define CYTP_MAX_MT_SLOTS 2 -+ -+struct cytp_contact { -+ int x; -+ int y; -+ int z; /* also named as touch pressure. */ -+}; -+ -+/* The structure of Cypress Trackpad event data. */ -+struct cytp_report_data { -+ int contact_cnt; -+ struct cytp_contact contacts[CYTP_MAX_MT_SLOTS]; -+ unsigned int left:1; -+ unsigned int right:1; -+ unsigned int middle:1; -+ unsigned int tap:1; /* multi-finger tap detected. */ -+}; -+ -+/* The structure of Cypress Trackpad device private data. */ -+struct cytp_data { -+ int fw_version; -+ -+ int pkt_size; -+ int mode; -+ -+ int tp_min_pressure; -+ int tp_max_pressure; -+ int tp_width; /* X direction physical size in mm. */ -+ int tp_high; /* Y direction physical size in mm. */ -+ int tp_max_abs_x; /* Max X absolute units that can be reported. */ -+ int tp_max_abs_y; /* Max Y absolute units that can be reported. */ -+ -+ int tp_res_x; /* X resolution in units/mm. */ -+ int tp_res_y; /* Y resolution in units/mm. */ -+ -+ int tp_metrics_supported; -+}; -+ -+ -+#ifdef CONFIG_MOUSE_PS2_CYPRESS -+int cypress_detect(struct psmouse *psmouse, bool set_properties); -+int cypress_init(struct psmouse *psmouse); -+bool cypress_supported(void); -+#else -+inline int cypress_detect(struct psmouse *psmouse, bool set_properties) -+{ -+ return -ENOSYS; -+} -+inline int cypress_init(struct psmouse *psmouse) -+{ -+ return -ENOSYS; -+} -+inline bool cypress_supported(void) -+{ -+ return 0; -+} -+#endif /* CONFIG_MOUSE_PS2_CYPRESS */ -+ -+#endif /* _CYPRESS_PS2_H */ -diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c -index 22fe254..cff065f 100644 ---- a/drivers/input/mouse/psmouse-base.c -+++ b/drivers/input/mouse/psmouse-base.c -@@ -34,6 +34,7 @@ - #include "touchkit_ps2.h" - #include "elantech.h" - #include "sentelic.h" -+#include "cypress_ps2.h" - - #define DRIVER_DESC "PS/2 mouse driver" - -@@ -759,6 +760,28 @@ static int psmouse_extensions(struct psmouse *psmouse, - } - - /* -+ * Try Cypress Trackpad. -+ * Must try it before Finger Sensing Pad because Finger Sensing Pad probe -+ * upsets some modules of Cypress Trackpads. -+ */ -+ if (max_proto > PSMOUSE_IMEX && -+ cypress_detect(psmouse, set_properties) == 0) { -+ if (cypress_supported()) { -+ if (cypress_init(psmouse) == 0) -+ return PSMOUSE_CYPRESS; -+ -+ /* -+ * Finger Sensing Pad probe upsets some modules of -+ * Cypress Trackpad, must avoid Finger Sensing Pad -+ * probe if Cypress Trackpad device detected. -+ */ -+ return PSMOUSE_PS2; -+ } -+ -+ max_proto = PSMOUSE_IMEX; -+ } -+ -+/* - * Try ALPS TouchPad - */ - if (max_proto > PSMOUSE_IMEX) { -@@ -896,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { - .alias = "thinkps", - .detect = thinking_detect, - }, -+#ifdef CONFIG_MOUSE_PS2_CYPRESS -+ { -+ .type = PSMOUSE_CYPRESS, -+ .name = "CyPS/2", -+ .alias = "cypress", -+ .detect = cypress_detect, -+ .init = cypress_init, -+ }, -+#endif - { - .type = PSMOUSE_GENPS, - .name = "GenPS/2", -diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index fe1df23..2f0b39d 100644 ---- a/drivers/input/mouse/psmouse.h -+++ b/drivers/input/mouse/psmouse.h -@@ -95,6 +95,7 @@ enum psmouse_type { - PSMOUSE_ELANTECH, - PSMOUSE_FSP, - PSMOUSE_SYNAPTICS_RELATIVE, -+ PSMOUSE_CYPRESS, - PSMOUSE_AUTO /* This one should always be last */ - }; - --- -1.7.7.6 - diff --git a/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch b/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch deleted file mode 100644 index 15abce521..000000000 --- a/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 81bb5d31fbf3893a8e041c649dea704dd11d5272 Mon Sep 17 00:00:00 2001 -From: Kamal Mostafa -Date: Thu, 21 Feb 2013 11:55:05 -0800 -Subject: [PATCH] Input: cypress_ps2 - fix trackpadi found in Dell XPS12 - -Avoid firmware glitch in Cypress PS/2 Trackpad firmware version 11 -(as observed in Dell XPS12) which prevents driver from recognizing -the trackpad. - -BugLink: http://launchpad.net/bugs/1103594 - -Signed-off-by: Kamal Mostafa -Cc: Dudley Du -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/cypress_ps2.c | 19 +++++++++++++------ - 1 file changed, 13 insertions(+), 6 deletions(-) - -diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c -index 1673dc6..f51765f 100644 ---- a/drivers/input/mouse/cypress_ps2.c -+++ b/drivers/input/mouse/cypress_ps2.c -@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse) - cytp->fw_version = param[2] & FW_VERSION_MASX; - cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; - -+ /* -+ * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to -+ * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594. -+ */ -+ if (cytp->fw_version >= 11) -+ cytp->tp_metrics_supported = 0; -+ - psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); - psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", - cytp->tp_metrics_supported); -@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) - cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; - cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; - -+ if (!cytp->tp_metrics_supported) -+ return 0; -+ - memset(param, 0, sizeof(param)); - if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { - /* Update trackpad parameters. */ -@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) - - static int cypress_query_hardware(struct psmouse *psmouse) - { -- struct cytp_data *cytp = psmouse->private; - int ret; - - ret = cypress_read_fw_version(psmouse); - if (ret) - return ret; - -- if (cytp->tp_metrics_supported) { -- ret = cypress_read_tp_metrics(psmouse); -- if (ret) -- return ret; -- } -+ ret = cypress_read_tp_metrics(psmouse); -+ if (ret) -+ return ret; - - return 0; - } --- -1.8.1.2 - diff --git a/alps-v2.patch b/alps-v2.patch deleted file mode 100644 index d394c4a92..000000000 --- a/alps-v2.patch +++ /dev/null @@ -1,2494 +0,0 @@ -From f822982515378982dc8d8e6058579288d0ee3cff Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:55:19 -0800 -Subject: [PATCH 01/15] Input: ALPS - document the alps.h data structures - -Add kernel-doc markup. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.h | 74 ++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 61 insertions(+), 13 deletions(-) - -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index ae1ac35..67be4e5 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -17,30 +17,78 @@ - #define ALPS_PROTO_V3 2 - #define ALPS_PROTO_V4 3 - -+/** -+ * struct alps_model_info - touchpad ID table -+ * @signature: E7 response string to match. -+ * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response -+ * (aka command mode response) identifies the firmware minor version. This -+ * can be used to distinguish different hardware models which are not -+ * uniquely identifiable through their E7 responses. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * -+ * Many (but not all) ALPS touchpads can be identified by looking at the -+ * values returned in the "E7 report" and/or the "EC report." This table -+ * lists a number of such touchpads. -+ */ - struct alps_model_info { -- unsigned char signature[3]; -- unsigned char command_mode_resp; /* v3/v4 only */ -+ unsigned char signature[3]; -+ unsigned char command_mode_resp; - unsigned char proto_version; -- unsigned char byte0, mask0; -- unsigned char flags; -+ unsigned char byte0, mask0; -+ unsigned char flags; - }; - -+/** -+ * struct alps_nibble_commands - encodings for register accesses -+ * @command: PS/2 command used for the nibble -+ * @data: Data supplied as an argument to the PS/2 command, if applicable -+ * -+ * The ALPS protocol uses magic sequences to transmit binary data to the -+ * touchpad, as it is generally not OK to send arbitrary bytes out the -+ * PS/2 port. Each of the sequences in this table sends one nibble of the -+ * register address or (write) data. Different versions of the ALPS protocol -+ * use slightly different encodings. -+ */ - struct alps_nibble_commands { - int command; - unsigned char data; - }; - -+/** -+ * struct alps_data - private data structure for the ALPS driver -+ * @dev2: "Relative" device used to report trackstick or mouse activity. -+ * @phys: Physical path for the relative device. -+ * @i: Information on the detected touchpad model. -+ * @nibble_commands: Command mapping used for touchpad register accesses. -+ * @addr_command: Command used to tell the touchpad that a register address -+ * follows. -+ * @prev_fin: Finger bit from previous packet. -+ * @multi_packet: Multi-packet data in progress. -+ * @multi_data: Saved multi-packet data. -+ * @x1: First X coordinate from last MT report. -+ * @x2: Second X coordinate from last MT report. -+ * @y1: First Y coordinate from last MT report. -+ * @y2: Second Y coordinate from last MT report. -+ * @fingers: Number of fingers from last MT report. -+ * @quirks: Bitmap of ALPS_QUIRK_*. -+ * @timer: Timer for flushing out the final report packet in the stream. -+ */ - struct alps_data { -- struct input_dev *dev2; /* Relative device */ -- char phys[32]; /* Phys */ -- const struct alps_model_info *i;/* Info */ -+ struct input_dev *dev2; -+ char phys[32]; -+ const struct alps_model_info *i; - const struct alps_nibble_commands *nibble_commands; -- int addr_command; /* Command to set register address */ -- int prev_fin; /* Finger bit from previous packet */ -- int multi_packet; /* Multi-packet data in progress */ -- unsigned char multi_data[6]; /* Saved multi-packet data */ -- int x1, x2, y1, y2; /* Coordinates from last MT report */ -- int fingers; /* Number of fingers from MT report */ -+ int addr_command; -+ int prev_fin; -+ int multi_packet; -+ unsigned char multi_data[6]; -+ int x1, x2, y1, y2; -+ int fingers; - u8 quirks; - struct timer_list timer; - }; --- -1.8.1.2 - - -From 196069863604cb55061a02ad5f046c5e4054ba54 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:56:33 -0800 -Subject: [PATCH 02/15] Input: ALPS - copy "model" info into alps_data struct - -Not every type of ALPS touchpad is well-suited to table-based detection. -Start moving the various alps_model_data attributes into the alps_data -struct so that we don't need a unique table entry for every possible -permutation of protocol version, flags, byte0/mask0, etc. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 63 +++++++++++++++++++++++----------------------- - drivers/input/mouse/alps.h | 14 +++++++++-- - 2 files changed, 43 insertions(+), 34 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index e229fa3..33ee6e0 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -122,10 +122,10 @@ static const struct alps_model_info alps_model_data[] = { - - /* Packet formats are described in Documentation/input/alps.txt */ - --static bool alps_is_valid_first_byte(const struct alps_model_info *model, -+static bool alps_is_valid_first_byte(struct alps_data *priv, - unsigned char data) - { -- return (data & model->mask0) == model->byte0; -+ return (data & priv->mask0) == priv->byte0; - } - - static void alps_report_buttons(struct psmouse *psmouse, -@@ -158,14 +158,13 @@ static void alps_report_buttons(struct psmouse *psmouse, - static void alps_process_packet_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; - int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; - -- if (model->proto_version == ALPS_PROTO_V1) { -+ if (priv->proto_version == ALPS_PROTO_V1) { - left = packet[2] & 0x10; - right = packet[2] & 0x08; - middle = 0; -@@ -181,12 +180,12 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - z = packet[5]; - } - -- if (model->flags & ALPS_FW_BK_1) { -+ if (priv->flags & ALPS_FW_BK_1) { - back = packet[0] & 0x10; - forward = packet[2] & 4; - } - -- if (model->flags & ALPS_FW_BK_2) { -+ if (priv->flags & ALPS_FW_BK_2) { - back = packet[3] & 4; - forward = packet[2] & 4; - if ((middle = forward && back)) -@@ -196,7 +195,7 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - ges = packet[2] & 1; - fin = packet[2] & 2; - -- if ((model->flags & ALPS_DUALPOINT) && z == 127) { -+ if ((priv->flags & ALPS_DUALPOINT) && z == 127) { - input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); - input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); - -@@ -239,15 +238,15 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - input_report_abs(dev, ABS_PRESSURE, z); - input_report_key(dev, BTN_TOOL_FINGER, z > 0); - -- if (model->flags & ALPS_WHEEL) -+ if (priv->flags & ALPS_WHEEL) - input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); - -- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { -+ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - input_report_key(dev, BTN_FORWARD, forward); - input_report_key(dev, BTN_BACK, back); - } - -- if (model->flags & ALPS_FOUR_BUTTONS) { -+ if (priv->flags & ALPS_FOUR_BUTTONS) { - input_report_key(dev, BTN_0, packet[2] & 4); - input_report_key(dev, BTN_1, packet[0] & 0x10); - input_report_key(dev, BTN_2, packet[3] & 4); -@@ -699,9 +698,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - static void alps_process_packet(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - alps_process_packet_v1_v2(psmouse); -@@ -765,7 +763,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - if (((psmouse->packet[3] | - psmouse->packet[4] | - psmouse->packet[5]) & 0x80) || -- (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { -+ (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { - psmouse_dbg(psmouse, - "refusing packet %4ph (suspected interleaved ps/2)\n", - psmouse->packet + 3); -@@ -844,7 +842,6 @@ static void alps_flush_packet(unsigned long data) - static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - - if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ - if (psmouse->pktcnt == 3) { -@@ -857,15 +854,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - - /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ - -- if ((model->flags & ALPS_PS2_INTERLEAVED) && -+ if ((priv->flags & ALPS_PS2_INTERLEAVED) && - psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { - return alps_handle_interleaved_ps2(psmouse); - } - -- if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { -+ if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) { - psmouse_dbg(psmouse, - "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", -- psmouse->packet[0], model->mask0, model->byte0); -+ psmouse->packet[0], priv->mask0, priv->byte0); - return PSMOUSE_BAD_DATA; - } - -@@ -1190,16 +1187,16 @@ static int alps_poll(struct psmouse *psmouse) - unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - -- if (priv->i->flags & ALPS_PASS) -+ if (priv->flags & ALPS_PASS) - alps_passthrough_mode_v2(psmouse, false); - -- if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) -+ if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) - return -1; - - if ((psmouse->badbyte & 0xc8) == 0x08) { -@@ -1217,9 +1214,8 @@ static int alps_poll(struct psmouse *psmouse) - static int alps_hw_init_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } -@@ -1234,7 +1230,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) - return -1; - } - -- if ((model->flags & ALPS_PASS) && -+ if ((priv->flags & ALPS_PASS) && - alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } -@@ -1520,10 +1516,9 @@ error: - static int alps_hw_init(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- const struct alps_model_info *model = priv->i; - int ret = -1; - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - ret = alps_hw_init_v1_v2(psmouse); -@@ -1585,7 +1580,10 @@ int alps_init(struct psmouse *psmouse) - if (!model) - goto init_fail; - -- priv->i = model; -+ priv->proto_version = model->proto_version; -+ priv->byte0 = model->byte0; -+ priv->mask0 = model->mask0; -+ priv->flags = model->flags; - - if (alps_hw_init(psmouse)) - goto init_fail; -@@ -1609,7 +1607,7 @@ int alps_init(struct psmouse *psmouse) - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - -- switch (model->proto_version) { -+ switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -@@ -1633,17 +1631,17 @@ int alps_init(struct psmouse *psmouse) - - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - -- if (model->flags & ALPS_WHEEL) { -+ if (priv->flags & ALPS_WHEEL) { - dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); - dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); - } - -- if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { -+ if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { - dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); - dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); - } - -- if (model->flags & ALPS_FOUR_BUTTONS) { -+ if (priv->flags & ALPS_FOUR_BUTTONS) { - dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); - dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); - dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); -@@ -1654,7 +1652,8 @@ int alps_init(struct psmouse *psmouse) - - snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys; -- dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; -+ dev2->name = (priv->flags & ALPS_DUALPOINT) ? -+ "DualPoint Stick" : "PS/2 Mouse"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_ALPS; -@@ -1673,7 +1672,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; -+ psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 67be4e5..efd0eea 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -63,10 +63,15 @@ struct alps_nibble_commands { - * struct alps_data - private data structure for the ALPS driver - * @dev2: "Relative" device used to report trackstick or mouse activity. - * @phys: Physical path for the relative device. -- * @i: Information on the detected touchpad model. - * @nibble_commands: Command mapping used for touchpad register accesses. - * @addr_command: Command used to tell the touchpad that a register address - * follows. -+ * @proto_version: Indicates V1/V2/V3/... -+ * @byte0: Helps figure out whether a position report packet matches the -+ * known format for this model. The first byte of the report, ANDed with -+ * mask0, should match byte0. -+ * @mask0: The mask used to check the first byte of the report. -+ * @flags: Additional device capabilities (passthrough port, trackstick, etc.). - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. - * @multi_data: Saved multi-packet data. -@@ -81,9 +86,14 @@ struct alps_nibble_commands { - struct alps_data { - struct input_dev *dev2; - char phys[32]; -- const struct alps_model_info *i; -+ -+ /* these are autodetected when the device is identified */ - const struct alps_nibble_commands *nibble_commands; - int addr_command; -+ unsigned char proto_version; -+ unsigned char byte0, mask0; -+ unsigned char flags; -+ - int prev_fin; - int multi_packet; - unsigned char multi_data[6]; --- -1.8.1.2 - - -From b856c913996a38ced60bdf41aeae4da00882bf1f Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 20:57:04 -0800 -Subject: [PATCH 03/15] Input: ALPS - move alps_get_model() down below hw_init - code - -This will minimize the number of forward declarations needed when -alps_get_model() starts assigning function pointers. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 186 ++++++++++++++++++++++----------------------- - 1 file changed, 93 insertions(+), 93 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 33ee6e0..c473549 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -998,99 +998,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) - return 0; - } - --static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) --{ -- struct ps2dev *ps2dev = &psmouse->ps2dev; -- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; -- unsigned char param[4]; -- const struct alps_model_info *model = NULL; -- int i; -- -- /* -- * First try "E6 report". -- * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. -- * The bits 0-2 of the first byte will be 1s if some buttons are -- * pressed. -- */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -- return NULL; -- -- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- -- if ((param[0] & 0xf8) != 0 || param[1] != 0 || -- (param[2] != 10 && param[2] != 100)) -- return NULL; -- -- /* -- * Now try "E7 report". Allowed responses are in -- * alps_model_data[].signature -- */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -- return NULL; -- -- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- -- if (version) { -- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) -- /* empty */; -- *version = (param[0] << 8) | (param[1] << 4) | i; -- } -- -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (!memcmp(param, alps_model_data[i].signature, -- sizeof(alps_model_data[i].signature))) { -- model = alps_model_data + i; -- break; -- } -- } -- -- if (model && model->proto_version > ALPS_PROTO_V2) { -- /* -- * Need to check command mode response to identify -- * model -- */ -- model = NULL; -- if (alps_enter_command_mode(psmouse, param)) { -- psmouse_warn(psmouse, -- "touchpad failed to enter command mode\n"); -- } else { -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -- alps_model_data[i].command_mode_resp == param[0]) { -- model = alps_model_data + i; -- break; -- } -- } -- alps_exit_command_mode(psmouse); -- -- if (!model) -- psmouse_dbg(psmouse, -- "Unknown command mode response %2.2x\n", -- param[0]); -- } -- } -- -- return model; --} -- - /* - * For DualPoint devices select the device that should respond to - * subsequent commands. It looks like glidepad is behind stickpointer, -@@ -1534,6 +1441,99 @@ static int alps_hw_init(struct psmouse *psmouse) - return ret; - } - -+static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; -+ unsigned char param[4]; -+ const struct alps_model_info *model = NULL; -+ int i; -+ -+ /* -+ * First try "E6 report". -+ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. -+ * The bits 0-2 of the first byte will be 1s if some buttons are -+ * pressed. -+ */ -+ param[0] = 0; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) -+ return NULL; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return NULL; -+ -+ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", -+ param[0], param[1], param[2]); -+ -+ if ((param[0] & 0xf8) != 0 || param[1] != 0 || -+ (param[2] != 10 && param[2] != 100)) -+ return NULL; -+ -+ /* -+ * Now try "E7 report". Allowed responses are in -+ * alps_model_data[].signature -+ */ -+ param[0] = 0; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) -+ return NULL; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return NULL; -+ -+ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", -+ param[0], param[1], param[2]); -+ -+ if (version) { -+ for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) -+ /* empty */; -+ *version = (param[0] << 8) | (param[1] << 4) | i; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (!memcmp(param, alps_model_data[i].signature, -+ sizeof(alps_model_data[i].signature))) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ -+ if (model && model->proto_version > ALPS_PROTO_V2) { -+ /* -+ * Need to check command mode response to identify -+ * model -+ */ -+ model = NULL; -+ if (alps_enter_command_mode(psmouse, param)) { -+ psmouse_warn(psmouse, -+ "touchpad failed to enter command mode\n"); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -+ alps_model_data[i].command_mode_resp == param[0]) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ alps_exit_command_mode(psmouse); -+ -+ if (!model) -+ psmouse_dbg(psmouse, -+ "Unknown command mode response %2.2x\n", -+ param[0]); -+ } -+ } -+ -+ return model; -+} -+ - static int alps_reconnect(struct psmouse *psmouse) - { - const struct alps_model_info *model; --- -1.8.1.2 - - -From b719d56d5743e2c338568f4edb6eab17ea9c9eec Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:19:01 -0800 -Subject: [PATCH 04/15] Input: ALPS - introduce helper function for repeated - commands - -Several ALPS driver init sequences repeat a command three times, then -issue PSMOUSE_CMD_GETINFO to read the result. Move this into a helper -function to simplify the code. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 71 ++++++++++++++++++++-------------------------- - 1 file changed, 30 insertions(+), 41 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index c473549..1ca854b 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -964,24 +964,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, - return __alps_command_mode_write_reg(psmouse, value); - } - -+static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, -+ int repeated_command, unsigned char *param) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ param[0] = 0; -+ if (init_command && ps2_command(ps2dev, param, init_command)) -+ return -EIO; -+ -+ if (ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command) || -+ ps2_command(ps2dev, NULL, repeated_command)) -+ return -EIO; -+ -+ param[0] = param[1] = param[2] = 0xff; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -EIO; -+ -+ psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", -+ repeated_command, param[0], param[1], param[2]); -+ return 0; -+} -+ - static int alps_enter_command_mode(struct psmouse *psmouse, - unsigned char *resp) - { - unsigned char param[4]; -- struct ps2dev *ps2dev = &psmouse->ps2dev; - -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { - psmouse_err(psmouse, "failed to enter command mode\n"); - return -1; - } - - if (param[0] != 0x88 && param[1] != 0x07) { - psmouse_dbg(psmouse, -- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -- param[0], param[1], param[2]); -+ "unknown response while entering command mode\n"); - return -1; - } - -@@ -1041,18 +1059,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) - - static int alps_get_status(struct psmouse *psmouse, char *param) - { -- struct ps2dev *ps2dev = &psmouse->ps2dev; -- - /* Get status: 0xF5 0xF5 0xF5 0xE9 */ -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || -- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param)) - return -1; - -- psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- - return 0; - } - -@@ -1443,7 +1453,6 @@ static int alps_hw_init(struct psmouse *psmouse) - - static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) - { -- struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; - const struct alps_model_info *model = NULL; -@@ -1455,20 +1464,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, -+ param)) - return NULL; - -- psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- - if ((param[0] & 0xf8) != 0 || param[1] != 0 || - (param[2] != 10 && param[2] != 100)) - return NULL; -@@ -1477,20 +1476,10 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * Now try "E7 report". Allowed responses are in - * alps_model_data[].signature - */ -- param[0] = 0; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) -- return NULL; -- -- param[0] = param[1] = param[2] = 0xff; -- if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, -+ param)) - return NULL; - -- psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", -- param[0], param[1], param[2]); -- - if (version) { - for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) - /* empty */; --- -1.8.1.2 - - -From c7fd5d0e90f577072ece70651aeecb37f62f5fdb Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:19:59 -0800 -Subject: [PATCH 05/15] Input: ALPS - rework detection sequence - -If the E6 report test passes, get the E7 and EC reports right away and -then try to match an entry in the table. - -Pass in the alps_data struct, so that the detection code will be able to -set operating parameters based on information found during detection. - -Change the version (psmouse->model) to report the protocol version only, -in preparation for supporting models that do not show up in the ID table. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 124 +++++++++++++++++++-------------------------- - drivers/input/mouse/alps.h | 8 +-- - 2 files changed, 56 insertions(+), 76 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 1ca854b..e6a27a5 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -1451,86 +1451,76 @@ static int alps_hw_init(struct psmouse *psmouse) - return ret; - } - --static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -+static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, -+ unsigned char *e7, unsigned char *ec) - { -- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; -- unsigned char param[4]; -- const struct alps_model_info *model = NULL; -+ const struct alps_model_info *model; - int i; - -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ model = &alps_model_data[i]; -+ -+ if (!memcmp(e7, model->signature, sizeof(model->signature)) && -+ (!model->command_mode_resp || -+ model->command_mode_resp == ec[2])) { -+ -+ priv->proto_version = model->proto_version; -+ priv->flags = model->flags; -+ priv->byte0 = model->byte0; -+ priv->mask0 = model->mask0; -+ -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) -+{ -+ unsigned char e6[4], e7[4], ec[4]; -+ - /* - * First try "E6 report". - * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ -- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, -- param)) -- return NULL; -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE11, e6)) -+ return -EIO; - -- if ((param[0] & 0xf8) != 0 || param[1] != 0 || -- (param[2] != 10 && param[2] != 100)) -- return NULL; -+ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) -+ return -EINVAL; - - /* -- * Now try "E7 report". Allowed responses are in -- * alps_model_data[].signature -+ * Now get the "E7" and "EC" reports. These will uniquely identify -+ * most ALPS touchpads. - */ -- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, -- param)) -- return NULL; -- -- if (version) { -- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) -- /* empty */; -- *version = (param[0] << 8) | (param[1] << 4) | i; -- } -- -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (!memcmp(param, alps_model_data[i].signature, -- sizeof(alps_model_data[i].signature))) { -- model = alps_model_data + i; -- break; -- } -- } -+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_SETSCALE21, e7) || -+ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, -+ PSMOUSE_CMD_RESET_WRAP, ec) || -+ alps_exit_command_mode(psmouse)) -+ return -EIO; - -- if (model && model->proto_version > ALPS_PROTO_V2) { -- /* -- * Need to check command mode response to identify -- * model -- */ -- model = NULL; -- if (alps_enter_command_mode(psmouse, param)) { -- psmouse_warn(psmouse, -- "touchpad failed to enter command mode\n"); -- } else { -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -- alps_model_data[i].command_mode_resp == param[0]) { -- model = alps_model_data + i; -- break; -- } -- } -- alps_exit_command_mode(psmouse); -+ if (alps_match_table(psmouse, priv, e7, ec) == 0) -+ return 0; - -- if (!model) -- psmouse_dbg(psmouse, -- "Unknown command mode response %2.2x\n", -- param[0]); -- } -- } -+ psmouse_info(psmouse, -+ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", -+ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); - -- return model; -+ return -EINVAL; - } - - static int alps_reconnect(struct psmouse *psmouse) - { -- const struct alps_model_info *model; -+ struct alps_data *priv = psmouse->private; - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, NULL); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) - return -1; - - return alps_hw_init(psmouse); -@@ -1549,9 +1539,7 @@ static void alps_disconnect(struct psmouse *psmouse) - int alps_init(struct psmouse *psmouse) - { - struct alps_data *priv; -- const struct alps_model_info *model; - struct input_dev *dev1 = psmouse->dev, *dev2; -- int version; - - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); - dev2 = input_allocate_device(); -@@ -1565,15 +1553,9 @@ int alps_init(struct psmouse *psmouse) - - psmouse_reset(psmouse); - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, priv) < 0) - goto init_fail; - -- priv->proto_version = model->proto_version; -- priv->byte0 = model->byte0; -- priv->mask0 = model->mask0; -- priv->flags = model->flags; -- - if (alps_hw_init(psmouse)) - goto init_fail; - -@@ -1678,18 +1660,16 @@ init_fail: - - int alps_detect(struct psmouse *psmouse, bool set_properties) - { -- int version; -- const struct alps_model_info *model; -+ struct alps_data dummy; - -- model = alps_get_model(psmouse, &version); -- if (!model) -+ if (alps_identify(psmouse, &dummy) < 0) - return -1; - - if (set_properties) { - psmouse->vendor = "ALPS"; -- psmouse->name = model->flags & ALPS_DUALPOINT ? -+ psmouse->name = dummy.flags & ALPS_DUALPOINT ? - "DualPoint TouchPad" : "GlidePoint"; -- psmouse->model = version; -+ psmouse->model = dummy.proto_version << 8; - } - return 0; - } -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index efd0eea..a81b318 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -12,10 +12,10 @@ - #ifndef _ALPS_H - #define _ALPS_H - --#define ALPS_PROTO_V1 0 --#define ALPS_PROTO_V2 1 --#define ALPS_PROTO_V3 2 --#define ALPS_PROTO_V4 3 -+#define ALPS_PROTO_V1 1 -+#define ALPS_PROTO_V2 2 -+#define ALPS_PROTO_V3 3 -+#define ALPS_PROTO_V4 4 - - /** - * struct alps_model_info - touchpad ID table --- -1.8.1.2 - - -From c7fb8a63ba1257e2ee829425ef7197c7cbe893a1 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:22:08 -0800 -Subject: [PATCH 06/15] Input: ALPS - use function pointers for different - protocol handlers - -In anticipation of adding more ALPS protocols and more per-device quirks, -use function pointers instead of switch statements to call functions that -differ from one device to the next. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 101 +++++++++++++++++++++------------------------ - drivers/input/mouse/alps.h | 7 ++++ - 2 files changed, 54 insertions(+), 54 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index e6a27a5..fe45687 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -114,6 +114,11 @@ static const struct alps_model_info alps_model_data[] = { - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1); -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1); -+ - /* - * XXX - this entry is suspicious. First byte has zero lower nibble, - * which is what a normal mouse would report. Also, the value 0x0e -@@ -695,24 +700,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - input_sync(dev); - } - --static void alps_process_packet(struct psmouse *psmouse) --{ -- struct alps_data *priv = psmouse->private; -- -- switch (priv->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- alps_process_packet_v1_v2(psmouse); -- break; -- case ALPS_PROTO_V3: -- alps_process_packet_v3(psmouse); -- break; -- case ALPS_PROTO_V4: -- alps_process_packet_v4(psmouse); -- break; -- } --} -- - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -770,7 +757,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - - /* Continue with the next packet */ - psmouse->packet[0] = psmouse->packet[6]; -@@ -814,6 +801,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) - static void alps_flush_packet(unsigned long data) - { - struct psmouse *psmouse = (struct psmouse *)data; -+ struct alps_data *priv = psmouse->private; - - serio_pause_rx(psmouse->ps2dev.serio); - -@@ -831,7 +819,7 @@ static void alps_flush_packet(unsigned long data) - "refusing packet %3ph (suspected interleaved ps/2)\n", - psmouse->packet + 3); - } else { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - } - psmouse->pktcnt = 0; - } -@@ -876,7 +864,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - } - - if (psmouse->pktcnt == psmouse->pktsize) { -- alps_process_packet(psmouse); -+ priv->process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } - -@@ -1430,25 +1418,26 @@ error: - return -1; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static void alps_set_defaults(struct alps_data *priv) - { -- struct alps_data *priv = psmouse->private; -- int ret = -1; -- - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -- ret = alps_hw_init_v1_v2(psmouse); -+ priv->hw_init = alps_hw_init_v1_v2; -+ priv->process_packet = alps_process_packet_v1_v2; -+ priv->set_abs_params = alps_set_abs_params_st; - break; - case ALPS_PROTO_V3: -- ret = alps_hw_init_v3(psmouse); -+ priv->hw_init = alps_hw_init_v3; -+ priv->process_packet = alps_process_packet_v3; -+ priv->set_abs_params = alps_set_abs_params_mt; - break; - case ALPS_PROTO_V4: -- ret = alps_hw_init_v4(psmouse); -+ priv->hw_init = alps_hw_init_v4; -+ priv->process_packet = alps_process_packet_v4; -+ priv->set_abs_params = alps_set_abs_params_mt; - break; - } -- -- return ret; - } - - static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, -@@ -1465,6 +1454,8 @@ static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, - model->command_mode_resp == ec[2])) { - - priv->proto_version = model->proto_version; -+ alps_set_defaults(priv); -+ - priv->flags = model->flags; - priv->byte0 = model->byte0; - priv->mask0 = model->mask0; -@@ -1523,7 +1514,7 @@ static int alps_reconnect(struct psmouse *psmouse) - if (alps_identify(psmouse, priv) < 0) - return -1; - -- return alps_hw_init(psmouse); -+ return priv->hw_init(psmouse); - } - - static void alps_disconnect(struct psmouse *psmouse) -@@ -1536,6 +1527,29 @@ static void alps_disconnect(struct psmouse *psmouse) - kfree(priv); - } - -+static void alps_set_abs_params_st(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+} -+ -+static void alps_set_abs_params_mt(struct alps_data *priv, -+ struct input_dev *dev1) -+{ -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ -+ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+} -+ - int alps_init(struct psmouse *psmouse) - { - struct alps_data *priv; -@@ -1556,7 +1570,7 @@ int alps_init(struct psmouse *psmouse) - if (alps_identify(psmouse, priv) < 0) - goto init_fail; - -- if (alps_hw_init(psmouse)) -+ if (priv->hw_init(psmouse)) - goto init_fail; - - /* -@@ -1578,28 +1592,7 @@ int alps_init(struct psmouse *psmouse) - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - -- switch (priv->proto_version) { -- case ALPS_PROTO_V1: -- case ALPS_PROTO_V2: -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -- break; -- case ALPS_PROTO_V3: -- case ALPS_PROTO_V4: -- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -- input_mt_init_slots(dev1, 2, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- -- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -- set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -- set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -- -- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -- break; -- } -- -+ priv->set_abs_params(priv, dev1); - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (priv->flags & ALPS_WHEEL) { -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index a81b318..0934f8b 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -72,6 +72,9 @@ struct alps_nibble_commands { - * mask0, should match byte0. - * @mask0: The mask used to check the first byte of the report. - * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * @hw_init: Protocol-specific hardware init function. -+ * @process_packet: Protocol-specific function to process a report packet. -+ * @set_abs_params: Protocol-specific function to configure the input_dev. - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. - * @multi_data: Saved multi-packet data. -@@ -94,6 +97,10 @@ struct alps_data { - unsigned char byte0, mask0; - unsigned char flags; - -+ int (*hw_init)(struct psmouse *psmouse); -+ void (*process_packet)(struct psmouse *psmouse); -+ void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); -+ - int prev_fin; - int multi_packet; - unsigned char multi_data[6]; --- -1.8.1.2 - - -From e2600c708bef8e1c8126ca9b8d4ce1f83c002688 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:23:04 -0800 -Subject: [PATCH 07/15] Input: ALPS - move {addr,nibble}_command settings into - alps_set_defaults() - -This allows alps_identify() to override these settings based on the -device characteristics, if it is ever necessary. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index fe45687..2221a00 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -1190,14 +1190,10 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) - - static int alps_hw_init_v3(struct psmouse *psmouse) - { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; - -- priv->nibble_commands = alps_v3_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -- - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -@@ -1343,13 +1339,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) - - static int alps_hw_init_v4(struct psmouse *psmouse) - { -- struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - -- priv->nibble_commands = alps_v4_nibble_commands; -- priv->addr_command = PSMOUSE_CMD_DISABLE; -- - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -@@ -1431,11 +1423,15 @@ static void alps_set_defaults(struct alps_data *priv) - priv->hw_init = alps_hw_init_v3; - priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - break; - case ALPS_PROTO_V4: - priv->hw_init = alps_hw_init_v4; - priv->process_packet = alps_process_packet_v4; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; - break; - } - } --- -1.8.1.2 - - -From df0bf385112a7b38c5c3d307bb9399f9f3b3bba2 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:23:34 -0800 -Subject: [PATCH 08/15] Input: ALPS - rework detection of Pinnacle AGx - touchpads - -The official ALPS driver uses the EC report, not the E7 report, to detect -these devices. Also, they check for a range of values; the original -table-based code only checked for two specific ones. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 2221a00..eafeae2 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -109,8 +109,6 @@ static const struct alps_model_info alps_model_data[] = { - { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ - { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -- { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -- { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - -@@ -1412,6 +1410,10 @@ error: - - static void alps_set_defaults(struct alps_data *priv) - { -+ priv->byte0 = 0x8f; -+ priv->mask0 = 0x8f; -+ priv->flags = ALPS_DUALPOINT; -+ - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -@@ -1491,8 +1493,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - alps_exit_command_mode(psmouse)) - return -EIO; - -- if (alps_match_table(psmouse, priv, e7, ec) == 0) -+ if (alps_match_table(psmouse, priv, e7, ec) == 0) { -+ return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x07 && -+ ec[2] >= 0x90 && ec[2] <= 0x9d) { -+ priv->proto_version = ALPS_PROTO_V3; -+ alps_set_defaults(priv); -+ - return 0; -+ } - - psmouse_info(psmouse, - "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", --- -1.8.1.2 - - -From 8e6493f800dc08a28abd59dfe63790aaade0c700 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:24:22 -0800 -Subject: [PATCH 09/15] Input: ALPS - fix command mode check - -Pinnacle class devices should return "88 07 xx" or "88 08 xx" when -entering command mode. If either the first byte or the second byte is -invalid, return an error. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index eafeae2..bfc1938 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -983,7 +983,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - return -1; - } - -- if (param[0] != 0x88 && param[1] != 0x07) { -+ if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { - psmouse_dbg(psmouse, - "unknown response while entering command mode\n"); - return -1; --- -1.8.1.2 - - -From 0302b4c4a1b4201bf82a45c46084f3ccd0ee696f Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:24:55 -0800 -Subject: [PATCH 10/15] Input: ALPS - move pixel and bitmap info into alps_data - struct - -Newer touchpads use different constants, so make them runtime- -configurable. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 47 ++++++++++++++++++++++++---------------------- - drivers/input/mouse/alps.h | 8 ++++++++ - 2 files changed, 33 insertions(+), 22 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index bfc1938..2cd8be7 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -27,12 +27,6 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ --#define ALPS_V3_X_MAX 2000 --#define ALPS_V3_Y_MAX 1400 -- --#define ALPS_BITMAP_X_BITS 15 --#define ALPS_BITMAP_Y_BITS 11 -- - #define ALPS_CMD_NIBBLE_10 0x01f2 - - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -269,7 +263,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - * These points are returned in x1, y1, x2, and y2 when the return value - * is greater than 0. - */ --static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+static int alps_process_bitmap(struct alps_data *priv, -+ unsigned int x_map, unsigned int y_map, - int *x1, int *y1, int *x2, int *y2) - { - struct alps_bitmap_point { -@@ -311,7 +306,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - * y bitmap is reversed for what we need (lower positions are in - * higher bits), so we process from the top end. - */ -- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); - prev_bit = 0; - point = &y_low; - for (i = 0; y_map != 0; i++, y_map <<= 1) { -@@ -357,16 +352,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, - } - } - -- *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - - if (fingers > 1) { -- *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_X_BITS - 1)); -- *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -- (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ *x2 = (priv->x_max * -+ (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (priv->x_bits - 1)); -+ *y2 = (priv->y_max * -+ (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (priv->y_bits - 1)); - } - - return fingers; -@@ -484,7 +481,8 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - ((packet[2] & 0x7f) << 1) | - (packet[4] & 0x01); - -- bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ bmap_fingers = alps_process_bitmap(priv, -+ x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* -@@ -641,7 +639,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) - ((priv->multi_data[3] & 0x1f) << 5) | - (priv->multi_data[1] & 0x1f); - -- fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, - &x1, &y1, &x2, &y2); - - /* Store MT data.*/ -@@ -1414,6 +1412,11 @@ static void alps_set_defaults(struct alps_data *priv) - priv->mask0 = 0x8f; - priv->flags = ALPS_DUALPOINT; - -+ priv->x_max = 2000; -+ priv->y_max = 1400; -+ priv->x_bits = 15; -+ priv->y_bits = 11; -+ - switch (priv->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: -@@ -1544,15 +1547,15 @@ static void alps_set_abs_params_mt(struct alps_data *priv, - { - set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); - input_mt_init_slots(dev1, 2, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); - - set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); - set_bit(BTN_TOOL_QUADTAP, dev1->keybit); - -- input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); - } - - int alps_init(struct psmouse *psmouse) -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 0934f8b..5e638be 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -72,6 +72,10 @@ struct alps_nibble_commands { - * mask0, should match byte0. - * @mask0: The mask used to check the first byte of the report. - * @flags: Additional device capabilities (passthrough port, trackstick, etc.). -+ * @x_max: Largest possible X position value. -+ * @y_max: Largest possible Y position value. -+ * @x_bits: Number of X bits in the MT bitmap. -+ * @y_bits: Number of Y bits in the MT bitmap. - * @hw_init: Protocol-specific hardware init function. - * @process_packet: Protocol-specific function to process a report packet. - * @set_abs_params: Protocol-specific function to configure the input_dev. -@@ -96,6 +100,10 @@ struct alps_data { - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; -+ int x_max; -+ int y_max; -+ int x_bits; -+ int y_bits; - - int (*hw_init)(struct psmouse *psmouse); - void (*process_packet)(struct psmouse *psmouse); --- -1.8.1.2 - - -From 3c9d054fef84ccc967445b330ab6012c6b6bd85b Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:26:11 -0800 -Subject: [PATCH 11/15] Input: ALPS - make the V3 packet field decoder - "pluggable" - -A number of different ALPS touchpad protocols can reuse -alps_process_touchpad_packet_v3() with small tweaks to the bitfield -decoding. Create a new priv->decode_fields() callback that handles the -per-model differences. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 101 +++++++++++++++++++++++++-------------------- - drivers/input/mouse/alps.h | 38 +++++++++++++++++ - 2 files changed, 95 insertions(+), 44 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 2cd8be7..270b7de 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -447,17 +447,49 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - return; - } - -+static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) -+{ -+ f->left = !!(p[3] & 0x01); -+ f->right = !!(p[3] & 0x02); -+ f->middle = !!(p[3] & 0x04); -+ -+ f->ts_left = !!(p[3] & 0x10); -+ f->ts_right = !!(p[3] & 0x20); -+ f->ts_middle = !!(p[3] & 0x40); -+} -+ -+static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) -+{ -+ f->first_mp = !!(p[4] & 0x40); -+ f->is_mp = !!(p[0] & 0x40); -+ -+ f->fingers = (p[5] & 0x3) + 1; -+ f->x_map = ((p[4] & 0x7e) << 8) | -+ ((p[1] & 0x7f) << 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y_map = ((p[3] & 0x70) << 4) | -+ ((p[2] & 0x7f) << 1) | -+ (p[4] & 0x01); -+ -+ f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | -+ ((p[0] & 0x30) >> 4); -+ f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); -+ f->z = p[5] & 0x7f; -+ -+ alps_decode_buttons_v3(f, p); -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; -- int x, y, z; -- int left, right, middle; - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - int fingers = 0, bmap_fingers; -- unsigned int x_bitmap, y_bitmap; -+ struct alps_fields f; -+ -+ priv->decode_fields(&f, packet); - - /* - * There's no single feature of touchpad position and bitmap packets -@@ -472,17 +504,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * packet. Check for this, and when it happens process the - * position packet as usual. - */ -- if (packet[0] & 0x40) { -- fingers = (packet[5] & 0x3) + 1; -- x_bitmap = ((packet[4] & 0x7e) << 8) | -- ((packet[1] & 0x7f) << 2) | -- ((packet[0] & 0x30) >> 4); -- y_bitmap = ((packet[3] & 0x70) << 4) | -- ((packet[2] & 0x7f) << 1) | -- (packet[4] & 0x01); -- -+ if (f.is_mp) { -+ fingers = f.fingers; - bmap_fingers = alps_process_bitmap(priv, -- x_bitmap, y_bitmap, -+ f.x_map, f.y_map, - &x1, &y1, &x2, &y2); - - /* -@@ -493,7 +518,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - fingers = bmap_fingers; - - /* Now process position packet */ -- packet = priv->multi_data; -+ priv->decode_fields(&f, priv->multi_data); - } else { - priv->multi_packet = 0; - } -@@ -507,10 +532,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * out misidentified bitmap packets, we reject anything with this - * bit set. - */ -- if (packet[0] & 0x40) -+ if (f.is_mp) - return; - -- if (!priv->multi_packet && (packet[4] & 0x40)) { -+ if (!priv->multi_packet && f.first_mp) { - priv->multi_packet = 1; - memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); - return; -@@ -518,22 +543,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - priv->multi_packet = 0; - -- left = packet[3] & 0x01; -- right = packet[3] & 0x02; -- middle = packet[3] & 0x04; -- -- x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -- ((packet[0] & 0x30) >> 4); -- y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -- z = packet[5] & 0x7f; -- - /* - * Sometimes the hardware sends a single packet with z = 0 - * in the middle of a stream. Real releases generate packets - * with x, y, and z all zero, so these seem to be flukes. - * Ignore them. - */ -- if (x && y && !z) -+ if (f.x && f.y && !f.z) - return; - - /* -@@ -541,12 +557,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * to rely on ST data. - */ - if (!fingers) { -- x1 = x; -- y1 = y; -- fingers = z > 0 ? 1 : 0; -+ x1 = f.x; -+ y1 = f.y; -+ fingers = f.z > 0 ? 1 : 0; - } - -- if (z >= 64) -+ if (f.z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); -@@ -555,26 +571,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - - input_mt_report_finger_count(dev, fingers); - -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -+ input_report_key(dev, BTN_LEFT, f.left); -+ input_report_key(dev, BTN_RIGHT, f.right); -+ input_report_key(dev, BTN_MIDDLE, f.middle); - -- if (z > 0) { -- input_report_abs(dev, ABS_X, x); -- input_report_abs(dev, ABS_Y, y); -+ if (f.z > 0) { -+ input_report_abs(dev, ABS_X, f.x); -+ input_report_abs(dev, ABS_Y, f.y); - } -- input_report_abs(dev, ABS_PRESSURE, z); -+ input_report_abs(dev, ABS_PRESSURE, f.z); - - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -- left = packet[3] & 0x10; -- right = packet[3] & 0x20; -- middle = packet[3] & 0x40; -- -- input_report_key(dev2, BTN_LEFT, left); -- input_report_key(dev2, BTN_RIGHT, right); -- input_report_key(dev2, BTN_MIDDLE, middle); -+ input_report_key(dev2, BTN_LEFT, f.ts_left); -+ input_report_key(dev2, BTN_RIGHT, f.ts_right); -+ input_report_key(dev2, BTN_MIDDLE, f.ts_middle); - input_sync(dev2); - } - } -@@ -1428,6 +1440,7 @@ static void alps_set_defaults(struct alps_data *priv) - priv->hw_init = alps_hw_init_v3; - priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; -+ priv->decode_fields = alps_decode_pinnacle; - priv->nibble_commands = alps_v3_nibble_commands; - priv->addr_command = PSMOUSE_CMD_RESET_WRAP; - break; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 5e638be..9704805 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -60,6 +60,42 @@ struct alps_nibble_commands { - }; - - /** -+ * struct alps_fields - decoded version of the report packet -+ * @x_map: Bitmap of active X positions for MT. -+ * @y_map: Bitmap of active Y positions for MT. -+ * @fingers: Number of fingers for MT. -+ * @x: X position for ST. -+ * @y: Y position for ST. -+ * @z: Z position for ST. -+ * @first_mp: Packet is the first of a multi-packet report. -+ * @is_mp: Packet is part of a multi-packet report. -+ * @left: Left touchpad button is active. -+ * @right: Right touchpad button is active. -+ * @middle: Middle touchpad button is active. -+ * @ts_left: Left trackstick button is active. -+ * @ts_right: Right trackstick button is active. -+ * @ts_middle: Middle trackstick button is active. -+ */ -+struct alps_fields { -+ unsigned int x_map; -+ unsigned int y_map; -+ unsigned int fingers; -+ unsigned int x; -+ unsigned int y; -+ unsigned int z; -+ unsigned int first_mp:1; -+ unsigned int is_mp:1; -+ -+ unsigned int left:1; -+ unsigned int right:1; -+ unsigned int middle:1; -+ -+ unsigned int ts_left:1; -+ unsigned int ts_right:1; -+ unsigned int ts_middle:1; -+}; -+ -+/** - * struct alps_data - private data structure for the ALPS driver - * @dev2: "Relative" device used to report trackstick or mouse activity. - * @phys: Physical path for the relative device. -@@ -78,6 +114,7 @@ struct alps_nibble_commands { - * @y_bits: Number of Y bits in the MT bitmap. - * @hw_init: Protocol-specific hardware init function. - * @process_packet: Protocol-specific function to process a report packet. -+ * @decode_fields: Protocol-specific function to read packet bitfields. - * @set_abs_params: Protocol-specific function to configure the input_dev. - * @prev_fin: Finger bit from previous packet. - * @multi_packet: Multi-packet data in progress. -@@ -107,6 +144,7 @@ struct alps_data { - - int (*hw_init)(struct psmouse *psmouse); - void (*process_packet)(struct psmouse *psmouse); -+ void (*decode_fields)(struct alps_fields *f, unsigned char *p); - void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); - - int prev_fin; --- -1.8.1.2 - - -From 9e7c99b6c125653f53ef0999a176c3a79de21be8 Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:27:08 -0800 -Subject: [PATCH 12/15] Input: ALPS - add support for "Rushmore" touchpads - -Rushmore touchpads are found on Dell E6230/E6430/E6530. They use the V3 -protocol with slightly tweaked init sequences and report formats. - -The E7 report is 73 03 0a, and the EC report is 88 08 1d - -Credits: Emmanuel Thome reported the MT bitmap changes. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 52 insertions(+) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 270b7de..bf2fa51 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -479,6 +479,14 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) - alps_decode_buttons_v3(f, p); - } - -+static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) -+{ -+ alps_decode_pinnacle(f, p); -+ -+ f->x_map |= (p[5] & 0x10) << 11; -+ f->y_map |= (p[5] & 0x20) << 6; -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -1329,6 +1337,40 @@ error: - return -1; - } - -+static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val, ret = -1; -+ -+ if (alps_enter_command_mode(psmouse, NULL) || -+ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || -+ alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) -+ goto error; -+ -+ /* enter absolute mode */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); -+ -+error: -+ alps_exit_command_mode(psmouse); -+ return ret; -+} -+ - /* Must be in command mode when calling this function */ - static int alps_absolute_mode_v4(struct psmouse *psmouse) - { -@@ -1511,6 +1553,16 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - - if (alps_match_table(psmouse, priv, e7, ec) == 0) { - return 0; -+ } else if (ec[0] == 0x88 && ec[1] == 0x08) { -+ priv->proto_version = ALPS_PROTO_V3; -+ alps_set_defaults(priv); -+ -+ priv->hw_init = alps_hw_init_rushmore_v3; -+ priv->decode_fields = alps_decode_rushmore; -+ priv->x_bits = 16; -+ priv->y_bits = 12; -+ -+ return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x07 && - ec[2] >= 0x90 && ec[2] <= 0x9d) { - priv->proto_version = ALPS_PROTO_V3; --- -1.8.1.2 - - -From e5ca58dc506fb7f64760b483ecd407593b764f3b Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Wed, 13 Feb 2013 22:28:07 -0800 -Subject: [PATCH 13/15] Input: ALPS - enable trackstick on Rushmore touchpads - -Separate out the common trackstick probe/setup sequences, then call them -from each of the v3 init functions. - -Credits: Emmanual Thome furnished the information on the trackstick init -and how it affected the report format. - -Signed-off-by: Kevin Cernekee -Tested-by: Dave Turvene -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 185 ++++++++++++++++++++++++++++----------------- - 1 file changed, 115 insertions(+), 70 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index bf2fa51..7b99fc7 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -29,6 +29,9 @@ - */ - #define ALPS_CMD_NIBBLE_10 0x01f2 - -+#define ALPS_REG_BASE_RUSHMORE 0xc2c0 -+#define ALPS_REG_BASE_PINNACLE 0x0000 -+ - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { - { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ - { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -@@ -1166,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) - } - - /* -- * Enable or disable passthrough mode to the trackstick. Must be in -- * command mode when calling this function. -+ * Enable or disable passthrough mode to the trackstick. - */ --static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) -+static int alps_passthrough_mode_v3(struct psmouse *psmouse, -+ int reg_base, bool enable) - { -- int reg_val; -+ int reg_val, ret = -1; - -- reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -- if (reg_val == -1) -+ if (alps_enter_command_mode(psmouse, NULL)) - return -1; - -+ reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); -+ if (reg_val == -1) -+ goto error; -+ - if (enable) - reg_val |= 0x01; - else - reg_val &= ~0x01; - -- if (__alps_command_mode_write_reg(psmouse, reg_val)) -- return -1; -+ ret = __alps_command_mode_write_reg(psmouse, reg_val); - -- return 0; -+error: -+ if (alps_exit_command_mode(psmouse)) -+ ret = -1; -+ return ret; - } - - /* Must be in command mode when calling this function */ -@@ -1204,69 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) - return 0; - } - --static int alps_hw_init_v3(struct psmouse *psmouse) -+static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) - { -- struct ps2dev *ps2dev = &psmouse->ps2dev; -- int reg_val; -- unsigned char param[4]; -+ int ret = -EIO, reg_val; - - if (alps_enter_command_mode(psmouse, NULL)) - goto error; - -- /* Check for trackstick */ -- reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); - if (reg_val == -1) - goto error; -- if (reg_val & 0x80) { -- if (alps_passthrough_mode_v3(psmouse, true)) -- goto error; -- if (alps_exit_command_mode(psmouse)) -- goto error; -+ -+ /* bit 7: trackstick is present */ -+ ret = reg_val & 0x80 ? 0 : -ENODEV; -+ -+error: -+ alps_exit_command_mode(psmouse); -+ return ret; -+} -+ -+static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int ret = 0; -+ unsigned char param[4]; -+ -+ if (alps_passthrough_mode_v3(psmouse, reg_base, true)) -+ return -EIO; -+ -+ /* -+ * E7 report for the trackstick -+ * -+ * There have been reports of failures to seem to trace back -+ * to the above trackstick check failing. When these occur -+ * this E7 report fails, so when that happens we continue -+ * with the assumption that there isn't a trackstick after -+ * all. -+ */ -+ if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { -+ psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ ret = -ENODEV; -+ } else { -+ psmouse_dbg(psmouse, -+ "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); - - /* -- * E7 report for the trackstick -- * -- * There have been reports of failures to seem to trace back -- * to the above trackstick check failing. When these occur -- * this E7 report fails, so when that happens we continue -- * with the assumption that there isn't a trackstick after -- * all. -+ * Not sure what this does, but it is absolutely -+ * essential. Without it, the touchpad does not -+ * work at all and the trackstick just emits normal -+ * PS/2 packets. - */ -- param[0] = 0x64; -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -- psmouse_warn(psmouse, "trackstick E7 report failed\n"); -- } else { -- psmouse_dbg(psmouse, -- "trackstick E7 report: %2.2x %2.2x %2.2x\n", -- param[0], param[1], param[2]); -- -- /* -- * Not sure what this does, but it is absolutely -- * essential. Without it, the touchpad does not -- * work at all and the trackstick just emits normal -- * PS/2 packets. -- */ -- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -- alps_command_mode_send_nibble(psmouse, 0x9) || -- alps_command_mode_send_nibble(psmouse, 0x4)) { -- psmouse_err(psmouse, -- "Error sending magic E6 sequence\n"); -- goto error_passthrough; -- } -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ alps_command_mode_send_nibble(psmouse, 0x9) || -+ alps_command_mode_send_nibble(psmouse, 0x4)) { -+ psmouse_err(psmouse, -+ "Error sending magic E6 sequence\n"); -+ ret = -EIO; -+ goto error; - } - -- if (alps_enter_command_mode(psmouse, NULL)) -- goto error_passthrough; -- if (alps_passthrough_mode_v3(psmouse, false)) -- goto error; -+ /* -+ * This ensures the trackstick packets are in the format -+ * supported by this driver. If bit 1 isn't set the packet -+ * format is different. -+ */ -+ if (alps_enter_command_mode(psmouse, NULL) || -+ alps_command_mode_write_reg(psmouse, -+ reg_base + 0x08, 0x82) || -+ alps_exit_command_mode(psmouse)) -+ ret = -EIO; - } - -- if (alps_absolute_mode_v3(psmouse)) { -+error: -+ if (alps_passthrough_mode_v3(psmouse, reg_base, false)) -+ ret = -EIO; -+ -+ return ret; -+} -+ -+static int alps_hw_init_v3(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val; -+ unsigned char param[4]; -+ -+ reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); -+ if (reg_val == -EIO) -+ goto error; -+ if (reg_val == 0 && -+ alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) -+ goto error; -+ -+ if (alps_enter_command_mode(psmouse, NULL) || -+ alps_absolute_mode_v3(psmouse)) { - psmouse_err(psmouse, "Failed to enter absolute mode\n"); - goto error; - } -@@ -1303,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) - goto error; - -- /* -- * This ensures the trackstick packets are in the format -- * supported by this driver. If bit 1 isn't set the packet -- * format is different. -- */ -- if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) -- goto error; -- - alps_exit_command_mode(psmouse); - - /* Set rate and enable data reporting */ -@@ -1323,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - - return 0; - --error_passthrough: -- /* Something failed while in passthrough mode, so try to get out */ -- if (!alps_enter_command_mode(psmouse, NULL)) -- alps_passthrough_mode_v3(psmouse, false); - error: - /* - * Leaving the touchpad in command mode will essentially render -@@ -1339,9 +1368,19 @@ error: - - static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) - { -+ struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val, ret = -1; - -+ if (priv->flags & ALPS_DUALPOINT) { -+ reg_val = alps_setup_trackstick_v3(psmouse, -+ ALPS_REG_BASE_RUSHMORE); -+ if (reg_val == -EIO) -+ goto error; -+ if (reg_val == -ENODEV) -+ priv->flags &= ~ALPS_DUALPOINT; -+ } -+ - if (alps_enter_command_mode(psmouse, NULL) || - alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || - alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) -@@ -1562,6 +1601,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - priv->x_bits = 16; - priv->y_bits = 12; - -+ /* hack to make addr_command, nibble_command available */ -+ psmouse->private = priv; -+ -+ if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) -+ priv->flags &= ~ALPS_DUALPOINT; -+ - return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x07 && - ec[2] >= 0x90 && ec[2] <= 0x9d) { --- -1.8.1.2 - - -From db7192fa07fa5c70c9849d8f658a7ff696cff99d Mon Sep 17 00:00:00 2001 -From: Kevin Cernekee -Date: Sat, 16 Feb 2013 22:40:03 -0800 -Subject: [PATCH 14/15] Input: ALPS - Remove unused argument to - alps_enter_command_mode() - -Now that alps_identify() explicitly issues an EC report using -alps_rpt_cmd(), we no longer need to look at the magic numbers returned -by alps_enter_command_mode(). - -Signed-off-by: Kevin Cernekee ---- - drivers/input/mouse/alps.c | 18 +++++++----------- - 1 file changed, 7 insertions(+), 11 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 7b99fc7..9c97531 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -994,8 +994,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, - return 0; - } - --static int alps_enter_command_mode(struct psmouse *psmouse, -- unsigned char *resp) -+static int alps_enter_command_mode(struct psmouse *psmouse) - { - unsigned char param[4]; - -@@ -1009,9 +1008,6 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - "unknown response while entering command mode\n"); - return -1; - } -- -- if (resp) -- *resp = param[2]; - return 0; - } - -@@ -1176,7 +1172,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, - { - int reg_val, ret = -1; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - return -1; - - reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); -@@ -1216,7 +1212,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) - { - int ret = -EIO, reg_val; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - goto error; - - reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); -@@ -1279,7 +1275,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) - * supported by this driver. If bit 1 isn't set the packet - * format is different. - */ -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_command_mode_write_reg(psmouse, - reg_base + 0x08, 0x82) || - alps_exit_command_mode(psmouse)) -@@ -1306,7 +1302,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) - goto error; - -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_absolute_mode_v3(psmouse)) { - psmouse_err(psmouse, "Failed to enter absolute mode\n"); - goto error; -@@ -1381,7 +1377,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) - priv->flags &= ~ALPS_DUALPOINT; - } - -- if (alps_enter_command_mode(psmouse, NULL) || -+ if (alps_enter_command_mode(psmouse) || - alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || - alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) - goto error; -@@ -1431,7 +1427,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - -- if (alps_enter_command_mode(psmouse, NULL)) -+ if (alps_enter_command_mode(psmouse)) - goto error; - - if (alps_absolute_mode_v4(psmouse)) { --- -1.8.1.2 - - -From 10740a25bb3b895b5de7773f926a978416b38409 Mon Sep 17 00:00:00 2001 -From: Dave Turvene -Date: Sat, 16 Feb 2013 22:40:04 -0800 -Subject: [PATCH 15/15] Input: ALPS - Add "Dolphin V1" touchpad support - -These touchpads use a different protocol; they have been seen on Dell -N5110, Dell 17R SE, and others. - -The official ALPS driver identifies them by looking for an exact match -on the E7 report: 73 03 50. Dolphin V1 returns an EC report of -73 01 xx (02 and 0d have been seen); Dolphin V2 returns an EC report of -73 02 xx (02 has been seen). - -Dolphin V2 probably needs a different initialization sequence and/or -report parser, so it is left for a future commit. - -Signed-off-by: Dave Turvene -Signed-off-by: Kevin Cernekee ---- - drivers/input/mouse/alps.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/alps.h | 1 + - 2 files changed, 66 insertions(+), 2 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 9c97531..0238e0e 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) - f->y_map |= (p[5] & 0x20) << 6; - } - -+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) -+{ -+ f->first_mp = !!(p[0] & 0x02); -+ f->is_mp = !!(p[0] & 0x20); -+ -+ f->fingers = ((p[0] & 0x6) >> 1 | -+ (p[0] & 0x10) >> 2); -+ f->x_map = ((p[2] & 0x60) >> 5) | -+ ((p[4] & 0x7f) << 2) | -+ ((p[5] & 0x7f) << 9) | -+ ((p[3] & 0x07) << 16) | -+ ((p[3] & 0x70) << 15) | -+ ((p[0] & 0x01) << 22); -+ f->y_map = (p[1] & 0x7f) | -+ ((p[2] & 0x1f) << 7); -+ -+ f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); -+ f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); -+ f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; -+ -+ alps_decode_buttons_v3(f, p); -+} -+ - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - } - - /* Bytes 2 - pktsize should have 0 in the highest bit */ -- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && -+ if (priv->proto_version != ALPS_PROTO_V5 && -+ psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, -@@ -1003,7 +1027,8 @@ static int alps_enter_command_mode(struct psmouse *psmouse) - return -1; - } - -- if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { -+ if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && -+ param[0] != 0x73) { - psmouse_dbg(psmouse, - "unknown response while entering command mode\n"); - return -1; -@@ -1495,6 +1520,23 @@ error: - return -1; - } - -+static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[2]; -+ -+ /* This is dolphin "v1" as empirically defined by florin9doi */ -+ param[0] = 0x64; -+ param[1] = 0x28; -+ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || -+ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) -+ return -1; -+ -+ return 0; -+} -+ - static void alps_set_defaults(struct alps_data *priv) - { - priv->byte0 = 0x8f; -@@ -1528,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) - priv->nibble_commands = alps_v4_nibble_commands; - priv->addr_command = PSMOUSE_CMD_DISABLE; - break; -+ case ALPS_PROTO_V5: -+ priv->hw_init = alps_hw_init_dolphin_v1; -+ priv->process_packet = alps_process_packet_v3; -+ priv->decode_fields = alps_decode_dolphin; -+ priv->set_abs_params = alps_set_abs_params_mt; -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -+ priv->byte0 = 0xc8; -+ priv->mask0 = 0xc8; -+ priv->flags = 0; -+ priv->x_max = 1360; -+ priv->y_max = 660; -+ priv->x_bits = 23; -+ priv->y_bits = 12; -+ break; - } - } - -@@ -1588,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) - - if (alps_match_table(psmouse, priv, e7, ec) == 0) { - return 0; -+ } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && -+ ec[0] == 0x73 && ec[1] == 0x01) { -+ priv->proto_version = ALPS_PROTO_V5; -+ alps_set_defaults(priv); -+ -+ return 0; - } else if (ec[0] == 0x88 && ec[1] == 0x08) { - priv->proto_version = ALPS_PROTO_V3; - alps_set_defaults(priv); -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 9704805..eee5985 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -16,6 +16,7 @@ - #define ALPS_PROTO_V2 2 - #define ALPS_PROTO_V3 3 - #define ALPS_PROTO_V4 4 -+#define ALPS_PROTO_V5 5 - - /** - * struct alps_model_info - touchpad ID table --- -1.8.1.2 - diff --git a/amd64_edac_fix_rank_count.patch b/amd64_edac_fix_rank_count.patch deleted file mode 100644 index eb58f0d03..000000000 --- a/amd64_edac_fix_rank_count.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 56ba4c93d909ef9dfab4f1101a8c3bf75bc4cdab Mon Sep 17 00:00:00 2001 -From: Mauro Carvalho Chehab -Date: Mon, 11 Mar 2013 08:19:52 -0400 -Subject: [PATCH EDAC] edac: merge mci.mem_is_per_rank with mci.csbased - -Both mci.mem_is_per_rank and mci.csbased have the same meaning: -the memory controller is csrows based. Merge both fields into one. - -There's no need for the driver to actually fill it, as the core -detectsi it by checking if one of the layes has the csrows type -as part of the memory hierarchy: - - if (layers[i].type == EDAC_MC_LAYER_CHIP_SELECT) - per_rank = true; -... - mci->csbased = per_rank; - -Signed-off-by: Mauro Carvalho Chehab - -From 2b6018dbd206e4af16edcfb80497b73105e97803 Mon Sep 17 00:00:00 2001 -From: Mauro Carvalho Chehab -Date: Mon, 11 Mar 2013 08:18:24 -0400 -Subject: [PATCH EDAC] amd64_edac: Correct dimm sizes - -We were filling the csrow size with a wrong value. 16a528ee3975 ("EDAC: -Fix csrow size reported in sysfs") tried to address the issue. It fixed -the report with the old API but not with the new one. Correct it for the -new API too. - -Signed-off-by: Mauro Carvalho Chehab -Signed-off-by: Borislav Petkov -diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c -index ad8bf2a..10ed0c7 100644 ---- a/drivers/edac/amd64_edac.c -+++ b/drivers/edac/amd64_edac.c -@@ -2148,12 +2148,18 @@ static int init_csrows(struct mem_ctl_info *mci) - edac_dbg(1, "MC node: %d, csrow: %d\n", - pvt->mc_node_id, i); - -- if (row_dct0) -+ if (row_dct0) { - nr_pages = amd64_csrow_nr_pages(pvt, 0, i); -+ csrow->channels[0]->dimm->nr_pages = nr_pages; -+ } - - /* K8 has only one DCT */ -- if (boot_cpu_data.x86 != 0xf && row_dct1) -- nr_pages += amd64_csrow_nr_pages(pvt, 1, i); -+ if (boot_cpu_data.x86 != 0xf && row_dct1) { -+ int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i); -+ -+ csrow->channels[1]->dimm->nr_pages = row_dct1_pages; -+ nr_pages += row_dct1_pages; -+ } - - mtype = amd64_determine_memory_type(pvt, i); - -@@ -2172,9 +2178,7 @@ static int init_csrows(struct mem_ctl_info *mci) - dimm = csrow->channels[j]->dimm; - dimm->mtype = mtype; - dimm->edac_mode = edac_mode; -- dimm->nr_pages = nr_pages; - } -- csrow->nr_pages = nr_pages; - } - - return empty; -@@ -2519,7 +2523,6 @@ static int amd64_init_one_instance(struct pci_dev *F2) - - mci->pvt_info = pvt; - mci->pdev = &pvt->F2->dev; -- mci->csbased = 1; - - setup_mci_misc_attrs(mci, fam_type); - -diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c -index cdb81aa..27e86d9 100644 ---- a/drivers/edac/edac_mc.c -+++ b/drivers/edac/edac_mc.c -@@ -86,7 +86,7 @@ static void edac_mc_dump_dimm(struct dimm_info *dimm, int number) - edac_dimm_info_location(dimm, location, sizeof(location)); - - edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", -- dimm->mci->mem_is_per_rank ? "rank" : "dimm", -+ dimm->mci->csbased ? "rank" : "dimm", - number, location, dimm->csrow, dimm->cschannel); - edac_dbg(4, " dimm = %p\n", dimm); - edac_dbg(4, " dimm->label = '%s'\n", dimm->label); -@@ -341,7 +341,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, - memcpy(mci->layers, layers, sizeof(*layer) * n_layers); - mci->nr_csrows = tot_csrows; - mci->num_cschannel = tot_channels; -- mci->mem_is_per_rank = per_rank; -+ mci->csbased = per_rank; - - /* - * Alocate and fill the csrow/channels structs -@@ -1235,7 +1235,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, - * incrementing the compat API counters - */ - edac_dbg(4, "%s csrows map: (%d,%d)\n", -- mci->mem_is_per_rank ? "rank" : "dimm", -+ mci->csbased ? "rank" : "dimm", - dimm->csrow, dimm->cschannel); - if (row == -1) - row = dimm->csrow; -diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c -index 4f4b613..6ab4a50 100644 ---- a/drivers/edac/edac_mc_sysfs.c -+++ b/drivers/edac/edac_mc_sysfs.c -@@ -180,9 +180,6 @@ static ssize_t csrow_size_show(struct device *dev, - int i; - u32 nr_pages = 0; - -- if (csrow->mci->csbased) -- return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages)); -- - for (i = 0; i < csrow->nr_channels; i++) - nr_pages += csrow->channels[i]->dimm->nr_pages; - return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); -@@ -612,7 +609,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, - device_initialize(&dimm->dev); - - dimm->dev.parent = &mci->dev; -- if (mci->mem_is_per_rank) -+ if (mci->csbased) - dev_set_name(&dimm->dev, "rank%d", index); - else - dev_set_name(&dimm->dev, "dimm%d", index); -@@ -778,14 +775,10 @@ static ssize_t mci_size_mb_show(struct device *dev, - for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { - struct csrow_info *csrow = mci->csrows[csrow_idx]; - -- if (csrow->mci->csbased) { -- total_pages += csrow->nr_pages; -- } else { -- for (j = 0; j < csrow->nr_channels; j++) { -- struct dimm_info *dimm = csrow->channels[j]->dimm; -+ for (j = 0; j < csrow->nr_channels; j++) { -+ struct dimm_info *dimm = csrow->channels[j]->dimm; - -- total_pages += dimm->nr_pages; -- } -+ total_pages += dimm->nr_pages; - } - } - -diff --git a/include/linux/edac.h b/include/linux/edac.h -index 4fd4999..0b76327 100644 ---- a/include/linux/edac.h -+++ b/include/linux/edac.h -@@ -561,7 +561,6 @@ struct csrow_info { - - u32 ue_count; /* Uncorrectable Errors for this csrow */ - u32 ce_count; /* Correctable Errors for this csrow */ -- u32 nr_pages; /* combined pages count of all channels */ - - struct mem_ctl_info *mci; /* the parent */ - -@@ -676,11 +675,11 @@ struct mem_ctl_info { - * sees memory sticks ("dimms"), and the ones that sees memory ranks. - * All old memory controllers enumerate memories per rank, but most - * of the recent drivers enumerate memories per DIMM, instead. -- * When the memory controller is per rank, mem_is_per_rank is true. -+ * When the memory controller is per rank, csbased is true. - */ - unsigned n_layers; - struct edac_mc_layer *layers; -- bool mem_is_per_rank; -+ bool csbased; - - /* - * DIMM info. Will eventually remove the entire csrows_info some day -@@ -741,8 +740,6 @@ struct mem_ctl_info { - u32 fake_inject_ue; - u16 fake_inject_count; - #endif -- __u8 csbased : 1, /* csrow-based memory controller */ -- __resv : 7; - }; - - #endif diff --git a/cfg80211-mac80211-disconnect-on-suspend.patch b/cfg80211-mac80211-disconnect-on-suspend.patch deleted file mode 100644 index 940ac2cc4..000000000 --- a/cfg80211-mac80211-disconnect-on-suspend.patch +++ /dev/null @@ -1,227 +0,0 @@ -From ad3a7b84092599eef931bce4de54e18e47612f9f Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Thu, 28 Feb 2013 09:55:25 +0000 -Subject: [PATCH] cfg80211/mac80211: disconnect on suspend - -If possible that after suspend, cfg80211 will receive request to -disconnect what require action on interface that was removed during -suspend. - -Problem can manifest itself by various warnings similar to below one: - -WARNING: at net/mac80211/driver-ops.h:12 ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211]() -wlan0: Failed check-sdata-in-driver check, flags: 0x4 -Call Trace: - [] warn_slowpath_fmt+0x33/0x40 - [] ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211] - [] ieee80211_recalc_ps_vif+0x2a/0x30 [mac80211] - [] ieee80211_set_disassoc+0xf6/0x500 [mac80211] - [] ieee80211_mgd_deauth+0x1f1/0x280 [mac80211] - [] ieee80211_deauth+0x16/0x20 [mac80211] - [] cfg80211_mlme_down+0x70/0xc0 [cfg80211] - [] __cfg80211_disconnect+0x1b1/0x1d0 [cfg80211] - -To fix the problem disconnect from any associated network before -suspend. User space is responsible to establish connection again -after resume. This basically need to be done by user space anyway, -because associated stations can go away during suspend (for example -NetworkManager disconnects on suspend and connect on resume by default). - -Patch also handle situation when driver refuse to suspend with wowlan -configured and try to suspend again without it. - -Signed-off-by: Stanislaw Gruszka -Signed-off-by: Johannes Berg ---- - net/mac80211/pm.c | 2 +- - net/wireless/core.c | 73 +++++++++++++++++++++++++++---------------------- - net/wireless/core.h | 3 ++ - net/wireless/rdev-ops.h | 7 +++-- - net/wireless/sysfs.c | 25 +++++++++++++---- - 5 files changed, 69 insertions(+), 41 deletions(-) - -diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c -index 79a48f3..ce4f973 100644 ---- a/net/mac80211/pm.c -+++ b/net/mac80211/pm.c -@@ -92,7 +92,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) - return err; - } else if (err > 0) { - WARN_ON(err != 1); -- local->wowlan = false; -+ return err; - } else { - list_for_each_entry(sdata, &local->interfaces, list) { - cancel_work_sync(&sdata->work); -diff --git a/net/wireless/core.c b/net/wireless/core.c -index b677eab..66cc98d 100644 ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -806,6 +806,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, - rdev->num_running_monitor_ifaces += num; - } - -+void cfg80211_leave(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev) -+{ -+ struct net_device *dev = wdev->netdev; -+ -+ switch (wdev->iftype) { -+ case NL80211_IFTYPE_ADHOC: -+ cfg80211_leave_ibss(rdev, dev, true); -+ break; -+ case NL80211_IFTYPE_P2P_CLIENT: -+ case NL80211_IFTYPE_STATION: -+ mutex_lock(&rdev->sched_scan_mtx); -+ __cfg80211_stop_sched_scan(rdev, false); -+ mutex_unlock(&rdev->sched_scan_mtx); -+ -+ wdev_lock(wdev); -+#ifdef CONFIG_CFG80211_WEXT -+ kfree(wdev->wext.ie); -+ wdev->wext.ie = NULL; -+ wdev->wext.ie_len = 0; -+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; -+#endif -+ __cfg80211_disconnect(rdev, dev, -+ WLAN_REASON_DEAUTH_LEAVING, true); -+ cfg80211_mlme_down(rdev, dev); -+ wdev_unlock(wdev); -+ break; -+ case NL80211_IFTYPE_MESH_POINT: -+ cfg80211_leave_mesh(rdev, dev); -+ break; -+ case NL80211_IFTYPE_AP: -+ cfg80211_stop_ap(rdev, dev); -+ break; -+ default: -+ break; -+ } -+ -+ wdev->beacon_interval = 0; -+} -+ - static int cfg80211_netdev_notifier_call(struct notifier_block *nb, - unsigned long state, - void *ndev) -@@ -874,38 +914,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, - dev->priv_flags |= IFF_DONT_BRIDGE; - break; - case NETDEV_GOING_DOWN: -- switch (wdev->iftype) { -- case NL80211_IFTYPE_ADHOC: -- cfg80211_leave_ibss(rdev, dev, true); -- break; -- case NL80211_IFTYPE_P2P_CLIENT: -- case NL80211_IFTYPE_STATION: -- mutex_lock(&rdev->sched_scan_mtx); -- __cfg80211_stop_sched_scan(rdev, false); -- mutex_unlock(&rdev->sched_scan_mtx); -- -- wdev_lock(wdev); --#ifdef CONFIG_CFG80211_WEXT -- kfree(wdev->wext.ie); -- wdev->wext.ie = NULL; -- wdev->wext.ie_len = 0; -- wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; --#endif -- __cfg80211_disconnect(rdev, dev, -- WLAN_REASON_DEAUTH_LEAVING, true); -- cfg80211_mlme_down(rdev, dev); -- wdev_unlock(wdev); -- break; -- case NL80211_IFTYPE_MESH_POINT: -- cfg80211_leave_mesh(rdev, dev); -- break; -- case NL80211_IFTYPE_AP: -- cfg80211_stop_ap(rdev, dev); -- break; -- default: -- break; -- } -- wdev->beacon_interval = 0; -+ cfg80211_leave(rdev, wdev); - break; - case NETDEV_DOWN: - cfg80211_update_iface_num(rdev, wdev->iftype, -1); -diff --git a/net/wireless/core.h b/net/wireless/core.h -index 3563097..49d79d9 100644 ---- a/net/wireless/core.h -+++ b/net/wireless/core.h -@@ -481,6 +481,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, - void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, - enum nl80211_iftype iftype, int num); - -+void cfg80211_leave(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev); -+ - #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 - - #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS -diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h -index 6c0c819..08e4145 100644 ---- a/net/wireless/rdev-ops.h -+++ b/net/wireless/rdev-ops.h -@@ -6,11 +6,12 @@ - #include "core.h" - #include "trace.h" - --static inline int rdev_suspend(struct cfg80211_registered_device *rdev) -+static inline int rdev_suspend(struct cfg80211_registered_device *rdev, -+ struct cfg80211_wowlan *wowlan) - { - int ret; -- trace_rdev_suspend(&rdev->wiphy, rdev->wowlan); -- ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); -+ trace_rdev_suspend(&rdev->wiphy, wowlan); -+ ret = rdev->ops->suspend(&rdev->wiphy, wowlan); - trace_rdev_return_int(&rdev->wiphy, ret); - return ret; - } -diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c -index 1f6f01e..a6a108b 100644 ---- a/net/wireless/sysfs.c -+++ b/net/wireless/sysfs.c -@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) - return 0; - } - -+static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) -+{ -+ struct wireless_dev *wdev; -+ -+ list_for_each_entry(wdev, &rdev->wdev_list, list) -+ cfg80211_leave(rdev, wdev); -+} -+ - static int wiphy_suspend(struct device *dev, pm_message_t state) - { - struct cfg80211_registered_device *rdev = dev_to_rdev(dev); -@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) - - rdev->suspend_at = get_seconds(); - -- if (rdev->ops->suspend) { -- rtnl_lock(); -- if (rdev->wiphy.registered) -- ret = rdev_suspend(rdev); -- rtnl_unlock(); -+ rtnl_lock(); -+ if (rdev->wiphy.registered) { -+ if (!rdev->wowlan) -+ cfg80211_leave_all(rdev); -+ if (rdev->ops->suspend) -+ ret = rdev_suspend(rdev, rdev->wowlan); -+ if (ret == 1) { -+ /* Driver refuse to configure wowlan */ -+ cfg80211_leave_all(rdev); -+ ret = rdev_suspend(rdev, NULL); -+ } - } -+ rtnl_unlock(); - - return ret; - } --- -1.8.1.2 - diff --git a/config-debug b/config-debug index e1b3f9db2..43655a1a1 100644 --- a/config-debug +++ b/config-debug @@ -96,6 +96,7 @@ CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y +CONFIG_KDB_CONTINUE_CATASTROPHIC=0 CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y diff --git a/config-generic b/config-generic index 6550abbbb..92827f15d 100644 --- a/config-generic +++ b/config-generic @@ -188,6 +188,8 @@ CONFIG_FW_LOADER=y # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER is not set + # CONFIG_CMA is not set # CONFIG_SPI is not set @@ -199,6 +201,7 @@ CONFIG_MTD=m # CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_AR7_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set # # User Modules And Translation Layers @@ -320,6 +323,7 @@ CONFIG_BLK_DEV_THROTTLING=y # CONFIG_IDE is not set # CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_RSXX is not set CONFIG_SCSI_VIRTIO=m CONFIG_VIRTIO_BLK=m @@ -328,7 +332,6 @@ CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_MMIO=m # CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set CONFIG_VIRTIO_NET=m -CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m CONFIG_VIRTIO_CONSOLE=y CONFIG_VHOST_NET=m @@ -394,7 +397,8 @@ CONFIG_SCSI_3W_9XXX=m CONFIG_SCSI_ACARD=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m -CONFIG_SCSI_AIC7XXX_OLD=m +# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004102.html +# CONFIG_SCSI_AIC7XXX_OLD is not set CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set @@ -428,6 +432,7 @@ CONFIG_SCSI_MPT3SAS_MAX_SGE=128 CONFIG_SCSI_MPT3SAS_LOGGING=y CONFIG_SCSI_UFSHCD=m +CONFIG_SCSI_UFSHCD_PCI=m CONFIG_SCSI_MVUMI=m @@ -437,6 +442,7 @@ CONFIG_SCSI_OSD_DPRINT_SENSE=1 # CONFIG_SCSI_OSD_DEBUG is not set CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_SCSI_BNX2X_FCOE=m CONFIG_BE2ISCSI=m CONFIG_SCSI_PMCRAID=m @@ -476,7 +482,9 @@ CONFIG_SCSI_DC390T=m CONFIG_SCSI_QLA_FC=m CONFIG_TCM_QLA2XXX=m CONFIG_SCSI_QLA_ISCSI=m -# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y # CONFIG_SCSI_DPT_I2O is not set CONFIG_SCSI_LPFC=m # CONFIG_SCSI_LPFC_DEBUG_FS is not set @@ -509,6 +517,7 @@ CONFIG_SATA_SX4=m CONFIG_SATA_ULI=m CONFIG_SATA_VIA=m CONFIG_SATA_VITESSE=m +# CONFIG_SATA_ZPODD is not set CONFIG_SATA_ACARD_AHCI=m # CONFIG_PATA_LEGACY is not set @@ -580,11 +589,14 @@ CONFIG_ASYNC_RAID6_TEST=m CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m CONFIG_DM_DEBUG=y -# CONFIG_DM_DELAY is not set +CONFIG_DM_DELAY=m CONFIG_DM_MIRROR=y CONFIG_DM_MULTIPATH=m CONFIG_DM_SNAPSHOT=y CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_MQ=m +CONFIG_DM_CACHE_CLEANER=m # CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set # CONFIG_DM_DEBUG_SPACE_MAPS is not set CONFIG_DM_UEVENT=y @@ -661,7 +673,7 @@ CONFIG_TCP_MD5SIG=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_DIAG is not set +CONFIG_PACKET_DIAG=m CONFIG_UNIX=y CONFIG_UNIX_DIAG=m CONFIG_NET_KEY=m @@ -761,6 +773,7 @@ CONFIG_NET_9P_RDMA=m # CONFIG_DECNET is not set CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y # PHY timestamping adds overhead CONFIG_NETWORK_PHY_TIMESTAMPING=y @@ -803,10 +816,12 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m CONFIG_NETFILTER_XT_MATCH_CLUSTER=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETFILTER_XT_MATCH_CPU=m CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m CONFIG_NETFILTER_XT_MATCH_CONNMARK=m CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y @@ -996,6 +1011,7 @@ CONFIG_SCTP_COOKIE_HMAC_SHA1=y CONFIG_ATM=m CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y CONFIG_LLC=m # CONFIG_LLC2 is not set CONFIG_IPX=m @@ -1020,7 +1036,8 @@ CONFIG_IP_DCCP_CCID3=y # # TIPC Configuration (EXPERIMENTAL) # -# CONFIG_TIPC is not set +CONFIG_TIPC=m +CONFIG_TIPC_PORTS=8192 # CONFIG_TIPC_ADVANCED is not set # CONFIG_TIPC_DEBUG is not set @@ -1093,6 +1110,7 @@ CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=y # CONFIG_BATMAN_ADV_DEBUG is not set CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m CONFIG_NETPRIO_CGROUP=m @@ -1260,6 +1278,7 @@ CONFIG_E100=m CONFIG_E1000=m CONFIG_E1000E=m CONFIG_IGB=m +CONFIG_IGB_HWMON=y CONFIG_IGB_DCA=y CONFIG_IGB_PTP=y CONFIG_IGBVF=m @@ -1412,6 +1431,8 @@ CONFIG_NET_PCI=y CONFIG_B44=m CONFIG_B44_PCI=y CONFIG_BNX2=m +CONFIG_BNX2X=m +CONFIG_BNX2X_SRIOV=y CONFIG_CNIC=m CONFIG_FEALNX=m CONFIG_NET_POCKET=y @@ -1428,7 +1449,6 @@ CONFIG_JME=m # # CONFIG_IP1000 is not set # CONFIG_MLX4_EN is not set -# CONFIG_MLX4_DEBUG is not set # CONFIG_SFC is not set # CONFIG_FDDI is not set @@ -1573,6 +1593,8 @@ CONFIG_LIBERTAS_SDIO=m # CONFIG_LIBERTAS_THINFIRM is not set CONFIG_LIBERTAS_MESH=y CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_SVTOOL=y @@ -1614,7 +1636,6 @@ CONFIG_RT2800PCI_RT53XX=y CONFIG_RT73USB=m CONFIG_RTL8180=m CONFIG_RTL8187=m -# CONFIG_RTLWIFI_DEBUG is not set # CONFIG_USB_ZD1201 is not set CONFIG_USB_NET_RNDIS_WLAN=m CONFIG_USB_NET_KALMIA=m @@ -1635,6 +1656,8 @@ CONFIG_WL1251=m CONFIG_WL1251_SPI=m CONFIG_WL1251_SDIO=m +CONFIG_RTLWIFI=m +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m @@ -1695,9 +1718,11 @@ CONFIG_NFC_LLCP=y # # Near Field Communication (NFC) devices # -CONFIG_PN544_NFC=m -CONFIG_PN544_HCI_NFC=m +CONFIG_NFC_PN544=m +CONFIG_NFC_PN544_I2C=m CONFIG_NFC_PN533=m +CONFIG_NFC_MICROREAD=m +CONFIG_NFC_MICROREAD_I2C=m # # IrDA (infrared) support @@ -1992,6 +2017,7 @@ CONFIG_MOUSE_APPLETOUCH=m CONFIG_MOUSE_BCM5974=m CONFIG_MOUSE_SYNAPTICS_I2C=m CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_MOUSE_CYAPA=m CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_ANALOG=m CONFIG_JOYSTICK_A3D=m @@ -2112,12 +2138,14 @@ CONFIG_TCG_TIS=m CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m # CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_ST33_I2C is not set CONFIG_TELCLOCK=m # # Serial drivers # CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CS=m CONFIG_SERIAL_8250_NR_UARTS=32 @@ -2279,6 +2307,7 @@ CONFIG_SENSORS_LM93=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6697=m CONFIG_SENSORS_MCP3021=m CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m @@ -2319,6 +2348,7 @@ CONFIG_SENSORS_WM831X=m CONFIG_SENSORS_LM73=m CONFIG_SENSORS_AMC6821=m CONFIG_SENSORS_INA2XX=m +CONFIG_SENSORS_INA209=m CONFIG_SENSORS_ADT7411=m CONFIG_SENSORS_ASC7621=m CONFIG_SENSORS_EMC1403=m @@ -2365,6 +2395,7 @@ CONFIG_SENSORS_MAX197=m # CONFIG_USB_SWITCH_FSA9480 is not set CONFIG_SERIAL_ARC=m CONFIG_SERIAL_ARC_NR_PORTS=1 +# CONFIG_SERIAL_RP2 is not set CONFIG_W1=m CONFIG_W1_CON=y @@ -2376,6 +2407,7 @@ CONFIG_W1_MASTER_DS1WM=m CONFIG_W1_SLAVE_THERM=m CONFIG_W1_SLAVE_SMEM=m CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2413=m CONFIG_W1_SLAVE_DS2423=m CONFIG_W1_SLAVE_DS2431=m CONFIG_W1_SLAVE_DS2433=m @@ -2451,6 +2483,7 @@ CONFIG_HW_RANDOM_TPM=m # CONFIG_GEN_RTC is not set CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y +# CONFIG_RTC_SYSTOHC is not set CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y @@ -2495,6 +2528,10 @@ CONFIG_RTC_DRV_MSM6242=m CONFIG_RTC_DRV_RP5C01=m CONFIG_RTC_DRV_EM3027=m CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_PCF50633=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_ISL12022=m +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set CONFIG_R3964=m # CONFIG_APPLICOM is not set @@ -2528,6 +2565,7 @@ CONFIG_DRM_CIRRUS_QEMU=m # do not enable on f17 or older # CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y +# CONFIG_DRM_RADEON_UMS is not set # CONFIG_DRM_I810 is not set # CONFIG_DRM_MGA is not set CONFIG_DRM_MGAG200=m # do not enable on f17 or older @@ -2544,10 +2582,12 @@ CONFIG_DRM_NOUVEAU_DEBUG=y # CONFIG_DRM_PSB is not set CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_UDL=m CONFIG_DRM_VMWGFX=m CONFIG_DRM_VMWGFX_FBCON=y CONFIG_DRM_VGEM=m +CONFIG_DRM_QXL=m # # PCMCIA character devices @@ -2578,6 +2618,7 @@ CONFIG_VIDEO_DEV=m # CONFIG_VIDEO_ADV_DEBUG is not set CONFIG_VIDEO_HELPER_CHIPS_AUTO=y CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_V4L2_INT_DEVICE is not set CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_VIDEO_VIVI is not set @@ -2592,6 +2633,7 @@ CONFIG_V4L_USB_DRIVERS=y CONFIG_VIDEO_CAPTURE_DRIVERS=y CONFIG_V4L_PCI_DRIVERS=y CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y CONFIG_VIDEO_BT848=m CONFIG_VIDEO_BT848_DVB=y CONFIG_VIDEO_BWQCAM=m @@ -2810,6 +2852,7 @@ CONFIG_IR_GPIO_CIR=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set # CONFIG_V4L_TEST_DRIVERS is not set # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -2895,6 +2938,7 @@ CONFIG_FB_EFI=y # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set # CONFIG_FB_UDL is not set +# CONFIG_FB_GOLDFISH is not set # CONFIG_FIRMWARE_EDID is not set @@ -3018,6 +3062,7 @@ CONFIG_SND_HDA_CODEC_CMEDIA=y CONFIG_SND_HDA_CODEC_SI3054=y CONFIG_SND_HDA_CODEC_HDMI=y CONFIG_SND_HDA_CODEC_CA0132=y +CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=y CONFIG_SND_HDA_POWER_SAVE=y CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 @@ -3202,9 +3247,11 @@ CONFIG_HID_ROCCAT_KONE=m CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m CONFIG_HID_SUNPLUS=m +CONFIG_HID_STEELSERIES=m CONFIG_HID_GREENASIA=m CONFIG_HID_SMARTJOYPLUS=m CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m @@ -3313,6 +3360,7 @@ CONFIG_USB_RTL8150=m CONFIG_USB_USBNET=m CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m CONFIG_USB_NET_DM9601=m CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_NET_GL620A=m @@ -3422,6 +3470,7 @@ CONFIG_USB_SERIAL_WHITEHEAT=m CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_QCAUX=m CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_XSENS_MT=m CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m CONFIG_USB_SERIAL_QT2=m @@ -3443,6 +3492,8 @@ CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m # CONFIG_OMAP_USB2 is not set +# CONFIG_OMAP_USB3 is not set +# CONFIG_OMAP_CONTROL_USB is not set CONFIG_USB_RCAR_PHY=m CONFIG_USB_ATM=m CONFIG_USB_CXACRU=m @@ -3463,6 +3514,7 @@ CONFIG_USB_IOWARRIOR=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m CONFIG_USB_EZUSB_FX2=m +CONFIG_USB_HSIC_USB3503=m CONFIG_USB_LCD=m CONFIG_USB_LD=m CONFIG_USB_LEGOTOWER=m @@ -3475,6 +3527,7 @@ CONFIG_USB_SISUSBVGA=m CONFIG_USB_SISUSBVGA_CON=y CONFIG_RADIO_SI470X=y CONFIG_USB_KEENE=m +CONFIG_USB_MA901=m CONFIG_USB_SI470X=m CONFIG_I2C_SI470X=m CONFIG_RADIO_SI4713=m @@ -3513,9 +3566,6 @@ CONFIG_PCF50633_GPIO=m # CONFIG_AB3100_CORE is not set CONFIG_INPUT_PCF50633_PMU=m CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -CONFIG_RTC_DRV_PCF50633=m -CONFIG_RTC_DRV_DS3232=m -CONFIG_RTC_DRV_ISL12022=m CONFIG_MFD_SUPPORT=y CONFIG_MFD_VX855=m @@ -3656,6 +3706,7 @@ CONFIG_DEBUG_FS=y # CONFIG_ADFS_FS is not set CONFIG_AFFS_FS=m CONFIG_ECRYPT_FS=m +# CONFIG_ECRYPT_FS_MESSAGING is not set CONFIG_HFS_FS=m CONFIG_HFSPLUS_FS=m CONFIG_BEFS_FS=m @@ -3899,6 +3950,7 @@ CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set # CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +# CONFIG_PANIC_ON_OOPS is not set CONFIG_ATOMIC64_SELFTEST=y CONFIG_MEMORY_FAILURE=y CONFIG_HWPOISON_INJECT=m @@ -3973,6 +4025,7 @@ CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_CCM=m CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=m CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_CTS=m CONFIG_CRYPTO_DEFLATE=m @@ -4112,9 +4165,10 @@ CONFIG_HWMON=y CONFIG_THERMAL_HWMON=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -CONFIG_FAIR_SHARE=y -CONFIG_STEP_WISE=y -# CONFIG_USER_SPACE is not set +CONFIG_THERMAL_GOV_FAIR_SHARE=y +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_EMULATION is not set # CONFIG_CPU_THERMAL is not set CONFIG_INOTIFY=y @@ -4209,6 +4263,7 @@ CONFIG_LEDS_DELL_NETBOOKS=m # CONFIG_LEDS_TCA6507 is not set # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_PWM is not set CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_ONESHOT=m @@ -4237,6 +4292,7 @@ CONFIG_LEDS_WM831X_STATUS=m CONFIG_DMADEVICES=y CONFIG_DMA_ENGINE=y CONFIG_DW_DMAC=m +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set # CONFIG_TIMB_DMA is not set # CONFIG_DMATEST is not set CONFIG_ASYNC_TX_DMA=y @@ -4250,6 +4306,7 @@ CONFIG_DYNAMIC_FTRACE=y # CONFIG_IRQSOFF_TRACER is not set CONFIG_SCHED_TRACER=y CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACER_SNAPSHOT=y CONFIG_FTRACE_SYSCALLS=y CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_FTRACE_STARTUP_TEST is not set @@ -4297,6 +4354,7 @@ CONFIG_APM_POWER=m # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set # CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_GOLDFISH is not set # CONFIG_CHARGER_ISP1704 is not set # CONFIG_CHARGER_MAX8903 is not set @@ -4342,9 +4400,6 @@ CONFIG_LIRC_TTUSBIR=m # CONFIG_DEVKMEM is not set -CONFIG_BNX2X=m -CONFIG_SCSI_BNX2X_FCOE=m - CONFIG_NOZOMI=m # CONFIG_TPS65010 is not set @@ -4390,6 +4445,7 @@ CONFIG_NET_DSA_MV88E6123_61_65=m # CONFIG_PHONET is not set # CONFIG_ICS932S401 is not set +# CONFIG_ATMEL_SSC is not set # CONFIG_C2PORT is not set @@ -4414,7 +4470,6 @@ CONFIG_UWB_WHCI=m CONFIG_UWB_I1480U=m CONFIG_STAGING=y -# CONFIG_RTLLIB is not set # CONFIG_ANDROID is not set CONFIG_STAGING_MEDIA=y # CONFIG_DVB_AS102 is not set @@ -4599,6 +4654,13 @@ CONFIG_GPIO_VIPERBOARD=m CONFIG_EVENT_POWER_TRACING_DEPRECATED=y CONFIG_TEST_KSTRTOX=y +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set # CONFIG_XZ_DEC_TEST is not set # CONFIG_POWER_AVS is not set @@ -4621,6 +4683,7 @@ CONFIG_PSTORE_RAM=m # CONFIG_AVERAGE is not set +# CONFIG_VMXNET3 is not set # CONFIG_SIGMA is not set @@ -4638,10 +4701,14 @@ CONFIG_BCMA_DRIVER_GPIO=y # CONFIG_INTEL_MID_PTI is not set CONFIG_IOMMU_SUPPORT=y +# CONFIG_MAILBOX is not set + # CONFIG_HSI is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_MODULE_SIG is not set +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set # CONFIG_MODULE_VERIFY_ELF is not set # CONFIG_CRYPTO_KEY_TYPE is not set # CONFIG_PGP_LIBRARY is not set diff --git a/config-nodebug b/config-nodebug index f5cbe10b9..aa7568c82 100644 --- a/config-nodebug +++ b/config-nodebug @@ -96,6 +96,7 @@ CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y +CONFIG_KDB_CONTINUE_CATASTROPHIC=0 # CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set # CONFIG_TEST_LIST_SORT is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 03341c818..b6df88ea8 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -346,6 +346,7 @@ CONFIG_I2C_MPC=m CONFIG_RFKILL_GPIO=m # CONFIG_CRYPTO_DEV_FSL_CAAM is not set +# CONFIG_CRYPTO_SHA1_PPC is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set @@ -381,8 +382,13 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RTC_DRV_SNVS is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_OF_DISPLAY_TIMING is not set +# CONFIG_OF_VIDEOMODE is not set + CONFIG_POWER_RESET_GPIO=y CONFIG_FB_SSD1307=m CONFIG_INPUT_PWM_BEEPER=m CONFIG_BACKLIGHT_PWM=m CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=n + +CONFIG_XZ_DEC_POWERPC=y diff --git a/config-powerpc64 b/config-powerpc64 index 7c0477cf1..d0e0aab5b 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -178,4 +178,6 @@ CONFIG_BPF_JIT=y # CONFIG_PPC_ICSWX_USE_SIGILL is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_PCIEPORTBUS is not set - +# CONFIG_PPC_TRANSACTIONAL_MEM is not set +# CONFIG_SND_HDA_INTEL is not set +CONFIG_BLK_DEV_RSXX=m diff --git a/config-powerpc64p7 b/config-powerpc64p7 index 9a8289588..285d9fff9 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -169,4 +169,5 @@ CONFIG_BPF_JIT=y # CONFIG_PPC_ICSWX_USE_SIGILL is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_PCIEPORTBUS is not set - +# CONFIG_SND_HDA_INTEL is not set +CONFIG_BLK_DEV_RSXX=m diff --git a/config-x86-32-generic b/config-x86-32-generic index 0e9b3f4be..6b6c60d30 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -3,6 +3,7 @@ CONFIG_X86_32_NON_STANDARD=y # CONFIG_X86_ELAN is not set +# CONFIG_X86_GOLDFISH is not set # CONFIG_X86_NUMAQ is not set # CONFIG_X86_SUMMIT is not set CONFIG_X86_BIGSMP=y @@ -227,3 +228,5 @@ CONFIG_BACKLIGHT_PWM=m # CONFIG_GPIO_ADNP is not set # CONFIG_BACKLIGHT_OT200 is not set # CONFIG_RTC_DRV_SNVS is not set +# CONFIG_OF_DISPLAY_TIMING is not set +# CONFIG_OF_VIDEOMODE is not set diff --git a/config-x86-generic b/config-x86-generic index 761e1da3f..67a9e1477 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -14,6 +14,7 @@ CONFIG_I8K=m CONFIG_SONYPI_COMPAT=y CONFIG_MICROCODE=m CONFIG_MICROCODE_INTEL=y +CONFIG_MICROCODE_INTEL_EARLY=y CONFIG_MICROCODE_AMD=y CONFIG_X86_MSR=y @@ -37,7 +38,7 @@ CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_EFI_VARS=y CONFIG_EFI_VARS_PSTORE=y -# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y CONFIG_EFI_PCDP=y CONFIG_FB_EFI=y @@ -69,7 +70,7 @@ CONFIG_ACPI_AC=y # CONFIG_ACPI_ASUS is not set CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_CONTAINER=y CONFIG_ACPI_DOCK=y CONFIG_ACPI_FAN=y CONFIG_ACPI_NUMA=y @@ -96,11 +97,12 @@ CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m CONFIG_ACPI_BGRT=y -CONFIG_X86_ACPI_CPUFREQ=y -CONFIG_X86_PCC_CPUFREQ=y +# CONFIG_X86_INTEL_PSTATE is not set +CONFIG_X86_ACPI_CPUFREQ=m +CONFIG_X86_PCC_CPUFREQ=m CONFIG_X86_ACPI_CPUFREQ_CPB=y -CONFIG_X86_POWERNOW_K8=y -CONFIG_X86_P4_CLOCKMOD=y +CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_P4_CLOCKMOD=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # @@ -144,6 +146,7 @@ CONFIG_I2C_AMD756_S4882=m CONFIG_I2C_AMD8111=m CONFIG_I2C_I801=m CONFIG_I2C_ISCH=m +CONFIG_I2C_ISMT=m CONFIG_I2C_NFORCE2=m CONFIG_I2C_NFORCE2_S4985=m CONFIG_I2C_PIIX4=m @@ -196,6 +199,7 @@ CONFIG_AMILO_RFKILL=m CONFIG_ASUS_LAPTOP=m CONFIG_COMPAL_LAPTOP=m CONFIG_DELL_LAPTOP=m +CONFIG_CHROMEOS_LAPTOP=m CONFIG_EEEPC_LAPTOP=m CONFIG_FUJITSU_TABLET=m CONFIG_FUJITSU_LAPTOP=m @@ -366,6 +370,7 @@ CONFIG_LPC_SCH=m CONFIG_LPC_ICH=m CONFIG_GPIO_ICH=m +# CONFIG_GPIO_LYNXPOINT is not set CONFIG_PCI_CNB20LE_QUIRK=y @@ -396,6 +401,7 @@ CONFIG_PCH_PHUB=m CONFIG_CRYPTO_AES_NI_INTEL=y CONFIG_CRYPTO_SERPENT_SSE2_586=m +CONFIG_CRYPTO_CRC32_PCLMUL=m CONFIG_HP_ACCEL=m @@ -425,14 +431,31 @@ CONFIG_DRM_GMA3600=y CONFIG_RCU_FANOUT_LEAF=16 CONFIG_INTEL_MEI=m +CONFIG_INTEL_MEI_ME=y # Maybe enable in debug kernels? # CONFIG_DEBUG_NMI_SELFTEST is not set +# CONFIG_X86_INTEL_LPSS is not set + +# CONFIG_INTEL_POWERCLAMP is not set + +CONFIG_VMWARE_VMCI=m +CONFIG_VMWARE_VMCI_VSOCKETS=m + +CONFIG_XZ_DEC_X86=y + CONFIG_MPILIB=y +CONFIG_PKCS7_MESSAGE_PARSER=y +CONFIG_PE_FILE_PARSER=y CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_ALL=y # CONFIG_MODULE_SIG_SHA1 is not set CONFIG_MODULE_SIG_SHA256=y # CONFIG_MODULE_SIG_FORCE is not set -CONFIG_MODULE_SIG_BLACKLIST=y +CONFIG_SYSTEM_BLACKLIST_KEYRING=y + CONFIG_MODULE_SIG_UEFI=y + +CONFIG_VMXNET3=m +CONFIG_VFIO_PCI_VGA=y diff --git a/config-x86_64-generic b/config-x86_64-generic index f4fc09d98..67ac161f3 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -130,6 +130,9 @@ CONFIG_BPF_JIT=y # Should be 32bit only, but lacks KConfig depends # CONFIG_XO15_EBOOK is not set +CONFIG_NTB=m +CONFIG_NTB_NETDEV=m + # 10GigE # CONFIG_IP1000=m diff --git a/debug-bad-pte-modules.patch b/debug-bad-pte-modules.patch index bcf328667..0cc7d550e 100644 --- a/debug-bad-pte-modules.patch +++ b/debug-bad-pte-modules.patch @@ -9,13 +9,13 @@ diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-tre #include #include ---- linux-3.8.6-104.fc17.noarch/mm/memory.c~ 2013-04-11 11:48:54.024470277 -0400 -+++ linux-3.8.6-104.fc17.noarch/mm/memory.c 2013-04-11 11:49:15.770425274 -0400 -@@ -718,6 +718,7 @@ static void print_bad_pte(struct vm_area +--- linux-3.9.0-200.fc18.x86_64/mm/memory.c~ 2013-05-06 15:04:30.324416922 -0400 ++++ linux-3.9.0-200.fc18.x86_64/mm/memory.c 2013-05-06 15:04:43.933398227 -0400 +@@ -723,6 +723,7 @@ static void print_bad_pte(struct vm_area if (vma->vm_file && vma->vm_file->f_op) print_symbol(KERN_ALERT "vma->vm_file->f_op->mmap: %s\n", (unsigned long)vma->vm_file->f_op->mmap); + print_modules(); dump_stack(); - add_taint(TAINT_BAD_PAGE); + add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); } diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch index c005a06ba..0f28ed240 100644 --- a/drm-i915-dp-stfu.patch +++ b/drm-i915-dp-stfu.patch @@ -11,15 +11,15 @@ index 296cfc2..516e1e2 100644 DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); -@@ -400,7 +400,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, +@@ -447,7 +447,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d } if (try == 3) { - WARN(1, "dp_aux_ch not started status 0x%08x\n", + DRM_ERROR("dp_aux_ch not started status 0x%08x\n", I915_READ(ch_ctl)); - return -EBUSY; - } + ret = -EBUSY; + goto out; @@ -1024,8 +1024,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) return; DRM_DEBUG_KMS("Turn eDP VDD on\n"); diff --git a/kernel.spec b/kernel.spec index 4344f9769..670eaf8cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -68,13 +68,13 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 8 +%define base_sublevel 9 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -666,9 +666,7 @@ Patch460: serial-460800.patch Patch470: die-floppy-die.patch Patch510: silence-noise.patch -Patch520: quiet-apm.patch Patch530: silence-fbcon-logo.patch -Patch540: silence-empty-ipi-mask-warning.patch Patch800: crash-driver.patch @@ -713,8 +711,6 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch -Patch14011: team-net-next-update-20130307.patch - Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -735,13 +731,6 @@ Patch22001: selinux-apply-different-permission-to-ptrace-child.patch #rhbz 859485 Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz 799564 -Patch22240: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch -Patch22241: Input-add-support-for-Cypress-PS2-Trackpads.patch - -#rhbz 912166 -Patch22243: Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch - #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch @@ -751,36 +740,15 @@ Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch -#rhbz 812111 -Patch24000: alps-v2.patch - -Patch24100: userns-avoid-recursion-in-put_user_ns.patch - -#rhbz 879462 -Patch24107: uvcvideo-suspend-fix.patch - -#rhbz 856863 892599 -Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch -Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch - #rhbz 859282 Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch -#rhbz 920586 -Patch25000: amd64_edac_fix_rank_count.patch - #rhbz 921500 Patch25001: i7300_edac_single_mode_fixup.patch -#rhbz 920218 -Patch25006: mac80211-Dont-restart-sta-timer-if-not-running.patch - #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -#rhbz 844750 -Patch25008: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch - #rhbz 919176 Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch @@ -1409,9 +1377,6 @@ ApplyPatch silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch silence-fbcon-logo.patch -# no-one cares about these warnings. -ApplyPatch silence-empty-ipi-mask-warning.patch - # Changes to upstream defaults. @@ -1419,7 +1384,7 @@ ApplyPatch silence-empty-ipi-mask-warning.patch ApplyPatch crash-driver.patch # secure boot -ApplyPatch secure-boot-20130409.patch +#ApplyPatch secure-boot-20130409.patch # Assorted Virt Fixes @@ -1436,7 +1401,6 @@ ApplyPatch drm-i915-tv-detect-hush.patch # silence the ACPI blacklist code ApplyPatch silence-acpi-blacklist.patch -ApplyPatch quiet-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty @@ -1470,54 +1434,24 @@ ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch #rhbz 859485 ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch -#rhbz 799564 -ApplyPatch Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch -ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch - -#rhbz 912166 -ApplyPatch Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch - #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch -#rhbz 812111 -ApplyPatch alps-v2.patch - #rhbz 903192 ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch #rhbz 916544 ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch -ApplyPatch userns-avoid-recursion-in-put_user_ns.patch - -#rhbz 920586 -ApplyPatch amd64_edac_fix_rank_count.patch - #rhbz 921500 ApplyPatch i7300_edac_single_mode_fixup.patch -#Team Driver update -ApplyPatch team-net-next-update-20130307.patch - -#rhbz 879462 -ApplyPatch uvcvideo-suspend-fix.patch - -#rhbz 856863 892599 -ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch -ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch - #rhbz 859282 ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch -#rhbz 920218 -ApplyPatch mac80211-Dont-restart-sta-timer-if-not-running.patch - #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -ApplyPatch 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch - #rhbz 919176 ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch @@ -1544,6 +1478,11 @@ mkdir configs rm -f kernel-%{version}-*debug.config %endif + +# FIXME: ARM config broken on 3.9 rebase +rm -f kernel-%{version}-arm*.config + + # now run oldconfig over all the config files for i in *.config do @@ -2381,6 +2320,25 @@ fi # ||----w | # || || %changelog +* Mon May 06 2013 Dave Jones - 3.9.0-200 +- Rebase to Linux 3.9 + merged: silence-empty-ipi-mask-warning.patch + merged: quiet-apm.patch + merged: Input-increase-struct-ps2dev-cmdbuf-to-8-bytes.patch + merged: Input-add-support-for-Cypress-PS2-Trackpads.patch + merged: Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch + merged: alps-v2.patch + merged: userns-avoid-recursion-in-put_user_ns.patch + merged: amd64_edac_fix_rank_count.patch + merged: team-net-next-update-20130307.patch + merged: uvcvideo-suspend-fix.patch + merged: cfg80211-mac80211-disconnect-on-suspend.patch + merged: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch + merged: mac80211-Dont-restart-sta-timer-if-not-running.patch + merged: 0001-bluetooth-Add-support-for-atheros-04ca-3004-device-t.patch + TODO: secure-boot + TODO: ARM configs. + * Wed May 01 2013 Justin M. Forbes - 3.8.11-200 - Linux v3.8.11 diff --git a/mac80211-Dont-restart-sta-timer-if-not-running.patch b/mac80211-Dont-restart-sta-timer-if-not-running.patch deleted file mode 100644 index 7727ad8f2..000000000 --- a/mac80211-Dont-restart-sta-timer-if-not-running.patch +++ /dev/null @@ -1,55 +0,0 @@ -From: Ben Greear - -I found another crash when deleting lots of virtual stations -in a congested environment. I think the problem is that -the ieee80211_mlme_notify_scan_completed could call -ieee80211_restart_sta_timer for a stopped interface -that was about to be deleted. Fix similar problem for -mesh interfaces as well. - -Signed-off-by: Ben Greear ---- -v4: Fix up mesh as well, add check in calling code instead of - in the methods that mucks iwth the timers. - -:100644 100644 67fcfdf... 02e3d75... M net/mac80211/mesh.c -:100644 100644 aec786d... 1d237e9... M net/mac80211/mlme.c - net/mac80211/mesh.c | 3 ++- - net/mac80211/mlme.c | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c -index 67fcfdf..02e3d75 100644 ---- a/net/mac80211/mesh.c -+++ b/net/mac80211/mesh.c -@@ -779,7 +779,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) - - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) -- if (ieee80211_vif_is_mesh(&sdata->vif)) -+ if (ieee80211_sdata_running(sdata) -+ && ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_queue_work(&local->hw, &sdata->work); - rcu_read_unlock(); - } -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index aec786d..1d237e9 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3054,7 +3054,8 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) - /* Restart STA timers */ - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) -- ieee80211_restart_sta_timer(sdata); -+ if (ieee80211_sdata_running(sdata)) -+ ieee80211_restart_sta_timer(sdata); - rcu_read_unlock(); - } - --- -1.7.3.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch b/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch deleted file mode 100644 index 8249ab38c..000000000 --- a/mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c -index 8be854e..6d2bab7 100644 ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -605,7 +605,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) - } - - ieee80211_adjust_monitor_flags(sdata, 1); -- ieee80211_configure_filter(local); -+ /* tell driver latter (if not suspended) */ - - netif_carrier_on(dev); - break; -@@ -804,8 +804,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, - sdata->dev->addr_len); - spin_unlock_bh(&local->filter_lock); - netif_addr_unlock_bh(sdata->dev); -- -- ieee80211_configure_filter(local); -+ /* configure filter latter (if not suspended) */ - } - - del_timer_sync(&local->dynamic_ps_timer); -@@ -872,32 +871,30 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, - */ - ieee80211_free_keys(sdata); - -- if (going_down) -+ if (going_down && !local->suspended) - drv_remove_interface(local, sdata); - } - - sdata->bss = NULL; - -- mutex_lock(&local->mtx); -- hw_reconf_flags |= __ieee80211_recalc_idle(local); -- mutex_unlock(&local->mtx); -- -- ieee80211_recalc_ps(local, -1); -+ if (!local->suspended) { -+ if (local->open_count == 0) { -+ if (local->ops->napi_poll) -+ napi_disable(&local->napi); -+ ieee80211_clear_tx_pending(local); -+ ieee80211_stop_device(local); -+ } else { -+ ieee80211_recalc_ps(local, -1); - -- if (local->open_count == 0) { -- if (local->ops->napi_poll) -- napi_disable(&local->napi); -- ieee80211_clear_tx_pending(local); -- ieee80211_stop_device(local); -+ mutex_lock(&local->mtx); -+ hw_reconf_flags |= __ieee80211_recalc_idle(local); -+ mutex_unlock(&local->mtx); - -- /* no reconfiguring after stop! */ -- hw_reconf_flags = 0; -+ if (hw_reconf_flags) -+ ieee80211_hw_config(local, hw_reconf_flags); -+ } - } - -- /* do after stop to avoid reconfiguring when we stop anyway */ -- if (hw_reconf_flags) -- ieee80211_hw_config(local, hw_reconf_flags); -- - spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { - skb_queue_walk_safe(&local->pending[i], skb, tmp) { diff --git a/quiet-apm.patch b/quiet-apm.patch deleted file mode 100644 index c38511c41..000000000 --- a/quiet-apm.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c -index a46bd38..416dd12 100644 ---- a/arch/x86/kernel/apm_32.c -+++ b/arch/x86/kernel/apm_32.c -@@ -903,7 +903,7 @@ static void apm_cpu_idle(void) - unsigned int jiffies_since_last_check = jiffies - last_jiffies; - unsigned int bucket; - -- WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); -+ printk_once(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); - recalc: - if (jiffies_since_last_check > IDLE_CALC_LIMIT) { - use_apm_idle = 0; diff --git a/serial-460800.patch b/serial-460800.patch index 0e68378e7..bdae70e31 100644 --- a/serial-460800.patch +++ b/serial-460800.patch @@ -1,7 +1,7 @@ diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 2209620..659c1bb 100644 ---- a/drivers/tty/serial/8250/8250.c -+++ b/drivers/tty/serial/8250/8250.c +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c @@ -7,6 +7,9 @@ * * Copyright (C) 2001 Russell King. diff --git a/silence-empty-ipi-mask-warning.patch b/silence-empty-ipi-mask-warning.patch deleted file mode 100644 index 65a637c06..000000000 --- a/silence-empty-ipi-mask-warning.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-3.6.noarch/arch/x86/kernel/apic/ipi.c~ 2013-01-23 10:48:14.716069615 -0500 -+++ linux-3.6.noarch/arch/x86/kernel/apic/ipi.c 2013-01-23 10:48:26.217046545 -0500 -@@ -106,7 +106,7 @@ void default_send_IPI_mask_logical(const - unsigned long mask = cpumask_bits(cpumask)[0]; - unsigned long flags; - -- if (WARN_ONCE(!mask, "empty IPI mask")) -+ if (!mask) - return; - - local_irq_save(flags); diff --git a/sources b/sources index b1f904923..06558d5b1 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz -76ec67882ad94b8ab43c70a46befca13 patch-3.8.11.xz +4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz diff --git a/taint-vbox.patch b/taint-vbox.patch index 5cb3e47c9..5cde0ce28 100644 --- a/taint-vbox.patch +++ b/taint-vbox.patch @@ -1,15 +1,13 @@ -diff --git a/kernel/module.c b/kernel/module.c -index 04379f92..d26c9a3 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -2653,6 +2653,10 @@ static int check_module_license_and_versions(struct module *mod) +--- linux-3.9.0-200.fc18.x86_64/kernel/module.c~ 2013-05-06 15:01:57.589631369 -0400 ++++ linux-3.9.0-200.fc18.x86_64/kernel/module.c 2013-05-06 15:02:30.635583966 -0400 +@@ -2873,6 +2873,10 @@ static int check_module_license_and_vers if (strcmp(mod->name, "ndiswrapper") == 0) - add_taint(TAINT_PROPRIETARY_MODULE); + add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE); + /* vbox is garbage. */ + if (strcmp(mod->name, "vboxdrv") == 0) -+ add_taint(TAINT_CRAP); ++ add_taint(TAINT_CRAP, LOCKDEP_NOW_UNRELIABLE); + /* driverloader was caught wrongly pretending to be under GPL */ if (strcmp(mod->name, "driverloader") == 0) - add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + add_taint_module(mod, TAINT_PROPRIETARY_MODULE, diff --git a/team-net-next-update-20130307.patch b/team-net-next-update-20130307.patch deleted file mode 100644 index ebaa06762..000000000 --- a/team-net-next-update-20130307.patch +++ /dev/null @@ -1,608 +0,0 @@ -Update team driver to 3.9-rc1. - -Split patches available here: -http://people.redhat.com/jpirko/f18_team_update_4/ - -Flavio Leitner (5): - team: implement carrier change - team: add ethtool support - team: update master carrier state - team: use strlcpy with ethtool_drvinfo fields - team: allow userspace to take control over carrier - -Jiri Pirko (5): - rtnl: expose carrier value with possibility to set it - net: add change_carrier netdev op - team: handle sending port list in the same way option list is sent - team: move netlink event notifiers after team_port_leave() - team: ab: set active port option as changed when port is leaving - - Documentation/networking/operstates.txt | 4 + - drivers/net/team/team.c | 246 +++++++++++++++++++----------- - drivers/net/team/team_mode_activebackup.c | 13 +- - include/linux/if_team.h | 1 + - include/linux/netdevice.h | 12 ++ - include/uapi/linux/if_link.h | 1 + - net/core/dev.c | 19 +++ - net/core/rtnetlink.c | 10 ++ - 8 files changed, 215 insertions(+), 91 deletions(-) - -Signed-off-by: Jiri Pirko - -diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt -index 1a77a3c..9769457 100644 ---- a/Documentation/networking/operstates.txt -+++ b/Documentation/networking/operstates.txt -@@ -88,6 +88,10 @@ set this flag. On netif_carrier_off(), the scheduler stops sending - packets. The name 'carrier' and the inversion are historical, think of - it as lower layer. - -+Note that for certain kind of soft-devices, which are not managing any -+real hardware, there is possible to set this bit from userpsace. -+One should use TVL IFLA_CARRIER to do so. -+ - netif_carrier_ok() can be used to query that bit. - - __LINK_STATE_DORMANT, maps to IFF_DORMANT: -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index ad86660..9e68014 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - - #define DRV_NAME "team" -@@ -507,6 +508,7 @@ static bool team_is_mode_set(struct team *team) - - static void team_set_no_mode(struct team *team) - { -+ team->user_carrier_enabled = false; - team->mode = &__team_no_mode; - } - -@@ -1129,10 +1131,6 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - return -ENOENT; - } - -- __team_option_inst_mark_removed_port(team, port); -- __team_options_change_check(team); -- __team_option_inst_del_port(team, port); -- __team_port_change_port_removed(port); - team_port_disable(team, port); - list_del_rcu(&port->list); - netdev_rx_handler_unregister(port_dev); -@@ -1141,6 +1139,12 @@ static int team_port_del(struct team *team, struct net_device *port_dev) - vlan_vids_del_by_dev(port_dev, dev); - dev_close(port_dev); - team_port_leave(team, port); -+ -+ __team_option_inst_mark_removed_port(team, port); -+ __team_options_change_check(team); -+ __team_option_inst_del_port(team, port); -+ __team_port_change_port_removed(port); -+ - team_port_set_orig_dev_addr(port); - dev_set_mtu(port_dev, port->orig.mtu); - synchronize_rcu(); -@@ -1399,13 +1403,11 @@ static void team_destructor(struct net_device *dev) - - static int team_open(struct net_device *dev) - { -- netif_carrier_on(dev); - return 0; - } - - static int team_close(struct net_device *dev) - { -- netif_carrier_off(dev); - return 0; - } - -@@ -1707,6 +1709,19 @@ static netdev_features_t team_fix_features(struct net_device *dev, - return features; - } - -+static int team_change_carrier(struct net_device *dev, bool new_carrier) -+{ -+ struct team *team = netdev_priv(dev); -+ -+ team->user_carrier_enabled = true; -+ -+ if (new_carrier) -+ netif_carrier_on(dev); -+ else -+ netif_carrier_off(dev); -+ return 0; -+} -+ - static const struct net_device_ops team_netdev_ops = { - .ndo_init = team_init, - .ndo_uninit = team_uninit, -@@ -1729,8 +1744,24 @@ static const struct net_device_ops team_netdev_ops = { - .ndo_add_slave = team_add_slave, - .ndo_del_slave = team_del_slave, - .ndo_fix_features = team_fix_features, -+ .ndo_change_carrier = team_change_carrier, - }; - -+/*********************** -+ * ethtool interface -+ ***********************/ -+ -+static void team_ethtool_get_drvinfo(struct net_device *dev, -+ struct ethtool_drvinfo *drvinfo) -+{ -+ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); -+ strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version)); -+} -+ -+static const struct ethtool_ops team_ethtool_ops = { -+ .get_drvinfo = team_ethtool_get_drvinfo, -+ .get_link = ethtool_op_get_link, -+}; - - /*********************** - * rt netlink interface -@@ -1780,6 +1811,7 @@ static void team_setup(struct net_device *dev) - ether_setup(dev); - - dev->netdev_ops = &team_netdev_ops; -+ dev->ethtool_ops = &team_ethtool_ops; - dev->destructor = team_destructor; - dev->tx_queue_len = 0; - dev->flags |= IFF_MULTICAST; -@@ -1941,30 +1973,6 @@ static void team_nl_team_put(struct team *team) - dev_put(team->dev); - } - --static int team_nl_send_generic(struct genl_info *info, struct team *team, -- int (*fill_func)(struct sk_buff *skb, -- struct genl_info *info, -- int flags, struct team *team)) --{ -- struct sk_buff *skb; -- int err; -- -- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -- if (!skb) -- return -ENOMEM; -- -- err = fill_func(skb, info, NLM_F_ACK, team); -- if (err < 0) -- goto err_fill; -- -- err = genlmsg_unicast(genl_info_net(info), skb, info->snd_portid); -- return err; -- --err_fill: -- nlmsg_free(skb); -- return err; --} -- - typedef int team_nl_send_func_t(struct sk_buff *skb, - struct team *team, u32 portid); - -@@ -2309,16 +2317,57 @@ team_put: - return err; - } - --static int team_nl_fill_port_list_get(struct sk_buff *skb, -- u32 portid, u32 seq, int flags, -- struct team *team, -- bool fillall) -+static int team_nl_fill_one_port_get(struct sk_buff *skb, -+ struct team_port *port) -+{ -+ struct nlattr *port_item; -+ -+ port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); -+ if (!port_item) -+ goto nest_cancel; -+ if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) -+ goto nest_cancel; -+ if (port->changed) { -+ if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) -+ goto nest_cancel; -+ port->changed = false; -+ } -+ if ((port->removed && -+ nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || -+ (port->state.linkup && -+ nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || -+ nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || -+ nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) -+ goto nest_cancel; -+ nla_nest_end(skb, port_item); -+ return 0; -+ -+nest_cancel: -+ nla_nest_cancel(skb, port_item); -+ return -EMSGSIZE; -+} -+ -+static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq, -+ int flags, team_nl_send_func_t *send_func, -+ struct team_port *one_port) - { - struct nlattr *port_list; -+ struct nlmsghdr *nlh; - void *hdr; - struct team_port *port; -+ int err; -+ struct sk_buff *skb = NULL; -+ bool incomplete; -+ int i; -+ -+ port = list_first_entry(&team->port_list, struct team_port, list); - -- hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags, -+start_again: -+ err = __send_and_alloc_skb(&skb, team, portid, send_func); -+ if (err) -+ return err; -+ -+ hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, - TEAM_CMD_PORT_LIST_GET); - if (!hdr) - return -EMSGSIZE; -@@ -2329,47 +2378,54 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb, - if (!port_list) - goto nla_put_failure; - -- list_for_each_entry(port, &team->port_list, list) { -- struct nlattr *port_item; -+ i = 0; -+ incomplete = false; - -- /* Include only changed ports if fill all mode is not on */ -- if (!fillall && !port->changed) -- continue; -- port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); -- if (!port_item) -- goto nla_put_failure; -- if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex)) -- goto nla_put_failure; -- if (port->changed) { -- if (nla_put_flag(skb, TEAM_ATTR_PORT_CHANGED)) -- goto nla_put_failure; -- port->changed = false; -+ /* If one port is selected, called wants to send port list containing -+ * only this port. Otherwise go through all listed ports and send all -+ */ -+ if (one_port) { -+ err = team_nl_fill_one_port_get(skb, one_port); -+ if (err) -+ goto errout; -+ } else { -+ list_for_each_entry(port, &team->port_list, list) { -+ err = team_nl_fill_one_port_get(skb, port); -+ if (err) { -+ if (err == -EMSGSIZE) { -+ if (!i) -+ goto errout; -+ incomplete = true; -+ break; -+ } -+ goto errout; -+ } -+ i++; - } -- if ((port->removed && -- nla_put_flag(skb, TEAM_ATTR_PORT_REMOVED)) || -- (port->state.linkup && -- nla_put_flag(skb, TEAM_ATTR_PORT_LINKUP)) || -- nla_put_u32(skb, TEAM_ATTR_PORT_SPEED, port->state.speed) || -- nla_put_u8(skb, TEAM_ATTR_PORT_DUPLEX, port->state.duplex)) -- goto nla_put_failure; -- nla_nest_end(skb, port_item); - } - - nla_nest_end(skb, port_list); -- return genlmsg_end(skb, hdr); -+ genlmsg_end(skb, hdr); -+ if (incomplete) -+ goto start_again; -+ -+send_done: -+ nlh = nlmsg_put(skb, portid, seq, NLMSG_DONE, 0, flags | NLM_F_MULTI); -+ if (!nlh) { -+ err = __send_and_alloc_skb(&skb, team, portid, send_func); -+ if (err) -+ goto errout; -+ goto send_done; -+ } -+ -+ return send_func(skb, team, portid); - - nla_put_failure: -+ err = -EMSGSIZE; -+errout: - genlmsg_cancel(skb, hdr); -- return -EMSGSIZE; --} -- --static int team_nl_fill_port_list_get_all(struct sk_buff *skb, -- struct genl_info *info, int flags, -- struct team *team) --{ -- return team_nl_fill_port_list_get(skb, info->snd_portid, -- info->snd_seq, NLM_F_ACK, -- team, true); -+ nlmsg_free(skb); -+ return err; - } - - static int team_nl_cmd_port_list_get(struct sk_buff *skb, -@@ -2382,7 +2438,8 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb, - if (!team) - return -EINVAL; - -- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all); -+ err = team_nl_send_port_list_get(team, info->snd_portid, info->snd_seq, -+ NLM_F_ACK, team_nl_send_unicast, NULL); - - team_nl_team_put(team); - -@@ -2433,27 +2490,11 @@ static int team_nl_send_event_options_get(struct team *team, - sel_opt_inst_list); - } - --static int team_nl_send_event_port_list_get(struct team *team) -+static int team_nl_send_event_port_get(struct team *team, -+ struct team_port *port) - { -- struct sk_buff *skb; -- int err; -- struct net *net = dev_net(team->dev); -- -- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -- if (!skb) -- return -ENOMEM; -- -- err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false); -- if (err < 0) -- goto err_fill; -- -- err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id, -- GFP_KERNEL); -- return err; -- --err_fill: -- nlmsg_free(skb); -- return err; -+ return team_nl_send_port_list_get(team, 0, 0, 0, team_nl_send_multicast, -+ port); - } - - static int team_nl_init(void) -@@ -2526,28 +2567,53 @@ static void __team_port_change_send(struct team_port *port, bool linkup) - port->state.duplex = 0; - - send_event: -- err = team_nl_send_event_port_list_get(port->team); -+ err = team_nl_send_event_port_get(port->team, port); - if (err && err != -ESRCH) - netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink (err %d)\n", - port->dev->name, err); - - } - -+static void __team_carrier_check(struct team *team) -+{ -+ struct team_port *port; -+ bool team_linkup; -+ -+ if (team->user_carrier_enabled) -+ return; -+ -+ team_linkup = false; -+ list_for_each_entry(port, &team->port_list, list) { -+ if (port->linkup) { -+ team_linkup = true; -+ break; -+ } -+ } -+ -+ if (team_linkup) -+ netif_carrier_on(team->dev); -+ else -+ netif_carrier_off(team->dev); -+} -+ - static void __team_port_change_check(struct team_port *port, bool linkup) - { - if (port->state.linkup != linkup) - __team_port_change_send(port, linkup); -+ __team_carrier_check(port->team); - } - - static void __team_port_change_port_added(struct team_port *port, bool linkup) - { - __team_port_change_send(port, linkup); -+ __team_carrier_check(port->team); - } - - static void __team_port_change_port_removed(struct team_port *port) - { - port->removed = true; - __team_port_change_send(port, false); -+ __team_carrier_check(port->team); - } - - static void team_port_change_check(struct team_port *port, bool linkup) -diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c -index 6262b4d..40fd338 100644 ---- a/drivers/net/team/team_mode_activebackup.c -+++ b/drivers/net/team/team_mode_activebackup.c -@@ -19,6 +19,7 @@ - - struct ab_priv { - struct team_port __rcu *active_port; -+ struct team_option_inst_info *ap_opt_inst_info; - }; - - static struct ab_priv *ab_priv(struct team *team) -@@ -54,8 +55,17 @@ drop: - - static void ab_port_leave(struct team *team, struct team_port *port) - { -- if (ab_priv(team)->active_port == port) -+ if (ab_priv(team)->active_port == port) { - RCU_INIT_POINTER(ab_priv(team)->active_port, NULL); -+ team_option_inst_set_change(ab_priv(team)->ap_opt_inst_info); -+ } -+} -+ -+static int ab_active_port_init(struct team *team, -+ struct team_option_inst_info *info) -+{ -+ ab_priv(team)->ap_opt_inst_info = info; -+ return 0; - } - - static int ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx) -@@ -88,6 +98,7 @@ static const struct team_option ab_options[] = { - { - .name = "activeport", - .type = TEAM_OPTION_TYPE_U32, -+ .init = ab_active_port_init, - .getter = ab_active_port_get, - .setter = ab_active_port_set, - }, -diff --git a/include/linux/if_team.h b/include/linux/if_team.h -index 0245def..4648d80 100644 ---- a/include/linux/if_team.h -+++ b/include/linux/if_team.h -@@ -186,6 +186,7 @@ struct team { - - const struct team_mode *mode; - struct team_mode_ops ops; -+ bool user_carrier_enabled; - bool queue_override_enabled; - struct list_head *qom_lists; /* array of queue override mapping lists */ - long mode_priv[TEAM_MODE_PRIV_LONGS]; -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index 9ef07d0..7ebddc7 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -894,6 +894,14 @@ struct netdev_fcoe_hbainfo { - * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh) - * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq, - * struct net_device *dev) -+ * -+ * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); -+ * Called to change device carrier. Soft-devices (like dummy, team, etc) -+ * which do not represent real hardware may define this to allow their -+ * userspace components to manage their virtual carrier state. Devices -+ * that determine carrier state from physical hardware properties (eg -+ * network cables) or protocol-dependent mechanisms (eg -+ * USB_CDC_NOTIFY_NETWORK_CONNECTION) should NOT implement this function. - */ - struct net_device_ops { - int (*ndo_init)(struct net_device *dev); -@@ -1011,6 +1019,8 @@ struct net_device_ops { - int (*ndo_bridge_getlink)(struct sk_buff *skb, - u32 pid, u32 seq, - struct net_device *dev); -+ int (*ndo_change_carrier)(struct net_device *dev, -+ bool new_carrier); - }; - - /* -@@ -2197,6 +2207,8 @@ extern int dev_set_mtu(struct net_device *, int); - extern void dev_set_group(struct net_device *, int); - extern int dev_set_mac_address(struct net_device *, - struct sockaddr *); -+extern int dev_change_carrier(struct net_device *, -+ bool new_carrier); - extern int dev_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev, - struct netdev_queue *txq); -diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h -index 60f3b6b..c4edfe1 100644 ---- a/include/uapi/linux/if_link.h -+++ b/include/uapi/linux/if_link.h -@@ -142,6 +142,7 @@ enum { - #define IFLA_PROMISCUITY IFLA_PROMISCUITY - IFLA_NUM_TX_QUEUES, - IFLA_NUM_RX_QUEUES, -+ IFLA_CARRIER, - __IFLA_MAX - }; - -diff --git a/net/core/dev.c b/net/core/dev.c -index f64e439..e0045ba 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -5027,6 +5027,25 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) - } - EXPORT_SYMBOL(dev_set_mac_address); - -+/** -+ * dev_change_carrier - Change device carrier -+ * @dev: device -+ * @new_carries: new value -+ * -+ * Change device carrier -+ */ -+int dev_change_carrier(struct net_device *dev, bool new_carrier) -+{ -+ const struct net_device_ops *ops = dev->netdev_ops; -+ -+ if (!ops->ndo_change_carrier) -+ return -EOPNOTSUPP; -+ if (!netif_device_present(dev)) -+ return -ENODEV; -+ return ops->ndo_change_carrier(dev, new_carrier); -+} -+EXPORT_SYMBOL(dev_change_carrier); -+ - /* - * Perform the SIOCxIFxxx calls, inside rcu_read_lock() - */ -diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index 1868625..2ef7a56 100644 ---- a/net/core/rtnetlink.c -+++ b/net/core/rtnetlink.c -@@ -780,6 +780,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, - + nla_total_size(4) /* IFLA_MTU */ - + nla_total_size(4) /* IFLA_LINK */ - + nla_total_size(4) /* IFLA_MASTER */ -+ + nla_total_size(1) /* IFLA_CARRIER */ - + nla_total_size(4) /* IFLA_PROMISCUITY */ - + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */ - + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ -@@ -909,6 +910,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, - nla_put_u32(skb, IFLA_LINK, dev->iflink)) || - (dev->master && - nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) || -+ nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) || - (dev->qdisc && - nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || - (dev->ifalias && -@@ -1108,6 +1110,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { - [IFLA_MTU] = { .type = NLA_U32 }, - [IFLA_LINK] = { .type = NLA_U32 }, - [IFLA_MASTER] = { .type = NLA_U32 }, -+ [IFLA_CARRIER] = { .type = NLA_U8 }, - [IFLA_TXQLEN] = { .type = NLA_U32 }, - [IFLA_WEIGHT] = { .type = NLA_U32 }, - [IFLA_OPERSTATE] = { .type = NLA_U8 }, -@@ -1438,6 +1441,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, - modified = 1; - } - -+ if (tb[IFLA_CARRIER]) { -+ err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER])); -+ if (err) -+ goto errout; -+ modified = 1; -+ } -+ - if (tb[IFLA_TXQLEN]) - dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); - diff --git a/userns-avoid-recursion-in-put_user_ns.patch b/userns-avoid-recursion-in-put_user_ns.patch deleted file mode 100644 index c3bb60444..000000000 --- a/userns-avoid-recursion-in-put_user_ns.patch +++ /dev/null @@ -1,117 +0,0 @@ -commit c61a2810a2161986353705b44d9503e6bb079f4f -Author: Eric W. Biederman -Date: Fri Dec 28 18:58:39 2012 -0800 - - userns: Avoid recursion in put_user_ns - - When freeing a deeply nested user namespace free_user_ns calls - put_user_ns on it's parent which may in turn call free_user_ns again. - When -fno-optimize-sibling-calls is passed to gcc one stack frame per - user namespace is left on the stack, potentially overflowing the - kernel stack. CONFIG_FRAME_POINTER forces -fno-optimize-sibling-calls - so we can't count on gcc to optimize this code. - - Remove struct kref and use a plain atomic_t. Making the code more - flexible and easier to comprehend. Make the loop in free_user_ns - explict to guarantee that the stack does not overflow with - CONFIG_FRAME_POINTER enabled. - - I have tested this fix with a simple program that uses unshare to - create a deeply nested user namespace structure and then calls exit. - With 1000 nesteuser namespaces before this change running my test - program causes the kernel to die a horrible death. With 10,000,000 - nested user namespaces after this change my test program runs to - completion and causes no harm. - - Acked-by: Serge Hallyn - Pointed-out-by: Vasily Kulikov - Signed-off-by: "Eric W. Biederman" - -diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h -index b9bd2e6..4ce0093 100644 ---- a/include/linux/user_namespace.h -+++ b/include/linux/user_namespace.h -@@ -21,7 +21,7 @@ struct user_namespace { - struct uid_gid_map uid_map; - struct uid_gid_map gid_map; - struct uid_gid_map projid_map; -- struct kref kref; -+ atomic_t count; - struct user_namespace *parent; - kuid_t owner; - kgid_t group; -@@ -35,18 +35,18 @@ extern struct user_namespace init_user_ns; - static inline struct user_namespace *get_user_ns(struct user_namespace *ns) - { - if (ns) -- kref_get(&ns->kref); -+ atomic_inc(&ns->count); - return ns; - } - - extern int create_user_ns(struct cred *new); - extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred); --extern void free_user_ns(struct kref *kref); -+extern void free_user_ns(struct user_namespace *ns); - - static inline void put_user_ns(struct user_namespace *ns) - { -- if (ns) -- kref_put(&ns->kref, free_user_ns); -+ if (ns && atomic_dec_and_test(&ns->count)) -+ free_user_ns(ns); - } - - struct seq_operations; -diff --git a/kernel/user.c b/kernel/user.c -index 33acb5e..57ebfd4 100644 ---- a/kernel/user.c -+++ b/kernel/user.c -@@ -47,9 +47,7 @@ struct user_namespace init_user_ns = { - .count = 4294967295U, - }, - }, -- .kref = { -- .refcount = ATOMIC_INIT(3), -- }, -+ .count = ATOMIC_INIT(3), - .owner = GLOBAL_ROOT_UID, - .group = GLOBAL_ROOT_GID, - .proc_inum = PROC_USER_INIT_INO, -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 2b042c4..24f8ec3 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -78,7 +78,7 @@ int create_user_ns(struct cred *new) - return ret; - } - -- kref_init(&ns->kref); -+ atomic_set(&ns->count, 1); - /* Leave the new->user_ns reference with the new user namespace. */ - ns->parent = parent_ns; - ns->owner = owner; -@@ -104,15 +104,16 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) - return create_user_ns(cred); - } - --void free_user_ns(struct kref *kref) -+void free_user_ns(struct user_namespace *ns) - { -- struct user_namespace *parent, *ns = -- container_of(kref, struct user_namespace, kref); -+ struct user_namespace *parent; - -- parent = ns->parent; -- proc_free_inum(ns->proc_inum); -- kmem_cache_free(user_ns_cachep, ns); -- put_user_ns(parent); -+ do { -+ parent = ns->parent; -+ proc_free_inum(ns->proc_inum); -+ kmem_cache_free(user_ns_cachep, ns); -+ ns = parent; -+ } while (atomic_dec_and_test(&parent->count)); - } - EXPORT_SYMBOL(free_user_ns); - diff --git a/uvcvideo-suspend-fix.patch b/uvcvideo-suspend-fix.patch deleted file mode 100644 index e8d825217..000000000 --- a/uvcvideo-suspend-fix.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a82a45f65377b05fe8cd3167c7b0a70c508356b8 Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Thu, 10 Jan 2013 07:04:55 -0300 -Subject: [PATCH] [media] uvcvideo: Fix race of open and suspend in error case - -Ming Lei reported: -IMO, there is a minor fault in the error handling path of -uvc_status_start() inside uvc_v4l2_open(), and the 'users' count should -have been decreased before usb_autopm_put_interface(). In theory, a [URB -resubmission] warning can be triggered when the device is opened just -between usb_autopm_put_interface() and atomic_dec(&stream->dev->users). -The fix is trivial. - -Reported-by: Ming Lei -Signed-off-by: Oliver Neukum -Signed-off-by: Laurent Pinchart -Signed-off-by: Mauro Carvalho Chehab ---- - drivers/media/usb/uvc/uvc_v4l2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c -index 97a4ffd..b2dc326 100644 ---- a/drivers/media/usb/uvc/uvc_v4l2.c -+++ b/drivers/media/usb/uvc/uvc_v4l2.c -@@ -501,8 +501,8 @@ static int uvc_v4l2_open(struct file *file) - if (atomic_inc_return(&stream->dev->users) == 1) { - ret = uvc_status_start(stream->dev); - if (ret < 0) { -- usb_autopm_put_interface(stream->dev->intf); - atomic_dec(&stream->dev->users); -+ usb_autopm_put_interface(stream->dev->intf); - kfree(handle); - return ret; - } --- -1.8.1.2 - From 904ddb1ce467f13b1b71f282e6621721ca755b58 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 7 May 2013 00:35:37 +0100 Subject: [PATCH 310/492] Initial rebase of ARM to 3.9 --- Makefile.config | 25 +- config-arm-kirkwood | 15 +- config-arm-omap | 370 --------------- config-armv7 | 620 +++++++++++++------------ config-armv7-generic | 467 +++++++++++++++++++ config-arm-tegra => config-armv7-tegra | 58 +-- kernel.spec | 13 +- 7 files changed, 836 insertions(+), 732 deletions(-) delete mode 100644 config-arm-omap create mode 100644 config-armv7-generic rename config-arm-tegra => config-armv7-tegra (66%) diff --git a/Makefile.config b/Makefile.config index 21c2a837b..e538387c7 100644 --- a/Makefile.config +++ b/Makefile.config @@ -11,7 +11,6 @@ CONFIGFILES = \ $(CFG)-s390x.config \ $(CFG)-armv5tel-kirkwood.config \ $(CFG)-armv7l.config $(CFG)-armv7hl.config \ - $(CFG)-armv7l-omap.config $(CFG)-armv7hl-omap.config \ $(CFG)-armv7l-tegra.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-ppc64.config $(CFG)-ppc64p7.config $(CFG)-ppc64-debug.config @@ -34,18 +33,18 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic -temp-armv7: config-armv7 temp-generic +temp-armv7-generic: config-armv7-generic temp-generic perl merge.pl $^ > $@ +temp-armv7: config-armv7 temp-armv7-generic + perl merge.pl $^ > $@ + +temp-armv7-tegra: config-armv7-tegra temp-armv7-generic + perl merge.pl $^ > $@ + temp-arm-generic: config-arm-generic temp-generic perl merge.pl $^ > $@ -temp-armv7l-omap: config-arm-omap temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv7l-tegra: config-arm-tegra temp-arm-generic - perl merge.pl $^ > $@ - temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic perl merge.pl $^ > $@ @@ -118,19 +117,13 @@ kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood kernel-$(VERSION)-armv7l.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra +kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7-tegra perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7hl.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7l-tegra +kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7-tegra perl merge.pl $^ arm > $@ kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 9f80aaf4a..b622c8051 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -12,6 +12,7 @@ CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_DLINK_KIRKWOOD_DT=y CONFIG_MACH_GOFLEXNET_DT=y CONFIG_MACH_GURUPLUG=y +CONFIG_MACH_GURUPLUG_DT=y CONFIG_MACH_ICONNECT_DT=y CONFIG_MACH_IB62X0_DT=y CONFIG_MACH_INETSPACE_V2=y @@ -43,7 +44,6 @@ CONFIG_MACH_TS219_DT=y CONFIG_MACH_TS41X=y CONFIG_MACH_T5325=y -# CONFIG_SPI is not set CONFIG_CACHE_FEROCEON_L2=y CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y CONFIG_MTD_NAND_ORION=m @@ -65,11 +65,22 @@ CONFIG_CRYPTO_DEV_MV_CESA=m CONFIG_PINCTRL_MVEBU=y CONFIG_PINCTRL_KIRKWOOD=y +# CONFIG_CPU_IDLE_KIRKWOOD is not set +CONFIG_POWER_RESET_QNAP=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_KIRKWOOD_THERMAL=m +CONFIG_REGULATOR_LP8755=m +# CONFIG_DRM_TILCDC is not set +CONFIG_OF_DISPLAY_TIMING=y +CONFIG_OF_VIDEOMODE=y +CONFIG_SND_ATMEL_SOC=m + # CONFIG_CPU_FEROCEON_OLD_ID is not set # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_HIGHPTE is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_EDAC is not set - +# CONFIG_SPI is not set CONFIG_FB_XGI=m diff --git a/config-arm-omap b/config-arm-omap deleted file mode 100644 index cbffc64d5..000000000 --- a/config-arm-omap +++ /dev/null @@ -1,370 +0,0 @@ -CONFIG_ARCH_OMAP=y -CONFIG_ARCH_OMAP_OTG=y -# CONFIG_ARCH_OMAP1 is not set -CONFIG_ARCH_OMAP2PLUS=y - -# -# OMAP Feature Selections -# -CONFIG_OMAP_RESET_CLOCKS=y -CONFIG_OMAP_MUX=y -# CONFIG_OMAP_MUX_DEBUG is not set -CONFIG_OMAP_MUX_WARNINGS=y -CONFIG_OMAP_MCBSP=y -CONFIG_OMAP_MBOX_FWK=m -CONFIG_OMAP_MBOX_KFIFO_SIZE=256 -CONFIG_OMAP_32K_TIMER=y -# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set -CONFIG_OMAP_32K_TIMER_HZ=128 -CONFIG_OMAP_DM_TIMER=y -# CONFIG_OMAP_PM_NONE is not set -CONFIG_OMAP_PM_NOOP=y -CONFIG_OMAP_IOMMU=y -# CONFIG_OMAP_IOMMU_DEBUG is not set -CONFIG_OMAP3_EMU=y -CONFIG_HWSPINLOCK_OMAP=m -CONFIG_DMA_OMAP=y -# CONFIG_DMADEVICES_VDEBUG is not set - -# -# TI OMAP2/3/4 Specific Features -# -CONFIG_ARCH_OMAP2PLUS_TYPICAL=y -# CONFIG_ARCH_OMAP2 is not set -CONFIG_ARCH_OMAP3=y -CONFIG_ARCH_OMAP4=y -CONFIG_SOC_OMAP3430=y -CONFIG_SOC_TI81XX=y -CONFIG_SOC_AM33XX=y -CONFIG_SOC_OMAPTI816X=y -# CONFIG_SOC_OMAP5 is not set -CONFIG_OMAP_PACKAGE_CBB=y -CONFIG_OMAP_PACKAGE_CBL=y -CONFIG_OMAP_PACKAGE_CBS=y -# CONFIG_OMAP4_ERRATA_I688 is not set - -# -# OMAP Board Type -# -CONFIG_MACH_CM_T35=y -CONFIG_MACH_CM_T3517=y -CONFIG_MACH_CRANEBOARD=y -CONFIG_MACH_DEVKIT8000=y -CONFIG_MACH_IGEP0020=y -CONFIG_MACH_IGEP0030=y -CONFIG_MACH_OMAP_GENERIC=y -CONFIG_MACH_OMAP_LDP=y -CONFIG_MACH_OMAP_ZOOM2=y -CONFIG_MACH_OMAP_ZOOM3=y -CONFIG_MACH_OMAP_3430SDP=y -CONFIG_MACH_OMAP_3630SDP=y -CONFIG_MACH_OMAP_4430SDP=y -CONFIG_MACH_OMAP3_BEAGLE=y -CONFIG_MACH_OMAP3_PANDORA=y -CONFIG_MACH_OMAP3_TOUCHBOOK=y -CONFIG_MACH_OMAP3_TORPEDO=y -CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y -CONFIG_MACH_OMAP3EVM=y -CONFIG_MACH_OMAP3517EVM=y -CONFIG_MACH_OMAP3530_LV_SOM=y -CONFIG_MACH_OMAP4_PANDA=y -CONFIG_MACH_OVERO=y -CONFIG_MACH_SBC3530=y -CONFIG_MACH_TI8148EVM=y -CONFIG_MACH_TI8168EVM=y -CONFIG_MACH_TOUCHBOOK=y -# CONFIG_MACH_NOKIA_RM680 is not set -# CONFIG_MACH_NOKIA_RX51 is not set - - -# CONFIG_OMAP3_SDRC_AC_TIMING is not set - - -# System MMU -CONFIG_CPU_32v6K=y -CONFIG_CPU_V7=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_ERRATA_430973=y -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_ARM_ERRATA_720789=y -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_ARM_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -CONFIG_ARM_GIC=y -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HZ=128 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_KSM is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="" -# CONFIG_AUTO_ZRELADDR is not set -CONFIG_VFPv3=y -CONFIG_NEON=y -CONFIG_BINFMT_MISC=m -CONFIG_PM_DEBUG=y -# CONFIG_PM_ADVANCED_DEBUG is not set -# CONFIG_PM_VERBOSE is not set -CONFIG_CAN_PM_TRACE=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_ARCH_HAS_OPP=y -CONFIG_PM_OPP=y - -# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES -CONFIG_OMAP_BANDGAP=y -CONFIG_OMAP4_THERMAL=y -CONFIG_OMAP5_THERMAL=y - -# OMAP3 thermal/power -CONFIG_POWER_AVS=y -CONFIG_POWER_AVS_OMAP=y -CONFIG_POWER_AVS_OMAP_CLASS3=y - -CONFIG_ARM_OMAP2PLUS_CPUFREQ=y - -# -# OMAP Hardware -# -CONFIG_WL_TI=y -CONFIG_WLCORE_SDIO=m -CONFIG_WLCORE_SPI=m -CONFIG_TI_ST=m -CONFIG_TI_DAC7512=m -# CONFIG_TI_CPSW is not set -CONFIG_MTD_NAND_OMAP2=y -CONFIG_MTD_NAND_OMAP_PREFETCH=y -CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y -CONFIG_WL1251_SPI=m -CONFIG_WL12XX_SPI=m -CONFIG_WL12XX_SDIO_TEST=m -CONFIG_WL18XX=m -CONFIG_SPI_DAVINCI=m -CONFIG_SPI_OMAP24XX=y -CONFIG_MFD_TI_SSP=m -CONFIG_SPI_TI_SSP=m -CONFIG_NFC_WILINK=m -CONFIG_INPUT_TWL4030_PWRBUTTON=m -CONFIG_INPUT_TWL4030_VIBRA=m -CONFIG_INPUT_TWL6040_VIBRA=m -CONFIG_KEYBOARD_OMAP4=m -CONFIG_KEYBOARD_TWL4030=m -CONFIG_TOUCHSCREEN_TI_TSCADC=m -CONFIG_SERIAL_OMAP=y -CONFIG_SERIAL_OMAP_CONSOLE=y -CONFIG_OMAP_WATCHDOG=y -CONFIG_CLK_TWL6040=m -CONFIG_TWL4030_CORE=y -CONFIG_TWL4030_MADC=m -CONFIG_TWL4030_POWER=y -CONFIG_TWL4030_CODEC=y -CONFIG_TWL4030_WATCHDOG=m -CONFIG_GPIO_TWL4030=m -CONFIG_GPIO_TWL6040=m -CONFIG_CHARGER_TWL4030=m -CONFIG_TWL6030_PWM=m -CONFIG_TWL6040_CORE=y -CONFIG_SENSORS_TWL4030_MADC=m -CONFIG_SENSORS_LIS3_I2C=m -CONFIG_RTC_DRV_OMAP=m -CONFIG_RTC_DRV_TWL4030=m -CONFIG_RTC_DRV_TPS65910=m -CONFIG_TI_DAVINCI_EMAC=m -CONFIG_TI_DAVINCI_MDIO=m -CONFIG_TI_DAVINCI_CPDMA=m - -CONFIG_LEDS_PWM=m -CONFIG_LEDS_LP8788=m -CONFIG_MTD_ONENAND_OMAP2=y -CONFIG_HDQ_MASTER_OMAP=m -CONFIG_I2C_OMAP=m -CONFIG_MFD_OMAP_USB_HOST=y -CONFIG_MFD_WL1273_CORE=m -CONFIG_MFD_LP8788=y -CONFIG_MFD_TPS65910=y -CONFIG_GPIO_TPS65910=y -CONFIG_REGULATOR_TWL4030=y -CONFIG_REGULATOR_LP8788=y -CONFIG_REGULATOR_TPS65217=y -CONFIG_REGULATOR_TPS65910=y -# Enable V4L2 drivers for OMAP2+ -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_OMAP2_VOUT=m -CONFIG_VIDEO_OMAP3=m -CONFIG_VIDEO_VPFE_CAPTURE=m -# The ones below are for TI Davinci -# CONFIG_VIDEO_VPSS_SYSTEM is not set -# CONFIG_VIDEO_DM6446_CCDC is not set -# CONFIG_VIDEO_DM644X_VPBE is not set -# CONFIG_VIDEO_DM355_CCDC is not set -# CONFIG_VIDEO_ISIF is not set -# Also enable vivi driver - useful for testing a full kernelspace V4L2 driver -CONFIG_V4L_TEST_DRIVERS=y -CONFIG_VIDEO_VIVI=m - -CONFIG_DRM=m -CONFIG_DRM_OMAP=m -CONFIG_DRM_OMAP_NUM_CRTCS=2 -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -# CONFIG_FB_OMAP_LCD_VGA is not set -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRAM_SIZE=0 -CONFIG_OMAP2_VRFB=y -# CONFIG_FB_OMAP2 is not set - -CONFIG_OMAP2_DSS=m -CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y -# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set -CONFIG_OMAP2_DSS_DPI=y -CONFIG_OMAP2_DSS_RFBI=y -CONFIG_OMAP2_DSS_VENC=y -CONFIG_OMAP4_DSS_HDMI=y -CONFIG_OMAP2_DSS_SDI=y -CONFIG_OMAP2_DSS_DSI=y -# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set -CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 -CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y -CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y - -CONFIG_FB_DA8XX=m -CONFIG_FB_DA8XX_CONSISTENT_DMA_SIZE=5 - -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_PANEL_GENERIC_DPI=m -CONFIG_PANEL_TFP410=m -CONFIG_PANEL_TAAL=m -CONFIG_PANEL_PICODLP=m -CONFIG_PANEL_SHARP_LS037V7DW01=m -CONFIG_PANEL_NEC_NL8048HL11_01B=m -CONFIG_PANEL_TPO_TD043MTEA1=m -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_PWM=m -CONFIG_BACKLIGHT_PANDORA=m - - -CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_DMIC=m -CONFIG_SND_OMAP_SOC_MCBSP=m -CONFIG_SND_OMAP_SOC_MCPDM=m -CONFIG_SND_OMAP_SOC_OVERO=m -CONFIG_SND_OMAP_SOC_OMAP3EVM=m -CONFIG_SND_OMAP_SOC_AM3517EVM=m -CONFIG_SND_OMAP_SOC_SDP3430=m -CONFIG_SND_OMAP_SOC_SDP4430=m -CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m -CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=m -CONFIG_SND_OMAP_SOC_ZOOM2=m -CONFIG_SND_OMAP_SOC_IGEP0020=m -CONFIG_SND_OMAP_SOC_OMAP_HDMI=m -CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m -CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_OMAP_SOC_RX51 is not set -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_TLV320AIC23=m -CONFIG_SND_SOC_TLV320AIC3X=m -CONFIG_SND_SOC_TWL4030=m -CONFIG_SND_SOC_TWL6040=m -CONFIG_RADIO_WL128X=m - -CONFIG_USB_OTG=y -CONFIG_USB_EHCI_HCD_OMAP=y -CONFIG_USB_OHCI_HCD_OMAP3=y -CONFIG_USB_MUSB_OMAP2PLUS=m -CONFIG_USB_MUSB_HDRC=m -CONFIG_USB_GADGET_MUSB_HDRC=m -CONFIG_TWL4030_USB=m -CONFIG_TWL6030_USB=m -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_MUSB_PIO_ONLY is not set -# CONFIG_USB_MUSB_DEBUG is not set -# - -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_ISP1301_OMAP is not set - -# This block is temporary until we work out why the MMC modules don't work as modules -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF=y -CONFIG_MMC_SPI=y - -CONFIG_MMC_OMAP=y -CONFIG_MMC_OMAP_HS=y - -CONFIG_PWM_TIECAP=m -CONFIG_PWM_TIEHRPWM=m -CONFIG_PWM_TWL=m -CONFIG_PWM_TWL_LED=m - -# CONFIG_IR_RX51 is not set -# CONFIG_BATTERY_RX51 is not set - -# CONFIG_TIDSPBRIDGE is not set -# CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 -# CONFIG_TIDSPBRIDGE_DEBUG is not set -# CONFIG_TIDSPBRIDGE_RECOVERY=y -# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set -# CONFIG_TIDSPBRIDGE_WDT3=y -# CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 -# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set -# CONFIG_TIDSPBRIDGE_BACKTRACE is not set - -# CONFIG_OMAP_REMOTEPROC is not set -# CONFIG_OMAP_IOVMM is not set - -CONFIG_CRYPTO_DEV_OMAP_SHAM=m -CONFIG_CRYPTO_DEV_OMAP_AES=m -CONFIG_HW_RANDOM_OMAP=m - -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_MTD_NAND_OMAP_BCH is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX77686 is not set -# CONFIG_MFD_MAX77693 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_SEC_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_REGULATOR_LP3972 is not set -# CONFIG_REGULATOR_LP872X is not set - -# CONFIG_OMAP2_DSS_DEBUG is not set -# CONFIG_OMAP2_DSS_DEBUGFS is not set diff --git a/config-armv7 b/config-armv7 index d7d128571..db8a2b69d 100644 --- a/config-armv7 +++ b/config-armv7 @@ -10,167 +10,32 @@ CONFIG_ARCH_MULTI_V7=y CONFIG_ARCH_HIGHBANK=y CONFIG_ARCH_MVEBU=y # CONFIG_ARCH_MXC is not set +CONFIG_ARCH_OMAP2PLUS=y CONFIG_ARCH_PICOXCELL=y CONFIG_ARCH_SOCFPGA=y CONFIG_ARCH_SUNXI=y CONFIG_ARCH_VEXPRESS_CA9X4=y CONFIG_ARCH_VEXPRESS_DT=y -# not enabling first round -# CONFIG_ARCH_ZYNQ is not set +CONFIG_ARCH_VIRT=y +# CONFIG_ARCH_WM8850 is not set +CONFIG_ARCH_ZYNQ=y -# generic ARM config options -CONFIG_CMDLINE="" -CONFIG_ARM_ARCH_TIMER=y -CONFIG_AEABI=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_UNWIND=y -CONFIG_ARM_THUMB=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_GIC=y -CONFIG_ARM_ASM_UNIFIED=y -CONFIG_ARM_CPU_TOPOLOGY=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_SWP_EMULATE=y -CONFIG_CPU_BPREDICT_DISABLE=y -CONFIG_CACHE_L2X0=y -CONFIG_HIGHPTE=y -CONFIG_AUTO_ZRELADDR=y -# CONFIG_XIP_KERNEL is not set -# CONFIG_OABI_COMPAT is not set -# CONFIG_ATAGS is not set -# CONFIG_ATAGS_PROC is not set -# CONFIG_FPE_NWFPE is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_APM_EMULATION is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_DMA_CACHE_RWFO is not set +# These are supported in the LPAE kernel # CONFIG_ARM_LPAE is not set -# CONFIG_THUMB2_KERNEL is not set # CONFIG_XEN is not set -# CONFIG_HVC_DCC is not set # CONFIG_VIRTIO_CONSOLE is not set - # CONFIG_ARM_VIRT_EXT is not set -# errata -# v5/v6 -# CONFIG_ARM_ERRATA_326103 is not set -# CONFIG_ARM_ERRATA_411920 is not set -# Cortex-A8 -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# Cortex-A9 -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_742230=y -CONFIG_ARM_ERRATA_742231=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_751472=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_ARM_ERRATA_754327=y -CONFIG_ARM_ERRATA_764369=y -CONFIG_ARM_ERRATA_775420=y -# Disabled due to causing highbank to crash -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -CONFIG_PL310_ERRATA_769419=y - -# generic that deviates from or should be merged into config-generic -CONFIG_SMP=y -CONFIG_NR_CPUS=4 -CONFIG_SMP_ON_UP=y -CONFIG_HIGHMEM=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y - -CONFIG_RCU_FANOUT=32 -CONFIG_RCU_FANOUT_LEAF=16 - -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_GOV_LADDER is not set -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y - -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - -CONFIG_SECCOMP=y -CONFIG_STRICT_DEVMEM=y - -CONFIG_PM=y -CONFIG_PM_STD_PARTITION="" -CONFIG_SUSPEND=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_CPU_TOPOLOGY=y - -CONFIG_LOCAL_TIMERS=y -CONFIG_HW_PERF_EVENTS=y -CONFIG_UACCESS_WITH_MEMCPY=y -CONFIG_CC_STACKPROTECTOR=y - -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 - -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y - -CONFIG_PINCTRL=y -CONFIG_PINCONF=y - -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_EARLY_PRINTK=y - -CONFIG_LBDAF=y - -CONFIG_COMMON_CLK=y -CONFIG_REGULATOR=y -CONFIG_THERMAL=y -CONFIG_PERF_EVENTS=y - -# Versatile and highbank -CONFIG_VEXPRESS_CONFIG=y -CONFIG_ARM_TIMER_SP804=y - -CONFIG_SERIO_AMBAKMI=m -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_8250_DW=y - -CONFIG_RTC_DRV_PL030=y -CONFIG_RTC_DRV_PL031=y - -CONFIG_PL330_DMA=y -CONFIG_AMBA_PL08X=y -CONFIG_ARM_SP805_WATCHDOG=m - # highbank -CONFIG_CPU_IDLE_CALXEDA=y - +# 2013/04/19 - stability issues +# CONFIG_CPU_IDLE_CALXEDA is not set CONFIG_EDAC_HIGHBANK_MC=m CONFIG_EDAC_HIGHBANK_L2=m - -CONFIG_OC_ETM=y - CONFIG_SATA_HIGHBANK=m +CONFIG_ARM_HIGHBANK_CPUFREQ=m # versatile +CONFIG_VEXPRESS_CONFIG=y CONFIG_FB=y CONFIG_FB_ARMCLCD=m CONFIG_FB_CFB_COPYAREA=m @@ -178,14 +43,8 @@ CONFIG_FB_CFB_FILLRECT=m CONFIG_FB_CFB_IMAGEBLIT=m CONFIG_TOUCHSCREEN_ADS7846=m -CONFIG_I2C_VERSATILE=m CONFIG_OC_ETM=y CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y -CONFIG_SENSORS_VEXPRESS=m -CONFIG_REGULATOR_VEXPRESS=m - -# unknown and needs review -CONFIG_ARM_AMBA=y # mvebu CONFIG_MACH_ARMADA_370_XP=y @@ -200,19 +59,284 @@ CONFIG_I2C_MV64XXX=m CONFIG_PINCTRL_MVEBU=y CONFIG_PINCTRL_ARMADA_370=y CONFIG_PINCTRL_ARMADA_XP=y +CONFIG_PINCTRL_DOVE=y CONFIG_EDAC_MV64X60=m -CONFIG_SATA_MV=m -CONFIG_MARVELL_PHY=m -CONFIG_RTC_DRV_S35390A=y +CONFIG_RTC_DRV_S35390A=m CONFIG_RTC_DRV_88PM80X=m CONFIG_RTC_DRV_MV=m -CONFIG_MVMDIO=m CONFIG_MVNETA=m CONFIG_GPIO_MVEBU=y CONFIG_MVEBU_CLK_CORE=y CONFIG_MVEBU_CLK_GATING=y +CONFIG_MMC_MVSDIO=m +CONFIG_SPI_ORION=m +CONFIG_USB_MV_UDC=m + +# omap +CONFIG_ARCH_OMAP2PLUS_TYPICAL=y +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_OMAP2420 is not set +# CONFIG_SOC_OMAP2430 is not set +CONFIG_SOC_OMAP3430=y +CONFIG_SOC_TI81XX=y +CONFIG_SOC_AM33XX=y +CONFIG_MACH_OMAP_GENERIC=y +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_DEVKIT8000=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OMAP3530_LV_SOM=y +CONFIG_MACH_OMAP3_TORPEDO=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3517EVM=y +CONFIG_MACH_CRANEBOARD=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_TOUCHBOOK=y +CONFIG_MACH_OMAP_3430SDP=y +# CONFIG_MACH_NOKIA_N8X0 is not set +# CONFIG_MACH_NOKIA_RM680 is not set +# CONFIG_MACH_NOKIA_RX51 is not set +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_CM_T35=y +CONFIG_MACH_CM_T3517=y +CONFIG_MACH_IGEP0030=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_OMAP_3630SDP=y +CONFIG_MACH_TI8168EVM=y +CONFIG_MACH_TI8148EVM=y +CONFIG_MACH_OMAP_4430SDP=y +CONFIG_MACH_OMAP4_PANDA=y + +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_MUX=y +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set + +CONFIG_OMAP_MCBSP=y +CONFIG_OMAP_MBOX_FWK=m +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 +CONFIG_OMAP_DM_TIMER=y +CONFIG_OMAP_PM_NOOP=y +CONFIG_OMAP_IOMMU=y +CONFIG_OMAP_IOVMM=m +CONFIG_OMAP3_EMU=y +# CONFIG_OMAP3_SDRC_AC_TIMING is not set +CONFIG_ARM_OMAP2PLUS_CPUFREQ=y + +CONFIG_TI_ST=m +CONFIG_TI_DAC7512=m +CONFIG_TI_DAVINCI_EMAC=m +CONFIG_TI_DAVINCI_MDIO=m +CONFIG_TI_DAVINCI_CPDMA=m +CONFIG_TI_CPSW=m +CONFIG_TI_CPTS=y +CONFIG_TI_EMIF=m +CONFIG_MFD_TPS65217=m +CONFIG_REGULATOR_TPS65217=m +CONFIG_BACKLIGHT_TPS65217=m + +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y + +CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_TWL6040=m +CONFIG_I2C_OMAP=m +CONFIG_CHARGER_TWL4030=m +CONFIG_OMAP_WATCHDOG=m +CONFIG_TWL4030_CORE=y +CONFIG_TWL4030_MADC=m +CONFIG_TWL4030_POWER=y +CONFIG_TWL4030_CODEC=y +CONFIG_TWL4030_WATCHDOG=m +CONFIG_TWL4030_USB=m +CONFIG_TWL6030_USB=m +CONFIG_TWL6030_PWM=m +CONFIG_TWL6040_CORE=y +CONFIG_CLK_TWL6040=m +CONFIG_OMAP_INTERCONNECT=m +# CONFIG_MFD_TPS80031 is not set +CONFIG_MFD_TI_AM335X_TSCADC=m +CONFIG_MFD_OMAP_USB_HOST=y +CONFIG_MTD_ONENAND_OMAP2=m +CONFIG_HDQ_MASTER_OMAP=m +CONFIG_REGULATOR_TWL4030=y +CONFIG_BACKLIGHT_PANDORA=m +CONFIG_OMAP_OCP2SCP=m +CONFIG_USB_EHCI_HCD_OMAP=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD_OMAP3=y +CONFIG_USB_MUSB_AM35X=m +CONFIG_USB_MUSB_OMAP2PLUS=m +CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_GADGET_MUSB_HDRC=m +# CONFIG_MUSB_PIO_ONLY is not set +# CONFIG_USB_MUSB_DEBUG is not set +CONFIG_OMAP_CONTROL_USB=m +CONFIG_NOP_USB_XCEIV=m +CONFIG_MMC_OMAP=y +CONFIG_MMC_OMAP_HS=y +CONFIG_RTC_DRV_MAX8907=m +# CONFIG_RTC_DRV_TWL92330 is not set +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_OMAP=m +# Note needs to be compiled in until we build MMC modular +CONFIG_DMA_OMAP=y +CONFIG_OMAP_IOVMM=m +CONFIG_HWSPINLOCK_OMAP=m +CONFIG_SENSORS_TWL4030_MADC=m + +CONFIG_WL_TI=y +CONFIG_WLCORE_SDIO=m +CONFIG_WLCORE_SPI=m +CONFIG_WL1251_SPI=m +CONFIG_WL12XX_SPI=m +CONFIG_WL12XX_SDIO_TEST=m +CONFIG_WL18XX=m +CONFIG_WILINK_PLATFORM_DATA=y +CONFIG_MFD_WL1273_CORE=m +CONFIG_NFC_WILINK=m + +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y +CONFIG_SPI_DAVINCI=m +CONFIG_SPI_OMAP24XX=y +CONFIG_MFD_TI_SSP=m +CONFIG_SPI_TI_SSP=m + +CONFIG_INPUT_TWL4030_PWRBUTTON=m +CONFIG_INPUT_TWL4030_VIBRA=m +CONFIG_INPUT_TWL6040_VIBRA=m +CONFIG_KEYBOARD_OMAP4=m +CONFIG_KEYBOARD_TWL4030=m +CONFIG_TOUCHSCREEN_TI_TSCADC=m + +# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES +CONFIG_OMAP_BANDGAP=y +CONFIG_OMAP4_THERMAL=y +CONFIG_OMAP5_THERMAL=y + +# OMAP3 thermal/power +CONFIG_POWER_AVS=y +CONFIG_POWER_AVS_OMAP=y +CONFIG_POWER_AVS_OMAP_CLASS3=y + +CONFIG_ARM_OMAP2PLUS_CPUFREQ=y + +CONFIG_PWM_TIECAP=m +CONFIG_PWM_TIEHRPWM=m +CONFIG_PWM_TWL=m +CONFIG_PWM_TWL_LED=m + +CONFIG_CRYPTO_DEV_OMAP_SHAM=m +CONFIG_CRYPTO_DEV_OMAP_AES=m +CONFIG_HW_RANDOM_OMAP=m + +# CONFIG_DRM_TILCDC is not set +CONFIG_DRM_OMAP=m +CONFIG_DRM_OMAP_NUM_CRTCS=2 +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRAM_SIZE=0 +CONFIG_OMAP2_VRFB=y +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +# CONFIG_FB_OMAP2 is not set +# CONFIG_FB_DA8XX is not set + +CONFIG_OMAP2_DSS=m +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DPI=y +CONFIG_OMAP2_DSS_RFBI=y +CONFIG_OMAP2_DSS_VENC=y +CONFIG_OMAP4_DSS_HDMI=y +CONFIG_OMAP2_DSS_SDI=y +CONFIG_OMAP2_DSS_DSI=y +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y +CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y + +CONFIG_PANEL_GENERIC_DPI=m +CONFIG_PANEL_TFP410=m +CONFIG_PANEL_SHARP_LS037V7DW01=m +CONFIG_PANEL_PICODLP=m +CONFIG_PANEL_TAAL=m +CONFIG_PANEL_NEC_NL8048HL11_01B=m +CONFIG_PANEL_TPO_TD043MTEA1=m +CONFIG_PANEL_LGPHILIPS_LB035Q02=m +CONFIG_PANEL_ACX565AKM=m +# CONFIG_PANEL_N8X0 is not set + +# Enable V4L2 drivers for OMAP2+ +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_OMAP2_VOUT is not set +# CONFIG_VIDEO_OMAP3 is not set +# CONFIG_VIDEO_VPFE_CAPTURE is not set +# The ones below are for TI Davinci +# CONFIG_VIDEO_VPSS_SYSTEM is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_VIDEO_DM644X_VPBE is not set +# CONFIG_VIDEO_DM355_CCDC is not set +# CONFIG_VIDEO_ISIF is not set +# Also enable vivi driver - useful for testing a full kernelspace V4L2 driver +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIVI=m + +CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m +CONFIG_SND_OMAP_SOC_OMAP_HDMI=m +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m + +CONFIG_SND_OMAP_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_OMAP_SOC_AM3517EVM=m +CONFIG_SND_OMAP_SOC_DMIC=m +CONFIG_SND_OMAP_SOC_IGEP0020=m +CONFIG_SND_OMAP_SOC_MCBSP=m +CONFIG_SND_OMAP_SOC_MCPDM=m +CONFIG_SND_OMAP_SOC_OMAP_HDMI=m +CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m +CONFIG_SND_OMAP_SOC_OMAP3EVM=m +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=m +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m +CONFIG_SND_OMAP_SOC_OVERO=m +# CONFIG_SND_OMAP_SOC_RX51 is not set +CONFIG_SND_OMAP_SOC_SDP4430=m +CONFIG_SND_SOC_TLV320AIC23=m +CONFIG_SND_SOC_TLV320AIC3X=m +CONFIG_SND_SOC_TWL4030=m +CONFIG_SND_SOC_TWL6040=m +CONFIG_RADIO_WL128X=m + +# CONFIG_OMAP_REMOTEPROC is not set + +# CONFIG_TIDSPBRIDGE is not set +# CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +# CONFIG_TIDSPBRIDGE_DEBUG is not set +# CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set +# CONFIG_TIDSPBRIDGE_WDT3=y +# CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 +# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set +# CONFIG_TIDSPBRIDGE_BACKTRACE is not set + +# CONFIG_OMAP2_DSS_DEBUGFS is not set +# CONFIG_OMAP_IOMMU_DEBUG is not set +# CONFIG_OMAP_MUX_DEBUG is not set +# CONFIG_VIDEO_OMAP3_DEBUG is not set # Allwinner a1x +CONFIG_PINCTRL_SUNXI=y # CONFIG_SUNXI_RFKILL=y # CONFIG_SUNXI_NAND=y # CONFIG_SUNXI_DBGREG=m @@ -249,7 +373,7 @@ CONFIG_MVEBU_CLK_GATING=y # CONFIG_RTC_DRV_SUN4I=y # imx -CONFIG_BACKLIGHT_PWM=m +# CONFIG_BACKLIGHT_PWM is not set # CONFIG_DRM_IMX is not set # CONFIG_DRM_IMX_FB_HELPER=m # CONFIG_DRM_IMX_PARALLEL_DISPLAY=m @@ -258,6 +382,7 @@ CONFIG_BACKLIGHT_PWM=m # CONFIG_VIDEO_CODA is not set CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_88PM80X_ONKEY=m # exynos # CONFIG_DRM_EXYNOS is not set @@ -266,122 +391,29 @@ CONFIG_INPUT_PWM_BEEPER=m # picoxcell CONFIG_CRYPTO_DEV_PICOXCELL=m +CONFIG_HW_RANDOM_PICOXCELL=m # ST Ericsson # CONFIG_I2C_NOMADIK is not set - -# OMAP # CONFIG_SENSORS_LIS3_I2C is not set -# General ARM drivers -# Device tree -CONFIG_DTC=y -CONFIG_OF=y -CONFIG_USE_OF=y -CONFIG_OF_DEVICE=y -CONFIG_OF_IRQ=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y -CONFIG_OF_GPIO=y -CONFIG_I2C_MUX_PINCTRL=m -CONFIG_OF_MDIO=m - -CONFIG_MDIO_BUS_MUX_GPIO=m -CONFIG_GPIOLIB=y +# ZYNQ +CONFIG_LATTICE_ECP3_CONFIG=m # MMC/SD -CONFIG_MMC=y -CONFIG_MMC_ARMMMCI=y -CONFIG_MMC_SDHCI_PLTFM=m -CONFIG_MMC_SDHCI_OF=m -CONFIG_MMC_SPI=m -CONFIG_MMC_DW=m -CONFIG_MMC_DW_PLTFM=m -CONFIG_MMC_DW_PCI=m -# CONFIG_MMC_DW_EXYNOS is not set -# CONFIG_MMC_DW_IDMAC is not set CONFIG_MMC_TMIO=m CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m -CONFIG_MMC_MVSDIO=m - -# usb -CONFIG_USB_ULPI=y -CONFIG_AX88796=m -CONFIG_AX88796_93CX6=y -CONFIG_SMC91X=m -CONFIG_SMC911X=m -CONFIG_SMSC911X=m -CONFIG_USB_ISP1760_HCD=m - -# HW crypto and rng -CONFIG_CRYPTO_SHA1_ARM=m -CONFIG_CRYPTO_AES_ARM=m -CONFIG_HW_RANDOM_ATMEL=m -CONFIG_HW_RANDOM_EXYNOS=m - -# Sound -CONFIG_SND_ARM=y -CONFIG_SND_ARMAACI=m -CONFIG_SND_SOC=m -CONFIG_SND_DESIGNWARE_I2S=m -CONFIG_SND_SIMPLE_CARD=m -CONFIG_SND_SOC_CACHE_LZO=y -CONFIG_SND_SOC_ALL_CODECS=m - -# EDAC -CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=m -CONFIG_EDAC_LEGACY_SYSFS=y - -# Watchdog -CONFIG_MPCORE_WATCHDOG=m # Multi function devices CONFIG_MFD_CORE=m +CONFIG_MFD_SYSCON=y +CONFIG_MFD_88PM800=m +CONFIG_MFD_88PM805=m CONFIG_MFD_T7L66XB=y CONFIG_MFD_TC6387XB=y -CONFIG_MFD_SYSCON=y -CONFIG_MFD_MAX8907=m -# CONFIG_MFD_DA9055 is not set -# CONFIG_MFD_SMSC is not set - -# RTC -CONFIG_RTC_DRV_SNVS=m - -# Pin stuff -CONFIG_PINMUX=y -CONFIG_PINCONF=y -CONFIG_PINCTRL_SINGLE=m -# CONFIG_PINCTRL_SAMSUNG is not set -# CONFIG_PINCTRL_EXYNOS4 is not set - -# GPIO -CONFIG_GPIO_GENERIC_PLATFORM=m -# CONFIG_GPIO_EM is not set -CONFIG_GPIO_ADNP=m -CONFIG_GPIO_MCP23S08=m -CONFIG_POWER_RESET_GPIO=y -CONFIG_RFKILL_GPIO=m -CONFIG_SERIAL_8250_EM=m -CONFIG_INPUT_GP2A=m -CONFIG_INPUT_GPIO_TILT_POLLED=m -CONFIG_MDIO_BUS_MUX_MMIOREG=m - -# MTD -CONFIG_MTD_OF_PARTS=y -# CONFIG_MG_DISK is not set - -# Framebuffers -CONFIG_FB_SSD1307=m # Regulator drivers -CONFIG_REGULATOR_FIXED_VOLTAGE=m CONFIG_REGULATOR_FAN53555=m # CONFIG_CHARGER_MANAGER is not set # CONFIG_REGULATOR_DUMMY is not set @@ -401,37 +433,23 @@ CONFIG_REGULATOR_LP3972=m CONFIG_REGULATOR_TPS51632=m CONFIG_REGULATOR_TPS62360=m CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6524X=m CONFIG_REGULATOR_TPS6507X=m +CONFIG_REGULATOR_TPS65912=m +CONFIG_REGULATOR_MAX8907=m +CONFIG_REGULATOR_LP872X=y +CONFIG_REGULATOR_LP8755=m # Needs work/investigation # CONFIG_ARM_CHARLCD is not set # CONFIG_MTD_AFS_PARTS is not set # CONFIG_IP_PNP_RARP is not set -# CONFIG_BPF_JIT is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set # CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_DEPRECATED_PARAM_STRUCT is not set -# CONFIG_IRQ_DOMAIN_DEBUG is not set -# CONFIG_COMMON_CLK_DEBUG is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_PINCTRL is not set - -# CONFIG_CS89x0 is not set -# CONFIG_DM9000 is not set - -# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set # CONFIG_ARM_KPROBES_TEST is not set -# CONFIG_LEDS_RENESAS_TPU is not set - -CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_PATA_PLATFORM is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_SGI_IOC4 is not set # Defined config options we don't use yet # CONFIG_PINCTRL_IMX35 is not set @@ -441,41 +459,33 @@ CONFIG_ETHERNET=y # CONFIG_DRM_IMX_IPUV3 is not set # CONFIG_REGULATOR_ANATOP is not set -# CONFIG_GPIO_TWL6040 is not set -# CONFIG_SND_OMAP_SOC_OMAP_TWL4030 is not set -# CONFIG_VIDEO_DM6446_CCDC is not set -# CONFIG_PANEL_TAAL is not set +# CONFIG_BATTERY_RX51 is not set # CONFIG_IR_RX51 is not set -# CONFIG_DRM_OMAP is not set - # CONFIG_GENERIC_CPUFREQ_CPU0 is not set -# CONFIG_GPIO_TWL6040 is not set # CONFIG_MFD_SMSC is not set +# CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_DA9055 is not set # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_MAX8907 is not set -# CONFIG_REGULATOR_FAN53555 is not set -# CONFIG_REGULATOR_ANATOP is not set -# CONFIG_IR_RX51 is not set -# CONFIG_VIDEO_DM6446_CCDC is not set -# CONFIG_PANEL_TAAL is not set -# CONFIG_SND_OMAP_SOC_OMAP_TWL4030 is not set - -# these modules all fail with missing __bad_udelay -# http://www.spinics.net/lists/arm/msg15615.html provides some background -# CONFIG_SUNGEM is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_RADEON is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_ATM_HE is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SFC is not set - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_DVB_USB_PCTV452E is not set # We need to fix these as they should be either generic includes or kconfig fixes @@ -483,3 +493,9 @@ CONFIG_ETHERNET=y # CONFIG_TOUCHSCREEN_EETI is not set # CONFIG_TOUCHSCREEN_EGALAX is not set # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set + +# CONFIG_VIRTUALIZATION is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_POWER_RESET_QNAP is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_OMAP2_DSS_DEBUG is not set diff --git a/config-armv7-generic b/config-armv7-generic new file mode 100644 index 000000000..abe4bdd1a --- /dev/null +++ b/config-armv7-generic @@ -0,0 +1,467 @@ +# arm configs for sharing between armv7 and armv7-lpae +# Generic ARM config options +CONFIG_ARM=y + +CONFIG_CMDLINE="" +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_AEABI=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_GIC=y +CONFIG_ARM_ASM_UNIFIED=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_SWP_EMULATE=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_HIGHPTE=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_EARLY_PRINTK=y +CONFIG_ATAGS=y +CONFIG_ATAGS_PROC=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 + +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y + +# CONFIG_OABI_COMPAT is not set +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_DMA_CACHE_RWFO is not set +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_HVC_DCC is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_ARM_VIRT_EXT is not set + +# errata +# v5/v6 +# CONFIG_ARM_ERRATA_326103 is not set +# CONFIG_ARM_ERRATA_411920 is not set +# Cortex-A8 +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# Cortex-A9 +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_ARM_ERRATA_742231=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_751472=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +# Disabled due to causing highbank to crash +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +CONFIG_PL310_ERRATA_753970=y +CONFIG_PL310_ERRATA_769419=y +# Cortex-A15 +CONFIG_ARM_ERRATA_798181=y + +# generic that deviates from or should be merged into config-generic +CONFIG_SMP=y +CONFIG_NR_CPUS=8 +CONFIG_SMP_ON_UP=y +CONFIG_HIGHMEM=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y + +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 + +# 2013/04/19 - disable due to stability issues in 3.9 for the moment +# CONFIG_CPU_IDLE is not set +## CONFIG_CPU_IDLE_GOV_LADDER is not set +# CONFIG_CPU_IDLE_GOV_MENU is not set +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set + +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +CONFIG_SECCOMP=y +CONFIG_STRICT_DEVMEM=y + +CONFIG_XZ_DEC_ARM=y +CONFIG_OC_ETM=y + +CONFIG_PM=y +CONFIG_PM_STD_PARTITION="" +CONFIG_SUSPEND=y +CONFIG_ARM_CPU_SUSPEND=y + +CONFIG_LOCAL_TIMERS=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_CC_STACKPROTECTOR=y + +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y + +# Root as NFS, different from mainline +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y + +CONFIG_LBDAF=y + +CONFIG_COMMON_CLK=y + +# Device tree +CONFIG_DTC=y +CONFIG_OF=y +CONFIG_USE_OF=y +CONFIG_OF_DEVICE=y +CONFIG_OF_IRQ=y +CONFIG_DMA_OF=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_GPIO=y +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_OF_MDIO=m + +CONFIG_OF_DISPLAY_TIMING=y +CONFIG_OF_VIDEOMODE=y + +# General vexpress ARM drivers +CONFIG_ARM_AMBA=y +CONFIG_ARM_TIMER_SP804=y + +CONFIG_SERIO_AMBAKMI=m +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_8250_DW=y + +CONFIG_RTC_DRV_PL030=y +CONFIG_RTC_DRV_PL031=y + +CONFIG_PL330_DMA=m +CONFIG_AMBA_PL08X=y +CONFIG_ARM_SP805_WATCHDOG=m +CONFIG_I2C_VERSATILE=m +CONFIG_GPIO_PL061=y +CONFIG_SENSORS_VEXPRESS=m +CONFIG_FB_ARMCLCD=m +CONFIG_REGULATOR_VEXPRESS=m + +# usb +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_ULPI=y +CONFIG_AX88796=m +CONFIG_AX88796_93CX6=y +CONFIG_SMC91X=m +CONFIG_SMC911X=m +CONFIG_SMSC911X=m +CONFIG_USB_ISP1760_HCD=m + +# Multifunction Devices +CONFIG_MFD_SYSCON=y +CONFIG_MFD_TPS65912_SPI=y +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_MC13XXX_SPI is not set + +# Pin stuff +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_SINGLE=m +# CONFIG_PINCTRL_SAMSUNG is not set +# CONFIG_PINCTRL_EXYNOS4 is not set + +# GPIO +CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_EXTCON_GPIO=m +CONFIG_GENERIC_GPIO=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +# CONFIG_GPIO_EM is not set +CONFIG_GPIO_ADNP=m +CONFIG_GPIO_MCP23S08=m +CONFIG_POWER_RESET_GPIO=y +CONFIG_RFKILL_GPIO=m +CONFIG_SERIAL_8250_EM=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_MDIO_BUS_MUX_MMIOREG=m +CONFIG_LEDS_GPIO=m +CONFIG_GPIOLIB=y +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_74X164=m +CONFIG_GPIO_TPS65912=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_CHARGER_GPIO=m + +CONFIG_SPI=y +CONFIG_SPI_GPIO=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_PL022=m +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_ALTERA=m +CONFIG_SPI_BUTTERFLY=m +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_OC_TINY=m +CONFIG_SPI_S3C64XX=m +CONFIG_SPI_SC18IS602=m +CONFIG_SPI_XCOMM=m +CONFIG_SPI_XILINX=m +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_TLE62X0=m + +# HW crypto and rng +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m + +# EDAC +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_LEGACY_SYSFS=y + +# Watchdog +CONFIG_MPCORE_WATCHDOG=m + +# Thermal / powersaving +CONFIG_THERMAL=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_ARM_PSCI=y + +# MTD +CONFIG_MTD_OF_PARTS=y +# CONFIG_MG_DISK is not set +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y +CONFIG_MTD_DATAFLASH_OTP=y +CONFIG_MTD_M25P80=m +CONFIG_MTD_SST25L=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93XX46=m + +# MMC/SD +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SPI=m +CONFIG_MMC_DW=m +CONFIG_MMC_DW_PLTFM=m +CONFIG_MMC_DW_PCI=m +CONFIG_SPI_DW_MMIO=m +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_IDMAC is not set + +# Sound +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=m +CONFIG_SND_SOC=m +CONFIG_SND_SPI=y +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SND_SOC_CACHE_LZO=y +CONFIG_SND_SOC_ALL_CODECS=m +# CONFIG_SND_ATMEL_SOC is not set + +# Displays +CONFIG_FB_SSD1307=m + +# PWM +CONFIG_PWM=y +CONFIG_BACKLIGHT_PWM=m + +# RTC +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_RX4581=m + +# Regulators +CONFIG_REGULATOR=y +CONFIG_RFKILL_REGULATOR=m +CONFIG_CHARGER_MANAGER=y +# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=m +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +CONFIG_REGULATOR_GPIO=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_FAN53555=m +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8973=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_LP3972=m +CONFIG_REGULATOR_LP8755=m +CONFIG_REGULATOR_TPS51632=m +CONFIG_REGULATOR_TPS62360=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_REGULATOR_TPS6524X=m +CONFIG_REGULATOR_TPS65912=m + +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_LIS3_SPI=m +CONFIG_SENSORS_GPIO_FAN=m + +CONFIG_LCD_L4F00242T03=m +CONFIG_LCD_LMS283GF05=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_TDO24M=m +CONFIG_LCD_VGG2432A4=m +CONFIG_LCD_S6E63M0=m +CONFIG_LCD_LD9040=m +CONFIG_LCD_AMS369FG06=m +CONFIG_LCD_LMS501KF03=m +CONFIG_LCD_HX8357=m + +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_ARIZONA_HAPTICS=m +CONFIG_INPUT_MC13783_PWRBUTTON=m + + +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_MC13783=m +CONFIG_TOUCHSCREEN_TSC2005=m + +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_PWM=m +CONFIG_BMP085_SPI=m + +# Ethernet +CONFIG_KS8851=m +CONFIG_ENC28J60=m +CONFIG_LIBERTAS_SPI=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=n +CONFIG_MICREL_KS8995MA=m +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m + +CONFIG_ARM_KPROBES_TEST=m + +# jffs2 +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_ZLIB=y + +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set + +# Should be in generic +CONFIG_ETHERNET=y +CONFIG_BPF_JIT=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set + +# CONFIG_PATA_PLATFORM is not set +CONFIG_PERF_EVENTS=y + +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_IMX is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_CS89x0 is not set +# CONFIG_DM9000 is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_EXYNOS is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_EZX_PCAP is not set + +# Needs work/investigation +# CONFIG_ARM_CHARLCD is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_IFX6X60 is not set + +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SFC is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set + +# Debug options. We need to deal with them at some point like x86 +# CONFIG_COMMON_CLK_DEBUG is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_DEBUG_PINCTRL is not set diff --git a/config-arm-tegra b/config-armv7-tegra similarity index 66% rename from config-arm-tegra rename to config-armv7-tegra index 8b62dedf5..20cda8a7b 100644 --- a/config-arm-tegra +++ b/config-armv7-tegra @@ -2,10 +2,15 @@ CONFIG_ARCH_TEGRA=y CONFIG_ARCH_TEGRA_2x_SOC=y # CONFIG_ARCH_TEGRA_3x_SOC is not set -# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_TEGRA_114_SOC is not set -CONFIG_VFP=y -CONFIG_VFPv3=y +# CONFIG_NEON is not set +# These are supported in the LPAE kernel +# CONFIG_ARM_LPAE is not set +# CONFIG_XEN is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_MACH_HARMONY is not set CONFIG_MACH_KAEN=y @@ -16,9 +21,6 @@ CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y CONFIG_MACH_VENTANA=y -CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_ARM_CPU_TOPOLOGY=y - CONFIG_TEGRA_PCI=y CONFIG_TEGRA_IOMMU_GART=y CONFIG_TEGRA_IOMMU_SMMU=y @@ -31,43 +33,19 @@ CONFIG_MMC_BLOCK=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_OF=y -CONFIG_MMC_SPI=y - CONFIG_MMC_SDHCI_TEGRA=y -# CONFIG_RCU_BOOST is not set CONFIG_TEGRA_SYSTEM_DMA=y CONFIG_TEGRA_EMC_SCALING_ENABLE=y CONFIG_TEGRA_AHB=y CONFIG_TEGRA20_APB_DMA=y CONFIG_SPI_TEGRA20_SFLASH=m CONFIG_SPI_TEGRA20_SLINK=m -CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -CONFIG_ARM_ERRATA_430973=y -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -CONFIG_ARM_ERRATA_742230=y -# CONFIG_ARM_ERRATA_742231 is not set -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_ARM_ERRATA_720789=y -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_ARM_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -# CONFIG_THUMB2_KERNEL is not set -# CONFIG_NEON is not set -CONFIG_GPIO_GENERIC_PLATFORM=y -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_KEYBOARD_TEGRA is not set + +CONFIG_KEYBOARD_TEGRA=m CONFIG_PINCTRL_TEGRA=y CONFIG_PINCTRL_TEGRA20=y +CONFIG_PINCTRL_TEGRA30=y CONFIG_USB_EHCI_TEGRA=y CONFIG_RTC_DRV_TEGRA=y @@ -75,12 +53,14 @@ CONFIG_SND_SOC_TEGRA=m CONFIG_SND_SOC_TEGRA_ALC5632=m CONFIG_SND_SOC_TEGRA_WM8753=m CONFIG_SND_SOC_TEGRA_WM8903=m +CONFIG_SND_SOC_TEGRA_WM9712=m CONFIG_SND_SOC_TEGRA_TRIMSLICE=m CONFIG_SND_SOC_TEGRA30_AHUB=m CONFIG_SND_SOC_TEGRA30_I2S=m +CONFIG_SND_SOC_TEGRA20_AC97=m # AC100 (PAZ00) -# CONFIG_MFD_NVEC is not set +CONFIG_MFD_NVEC=y CONFIG_MFD_TPS80031=y CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y @@ -106,16 +86,13 @@ CONFIG_CMA_AREAS=7 CONFIG_DRM_TEGRA=m -CONFIG_CPU_PM=y -CONFIG_ARM_CPU_SUSPEND=y - CONFIG_CRYPTO_DEV_TEGRA_AES=m -CONFIG_PL310_ERRATA_753970=y CONFIG_LEDS_RENESAS_TPU=y CONFIG_OF=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_TEGRA=y CONFIG_OF_GPIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y @@ -124,3 +101,8 @@ CONFIG_OF_PCI_IRQ=y # CONFIG_TI_DAC7512 is not set # CONFIG_SPI_TOPCLIFF_PCH is not set # CONFIG_SPI_DW_PCI is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_PINCTRL_EXYNOS is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set diff --git a/kernel.spec b/kernel.spec index 670eaf8cb..ac44249c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -487,6 +487,8 @@ Provides: kernel-modeset = 1\ Provides: kernel-uname-r = %{KVERREL}%{?1:.%{1}}\ Provides: kernel-highbank\ Provides: kernel-highbank-uname-r = %{KVERREL}%{?1:.%{1}}\ +Provides: kernel-omap\ +Provides: kernel-omap-uname-r = %{KVERREL}%{?1:.%{1}}\ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ @@ -582,12 +584,12 @@ Source70: config-s390x # Unified ARM kernels Source100: config-armv7 +Source101: config-armv7-generic +Source102: config-armv7-tegra # Legacy ARM kernels -Source105: config-arm-generic -Source110: config-arm-omap -Source111: config-arm-tegra -Source112: config-arm-kirkwood +Source104: config-arm-generic +Source105: config-arm-kirkwood # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -2320,6 +2322,9 @@ fi # ||----w | # || || %changelog +* Mon May 6 2013 Peter Robinson +- Initial rebase of ARM to 3.9 + * Mon May 06 2013 Dave Jones - 3.9.0-200 - Rebase to Linux 3.9 merged: silence-empty-ipi-mask-warning.patch From a46818861466df8172c648a410ef7bf169f5294d Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 7 May 2013 00:45:04 +0100 Subject: [PATCH 311/492] and drop the kernel-omap sub package is the spec --- kernel.spec | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/kernel.spec b/kernel.spec index ac44249c3..d8095c1fb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -132,8 +132,6 @@ Summary: The Linux kernel %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} -# ARM OMAP (Beagle/Panda Board) -%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} # kernel-tegra (only valid for arm) %define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} # kernel-kirkwood (only valid for arm) @@ -254,9 +252,8 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel up (versatile express), tegra and omap are only built on armv7 hfp/sfp +# kernel up (versatile express), and tegra are only built on armv7 hfp/sfp %ifnarch armv7hl armv7l -%define with_omap 0 %define with_tegra 0 %endif @@ -1042,12 +1039,6 @@ on kernel bugs, as some of these options impact performance noticably. This package includes a version of the Linux kernel with support for marvell kirkwood based systems, i.e., guruplug, sheevaplug -%define variant_summary The Linux kernel compiled for TI-OMAP boards -%kernel_variant_package omap -%description omap -This package includes a version of the Linux kernel with support for -TI-OMAP based systems, i.e., BeagleBoard-xM. - %define variant_summary The Linux kernel compiled for tegra boards %kernel_variant_package tegra %description tegra @@ -1817,10 +1808,6 @@ BuildKernel %make_target %kernel_image PAE BuildKernel %make_target %kernel_image kirkwood %endif -%if %{with_omap} -BuildKernel %make_target %kernel_image omap -%endif - %if %{with_tegra} BuildKernel %make_target %kernel_image tegra %endif @@ -2156,9 +2143,6 @@ fi}\ %kernel_variant_preun kirkwood %kernel_variant_post -v kirkwood -%kernel_variant_preun omap -%kernel_variant_post -v omap - %kernel_variant_preun tegra %kernel_variant_post -v tegra @@ -2306,7 +2290,6 @@ fi %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug %kernel_variant_files %{with_kirkwood} kirkwood -%kernel_variant_files %{with_omap} omap %kernel_variant_files %{with_tegra} tegra # plz don't put in a version string unless you're going to tag From f10fcf750f84a1a50ad03dc4e5ac5e959167a601 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 6 May 2013 16:30:00 -0400 Subject: [PATCH 312/492] Rebase F18 secure-boot patchset to Linux v3.9 --- config-x86-generic | 4 +- kernel.spec | 9 +- ...130409.patch => secure-boot-20130506.patch | 173 ++++++++++-------- 3 files changed, 105 insertions(+), 81 deletions(-) rename secure-boot-20130409.patch => secure-boot-20130506.patch (89%) diff --git a/config-x86-generic b/config-x86-generic index 67a9e1477..d8084b246 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -447,13 +447,13 @@ CONFIG_XZ_DEC_X86=y CONFIG_MPILIB=y CONFIG_PKCS7_MESSAGE_PARSER=y -CONFIG_PE_FILE_PARSER=y +CONFIG_EFI_SIGNATURE_LIST_PARSER=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_ALL=y # CONFIG_MODULE_SIG_SHA1 is not set CONFIG_MODULE_SIG_SHA256=y # CONFIG_MODULE_SIG_FORCE is not set -CONFIG_SYSTEM_BLACKLIST_KEYRING=y +CONFIG_MODULE_SIG_BLACKLIST=y CONFIG_MODULE_SIG_UEFI=y diff --git a/kernel.spec b/kernel.spec index d8095c1fb..ac8b924d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -670,7 +670,7 @@ Patch530: silence-fbcon-logo.patch Patch800: crash-driver.patch # secure boot -Patch1000: secure-boot-20130409.patch +Patch1000: secure-boot-20130506.patch # virt + ksm patches @@ -1377,7 +1377,7 @@ ApplyPatch silence-fbcon-logo.patch ApplyPatch crash-driver.patch # secure boot -#ApplyPatch secure-boot-20130409.patch +ApplyPatch secure-boot-20130506.patch # Assorted Virt Fixes @@ -2305,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Mon May 06 2013 Josh Boyer +- Rebase F18 secure-boot patchset to Linux v3.9 + * Mon May 6 2013 Peter Robinson - Initial rebase of ARM to 3.9 diff --git a/secure-boot-20130409.patch b/secure-boot-20130506.patch similarity index 89% rename from secure-boot-20130409.patch rename to secure-boot-20130506.patch index 81b2561e0..f2267f23a 100644 --- a/secure-boot-20130409.patch +++ b/secure-boot-20130506.patch @@ -1,4 +1,4 @@ -From 21d9399006e65d7c7cf94c0f4d5378fd450e4d9a Mon Sep 17 00:00:00 2001 +From 5b93084a9e220fb63d549c0acba389dc39c12ea5 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:56 -0400 Subject: [PATCH 01/19] Secure boot: Add new capability @@ -35,7 +35,7 @@ index ba478fa..7109e65 100644 1.8.1.4 -From 2284c2baab55a3d1b70e579974b002ec255713e2 Mon Sep 17 00:00:00 2001 +From 01cd96f927fd11fd43ba4631bd7a314e09ca9939 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:05 -0400 Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability @@ -68,7 +68,7 @@ index 14d04e6..ed99a2d 100644 1.8.1.4 -From ad44e5d0bff09944532508591d9eab77dc24455e Mon Sep 17 00:00:00 2001 +From aabe98772f0b63652df87a2dd566ad2e66fbe14f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:02 -0400 Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will @@ -85,10 +85,10 @@ Signed-off-by: Josh Boyer 2 files changed, 24 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 986614d..cd531ba 100644 +index 8ccbf27..5bd14a4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -2659,6 +2659,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -2706,6 +2706,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Note: increases power consumption, thus should only be enabled if running jitter sensitive (HPC/RT) workloads. @@ -134,7 +134,7 @@ index e0573a4..c3f4e3e 100644 1.8.1.4 -From 829b1ec4f2102775b6d60d7ba85c17333e6d4cec Mon Sep 17 00:00:00 2001 +From 76de11cca755aca928ed2f6b6c99ffc3328cde13 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:03 -0400 Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when @@ -148,13 +148,14 @@ EFI_SECURE_BOOT bit for use with efi_enabled. Signed-off-by: Matthew Garrett Signed-off-by: Josh Boyer --- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ - arch/x86/include/uapi/asm/bootparam.h | 3 ++- - arch/x86/kernel/setup.c | 7 +++++++ - include/linux/cred.h | 2 ++ - include/linux/efi.h | 1 + - 6 files changed, 46 insertions(+), 1 deletion(-) + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ + arch/x86/include/asm/bootparam_utils.h | 8 ++++++-- + arch/x86/include/uapi/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 7 +++++++ + include/linux/cred.h | 2 ++ + include/linux/efi.h | 1 + + 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt index 199f453..ff651d3 100644 @@ -170,10 +171,10 @@ index 199f453..ff651d3 100644 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures 2D0/A00 ALL e820_map E820 memory map table diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index c205035..96d859d 100644 +index 35ee62f..0998ec7 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -861,6 +861,36 @@ fail: +@@ -906,6 +906,36 @@ fail: return status; } @@ -210,7 +211,7 @@ index c205035..96d859d 100644 /* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create -@@ -1155,6 +1185,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, +@@ -1200,6 +1230,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; @@ -218,12 +219,32 @@ index c205035..96d859d 100644 + setup_graphics(boot_params); - setup_efi_pci(boot_params); + setup_efi_vars(boot_params); +diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h +index 653668d..7856ca7 100644 +--- a/arch/x86/include/asm/bootparam_utils.h ++++ b/arch/x86/include/asm/bootparam_utils.h +@@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params) + memset(&boot_params->olpc_ofw_header, 0, + (char *)&boot_params->efi_info - + (char *)&boot_params->olpc_ofw_header); +- memset(&boot_params->kbd_status, 0, ++ memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status)); ++ /* don't clear boot_params->secure_boot. we set that ourselves ++ * earlier. ++ */ ++ memset(&boot_params->_pad5[0], 0, + (char *)&boot_params->hdr - +- (char *)&boot_params->kbd_status); ++ (char *)&boot_params->_pad5[0]); + memset(&boot_params->_pad7[0], 0, + (char *)&boot_params->edd_mbr_sig_buffer[0] - + (char *)&boot_params->_pad7[0]); diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h -index c15ddaf..85d7685 100644 +index 0874424..56b7d39 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h -@@ -131,7 +131,8 @@ struct boot_params { +@@ -132,7 +132,8 @@ struct boot_params { __u8 eddbuf_entries; /* 0x1e9 */ __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ __u8 kbd_status; /* 0x1eb */ @@ -234,10 +255,10 @@ index c15ddaf..85d7685 100644 * The sentinel is set to a nonzero value (0xff) in header.S. * diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 8b24289..d74b441 100644 +index fae9134..b7465a5 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -1042,6 +1042,13 @@ void __init setup_arch(char **cmdline_p) +@@ -1133,6 +1133,13 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); @@ -265,10 +286,10 @@ index 04421e8..9e69542 100644 * check for validity of credentials */ diff --git a/include/linux/efi.h b/include/linux/efi.h -index 7a9498a..1ae16b6 100644 +index 3d7df3d..178b32c 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -627,6 +627,7 @@ extern int __init efi_setup_pcdp_console(char *); +@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ #define EFI_64BIT 5 /* Is the firmware 64-bit? */ @@ -280,7 +301,7 @@ index 7a9498a..1ae16b6 100644 1.8.1.4 -From 980c3259cd54d71e8d20916453b3f90fd710d146 Mon Sep 17 00:00:00 2001 +From cd3b94aed727f9f77901e319058f2bc7257e64c8 Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:30:54 -0400 Subject: [PATCH 05/19] Add EFI signature data types @@ -294,10 +315,10 @@ Signed-off-by: David Howells 1 file changed, 20 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index 1ae16b6..de7021d 100644 +index 178b32c..77373a7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -388,6 +388,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si #define EFI_FILE_SYSTEM_GUID \ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) @@ -310,7 +331,7 @@ index 1ae16b6..de7021d 100644 typedef struct { efi_guid_t guid; u64 table; -@@ -523,6 +529,20 @@ typedef struct { +@@ -524,6 +530,20 @@ typedef struct { #define EFI_INVALID_TABLE_ADDR (~0UL) @@ -335,7 +356,7 @@ index 1ae16b6..de7021d 100644 1.8.1.4 -From e381c3c9b22585601a41b2eb616e03107f6bb677 Mon Sep 17 00:00:00 2001 +From 62e8fff1a3d879c9377f3e8b9bb3aac2bc115b5f Mon Sep 17 00:00:00 2001 From: Dave Howells Date: Tue, 23 Oct 2012 09:36:28 -0400 Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader. @@ -496,10 +517,10 @@ index 0000000..636feb1 + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index de7021d..64b3e55 100644 +index 77373a7..9dab408 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -612,6 +612,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); +@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; @@ -514,7 +535,7 @@ index de7021d..64b3e55 100644 1.8.1.4 -From 4a6aa76febc26971c3a49ce37d9cab6ed0ee410a Mon Sep 17 00:00:00 2001 +From 7a798ef2fea17b56c4769c9c942d678dd8341fd3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:36:24 -0400 Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring @@ -533,12 +554,12 @@ Signed-off-by: Josh Boyer 4 files changed, 37 insertions(+) diff --git a/init/Kconfig b/init/Kconfig -index be8b7f5..d972b77 100644 +index 5341d72..9fa68df 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1665,6 +1665,14 @@ config MODULE_SIG_FORCE - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. +@@ -1679,6 +1679,14 @@ config MODULE_SIG_ALL + comment "Do not forget to sign required modules with scripts/sign-file" + depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL +config MODULE_SIG_BLACKLIST + bool "Support for blacklisting module signature certificates" @@ -623,7 +644,7 @@ index f2970bd..5423195 100644 1.8.1.4 -From ffe139eb9b68b1997b25c12123962e5fc79a6666 Mon Sep 17 00:00:00 2001 +From a245b231b8d61f9c12c389043c77c390d0f3c23d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 12:42:16 -0400 Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot @@ -651,10 +672,10 @@ Signed-off-by: Josh Boyer create mode 100644 kernel/modsign_uefi.c diff --git a/include/linux/efi.h b/include/linux/efi.h -index 64b3e55..76fe526 100644 +index 9dab408..b1a1809 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -394,6 +394,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, +@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si #define EFI_CERT_X509_GUID \ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) @@ -668,10 +689,10 @@ index 64b3e55..76fe526 100644 efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index d972b77..27e3a82 100644 +index 9fa68df..606295c 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1673,6 +1673,15 @@ config MODULE_SIG_BLACKLIST +@@ -1687,6 +1687,15 @@ config MODULE_SIG_BLACKLIST should not pass module signature verification. If a module is signed with something in this keyring, the load will be rejected. @@ -688,10 +709,10 @@ index d972b77..27e3a82 100644 prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG diff --git a/kernel/Makefile b/kernel/Makefile -index 6c072b6..8848829 100644 +index bbde5f1..d102fb2 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o +@@ -53,6 +53,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o @@ -699,7 +720,7 @@ index 6c072b6..8848829 100644 obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o -@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o +@@ -112,6 +113,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o $(obj)/configs.o: $(obj)/config_data.h @@ -808,7 +829,7 @@ index 0000000..b9237d7 1.8.1.4 -From cf1c95fca2c16e4de7b0ae8786c234d48d4bae87 Mon Sep 17 00:00:00 2001 +From 39e04e6106f21d0440c099fd6911863a0023f52a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:57 -0400 Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments @@ -876,7 +897,7 @@ index 9c6e9bb..09c311e 100644 } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index 9b8505c..35580bc 100644 +index 0b00947..7639f68 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof @@ -925,7 +946,7 @@ index e1c1ec5..97e785f 100644 1.8.1.4 -From c6ecf3e5233060dcfc972625ef6655c46ced7f71 Mon Sep 17 00:00:00 2001 +From 45e3db2ab117829efd167f96487ea7d6f9e1ea6d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:58 -0400 Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot @@ -943,7 +964,7 @@ Signed-off-by: Matthew Garrett 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c -index 8c96897..a2578c4 100644 +index 4ddaf66..f505995 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -28,7 +28,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) @@ -955,7 +976,7 @@ index 8c96897..a2578c4 100644 return -EPERM; /* -@@ -102,7 +102,7 @@ long sys_iopl(unsigned int level, struct pt_regs *regs) +@@ -103,7 +103,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { @@ -965,12 +986,12 @@ index 8c96897..a2578c4 100644 } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index c6fa3bc..fc28099 100644 +index 2c644af..7eee4d8 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, unsigned long i = *ppos; - const char __user * tmp = buf; + const char __user *tmp = buf; + if (!capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; @@ -982,7 +1003,7 @@ index c6fa3bc..fc28099 100644 1.8.1.4 -From 083d92056bae5c74c99a7942deb33f5f59e608a6 Mon Sep 17 00:00:00 2001 +From 62cc8b181cd49e047f4999a3e4f65a4f222fb2c9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:40:59 -0400 Subject: [PATCH 11/19] ACPI: Limit access to custom_method @@ -997,7 +1018,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index 5d42c24..247d58b 100644 +index 12b62f2..edf0710 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, @@ -1014,7 +1035,7 @@ index 5d42c24..247d58b 100644 1.8.1.4 -From 39ac07b200114ac8603388fa7d0eee3cc6e3d5ed Mon Sep 17 00:00:00 2001 +From b11830a03ddfa478ad5a73a88067a2a7d55dce5b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:00 -0400 Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface @@ -1030,10 +1051,10 @@ Signed-off-by: Matthew Garrett 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index f80ae4d..059195f 100644 +index c11b242..6d5f88f 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data) +@@ -1617,6 +1617,9 @@ static int show_dsts(struct seq_file *m, void *data) int err; u32 retval = -1; @@ -1043,7 +1064,7 @@ index f80ae4d..059195f 100644 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); if (err < 0) -@@ -1537,6 +1540,9 @@ static int show_devs(struct seq_file *m, void *data) +@@ -1633,6 +1636,9 @@ static int show_devs(struct seq_file *m, void *data) int err; u32 retval = -1; @@ -1053,7 +1074,7 @@ index f80ae4d..059195f 100644 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, &retval); -@@ -1561,6 +1567,9 @@ static int show_call(struct seq_file *m, void *data) +@@ -1657,6 +1663,9 @@ static int show_call(struct seq_file *m, void *data) union acpi_object *obj; acpi_status status; @@ -1067,7 +1088,7 @@ index f80ae4d..059195f 100644 1.8.1.4 -From c3726b30a361079f7121b438326d1c5252a4d805 Mon Sep 17 00:00:00 2001 +From 0d64b3972b75e420cddde5ba5c85f98046774450 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 20 Sep 2012 10:41:01 -0400 Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups @@ -1081,7 +1102,7 @@ Signed-off-by: Matthew Garrett 1 file changed, 6 insertions(+) diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index fc28099..b5df7a8 100644 +index 7eee4d8..772ee2b 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, @@ -1095,7 +1116,7 @@ index fc28099..b5df7a8 100644 return -EFAULT; @@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, - char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ int err = 0; + if (!capable(CAP_COMPROMISE_KERNEL)) @@ -1108,7 +1129,7 @@ index fc28099..b5df7a8 100644 1.8.1.4 -From 1d9ea90d4d22bf8c5e029d4c31621d793e6f8d13 Mon Sep 17 00:00:00 2001 +From 9f39d364fb1b8270a85ad9541710d4a7dd3bc0b5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Sep 2012 10:41:04 -0400 Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure @@ -1127,10 +1148,10 @@ Signed-off-by: Josh Boyer 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index bd22f86..d68c04f 100644 +index 586e7e9..8950454 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c -@@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); +@@ -245,7 +245,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); acpi_physical_address __init acpi_os_get_root_pointer(void) { #ifdef CONFIG_KEXEC @@ -1143,7 +1164,7 @@ index bd22f86..d68c04f 100644 1.8.1.4 -From 8b40ad15b16627302d4126aba2a6f2e0fb931504 Mon Sep 17 00:00:00 2001 +From c06f86d634932ceb788e9d883346e2d5e4117f52 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 4 Sep 2012 11:55:13 -0400 Subject: [PATCH 15/19] kexec: Disable in a secure boot environment @@ -1159,10 +1180,10 @@ Signed-off-by: Matthew Garrett 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c -index 5e4bd78..dd464e0 100644 +index ffd4e11..e276744 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c -@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, +@@ -946,7 +946,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, int result; /* We only trust the superuser with rebooting the system. */ @@ -1175,7 +1196,7 @@ index 5e4bd78..dd464e0 100644 1.8.1.4 -From 4b01a77b889d37bee6a1e4f547b9bba0050f5e7c Mon Sep 17 00:00:00 2001 +From 3555227817a9adbed51995104f4aeae4c6c36be9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Oct 2012 10:12:48 -0400 Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot @@ -1218,7 +1239,7 @@ index c3f4e3e..c5554e0 100644 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ diff --git a/kernel/module.c b/kernel/module.c -index eab0827..93a16dc 100644 +index 0925c9a..af4a476 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ @@ -1237,7 +1258,7 @@ index eab0827..93a16dc 100644 1.8.1.4 -From f95db0134af575215a14e77f3a29f0037ea9149a Mon Sep 17 00:00:00 2001 +From 844991aad05c36af54bf4540a71e2f5430da444f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Oct 2012 14:02:09 -0400 Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment @@ -1309,7 +1330,7 @@ index b26f5f1..7f63cb4 100644 len = p ? p - buf : n; diff --git a/kernel/power/main.c b/kernel/power/main.c -index 1c16f91..4f915fc 100644 +index d77663b..78f8ed5 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,6 +15,7 @@ @@ -1351,7 +1372,7 @@ index 4ed81e7..b11a0f4 100644 1.8.1.4 -From b9d7a7423b330552c89e32d10c9964e6447eadf2 Mon Sep 17 00:00:00 2001 +From 6f6d20668d3294e6a29d01a13a7415a542cb6413 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 5 Feb 2013 19:25:05 -0500 Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode @@ -1368,10 +1389,10 @@ Signed-off-by: Josh Boyer 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 96d859d..c9ffd2f 100644 +index 0998ec7..4945ee5 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -863,8 +863,9 @@ fail: +@@ -908,8 +908,9 @@ fail: static int get_secure_boot(efi_system_table_t *_table) { @@ -1382,7 +1403,7 @@ index 96d859d..c9ffd2f 100644 efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_status_t status; -@@ -888,6 +889,23 @@ static int get_secure_boot(efi_system_table_t *_table) +@@ -933,6 +934,23 @@ static int get_secure_boot(efi_system_table_t *_table) if (setup == 1) return 0; @@ -1410,7 +1431,7 @@ index 96d859d..c9ffd2f 100644 1.8.1.4 -From 627b4ba6ba59f095aaea33b1374186506fe2561f Mon Sep 17 00:00:00 2001 +From 53afc5a04d5b0fbdad1e4a34fbbecfdb5ff2f6dd Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 8 Feb 2013 11:12:13 -0800 Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot @@ -1424,7 +1445,7 @@ Signed-off-by: Kees Cook 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c -index 4929502..adaab3d 100644 +index ce13049..fa4dc6c 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, From 06b327f4ff9e5e56fd3a7792d8675666e20c3569 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 6 May 2013 19:52:54 -0400 Subject: [PATCH 313/492] 3.9.1-rc1 --- ...fi-fix-freeing-uninitialized-pointer.patch | 51 ------------------- kernel.spec | 21 +++----- ...fix-channel-disabling-race-condition.patch | 40 --------------- 3 files changed, 7 insertions(+), 105 deletions(-) delete mode 100644 iwlwifi-fix-freeing-uninitialized-pointer.patch delete mode 100644 wireless-regulatory-fix-channel-disabling-race-condition.patch diff --git a/iwlwifi-fix-freeing-uninitialized-pointer.patch b/iwlwifi-fix-freeing-uninitialized-pointer.patch deleted file mode 100644 index 90e6b6f64..000000000 --- a/iwlwifi-fix-freeing-uninitialized-pointer.patch +++ /dev/null @@ -1,51 +0,0 @@ -If on iwl_dump_nic_event_log() error occurs before that function -initialize buf, we process uninitiated pointer in -iwl_dbgfs_log_event_read() and can hit "BUG at mm/slub.c:3409" - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=951241 - -Reported-by: ian.odette@eprize.com -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- -Patch is only compile tested, but I'm sure it fixes the problem. - - drivers/net/wireless/iwlwifi/dvm/debugfs.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c -index 7b8178b..cb6dd58 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c -+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c -@@ -2237,15 +2237,15 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, - size_t count, loff_t *ppos) - { - struct iwl_priv *priv = file->private_data; -- char *buf; -- int pos = 0; -- ssize_t ret = -ENOMEM; -+ char *buf = NULL; -+ ssize_t ret; - -- ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); -- if (buf) { -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- } -+ ret = iwl_dump_nic_event_log(priv, true, &buf, true); -+ if (ret < 0) -+ goto err; -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); -+err: -+ kfree(buf); - return ret; - } - --- -1.7.11.7 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index ac8b924d4..4947fc270 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,9 +74,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -748,12 +748,6 @@ Patch25001: i7300_edac_single_mode_fixup.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -#rhbz 919176 -Patch25010: wireless-regulatory-fix-channel-disabling-race-condition.patch - -#rhbz 951241 -Patch25011: iwlwifi-fix-freeing-uninitialized-pointer.patch - # END OF PATCH DEFINITIONS %endif @@ -1445,12 +1439,6 @@ ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -#rhbz 919176 -ApplyPatch wireless-regulatory-fix-channel-disabling-race-condition.patch - -#rhbz 951241 -ApplyPatch iwlwifi-fix-freeing-uninitialized-pointer.patch - # END OF PATCH APPLICATIONS %endif @@ -2305,6 +2293,11 @@ fi # ||----w | # || || %changelog +* Mon May 06 2013 Dave Jones - 3.9.1-0.rc1.200 +- Linux 3.9.1-rc1 + merged: wireless-regulatory-fix-channel-disabling-race-condition.patch + merged: iwlwifi-fix-freeing-uninitialized-pointer.patch + * Mon May 06 2013 Josh Boyer - Rebase F18 secure-boot patchset to Linux v3.9 diff --git a/wireless-regulatory-fix-channel-disabling-race-condition.patch b/wireless-regulatory-fix-channel-disabling-race-condition.patch deleted file mode 100644 index 313735377..000000000 --- a/wireless-regulatory-fix-channel-disabling-race-condition.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Johannes Berg - -When a full scan 2.4 and 5 GHz scan is scheduled, but then the 2.4 GHz -part of the scan disables a 5.2 GHz channel due to, e.g. receiving -country or frequency information, that 5.2 GHz channel might already -be in the list of channels to scan next. Then, when the driver checks -if it should do a passive scan, that will return false and attempt an -active scan. This is not only wrong but can also lead to the iwlwifi -device firmware crashing since it checks regulatory as well. - -Fix this by not setting the channel flags to just disabled but rather -OR'ing in the disabled flag. That way, even if the race happens, the -channel will be scanned passively which is still (mostly) correct. - -Cc: stable@vger.kernel.org -Signed-off-by: Johannes Berg ---- - net/wireless/reg.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/wireless/reg.c b/net/wireless/reg.c -index 93ab840..507c28e 100644 ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy, - return; - - REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); -- chan->flags = IEEE80211_CHAN_DISABLED; -+ chan->flags |= IEEE80211_CHAN_DISABLED; - return; - } - --- -1.8.0 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From f2aedf44462886c5501d8815a56ee2f4c876216a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 6 May 2013 20:01:33 -0400 Subject: [PATCH 314/492] remove fixme --- kernel.spec | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index 4947fc270..701d22e51 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1460,10 +1460,6 @@ rm -f kernel-%{version}-*debug.config %endif -# FIXME: ARM config broken on 3.9 rebase -rm -f kernel-%{version}-arm*.config - - # now run oldconfig over all the config files for i in *.config do From 1ddb55578b10c4e1d1694b72369e7e0dfca517e6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 May 2013 12:05:38 -0400 Subject: [PATCH 315/492] fix ver for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 701d22e51..786ad4e8f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2289,7 +2289,7 @@ fi # ||----w | # || || %changelog -* Mon May 06 2013 Dave Jones - 3.9.1-0.rc1.200 +* Mon May 06 2013 Dave Jones - 3.9.1-0.rc1.201 - Linux 3.9.1-rc1 merged: wireless-regulatory-fix-channel-disabling-race-condition.patch merged: iwlwifi-fix-freeing-uninitialized-pointer.patch From 4b5f226f638629c5f880764349014f0193bcf09d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 May 2013 12:17:28 -0400 Subject: [PATCH 316/492] upload rc1 --- sources | 1 + 1 file changed, 1 insertion(+) diff --git a/sources b/sources index 06558d5b1..1e0461c90 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz +8593d817ac34645b0ce4d17f6650b6b4 patch-3.9.1-rc1.xz From 70e5203dd0c65c654aa62bd086ba096f60ae0b0b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 May 2013 12:26:32 -0400 Subject: [PATCH 317/492] build require bc --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 786ad4e8f..cfa6879ba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -522,7 +522,7 @@ ExclusiveOS: Linux BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config, hmaccalc -BuildRequires: net-tools, hostname +BuildRequires: net-tools, hostname, bc BuildRequires: xmlto, asciidoc %if %{with_sparse} BuildRequires: sparse >= 0.4.1 From c2a687eb09e3c7f65977ca698e77934f16c4fde6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 7 May 2013 12:29:25 -0400 Subject: [PATCH 318/492] Fix dmesg_restrict patch to avoid regression (rhbz 952655) --- ...or-dmesg_restrict-sysctl-on-dev-kmsg.patch | 182 ++++++++++++------ kernel.spec | 3 + 2 files changed, 127 insertions(+), 58 deletions(-) diff --git a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch index c42c8c4f1..7197f7f7a 100644 --- a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch +++ b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch @@ -1,33 +1,106 @@ -From ce10d1b72b4da3c98bbbcb1b945687d964c31923 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 9 Apr 2013 11:08:13 -0400 -Subject: [PATCH] kmsg: Honor dmesg_restrict sysctl on /dev/kmsg +To fix /dev/kmsg, let's compare the existing interfaces and what they allow: -The dmesg_restrict sysctl currently covers the syslog method for access -dmesg, however /dev/kmsg isn't covered by the same protections. Most -people haven't noticed because util-linux dmesg(1) defaults to using the -syslog method for access in older versions. With util-linux dmesg(1) -defaults to reading directly from /dev/kmsg. +- /proc/kmsg allows: + - open (SYSLOG_ACTION_OPEN) if CAP_SYSLOG since it uses a destructive + single-reader interface (SYSLOG_ACTION_READ). + - everything, after an open. -Fix this by reworking all of the access methods to use the -check_syslog_permissions function and adding checks to devkmsg_open and -devkmsg_read. +- syslog syscall allows: + - anything, if CAP_SYSLOG. + - SYSLOG_ACTION_READ_ALL and SYSLOG_ACTION_SIZE_BUFFER, if dmesg_restrict==0. + - nothing else (EPERM). -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=903192 +The use-cases were: +- dmesg(1) needs to do non-destructive SYSLOG_ACTION_READ_ALLs. +- sysklog(1) needs to open /proc/kmsg, drop privs, and still issue the + destructive SYSLOG_ACTION_READs. +AIUI, dmesg(1) is moving to /dev/kmsg, and systemd-journald doesn't +clear the ring buffer. + +Based on the comments in devkmsg_llseek, it sounds like actions besides +reading aren't going to be supported by /dev/kmsg (i.e. SYSLOG_ACTION_CLEAR), +so we have a strict subset of the non-destructive syslog syscall actions. + +To this end, move the check as Josh had done, but also rename the constants +to reflect their new uses (SYSLOG_FROM_CALL becomes SYSLOG_FROM_READER, and +SYSLOG_FROM_FILE becomes SYSLOG_FROM_PROC). SYSLOG_FROM_READER allows +non-destructive actions, and SYSLOG_FROM_PROC allows destructive actions +after a capabilities-constrained SYSLOG_ACTION_OPEN check. + +- /dev/kmsg allows: + - open if CAP_SYSLOG or dmesg_restrict==0 + - reading/polling, after open + +Signed-off-by: Kees Cook Reported-by: Christian Kujau -CC: stable@vger.kernel.org -Signed-off-by: Eric Paris -Signed-off-by: Josh Boyer +Cc: Josh Boyer +Cc: Kay Sievers +Cc: stable@vger.kernel.org --- - kernel/printk.c | 91 +++++++++++++++++++++++++++++---------------------------- - 1 file changed, 47 insertions(+), 44 deletions(-) + fs/proc/kmsg.c | 10 +++--- + include/linux/syslog.h | 4 +-- + kernel/printk.c | 91 ++++++++++++++++++++++++++---------------------- + 3 files changed, 57 insertions(+), 48 deletions(-) +diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c +index bd4b5a7..bdfabda 100644 +--- a/fs/proc/kmsg.c ++++ b/fs/proc/kmsg.c +@@ -21,12 +21,12 @@ extern wait_queue_head_t log_wait; + + static int kmsg_open(struct inode * inode, struct file * file) + { +- return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE); ++ return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC); + } + + static int kmsg_release(struct inode * inode, struct file * file) + { +- (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE); ++ (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_PROC); + return 0; + } + +@@ -34,15 +34,15 @@ static ssize_t kmsg_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { + if ((file->f_flags & O_NONBLOCK) && +- !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) ++ !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) + return -EAGAIN; +- return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE); ++ return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_PROC); + } + + static unsigned int kmsg_poll(struct file *file, poll_table *wait) + { + poll_wait(file, &log_wait, wait); +- if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) ++ if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) + return POLLIN | POLLRDNORM; + return 0; + } +diff --git a/include/linux/syslog.h b/include/linux/syslog.h +index 3891139..98a3153 100644 +--- a/include/linux/syslog.h ++++ b/include/linux/syslog.h +@@ -44,8 +44,8 @@ + /* Return size of the log buffer */ + #define SYSLOG_ACTION_SIZE_BUFFER 10 + +-#define SYSLOG_FROM_CALL 0 +-#define SYSLOG_FROM_FILE 1 ++#define SYSLOG_FROM_READER 0 ++#define SYSLOG_FROM_PROC 1 + + int do_syslog(int type, char __user *buf, int count, bool from_file); + diff --git a/kernel/printk.c b/kernel/printk.c -index abbdd9e..5541095 100644 +index abbdd9e..53b5c5e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c -@@ -368,6 +368,46 @@ static void log_store(int facility, int level, +@@ -368,6 +368,53 @@ static void log_store(int facility, int level, log_next_seq++; } @@ -41,8 +114,12 @@ index abbdd9e..5541095 100644 +{ + if (dmesg_restrict) + return 1; -+ /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ -+ return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; ++ /* ++ * Unless restricted, we allow "read all" and "get buffer size" ++ * for everybody. ++ */ ++ return type != SYSLOG_ACTION_READ_ALL && ++ type != SYSLOG_ACTION_SIZE_BUFFER; +} + +static int check_syslog_permissions(int type, bool from_file) @@ -52,55 +129,42 @@ index abbdd9e..5541095 100644 + * already done the capabilities checks at open time. + */ + if (from_file && type != SYSLOG_ACTION_OPEN) -+ goto ok; ++ return 0; + + if (syslog_action_restricted(type)) { + if (capable(CAP_SYSLOG)) -+ goto ok; -+ /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ ++ return 0; ++ /* ++ * For historical reasons, accept CAP_SYS_ADMIN too, with ++ * a warning. ++ */ + if (capable(CAP_SYS_ADMIN)) { + printk_once(KERN_WARNING "%s (%d): " + "Attempt to access syslog with CAP_SYS_ADMIN " + "but no CAP_SYSLOG (deprecated).\n", + current->comm, task_pid_nr(current)); -+ goto ok; ++ return 0; + } + return -EPERM; + } -+ok: + return security_syslog(type); +} ++ + /* /dev/kmsg - userspace message inject/listen interface */ struct devkmsg_user { u64 seq; -@@ -443,10 +483,16 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, - char cont = '-'; - size_t len; - ssize_t ret; -+ int err; - - if (!user) - return -EBADF; - -+ err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, -+ SYSLOG_FROM_FILE); -+ if (err) -+ return err; -+ - ret = mutex_lock_interruptible(&user->lock); - if (ret) - return ret; -@@ -624,7 +670,7 @@ static int devkmsg_open(struct inode *inode, struct file *file) +@@ -624,7 +671,8 @@ static int devkmsg_open(struct inode *inode, struct file *file) if ((file->f_flags & O_ACCMODE) == O_WRONLY) return 0; - err = security_syslog(SYSLOG_ACTION_READ_ALL); -+ err = check_syslog_permissions(SYSLOG_ACTION_OPEN, SYSLOG_FROM_FILE); ++ err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, ++ SYSLOG_FROM_READER); if (err) return err; -@@ -817,45 +863,6 @@ static inline void boot_delay_msec(int level) +@@ -817,45 +865,6 @@ static inline void boot_delay_msec(int level) } #endif @@ -146,17 +210,19 @@ index abbdd9e..5541095 100644 #if defined(CONFIG_PRINTK_TIME) static bool printk_time = 1; #else -@@ -1131,10 +1138,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) - if (error) - goto out; +@@ -1253,7 +1262,7 @@ out: -- error = security_syslog(type); -- if (error) -- return error; -- - switch (type) { - case SYSLOG_ACTION_CLOSE: /* Close log */ - break; + SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) + { +- return do_syslog(type, buf, len, SYSLOG_FROM_CALL); ++ return do_syslog(type, buf, len, SYSLOG_FROM_READER); + } + + /* -- -1.8.1.4 +1.7.9.5 + +-- +Kees Cook +Chrome OS Security diff --git a/kernel.spec b/kernel.spec index cfa6879ba..e6043ac98 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2289,6 +2289,9 @@ fi # ||----w | # || || %changelog +* Tue May 07 2013 Josh Boyer +- Fix dmesg_restrict patch to avoid regression (rhbz 952655) + * Mon May 06 2013 Dave Jones - 3.9.1-0.rc1.201 - Linux 3.9.1-rc1 merged: wireless-regulatory-fix-channel-disabling-race-condition.patch From 05b62eef85d326e42dc496c792c4627e12b7cf8c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 6 May 2013 10:22:52 -0400 Subject: [PATCH 319/492] Don't remove headers explicitly exported via UAPI (rhbz 959467) --- kernel.spec | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index e6043ac98..713ea3a83 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1966,11 +1966,6 @@ find $RPM_BUILD_ROOT/usr/include \ \( -name .install -o -name .check -o \ -name ..install.cmd -o -name ..check.cmd \) | xargs rm -f -# glibc provides scsi headers for itself, for now -rm -rf $RPM_BUILD_ROOT/usr/include/scsi -rm -f $RPM_BUILD_ROOT/usr/include/asm*/atomic.h -rm -f $RPM_BUILD_ROOT/usr/include/asm*/io.h -rm -f $RPM_BUILD_ROOT/usr/include/asm*/irq.h %endif %if %{with_perf} @@ -2289,6 +2284,9 @@ fi # ||----w | # || || %changelog +* Wed May 08 2013 Josh Boyer +- Don't remove headers explicitly exported via UAPI (rhbz 959467) + * Tue May 07 2013 Josh Boyer - Fix dmesg_restrict patch to avoid regression (rhbz 952655) From a76c0c48328445769c3900bba9a4184d0044ea44 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 8 May 2013 12:22:30 -0400 Subject: [PATCH 320/492] Linux 3.9.1 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 713ea3a83..52ba12375 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -76,7 +76,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 1 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2284,6 +2284,9 @@ fi # ||----w | # || || %changelog +* Wed May 08 2013 Dave Jones - 3.9.1-200 +- Linux 3.9.1 + * Wed May 08 2013 Josh Boyer - Don't remove headers explicitly exported via UAPI (rhbz 959467) diff --git a/sources b/sources index 1e0461c90..f74ebc7ea 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -8593d817ac34645b0ce4d17f6650b6b4 patch-3.9.1-rc1.xz +66f171a17aa39b6dc6eb8bb51a4117c7 patch-3.9.1.xz From 597b5bc924cad2f83ccce4d347c6002a61338a35 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Wed, 8 May 2013 17:30:41 +0100 Subject: [PATCH 321/492] Add the ARM patches needed for 3.9 :-/ --- Makefile.config | 2 +- arm-export-read_current_timer.patch | 10 ++ arm-of-dma.patch | 43 +++++++ arm-omap-ehci-fix.patch | 190 ++++++++++++++++++++++++++++ arm-tegra-fixclk.patch | 28 ++++ kernel.spec | 17 ++- 6 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 arm-export-read_current_timer.patch create mode 100644 arm-of-dma.patch create mode 100644 arm-omap-ehci-fix.patch create mode 100644 arm-tegra-fixclk.patch diff --git a/Makefile.config b/Makefile.config index e538387c7..790ed2444 100644 --- a/Makefile.config +++ b/Makefile.config @@ -40,7 +40,7 @@ temp-armv7: config-armv7 temp-armv7-generic perl merge.pl $^ > $@ temp-armv7-tegra: config-armv7-tegra temp-armv7-generic - perl merge.pl $^ > $@ + perl merge.pl $^ > $@ temp-arm-generic: config-arm-generic temp-generic perl merge.pl $^ > $@ diff --git a/arm-export-read_current_timer.patch b/arm-export-read_current_timer.patch new file mode 100644 index 000000000..5059d6862 --- /dev/null +++ b/arm-export-read_current_timer.patch @@ -0,0 +1,10 @@ +--- linux-3.7.0-0.rc2.git1.2.fc19.x86_64/arch/arm/kernel/armksyms.c.orig 2012-10-01 00:47:46.000000000 +0100 ++++ linux-3.7.0-0.rc2.git1.2.fc19.x86_64/arch/arm/kernel/armksyms.c 2012-10-24 09:06:46.570452677 +0100 +@@ -50,6 +50,7 @@ + + /* platform dependent support */ + EXPORT_SYMBOL(arm_delay_ops); ++EXPORT_SYMBOL(read_current_timer); + + /* networking */ + EXPORT_SYMBOL(csum_partial); diff --git a/arm-of-dma.patch b/arm-of-dma.patch new file mode 100644 index 000000000..c3223a4e6 --- /dev/null +++ b/arm-of-dma.patch @@ -0,0 +1,43 @@ +From 7362f04c2888b14c20f8aaa02e1a897025261768 Mon Sep 17 00:00:00 2001 +From: Viresh Kumar +Date: Fri, 15 Mar 2013 08:48:20 +0000 +Subject: DMA: OF: Check properties value before running be32_to_cpup() on it + +In of_dma_controller_register() routine we are calling of_get_property() as an +parameter to be32_to_cpup(). In case the property doesn't exist we will get a +crash. + +This patch changes this code to check if we got a valid property first and then +runs be32_to_cpup() on it. + +Signed-off-by: Viresh Kumar +Signed-off-by: Vinod Koul +--- +diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c +index 6036cd0..00db454 100644 +--- a/drivers/dma/of-dma.c ++++ b/drivers/dma/of-dma.c +@@ -93,6 +93,7 @@ int of_dma_controller_register(struct device_node *np, + { + struct of_dma *ofdma; + int nbcells; ++ const __be32 *prop; + + if (!np || !of_dma_xlate) { + pr_err("%s: not enough information provided\n", __func__); +@@ -103,8 +104,11 @@ int of_dma_controller_register(struct device_node *np, + if (!ofdma) + return -ENOMEM; + +- nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL)); +- if (!nbcells) { ++ prop = of_get_property(np, "#dma-cells", NULL); ++ if (prop) ++ nbcells = be32_to_cpup(prop); ++ ++ if (!prop || !nbcells) { + pr_err("%s: #dma-cells property is missing or invalid\n", + __func__); + kfree(ofdma); +-- +cgit v0.9.1 diff --git a/arm-omap-ehci-fix.patch b/arm-omap-ehci-fix.patch new file mode 100644 index 000000000..f6fc0a934 --- /dev/null +++ b/arm-omap-ehci-fix.patch @@ -0,0 +1,190 @@ +From 54a419668b0f27b7982807fb2376d237e0a0ce05 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 12 Mar 2013 10:44:39 +0000 +Subject: USB: EHCI: split ehci-omap out to a separate driver + +This patch (as1645) converts ehci-omap over to the new "ehci-hcd is a +library" approach, so that it can coexist peacefully with other EHCI +platform drivers and can make use of the private area allocated at +the end of struct ehci_hcd. + +Signed-off-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman +--- +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index c59a112..62f4e9a 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -155,7 +155,7 @@ config USB_EHCI_MXC + Variation of ARC USB block used in some Freescale chips. + + config USB_EHCI_HCD_OMAP +- bool "EHCI support for OMAP3 and later chips" ++ tristate "EHCI support for OMAP3 and later chips" + depends on USB_EHCI_HCD && ARCH_OMAP + default y + ---help--- +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index 001fbff..56de410 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o + obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o + obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o + obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o ++obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o + + obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o + obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index b416a3f..303b022 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -1252,11 +1252,6 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_hcd_sh_driver + #endif + +-#ifdef CONFIG_USB_EHCI_HCD_OMAP +-#include "ehci-omap.c" +-#define PLATFORM_DRIVER ehci_hcd_omap_driver +-#endif +- + #ifdef CONFIG_PPC_PS3 + #include "ehci-ps3.c" + #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver +@@ -1346,6 +1341,7 @@ MODULE_LICENSE ("GPL"); + !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ + !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ ++ !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ +diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c +index 0555ee4..fa66757 100644 +--- a/drivers/usb/host/ehci-omap.c ++++ b/drivers/usb/host/ehci-omap.c +@@ -36,6 +36,9 @@ + * - convert to use hwmod and runtime PM + */ + ++#include ++#include ++#include + #include + #include + #include +@@ -43,6 +46,10 @@ + #include + #include + #include ++#include ++#include ++ ++#include "ehci.h" + + #include + +@@ -57,9 +64,11 @@ + #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 + #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 + +-/*-------------------------------------------------------------------------*/ ++#define DRIVER_DESC "OMAP-EHCI Host Controller driver" + +-static const struct hc_driver ehci_omap_hc_driver; ++static const char hcd_name[] = "ehci-omap"; ++ ++/*-------------------------------------------------------------------------*/ + + + static inline void ehci_write(void __iomem *base, u32 reg, u32 val) +@@ -166,6 +175,12 @@ static void disable_put_regulator( + /* configure so an HC device and id are always provided */ + /* always called with process context; sleeping is OK */ + ++static struct hc_driver __read_mostly ehci_omap_hc_driver; ++ ++static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { ++ .reset = omap_ehci_init, ++}; ++ + /** + * ehci_hcd_omap_probe - initialize TI-based HCDs + * +@@ -315,56 +330,33 @@ static struct platform_driver ehci_hcd_omap_driver = { + /*.suspend = ehci_hcd_omap_suspend, */ + /*.resume = ehci_hcd_omap_resume, */ + .driver = { +- .name = "ehci-omap", ++ .name = hcd_name, + } + }; + + /*-------------------------------------------------------------------------*/ + +-static const struct hc_driver ehci_omap_hc_driver = { +- .description = hcd_name, +- .product_desc = "OMAP-EHCI Host Controller", +- .hcd_priv_size = sizeof(struct ehci_hcd), +- +- /* +- * generic hardware linkage +- */ +- .irq = ehci_irq, +- .flags = HCD_MEMORY | HCD_USB2, +- +- /* +- * basic lifecycle operations +- */ +- .reset = omap_ehci_init, +- .start = ehci_run, +- .stop = ehci_stop, +- .shutdown = ehci_shutdown, +- +- /* +- * managing i/o requests and associated device resources +- */ +- .urb_enqueue = ehci_urb_enqueue, +- .urb_dequeue = ehci_urb_dequeue, +- .endpoint_disable = ehci_endpoint_disable, +- .endpoint_reset = ehci_endpoint_reset, ++static int __init ehci_omap_init(void) ++{ ++ if (usb_disabled()) ++ return -ENODEV; + +- /* +- * scheduling support +- */ +- .get_frame_number = ehci_get_frame, ++ pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +- /* +- * root hub support +- */ +- .hub_status_data = ehci_hub_status_data, +- .hub_control = ehci_hub_control, +- .bus_suspend = ehci_bus_suspend, +- .bus_resume = ehci_bus_resume, ++ ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); ++ return platform_driver_register(&ehci_hcd_omap_driver); ++} ++module_init(ehci_omap_init); + +- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +-}; ++static void __exit ehci_omap_cleanup(void) ++{ ++ platform_driver_unregister(&ehci_hcd_omap_driver); ++} ++module_exit(ehci_omap_cleanup); + + MODULE_ALIAS("platform:ehci-omap"); + MODULE_AUTHOR("Texas Instruments, Inc."); + MODULE_AUTHOR("Felipe Balbi "); + ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_LICENSE("GPL"); +-- +cgit v0.9.1 diff --git a/arm-tegra-fixclk.patch b/arm-tegra-fixclk.patch new file mode 100644 index 000000000..df0991293 --- /dev/null +++ b/arm-tegra-fixclk.patch @@ -0,0 +1,28 @@ +diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c +index 788486e..2f4d0e3 100644 +--- a/drivers/clk/tegra/clk-periph.c ++++ b/drivers/clk/tegra/clk-periph.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "clk.h" + +@@ -128,6 +129,7 @@ void tegra_periph_reset_deassert(struct clk *c) + + tegra_periph_reset(gate, 0); + } ++EXPORT_SYMBOL_GPL(tegra_periph_reset_deassert); + + void tegra_periph_reset_assert(struct clk *c) + { +@@ -147,6 +149,7 @@ void tegra_periph_reset_assert(struct clk *c) + + tegra_periph_reset(gate, 1); + } ++EXPORT_SYMBOL_GPL(tegra_periph_reset_assert); + + const struct clk_ops tegra_clk_periph_ops = { + .get_parent = clk_periph_get_parent, diff --git a/kernel.spec b/kernel.spec index 713ea3a83..beadf271f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -252,7 +252,7 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel up (versatile express), and tegra are only built on armv7 hfp/sfp +# kernel up (mutliplatform inc VExpress, highbank, omap), and tegra are only built on armv7 hfp/sfp %ifnarch armv7hl armv7l %define with_tegra 0 %endif @@ -715,9 +715,16 @@ Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM +Patch21000: arm-export-read_current_timer.patch +# https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-March/029029.html +Patch21001: arm-of-dma.patch + +# ARM omap +Patch21003: arm-omap-ehci-fix.patch # ARM tegra Patch21005: arm-tegra-usb-no-reset-linux33.patch +Patch21006: arm-tegra-fixclk.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1305,8 +1312,11 @@ ApplyPatch debug-bad-pte-modules.patch # # ARM # - +ApplyPatch arm-export-read_current_timer.patch +ApplyPatch arm-of-dma.patch +ApplyPatch arm-omap-ehci-fix.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch +ApplyPatch arm-tegra-fixclk.patch # # bugfixes to drivers and filesystems @@ -2284,6 +2294,9 @@ fi # ||----w | # || || %changelog +* Wed May 8 2013 Peter Robinson +- Add the ARM patches needed for 3.9 :-/ + * Wed May 08 2013 Josh Boyer - Don't remove headers explicitly exported via UAPI (rhbz 959467) From 9d5f83dd23e5ddc37d48c4afca1212557e873ecb Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 9 May 2013 22:47:33 +0100 Subject: [PATCH 322/492] Disable PL330 on ARM as it's broken on highbank --- config-armv7-generic | 3 ++- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-armv7-generic b/config-armv7-generic index abe4bdd1a..7b4d546c7 100644 --- a/config-armv7-generic +++ b/config-armv7-generic @@ -161,7 +161,8 @@ CONFIG_SERIAL_8250_DW=y CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y -CONFIG_PL330_DMA=m +# disable because it's currently broken on highbank :-/ +# CONFIG_PL330_DMA is not set CONFIG_AMBA_PL08X=y CONFIG_ARM_SP805_WATCHDOG=m CONFIG_I2C_VERSATILE=m diff --git a/kernel.spec b/kernel.spec index 24486c8ab..66a42e1a0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2294,6 +2294,9 @@ fi # ||----w | # || || %changelog +* Thu May 9 2013 Peter Robinson +- Disable PL330 on ARM as it's broken on highbank + * Wed May 8 2013 Peter Robinson - Add the ARM patches needed for 3.9 :-/ From e32be2554116559d927d870c73e4ed5aec3916d7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 10 May 2013 12:21:13 -0400 Subject: [PATCH 323/492] Linux 3.9.2-rc1 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 66a42e1a0..b72d675b9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,9 +74,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2294,6 +2294,9 @@ fi # ||----w | # || || %changelog +* Fri May 10 2013 Dave Jones - 3.9.2-0.rc1.200 +- Linux 3.9.2-rc1 + * Thu May 9 2013 Peter Robinson - Disable PL330 on ARM as it's broken on highbank diff --git a/sources b/sources index f74ebc7ea..2e5a4d061 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -66f171a17aa39b6dc6eb8bb51a4117c7 patch-3.9.1.xz +9b40baaff1f2487e95f975bd88ff8e05 patch-3.9.2-rc1.xz From 28a3cd9c35f4eae8e513b0fc8f7ca03efdfdcd03 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 10 May 2013 12:30:27 -0400 Subject: [PATCH 324/492] incremental, duh --- sources | 1 + 1 file changed, 1 insertion(+) diff --git a/sources b/sources index 2e5a4d061..677b3ca77 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz +66f171a17aa39b6dc6eb8bb51a4117c7 patch-3.9.1.xz 9b40baaff1f2487e95f975bd88ff8e05 patch-3.9.2-rc1.xz From acc1b9e2ce219c609ed690e5a2738411d8e3153f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 13 May 2013 09:44:07 -0400 Subject: [PATCH 325/492] Linux 3.9.2 --- kernel.spec | 5 ++++- sources | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index b72d675b9..1fb827bd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -76,7 +76,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 2 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2294,6 +2294,9 @@ fi # ||----w | # || || %changelog +* Mon May 13 2013 Dave Jones - 3.9.2-200 +- Linux 3.9.2 + * Fri May 10 2013 Dave Jones - 3.9.2-0.rc1.200 - Linux 3.9.2-rc1 diff --git a/sources b/sources index 677b3ca77..fcd96b534 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -66f171a17aa39b6dc6eb8bb51a4117c7 patch-3.9.1.xz -9b40baaff1f2487e95f975bd88ff8e05 patch-3.9.2-rc1.xz +adeb2556568f79e827e7a0ce4c483605 patch-3.9.2.xz From 033f53a432a7deca4e9a9164ab700b1a867d352e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 16 May 2013 10:40:24 -0400 Subject: [PATCH 326/492] Fix config-local usage (rhbz 950841) --- kernel.spec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 1fb827bd0..0b3ea0d05 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1276,14 +1276,12 @@ make -f %{SOURCE19} config-release make -f %{SOURCE20} VERSION=%{version} configs # Merge in any user-provided local config option changes -%if %{?all_arch_configs:1}%{!?all_arch_configs:0} -for i in %{all_arch_configs} +for i in kernel-%{version}-*.config do mv $i $i.tmp ./merge.pl %{SOURCE1000} $i.tmp > $i rm $i.tmp done -%endif ApplyPatch makefile-after_link.patch @@ -2294,6 +2292,9 @@ fi # ||----w | # || || %changelog +* Thu May 16 2013 Josh Boyer +- Fix config-local usage (rhbz 950841) + * Mon May 13 2013 Dave Jones - 3.9.2-200 - Linux 3.9.2 From 58f61257fc7ad9dedac183e1a26a6090fc77a3c1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 20 May 2013 08:33:56 -0400 Subject: [PATCH 327/492] Linux 3.9.3 --- arm-of-dma.patch | 43 ------------------------------------------- kernel.spec | 8 ++++---- sources | 2 +- 3 files changed, 5 insertions(+), 48 deletions(-) delete mode 100644 arm-of-dma.patch diff --git a/arm-of-dma.patch b/arm-of-dma.patch deleted file mode 100644 index c3223a4e6..000000000 --- a/arm-of-dma.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 7362f04c2888b14c20f8aaa02e1a897025261768 Mon Sep 17 00:00:00 2001 -From: Viresh Kumar -Date: Fri, 15 Mar 2013 08:48:20 +0000 -Subject: DMA: OF: Check properties value before running be32_to_cpup() on it - -In of_dma_controller_register() routine we are calling of_get_property() as an -parameter to be32_to_cpup(). In case the property doesn't exist we will get a -crash. - -This patch changes this code to check if we got a valid property first and then -runs be32_to_cpup() on it. - -Signed-off-by: Viresh Kumar -Signed-off-by: Vinod Koul ---- -diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c -index 6036cd0..00db454 100644 ---- a/drivers/dma/of-dma.c -+++ b/drivers/dma/of-dma.c -@@ -93,6 +93,7 @@ int of_dma_controller_register(struct device_node *np, - { - struct of_dma *ofdma; - int nbcells; -+ const __be32 *prop; - - if (!np || !of_dma_xlate) { - pr_err("%s: not enough information provided\n", __func__); -@@ -103,8 +104,11 @@ int of_dma_controller_register(struct device_node *np, - if (!ofdma) - return -ENOMEM; - -- nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL)); -- if (!nbcells) { -+ prop = of_get_property(np, "#dma-cells", NULL); -+ if (prop) -+ nbcells = be32_to_cpup(prop); -+ -+ if (!prop || !nbcells) { - pr_err("%s: #dma-cells property is missing or invalid\n", - __func__); - kfree(ofdma); --- -cgit v0.9.1 diff --git a/kernel.spec b/kernel.spec index 0b3ea0d05..9e7bf5d36 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -716,8 +716,6 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-export-read_current_timer.patch -# https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-March/029029.html -Patch21001: arm-of-dma.patch # ARM omap Patch21003: arm-omap-ehci-fix.patch @@ -1311,7 +1309,6 @@ ApplyPatch debug-bad-pte-modules.patch # ARM # ApplyPatch arm-export-read_current_timer.patch -ApplyPatch arm-of-dma.patch ApplyPatch arm-omap-ehci-fix.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-tegra-fixclk.patch @@ -2292,6 +2289,9 @@ fi # ||----w | # || || %changelog +* Mon May 20 2013 Josh Boyer - 3.9.3-200 +- Linux 3.9.3 + * Thu May 16 2013 Josh Boyer - Fix config-local usage (rhbz 950841) diff --git a/sources b/sources index fcd96b534..d004fc552 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -adeb2556568f79e827e7a0ce4c483605 patch-3.9.2.xz +71b31e29e0cb437a27017c781293b6f4 patch-3.9.3.xz From d03943819eeaba93ec973ea045876966d9735487 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 20 May 2013 10:31:40 -0400 Subject: [PATCH 328/492] Update s390x config now that F18 is on 3.9 --- config-s390x | 15 ++++++++++++--- kernel.spec | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/config-s390x b/config-s390x index c0ae0aa0a..9ab57f8aa 100644 --- a/config-s390x +++ b/config-s390x @@ -260,6 +260,15 @@ CONFIG_HOTPLUG_PCI_S390=m # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set -# CONFIG_PCI is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_PTP_1588_CLOCK_PCH is not set +# CONFIG_MEDIA_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_DRM is not set +# CONFIG_SOUND is not set +# CONFIG_DW_DMAC is not set +# CONFIG_I2C_SMBUS is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_NFORCE2 is not set + diff --git a/kernel.spec b/kernel.spec index 9e7bf5d36..a89b06a0b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2291,6 +2291,7 @@ fi %changelog * Mon May 20 2013 Josh Boyer - 3.9.3-200 - Linux 3.9.3 +- Update s390x config * Thu May 16 2013 Josh Boyer - Fix config-local usage (rhbz 950841) From ea06f6447b76874ea067854850a1c2fed4294917 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 21 May 2013 12:42:36 -0400 Subject: [PATCH 329/492] Fix modules-extra signing with 3.9 kernels (rhbz 965181) --- kernel.spec | 5 ++++- mod-extra-sign.sh | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index a89b06a0b..b0637357e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2289,6 +2289,9 @@ fi # ||----w | # || || %changelog +* Tue May 21 2013 Josh Boyer - 3.9.3-201 +- Fix modules-extra signing with 3.9 kernels (rhbz 965181) + * Mon May 20 2013 Josh Boyer - 3.9.3-200 - Linux 3.9.3 - Update s390x config diff --git a/mod-extra-sign.sh b/mod-extra-sign.sh index 9b24a4098..a6db8b5eb 100755 --- a/mod-extra-sign.sh +++ b/mod-extra-sign.sh @@ -21,7 +21,7 @@ do dir=`dirname $mod` file=`basename $mod` - ./scripts/sign-file ${MODSECKEY} ${MODPUBKEY} ${dir}/${file} \ + ./scripts/sign-file sha256 ${MODSECKEY} ${MODPUBKEY} ${dir}/${file} \ ${dir}/${file}.signed mv ${dir}/${file}.signed ${dir}/${file} rm -f ${dir}/${file}.{sig,dig} From 5d01e4986944da71da77a62a9d21705a417c1614 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 22 May 2013 08:22:02 -0400 Subject: [PATCH 330/492] Fix memset error in iwlwifi --- iwlwifi-dvm-fix-memset.patch | 39 ++++++++++++++++++++++++++++++++++++ kernel.spec | 9 ++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-dvm-fix-memset.patch diff --git a/iwlwifi-dvm-fix-memset.patch b/iwlwifi-dvm-fix-memset.patch new file mode 100644 index 000000000..ef063f2a9 --- /dev/null +++ b/iwlwifi-dvm-fix-memset.patch @@ -0,0 +1,39 @@ +From: Emmanuel Grumbach + +In 63b77bf489881747c5118476918cc8c29378ee63 + + iwlwifi: dvm: don't send zeroed LQ cmd + +I tried to avoid to send zeroed LQ cmd, but I made a (very) +stupid mistake in the memcmp. +Since this patch has been ported to stable, the fix should +go to stable too. + +This fixes https://bugzilla.kernel.org/show_bug.cgi?id=58341 + +Change-Id: I0af4b3fdd537a1f674e85eb02dc0f5b5ac1ee7ac +Cc: stable@vger.kernel.org +Reported-by: Hinnerk van Bruinehsen +Signed-off-by: Emmanuel Grumbach +--- +Josh, this fix ugly -stable 3.8, 3.9 regression, please apply. + + drivers/net/wireless/iwlwifi/dvm/sta.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c +index 5175368..8212097 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/sta.c ++++ b/drivers/net/wireless/iwlwifi/dvm/sta.c +@@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + memcpy(&lq, priv->stations[i].lq, + sizeof(struct iwl_link_quality_cmd)); + +- if (!memcmp(&lq, &zero_lq, sizeof(lq))) ++ if (memcmp(&lq, &zero_lq, sizeof(lq))) + send_lq = true; + } + spin_unlock_bh(&priv->sta_lock); +-- +1.7.10.4 + diff --git a/kernel.spec b/kernel.spec index b0637357e..0e7f57a81 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -753,6 +753,8 @@ Patch25001: i7300_edac_single_mode_fixup.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch +Patch25022: iwlwifi-dvm-fix-memset.patch + # END OF PATCH DEFINITIONS %endif @@ -1444,6 +1446,8 @@ ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch +ApplyPatch iwlwifi-dvm-fix-memset.patch + # END OF PATCH APPLICATIONS %endif @@ -2289,6 +2293,9 @@ fi # ||----w | # || || %changelog +* Wed May 22 2013 Josh Boyer +- Fix memset error in iwlwifi + * Tue May 21 2013 Josh Boyer - 3.9.3-201 - Fix modules-extra signing with 3.9 kernels (rhbz 965181) From 08acba8d9c216f98215260828bbdcd0cca7afbaa Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 22 May 2013 09:47:27 -0400 Subject: [PATCH 331/492] memcmp, not memset. I promise I read the code before I applied the patch. --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 0e7f57a81..60eaf1f77 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2294,7 +2294,7 @@ fi # || || %changelog * Wed May 22 2013 Josh Boyer -- Fix memset error in iwlwifi +- Fix memcmp error in iwlwifi * Tue May 21 2013 Josh Boyer - 3.9.3-201 - Fix modules-extra signing with 3.9 kernels (rhbz 965181) From afcba0a0efc35494e4c414d83e8d132cc380c65b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 23 May 2013 16:12:08 -0400 Subject: [PATCH 332/492] Fix oops from incorrect rfkill set in hp-wmi (rhbz 964367) --- hp-wmi-fix-incorrect-rfkill-set-hw-state.patch | 13 +++++++++++++ kernel.spec | 11 ++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 hp-wmi-fix-incorrect-rfkill-set-hw-state.patch diff --git a/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch b/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch new file mode 100644 index 000000000..07f27b6c2 --- /dev/null +++ b/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c +index 8df0c5a..d111c86 100644 +--- a/drivers/platform/x86/hp-wmi.c ++++ b/drivers/platform/x86/hp-wmi.c +@@ -703,7 +703,7 @@ static int hp_wmi_rfkill_setup(struct platform_device *device) + } + rfkill_init_sw_state(gps_rfkill, + hp_wmi_get_sw_state(HPWMI_GPS)); +- rfkill_set_hw_state(bluetooth_rfkill, ++ rfkill_set_hw_state(gps_rfkill, + hp_wmi_get_hw_state(HPWMI_GPS)); + err = rfkill_register(gps_rfkill); + if (err) diff --git a/kernel.spec b/kernel.spec index 60eaf1f77..08cc60980 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -755,6 +755,9 @@ Patch25007: fix-child-thread-introspection.patch Patch25022: iwlwifi-dvm-fix-memset.patch +#rhbz 964367 +Patch25023: hp-wmi-fix-incorrect-rfkill-set-hw-state.patch + # END OF PATCH DEFINITIONS %endif @@ -1448,6 +1451,9 @@ ApplyPatch fix-child-thread-introspection.patch ApplyPatch iwlwifi-dvm-fix-memset.patch +#rhbz 964367 +ApplyPatch hp-wmi-fix-incorrect-rfkill-set-hw-state.patch + # END OF PATCH APPLICATIONS %endif @@ -2293,6 +2299,9 @@ fi # ||----w | # || || %changelog +* Thu May 23 2013 Josh Boyer +- Fix oops from incorrect rfkill set in hp-wmi (rhbz 964367) + * Wed May 22 2013 Josh Boyer - Fix memcmp error in iwlwifi From b51f2e35a85686fb1d1b2cbb2a8a6a2858b38894 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 24 May 2013 12:58:52 -0400 Subject: [PATCH 333/492] Add patch to quiet irq remapping failures (rhbz 948262) --- ...ning-if-enabling-irq-remapping-fails.patch | 25 +++++++++++++++++++ kernel.spec | 9 +++++++ 2 files changed, 34 insertions(+) create mode 100644 intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch diff --git a/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch b/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch new file mode 100644 index 000000000..424d60350 --- /dev/null +++ b/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch @@ -0,0 +1,25 @@ +This triggers on a MacBook Pro. + +Signed-off-by: Andy Lutomirski +https://bugzilla.redhat.com/show_bug.cgi?id=948262 +--- + drivers/iommu/intel_irq_remapping.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c +index f3b8f23..a7e0ad1 100644 +--- a/drivers/iommu/intel_irq_remapping.c ++++ b/drivers/iommu/intel_irq_remapping.c +@@ -654,8 +654,7 @@ error: + */ + + if (x2apic_present) +- WARN(1, KERN_WARNING +- "Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); ++ pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); + + return -1; + } +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 08cc60980..27079d050 100644 --- a/kernel.spec +++ b/kernel.spec @@ -758,6 +758,9 @@ Patch25022: iwlwifi-dvm-fix-memset.patch #rhbz 964367 Patch25023: hp-wmi-fix-incorrect-rfkill-set-hw-state.patch +#rhbz 948262 +Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch + # END OF PATCH DEFINITIONS %endif @@ -1454,6 +1457,9 @@ ApplyPatch iwlwifi-dvm-fix-memset.patch #rhbz 964367 ApplyPatch hp-wmi-fix-incorrect-rfkill-set-hw-state.patch +#rhbz 948262 +ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch + # END OF PATCH APPLICATIONS %endif @@ -2299,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Fri May 24 2013 Josh Boyer +- Add patch to quiet irq remapping failures (rhbz 948262) + * Thu May 23 2013 Josh Boyer - Fix oops from incorrect rfkill set in hp-wmi (rhbz 964367) From 805d0e40adc3f86c9b1894dd10e3b5eef5d81afd Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 24 May 2013 14:42:54 -0500 Subject: [PATCH 334/492] Linux v3.9.4 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 27079d050..bd2f8dc93 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2305,6 +2305,9 @@ fi # ||----w | # || || %changelog +* Fri May 24 2013 Justin M. Forbes - 3.9.4-200 +- Linux v3.9.4 + * Fri May 24 2013 Josh Boyer - Add patch to quiet irq remapping failures (rhbz 948262) diff --git a/sources b/sources index d004fc552..50d708523 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -71b31e29e0cb437a27017c781293b6f4 patch-3.9.3.xz +922c4553299e6692a28761d3032fc012 patch-3.9.4.xz From 4ae24030286eaea8f61fd1005edb1474226a73bd Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 31 May 2013 07:33:17 -0400 Subject: [PATCH 335/492] CVE-2013-2850 iscsi-target: heap buffer overflow on large key error (rhbz 968036 969272) --- ...et-fix-heap-buffer-overflow-on-error.patch | 63 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 72 insertions(+) create mode 100644 iscsi-target-fix-heap-buffer-overflow-on-error.patch diff --git a/iscsi-target-fix-heap-buffer-overflow-on-error.patch b/iscsi-target-fix-heap-buffer-overflow-on-error.patch new file mode 100644 index 000000000..7b368122d --- /dev/null +++ b/iscsi-target-fix-heap-buffer-overflow-on-error.patch @@ -0,0 +1,63 @@ +From cea4dcfdad926a27a18e188720efe0f2c9403456 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Thu, 23 May 2013 17:32:17 +0000 +Subject: iscsi-target: fix heap buffer overflow on error + +If a key was larger than 64 bytes, as checked by iscsi_check_key(), the +error response packet, generated by iscsi_add_notunderstood_response(), +would still attempt to copy the entire key into the packet, overflowing +the structure on the heap. + +Remote preauthentication kernel memory corruption was possible if a +target was configured and listening on the network. + +CVE-2013-2850 + +Signed-off-by: Kees Cook +Cc: stable@vger.kernel.org +Signed-off-by: Nicholas Bellinger +--- +diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c +index c2185fc..e382221 100644 +--- a/drivers/target/iscsi/iscsi_target_parameters.c ++++ b/drivers/target/iscsi/iscsi_target_parameters.c +@@ -758,9 +758,9 @@ static int iscsi_add_notunderstood_response( + } + INIT_LIST_HEAD(&extra_response->er_list); + +- strncpy(extra_response->key, key, strlen(key) + 1); +- strncpy(extra_response->value, NOTUNDERSTOOD, +- strlen(NOTUNDERSTOOD) + 1); ++ strlcpy(extra_response->key, key, sizeof(extra_response->key)); ++ strlcpy(extra_response->value, NOTUNDERSTOOD, ++ sizeof(extra_response->value)); + + list_add_tail(&extra_response->er_list, + ¶m_list->extra_response_list); +@@ -1629,8 +1629,6 @@ int iscsi_decode_text_input( + + if (phase & PHASE_SECURITY) { + if (iscsi_check_for_auth_key(key) > 0) { +- char *tmpptr = key + strlen(key); +- *tmpptr = '='; + kfree(tmpbuf); + return 1; + } +diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h +index 915b067..a47046a 100644 +--- a/drivers/target/iscsi/iscsi_target_parameters.h ++++ b/drivers/target/iscsi/iscsi_target_parameters.h +@@ -1,8 +1,10 @@ + #ifndef ISCSI_PARAMETERS_H + #define ISCSI_PARAMETERS_H + ++#include ++ + struct iscsi_extra_response { +- char key[64]; ++ char key[KEY_MAXLEN]; + char value[32]; + struct list_head er_list; + } ____cacheline_aligned; +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index bd2f8dc93..1ca55c041 100644 --- a/kernel.spec +++ b/kernel.spec @@ -761,6 +761,9 @@ Patch25023: hp-wmi-fix-incorrect-rfkill-set-hw-state.patch #rhbz 948262 Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch +#CVE-2013-2850 rhbz 968036 969272 +Patch25025: iscsi-target-fix-heap-buffer-overflow-on-error.patch + # END OF PATCH DEFINITIONS %endif @@ -1460,6 +1463,9 @@ ApplyPatch hp-wmi-fix-incorrect-rfkill-set-hw-state.patch #rhbz 948262 ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch +#CVE-2013-2850 rhbz 968036 969272 +ApplyPatch iscsi-target-fix-heap-buffer-overflow-on-error.patch + # END OF PATCH APPLICATIONS %endif @@ -2305,6 +2311,9 @@ fi # ||----w | # || || %changelog +* Fri May 31 2013 Josh Boyer +- CVE-2013-2850 iscsi-target: heap buffer overflow on large key error (rhbz 968036 969272) + * Fri May 24 2013 Justin M. Forbes - 3.9.4-200 - Linux v3.9.4 From 342e72364ae91a115b6e5540e8260f26b836d6d8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Jun 2013 19:05:22 -0400 Subject: [PATCH 336/492] Fix UEFI anti-bricking code (rhbz 964335) --- Modify-UEFI-anti-bricking-code.patch | 371 +++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 Modify-UEFI-anti-bricking-code.patch diff --git a/Modify-UEFI-anti-bricking-code.patch b/Modify-UEFI-anti-bricking-code.patch new file mode 100644 index 000000000..862574556 --- /dev/null +++ b/Modify-UEFI-anti-bricking-code.patch @@ -0,0 +1,371 @@ +From 2380baac8b96f6e93ef72135d1b60d686d7f82e6 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sat, 1 Jun 2013 16:06:20 -0400 +Subject: [PATCH] Modify UEFI anti-bricking code + +This patch reworks the UEFI anti-bricking code, including an effective +reversion of cc5a080c and 31ff2f20. It turns out that calling +QueryVariableInfo() from boot services results in some firmware +implementations jumping to physical addresses even after entering virtual +mode, so until we have 1:1 mappings for UEFI runtime space this isn't +going to work so well. + +Reverting these gets us back to the situation where we'd refuse to create +variables on some systems because they classify deleted variables as "used" +until the firmware triggers a garbage collection run, which they won't do +until they reach a lower threshold. This results in it being impossible to +install a bootloader, which is unhelpful. + +Feedback from Samsung indicates that the firmware doesn't need more than +5KB of storage space for its own purposes, so that seems like a reasonable +threshold. However, there's still no guarantee that a platform will attempt +garbage collection merely because it drops below this threshold. It seems +that this is often only triggered if an attempt to write generates a +genuine EFI_OUT_OF_RESOURCES error. We can force that by attempting to +create a variable larger than the remaining space. This should fail, but if +it somehow succeeds we can then immediately delete it. + +I've tested this on the UEFI machines I have available, but I don't have +a Samsung and so can't verify that it avoids the bricking problem. + +Signed-off-by: Matthew Garrett +--- + arch/x86/boot/compressed/eboot.c | 47 ---------- + arch/x86/include/asm/efi.h | 7 -- + arch/x86/include/uapi/asm/bootparam.h | 1 - + arch/x86/platform/efi/efi.c | 167 +++++++++------------------------- + 4 files changed, 44 insertions(+), 178 deletions(-) + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 35ee62f..c205035 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -251,51 +251,6 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size) + *size = len; + } + +-static efi_status_t setup_efi_vars(struct boot_params *params) +-{ +- struct setup_data *data; +- struct efi_var_bootdata *efidata; +- u64 store_size, remaining_size, var_size; +- efi_status_t status; +- +- if (sys_table->runtime->hdr.revision < EFI_2_00_SYSTEM_TABLE_REVISION) +- return EFI_UNSUPPORTED; +- +- data = (struct setup_data *)(unsigned long)params->hdr.setup_data; +- +- while (data && data->next) +- data = (struct setup_data *)(unsigned long)data->next; +- +- status = efi_call_phys4((void *)sys_table->runtime->query_variable_info, +- EFI_VARIABLE_NON_VOLATILE | +- EFI_VARIABLE_BOOTSERVICE_ACCESS | +- EFI_VARIABLE_RUNTIME_ACCESS, &store_size, +- &remaining_size, &var_size); +- +- if (status != EFI_SUCCESS) +- return status; +- +- status = efi_call_phys3(sys_table->boottime->allocate_pool, +- EFI_LOADER_DATA, sizeof(*efidata), &efidata); +- +- if (status != EFI_SUCCESS) +- return status; +- +- efidata->data.type = SETUP_EFI_VARS; +- efidata->data.len = sizeof(struct efi_var_bootdata) - +- sizeof(struct setup_data); +- efidata->data.next = 0; +- efidata->store_size = store_size; +- efidata->remaining_size = remaining_size; +- efidata->max_var_size = var_size; +- +- if (data) +- data->next = (unsigned long)efidata; +- else +- params->hdr.setup_data = (unsigned long)efidata; +- +-} +- + static efi_status_t setup_efi_pci(struct boot_params *params) + { + efi_pci_io_protocol *pci; +@@ -1202,8 +1157,6 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, + + setup_graphics(boot_params); + +- setup_efi_vars(boot_params); +- + setup_efi_pci(boot_params); + + status = efi_call_phys3(sys_table->boottime->allocate_pool, +diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h +index 2fb5d58..60c89f3 100644 +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -102,13 +102,6 @@ extern void efi_call_phys_epilog(void); + extern void efi_unmap_memmap(void); + extern void efi_memory_uc(u64 addr, unsigned long size); + +-struct efi_var_bootdata { +- struct setup_data data; +- u64 store_size; +- u64 remaining_size; +- u64 max_var_size; +-}; +- + #ifdef CONFIG_EFI + + static inline bool efi_is_native(void) +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 0874424..c15ddaf 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -6,7 +6,6 @@ + #define SETUP_E820_EXT 1 + #define SETUP_DTB 2 + #define SETUP_PCI 3 +-#define SETUP_EFI_VARS 4 + + /* ram_size flags */ + #define RAMDISK_IMAGE_START_MASK 0x07FF +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index e4a86a6..beb5d5f 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -41,7 +41,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -52,13 +51,6 @@ + + #define EFI_DEBUG 1 + +-/* +- * There's some additional metadata associated with each +- * variable. Intel's reference implementation is 60 bytes - bump that +- * to account for potential alignment constraints +- */ +-#define VAR_METADATA_SIZE 64 +- + struct efi __read_mostly efi = { + .mps = EFI_INVALID_TABLE_ADDR, + .acpi = EFI_INVALID_TABLE_ADDR, +@@ -77,13 +69,6 @@ struct efi_memory_map memmap; + static struct efi efi_phys __initdata; + static efi_system_table_t efi_systab __initdata; + +-static u64 efi_var_store_size; +-static u64 efi_var_remaining_size; +-static u64 efi_var_max_var_size; +-static u64 boot_used_size; +-static u64 boot_var_size; +-static u64 active_size; +- + unsigned long x86_efi_facility; + + /* +@@ -186,53 +171,8 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *vendor) + { +- efi_status_t status; +- static bool finished = false; +- static u64 var_size; +- +- status = efi_call_virt3(get_next_variable, ++ return efi_call_virt3(get_next_variable, + name_size, name, vendor); +- +- if (status == EFI_NOT_FOUND) { +- finished = true; +- if (var_size < boot_used_size) { +- boot_var_size = boot_used_size - var_size; +- active_size += boot_var_size; +- } else { +- printk(KERN_WARNING FW_BUG "efi: Inconsistent initial sizes\n"); +- } +- } +- +- if (boot_used_size && !finished) { +- unsigned long size; +- u32 attr; +- efi_status_t s; +- void *tmp; +- +- s = virt_efi_get_variable(name, vendor, &attr, &size, NULL); +- +- if (s != EFI_BUFFER_TOO_SMALL || !size) +- return status; +- +- tmp = kmalloc(size, GFP_ATOMIC); +- +- if (!tmp) +- return status; +- +- s = virt_efi_get_variable(name, vendor, &attr, &size, tmp); +- +- if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) { +- var_size += size; +- var_size += ucs2_strsize(name, 1024); +- active_size += size; +- active_size += VAR_METADATA_SIZE; +- active_size += ucs2_strsize(name, 1024); +- } +- +- kfree(tmp); +- } +- +- return status; + } + + static efi_status_t virt_efi_set_variable(efi_char16_t *name, +@@ -241,34 +181,9 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, + unsigned long data_size, + void *data) + { +- efi_status_t status; +- u32 orig_attr = 0; +- unsigned long orig_size = 0; +- +- status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size, +- NULL); +- +- if (status != EFI_BUFFER_TOO_SMALL) +- orig_size = 0; +- +- status = efi_call_virt5(set_variable, +- name, vendor, attr, +- data_size, data); +- +- if (status == EFI_SUCCESS) { +- if (orig_size) { +- active_size -= orig_size; +- active_size -= ucs2_strsize(name, 1024); +- active_size -= VAR_METADATA_SIZE; +- } +- if (data_size) { +- active_size += data_size; +- active_size += ucs2_strsize(name, 1024); +- active_size += VAR_METADATA_SIZE; +- } +- } +- +- return status; ++ return efi_call_virt5(set_variable, ++ name, vendor, attr, ++ data_size, data); + } + + static efi_status_t virt_efi_query_variable_info(u32 attr, +@@ -776,9 +691,6 @@ void __init efi_init(void) + char vendor[100] = "unknown"; + int i = 0; + void *tmp; +- struct setup_data *data; +- struct efi_var_bootdata *efi_var_data; +- u64 pa_data; + + #ifdef CONFIG_X86_32 + if (boot_params.efi_info.efi_systab_hi || +@@ -796,22 +708,6 @@ void __init efi_init(void) + if (efi_systab_init(efi_phys.systab)) + return; + +- pa_data = boot_params.hdr.setup_data; +- while (pa_data) { +- data = early_ioremap(pa_data, sizeof(*efi_var_data)); +- if (data->type == SETUP_EFI_VARS) { +- efi_var_data = (struct efi_var_bootdata *)data; +- +- efi_var_store_size = efi_var_data->store_size; +- efi_var_remaining_size = efi_var_data->remaining_size; +- efi_var_max_var_size = efi_var_data->max_var_size; +- } +- pa_data = data->next; +- early_iounmap(data, sizeof(*efi_var_data)); +- } +- +- boot_used_size = efi_var_store_size - efi_var_remaining_size; +- + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); + + /* +@@ -1131,28 +1027,53 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) + if (status != EFI_SUCCESS) + return status; + +- if (!max_size && remaining_size > size) +- printk_once(KERN_ERR FW_BUG "Broken EFI implementation" +- " is returning MaxVariableSize=0\n"); + /* + * Some firmware implementations refuse to boot if there's insufficient + * space in the variable store. We account for that by refusing the + * write if permitting it would reduce the available space to under +- * 50%. However, some firmware won't reclaim variable space until +- * after the used (not merely the actively used) space drops below +- * a threshold. We can approximate that case with the value calculated +- * above. If both the firmware and our calculations indicate that the +- * available space would drop below 50%, refuse the write. ++ * 5KB. This figure was provided by Samsung, so should be safe. + */ ++ if ((remaining_size - size < 5120) && !efi_no_storage_paranoia) { ++ /* ++ * Triggering garbage collection may require that the firmware ++ * generate a real EFI_OUT_OF_RESOURCES error. We can force ++ * that by attempting to use more space than is available. ++ */ ++ unsigned long dummy_size = remaining_size + 1024; ++ void *dummy = kmalloc(dummy_size, GFP_ATOMIC); ++ efi_char16_t efi_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; ++ efi_guid_t guid = EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, ++ 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, ++ 0xa9); ++ ++ status = efi.set_variable(efi_name, &guid, attributes, ++ dummy_size, dummy); ++ ++ if (status == EFI_SUCCESS) { ++ /* ++ * This should have failed, so if it didn't make sure ++ * that we delete it... ++ */ ++ efi.set_variable(efi_name, &guid, attributes, 0, ++ dummy); ++ } + +- if (!storage_size || size > remaining_size || +- (max_size && size > max_size)) +- return EFI_OUT_OF_RESOURCES; ++ /* ++ * The runtime code may now have triggered a garbage collection ++ * run, so check the variable info again ++ */ ++ status = efi.query_variable_info(attributes, &storage_size, ++ &remaining_size, &max_size); + +- if (!efi_no_storage_paranoia && +- ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) && +- (remaining_size - size < storage_size / 2))) +- return EFI_OUT_OF_RESOURCES; ++ if (status != EFI_SUCCESS) ++ return status; ++ ++ /* ++ * There still isn't enough room, so return an error ++ */ ++ if (remaining_size - size < 5120) ++ return EFI_OUT_OF_RESOURCES; ++ } + + return EFI_SUCCESS; + } +-- +1.8.1.4 + diff --git a/kernel.spec b/kernel.spec index 1ca55c041..a803f0b44 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -764,6 +764,9 @@ Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.pa #CVE-2013-2850 rhbz 968036 969272 Patch25025: iscsi-target-fix-heap-buffer-overflow-on-error.patch +#rhbz 964335 +Patch25026: Modify-UEFI-anti-bricking-code.patch + # END OF PATCH DEFINITIONS %endif @@ -1466,6 +1469,9 @@ ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.pat #CVE-2013-2850 rhbz 968036 969272 ApplyPatch iscsi-target-fix-heap-buffer-overflow-on-error.patch +#rhbz 964335 +ApplyPatch Modify-UEFI-anti-bricking-code.patch + # END OF PATCH APPLICATIONS %endif @@ -2311,6 +2317,9 @@ fi # ||----w | # || || %changelog +* Mon Jun 03 2013 Josh Boyer +- Fix UEFI anti-bricking code (rhbz 964335) + * Fri May 31 2013 Josh Boyer - CVE-2013-2850 iscsi-target: heap buffer overflow on large key error (rhbz 968036 969272) From 3339e89a99ef573c48740630b390e38f333d9b19 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 5 Jun 2013 16:10:51 -0400 Subject: [PATCH 337/492] CVE-2013-2140 xen: blkback: insufficient permission checks for BLKIF_OP_DISCARD (rhbz 971146 971148) --- kernel.spec | 11 +++- ...k-device-permissions-before-allowing.patch | 54 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 xen-blkback-Check-device-permissions-before-allowing.patch diff --git a/kernel.spec b/kernel.spec index a803f0b44..e9f1ea445 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -767,6 +767,9 @@ Patch25025: iscsi-target-fix-heap-buffer-overflow-on-error.patch #rhbz 964335 Patch25026: Modify-UEFI-anti-bricking-code.patch +#CVE-2013-2140 rhbz 971146 971148 +Patch25031: xen-blkback-Check-device-permissions-before-allowing.patch + # END OF PATCH DEFINITIONS %endif @@ -1472,6 +1475,9 @@ ApplyPatch iscsi-target-fix-heap-buffer-overflow-on-error.patch #rhbz 964335 ApplyPatch Modify-UEFI-anti-bricking-code.patch +#CVE-2013-2140 rhbz 971146 971148 +ApplyPatch xen-blkback-Check-device-permissions-before-allowing.patch + # END OF PATCH APPLICATIONS %endif @@ -2317,6 +2323,9 @@ fi # ||----w | # || || %changelog +* Wed Jun 05 2013 Josh Boyer +- CVE-2013-2140 xen: blkback: insufficient permission checks for BLKIF_OP_DISCARD (rhbz 971146 971148) + * Mon Jun 03 2013 Josh Boyer - Fix UEFI anti-bricking code (rhbz 964335) diff --git a/xen-blkback-Check-device-permissions-before-allowing.patch b/xen-blkback-Check-device-permissions-before-allowing.patch new file mode 100644 index 000000000..933e82890 --- /dev/null +++ b/xen-blkback-Check-device-permissions-before-allowing.patch @@ -0,0 +1,54 @@ +From e029d62efa5eb46831a9e1414468e582379b743f Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 16 Jan 2013 11:33:52 -0500 +Subject: [PATCH] xen/blkback: Check device permissions before allowing + OP_DISCARD + +We need to make sure that the device is not RO or that +the request is not past the number of sectors we want to +issue the DISCARD operation for. + +Cc: stable () vger kernel org +Acked-by: Jan Beulich +Acked-by: Ian Campbell +[v1: Made it pr_warn instead of pr_debug] +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/block/xen-blkback/blkback.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index e79ab45..4119bcd 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -876,7 +876,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif, + int status = BLKIF_RSP_OKAY; + struct block_device *bdev = blkif->vbd.bdev; + unsigned long secure; ++ struct phys_req preq; ++ ++ preq.sector_number = req->u.discard.sector_number; ++ preq.nr_sects = req->u.discard.nr_sectors; + ++ err = xen_vbd_translate(&preq, blkif, WRITE); ++ if (err) { ++ pr_warn(DRV_PFX "access denied: DISCARD [%llu->%llu] on dev=%04x\n", ++ preq.sector_number, ++ preq.sector_number + preq.nr_sects, blkif->vbd.pdevice); ++ goto fail_response; ++ } + blkif->st_ds_req++; + + xen_blkif_get(blkif); +@@ -887,7 +898,7 @@ static int dispatch_discard_io(struct xen_blkif *blkif, + err = blkdev_issue_discard(bdev, req->u.discard.sector_number, + req->u.discard.nr_sectors, + GFP_KERNEL, secure); +- ++fail_response: + if (err == -EOPNOTSUPP) { + pr_debug(DRV_PFX "discard op failed, not supported\n"); + status = BLKIF_RSP_EOPNOTSUPP; +-- +1.8.1.4 + From aec19f244689338841defe8ca92779df18ce4359 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 6 Jun 2013 08:20:24 -0400 Subject: [PATCH 338/492] CVE-2013-2147 cpqarray/cciss: information leak via ioctl (rhbz 971242 971249) --- cve-2013-2147-ciss-info-leak.patch | 27 +++++++++++++++++++++++++++ kernel.spec | 9 +++++++++ 2 files changed, 36 insertions(+) create mode 100644 cve-2013-2147-ciss-info-leak.patch diff --git a/cve-2013-2147-ciss-info-leak.patch b/cve-2013-2147-ciss-info-leak.patch new file mode 100644 index 000000000..ee49d3bfb --- /dev/null +++ b/cve-2013-2147-ciss-info-leak.patch @@ -0,0 +1,27 @@ +diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c +index 639d26b..2b94403 100644 +--- a/drivers/block/cpqarray.c ++++ b/drivers/block/cpqarray.c +@@ -1193,6 +1193,7 @@ out_passthru: + ida_pci_info_struct pciinfo; + + if (!arg) return -EINVAL; ++ memset(&pciinfo, 0, sizeof(pciinfo)); + pciinfo.bus = host->pci_dev->bus->number; + pciinfo.dev_fn = host->pci_dev->devfn; + pciinfo.board_id = host->board_id; + + diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index 6374dc1..34971aa 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -1201,6 +1201,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, + int err; + u32 cp; + ++ memset(&arg64, 0, sizeof(arg64)); + err = 0; + err |= + copy_from_user(&arg64.LUN_info, &arg32->LUN_info, + + \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index e9f1ea445..b11dd1bed 100644 --- a/kernel.spec +++ b/kernel.spec @@ -770,6 +770,9 @@ Patch25026: Modify-UEFI-anti-bricking-code.patch #CVE-2013-2140 rhbz 971146 971148 Patch25031: xen-blkback-Check-device-permissions-before-allowing.patch +#CVE-2013-2147 rhbz 971242 971249 +Patch25032: cve-2013-2147-ciss-info-leak.patch + # END OF PATCH DEFINITIONS %endif @@ -1478,6 +1481,9 @@ ApplyPatch Modify-UEFI-anti-bricking-code.patch #CVE-2013-2140 rhbz 971146 971148 ApplyPatch xen-blkback-Check-device-permissions-before-allowing.patch +#CVE-2013-2147 rhbz 971242 971249 +ApplyPatch cve-2013-2147-ciss-info-leak.patch + # END OF PATCH APPLICATIONS %endif @@ -2323,6 +2329,9 @@ fi # ||----w | # || || %changelog +* Thu Jun 06 2013 Josh Boyer +- CVE-2013-2147 cpqarray/cciss: information leak via ioctl (rhbz 971242 971249) + * Wed Jun 05 2013 Josh Boyer - CVE-2013-2140 xen: blkback: insufficient permission checks for BLKIF_OP_DISCARD (rhbz 971146 971148) From 21d95660dd5b585622a581325901b05e41c9ef9e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 6 Jun 2013 08:24:07 -0400 Subject: [PATCH 339/492] CVE-2013-2148 fanotify: info leak in copy_event_to_user (rhbz 971258 971261) --- fanotify-info-leak-in-copy_event_to_user.patch | 14 ++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 fanotify-info-leak-in-copy_event_to_user.patch diff --git a/fanotify-info-leak-in-copy_event_to_user.patch b/fanotify-info-leak-in-copy_event_to_user.patch new file mode 100644 index 000000000..92b218b1c --- /dev/null +++ b/fanotify-info-leak-in-copy_event_to_user.patch @@ -0,0 +1,14 @@ +diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c +index 6c80083..77cc85d 100644 +--- a/fs/notify/fanotify/fanotify_user.c ++++ b/fs/notify/fanotify/fanotify_user.c +@@ -122,6 +122,7 @@ static int fill_event_metadata(struct fsnotify_group *group, + metadata->event_len = FAN_EVENT_METADATA_LEN; + metadata->metadata_len = FAN_EVENT_METADATA_LEN; + metadata->vers = FANOTIFY_METADATA_VERSION; ++ metadata->reserved = 0; + metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS; + metadata->pid = pid_vnr(event->tgid); + if (unlikely(event->mask & FAN_Q_OVERFLOW)) + + \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index b11dd1bed..f92c1fb32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -773,6 +773,9 @@ Patch25031: xen-blkback-Check-device-permissions-before-allowing.patch #CVE-2013-2147 rhbz 971242 971249 Patch25032: cve-2013-2147-ciss-info-leak.patch +#CVE-2013-2148 rhbz 971258 971261 +Patch25033: fanotify-info-leak-in-copy_event_to_user.patch + # END OF PATCH DEFINITIONS %endif @@ -1484,6 +1487,9 @@ ApplyPatch xen-blkback-Check-device-permissions-before-allowing.patch #CVE-2013-2147 rhbz 971242 971249 ApplyPatch cve-2013-2147-ciss-info-leak.patch +#CVE-2013-2148 rhbz 971258 971261 +ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch + # END OF PATCH APPLICATIONS %endif @@ -2330,6 +2336,7 @@ fi # || || %changelog * Thu Jun 06 2013 Josh Boyer +- CVE-2013-2148 fanotify: info leak in copy_event_to_user (rhbz 971258 971261) - CVE-2013-2147 cpqarray/cciss: information leak via ioctl (rhbz 971242 971249) * Wed Jun 05 2013 Josh Boyer From 4c6eb690b86035cd7767181f485e69cba7cd4e1b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 7 Jun 2013 08:15:42 -0400 Subject: [PATCH 340/492] CVE-2013-2852 b43: format string leaking into error msgs (rhbz 969518 971665) --- ...ormat-string-leaking-into-error-msgs.patch | 32 +++++++++++++++++++ kernel.spec | 9 ++++++ 2 files changed, 41 insertions(+) create mode 100644 b43-stop-format-string-leaking-into-error-msgs.patch diff --git a/b43-stop-format-string-leaking-into-error-msgs.patch b/b43-stop-format-string-leaking-into-error-msgs.patch new file mode 100644 index 000000000..84249e5eb --- /dev/null +++ b/b43-stop-format-string-leaking-into-error-msgs.patch @@ -0,0 +1,32 @@ +From 9538cbaab6e8b8046039b4b2eb6c9d614dc782bd Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 10 May 2013 21:48:21 +0000 +Subject: b43: stop format string leaking into error msgs + +The module parameter "fwpostfix" is userspace controllable, unfiltered, +and is used to define the firmware filename. b43_do_request_fw() populates +ctx->errors[] on error, containing the firmware filename. b43err() +parses its arguments as a format string. For systems with b43 hardware, +this could lead to a uid-0 to ring-0 escalation. + +CVE-2013-2852 + +Signed-off-by: Kees Cook +Cc: stable@vger.kernel.org +Signed-off-by: John W. Linville +--- +diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c +index 6dd07e2..a95b77a 100644 +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2458,7 +2458,7 @@ static void b43_request_firmware(struct work_struct *work) + for (i = 0; i < B43_NR_FWTYPES; i++) { + errmsg = ctx->errors[i]; + if (strlen(errmsg)) +- b43err(dev->wl, errmsg); ++ b43err(dev->wl, "%s", errmsg); + } + b43_print_fw_helptext(dev->wl, 1); + goto out; +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index f92c1fb32..403477d04 100644 --- a/kernel.spec +++ b/kernel.spec @@ -776,6 +776,9 @@ Patch25032: cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 Patch25033: fanotify-info-leak-in-copy_event_to_user.patch +#CVE-2013-2852 rhbz 969518 971665 +Patch25034: b43-stop-format-string-leaking-into-error-msgs.patch + # END OF PATCH DEFINITIONS %endif @@ -1490,6 +1493,9 @@ ApplyPatch cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch +#CVE-2013-2852 rhbz 969518 971665 +ApplyPatch b43-stop-format-string-leaking-into-error-msgs.patch + # END OF PATCH APPLICATIONS %endif @@ -2335,6 +2341,9 @@ fi # ||----w | # || || %changelog +* Fri Jun 07 2013 Josh Boyer +- CVE-2013-2852 b43: format string leaking into error msgs (rhbz 969518 971665) + * Thu Jun 06 2013 Josh Boyer - CVE-2013-2148 fanotify: info leak in copy_event_to_user (rhbz 971258 971261) - CVE-2013-2147 cpqarray/cciss: information leak via ioctl (rhbz 971242 971249) From 33c1a67054b5670c59b021e8ca5d730a17195f84 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 7 Jun 2013 08:23:01 -0400 Subject: [PATCH 341/492] CVE-2013-2851 block: passing disk names as format strings (rhbz 969515 971662) --- ...ot-pass-disk-names-as-format-strings.patch | 64 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 71 insertions(+) create mode 100644 block-do-not-pass-disk-names-as-format-strings.patch diff --git a/block-do-not-pass-disk-names-as-format-strings.patch b/block-do-not-pass-disk-names-as-format-strings.patch new file mode 100644 index 000000000..496111dcd --- /dev/null +++ b/block-do-not-pass-disk-names-as-format-strings.patch @@ -0,0 +1,64 @@ +Disk names may contain arbitrary strings, so they must not be interpreted +as format strings. It seems that only md allows arbitrary strings to be +used for disk names, but this could allow for a local memory corruption +from uid 0 into ring 0. + +CVE-2013-2851 + +Signed-off-by: Kees Cook +Cc: stable@vger.kernel.org +Cc: Jens Axboe +--- + block/genhd.c | 2 +- + drivers/block/nbd.c | 3 ++- + drivers/scsi/osd/osd_uld.c | 2 +- + 3 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/block/genhd.c b/block/genhd.c +index 20625ee..cdeb527 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -512,7 +512,7 @@ static void register_disk(struct gendisk *disk) + + ddev->parent = disk->driverfs_dev; + +- dev_set_name(ddev, disk->disk_name); ++ dev_set_name(ddev, "%s", disk->disk_name); + + /* delay uevents, until we scanned partition table */ + dev_set_uevent_suppress(ddev, 1); +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 037288e..46b35f7 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -714,7 +714,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, + else + blk_queue_flush(nbd->disk->queue, 0); + +- thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name); ++ thread = kthread_create(nbd_thread, nbd, "%s", ++ nbd->disk->disk_name); + if (IS_ERR(thread)) { + mutex_lock(&nbd->tx_lock); + return PTR_ERR(thread); +diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c +index 0fab6b5..9d86947 100644 +--- a/drivers/scsi/osd/osd_uld.c ++++ b/drivers/scsi/osd/osd_uld.c +@@ -485,7 +485,7 @@ static int osd_probe(struct device *dev) + oud->class_dev.class = &osd_uld_class; + oud->class_dev.parent = dev; + oud->class_dev.release = __remove; +- error = dev_set_name(&oud->class_dev, disk->disk_name); ++ error = dev_set_name(&oud->class_dev, "%s", disk->disk_name); + if (error) { + OSD_ERR("dev_set_name failed => %d\n", error); + goto err_put_cdev; +-- +1.7.9.5 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 403477d04..c7cf0c5ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,9 @@ Patch25033: fanotify-info-leak-in-copy_event_to_user.patch #CVE-2013-2852 rhbz 969518 971665 Patch25034: b43-stop-format-string-leaking-into-error-msgs.patch +#CVE-2013-2851 rhbz 969515 971662 +Patch25035: block-do-not-pass-disk-names-as-format-strings.patch + # END OF PATCH DEFINITIONS %endif @@ -1496,6 +1499,9 @@ ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch #CVE-2013-2852 rhbz 969518 971665 ApplyPatch b43-stop-format-string-leaking-into-error-msgs.patch +#CVE-2013-2851 rhbz 969515 971662 +ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch + # END OF PATCH APPLICATIONS %endif @@ -2342,6 +2348,7 @@ fi # || || %changelog * Fri Jun 07 2013 Josh Boyer +- CVE-2013-2851 block: passing disk names as format strings (rhbz 969515 971662) - CVE-2013-2852 b43: format string leaking into error msgs (rhbz 969518 971665) * Thu Jun 06 2013 Josh Boyer From a5e016d48a145fdcb111edb9e6e5071f90261739 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 10 Jun 2013 07:29:37 -0400 Subject: [PATCH 342/492] Linux v3.9.5 --- ...et-fix-heap-buffer-overflow-on-error.patch | 63 ------------------- iwlwifi-dvm-fix-memset.patch | 39 ------------ kernel.spec | 17 ++--- sources | 2 +- 4 files changed, 6 insertions(+), 115 deletions(-) delete mode 100644 iscsi-target-fix-heap-buffer-overflow-on-error.patch delete mode 100644 iwlwifi-dvm-fix-memset.patch diff --git a/iscsi-target-fix-heap-buffer-overflow-on-error.patch b/iscsi-target-fix-heap-buffer-overflow-on-error.patch deleted file mode 100644 index 7b368122d..000000000 --- a/iscsi-target-fix-heap-buffer-overflow-on-error.patch +++ /dev/null @@ -1,63 +0,0 @@ -From cea4dcfdad926a27a18e188720efe0f2c9403456 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Thu, 23 May 2013 17:32:17 +0000 -Subject: iscsi-target: fix heap buffer overflow on error - -If a key was larger than 64 bytes, as checked by iscsi_check_key(), the -error response packet, generated by iscsi_add_notunderstood_response(), -would still attempt to copy the entire key into the packet, overflowing -the structure on the heap. - -Remote preauthentication kernel memory corruption was possible if a -target was configured and listening on the network. - -CVE-2013-2850 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Signed-off-by: Nicholas Bellinger ---- -diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c -index c2185fc..e382221 100644 ---- a/drivers/target/iscsi/iscsi_target_parameters.c -+++ b/drivers/target/iscsi/iscsi_target_parameters.c -@@ -758,9 +758,9 @@ static int iscsi_add_notunderstood_response( - } - INIT_LIST_HEAD(&extra_response->er_list); - -- strncpy(extra_response->key, key, strlen(key) + 1); -- strncpy(extra_response->value, NOTUNDERSTOOD, -- strlen(NOTUNDERSTOOD) + 1); -+ strlcpy(extra_response->key, key, sizeof(extra_response->key)); -+ strlcpy(extra_response->value, NOTUNDERSTOOD, -+ sizeof(extra_response->value)); - - list_add_tail(&extra_response->er_list, - ¶m_list->extra_response_list); -@@ -1629,8 +1629,6 @@ int iscsi_decode_text_input( - - if (phase & PHASE_SECURITY) { - if (iscsi_check_for_auth_key(key) > 0) { -- char *tmpptr = key + strlen(key); -- *tmpptr = '='; - kfree(tmpbuf); - return 1; - } -diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h -index 915b067..a47046a 100644 ---- a/drivers/target/iscsi/iscsi_target_parameters.h -+++ b/drivers/target/iscsi/iscsi_target_parameters.h -@@ -1,8 +1,10 @@ - #ifndef ISCSI_PARAMETERS_H - #define ISCSI_PARAMETERS_H - -+#include -+ - struct iscsi_extra_response { -- char key[64]; -+ char key[KEY_MAXLEN]; - char value[32]; - struct list_head er_list; - } ____cacheline_aligned; --- -cgit v0.9.2 diff --git a/iwlwifi-dvm-fix-memset.patch b/iwlwifi-dvm-fix-memset.patch deleted file mode 100644 index ef063f2a9..000000000 --- a/iwlwifi-dvm-fix-memset.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Emmanuel Grumbach - -In 63b77bf489881747c5118476918cc8c29378ee63 - - iwlwifi: dvm: don't send zeroed LQ cmd - -I tried to avoid to send zeroed LQ cmd, but I made a (very) -stupid mistake in the memcmp. -Since this patch has been ported to stable, the fix should -go to stable too. - -This fixes https://bugzilla.kernel.org/show_bug.cgi?id=58341 - -Change-Id: I0af4b3fdd537a1f674e85eb02dc0f5b5ac1ee7ac -Cc: stable@vger.kernel.org -Reported-by: Hinnerk van Bruinehsen -Signed-off-by: Emmanuel Grumbach ---- -Josh, this fix ugly -stable 3.8, 3.9 regression, please apply. - - drivers/net/wireless/iwlwifi/dvm/sta.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c -index 5175368..8212097 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/sta.c -+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c -@@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - memcpy(&lq, priv->stations[i].lq, - sizeof(struct iwl_link_quality_cmd)); - -- if (!memcmp(&lq, &zero_lq, sizeof(lq))) -+ if (memcmp(&lq, &zero_lq, sizeof(lq))) - send_lq = true; - } - spin_unlock_bh(&priv->sta_lock); --- -1.7.10.4 - diff --git a/kernel.spec b/kernel.spec index c7cf0c5ff..dfad7ddbc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -753,17 +753,12 @@ Patch25001: i7300_edac_single_mode_fixup.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -Patch25022: iwlwifi-dvm-fix-memset.patch - #rhbz 964367 Patch25023: hp-wmi-fix-incorrect-rfkill-set-hw-state.patch #rhbz 948262 Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#CVE-2013-2850 rhbz 968036 969272 -Patch25025: iscsi-target-fix-heap-buffer-overflow-on-error.patch - #rhbz 964335 Patch25026: Modify-UEFI-anti-bricking-code.patch @@ -1473,17 +1468,12 @@ ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -ApplyPatch iwlwifi-dvm-fix-memset.patch - #rhbz 964367 ApplyPatch hp-wmi-fix-incorrect-rfkill-set-hw-state.patch #rhbz 948262 ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#CVE-2013-2850 rhbz 968036 969272 -ApplyPatch iscsi-target-fix-heap-buffer-overflow-on-error.patch - #rhbz 964335 ApplyPatch Modify-UEFI-anti-bricking-code.patch @@ -2347,6 +2337,9 @@ fi # ||----w | # || || %changelog +* Mon Jun 10 2013 Josh Boyer +- Linux v3.9.5 + * Fri Jun 07 2013 Josh Boyer - CVE-2013-2851 block: passing disk names as format strings (rhbz 969515 971662) - CVE-2013-2852 b43: format string leaking into error msgs (rhbz 969518 971665) diff --git a/sources b/sources index 50d708523..2e345eb6b 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -922c4553299e6692a28761d3032fc012 patch-3.9.4.xz +aa22187ae5cd482a69097e9e59244491 patch-3.9.5.xz From c7995c2f976bbd1db81a486043a70e5e510a39d2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 10 Jun 2013 10:04:12 -0400 Subject: [PATCH 343/492] Add patch to fix 3.9.5 build on powerpc --- kernel.spec | 6 ++++++ powerpc-3.9.5-fix.patch | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 powerpc-3.9.5-fix.patch diff --git a/kernel.spec b/kernel.spec index dfad7ddbc..caf85006c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -777,6 +777,9 @@ Patch25034: b43-stop-format-string-leaking-into-error-msgs.patch #CVE-2013-2851 rhbz 969515 971662 Patch25035: block-do-not-pass-disk-names-as-format-strings.patch +# Fix for build failure on powerpc in 3.9.5 +Patch25037: powerpc-3.9.5-fix.patch + # END OF PATCH DEFINITIONS %endif @@ -1492,6 +1495,9 @@ ApplyPatch b43-stop-format-string-leaking-into-error-msgs.patch #CVE-2013-2851 rhbz 969515 971662 ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch +# Fix for build failure on powerpc in 3.9.5 +ApplyPatch powerpc-3.9.5-fix.patch + # END OF PATCH APPLICATIONS %endif diff --git a/powerpc-3.9.5-fix.patch b/powerpc-3.9.5-fix.patch new file mode 100644 index 000000000..5cc7e4fa0 --- /dev/null +++ b/powerpc-3.9.5-fix.patch @@ -0,0 +1,13 @@ +diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c +index 1c22b2d..29857c6 100644 +--- a/arch/powerpc/kernel/traps.c ++++ b/arch/powerpc/kernel/traps.c +@@ -1151,7 +1151,7 @@ void alignment_exception(struct pt_regs *regs) + local_irq_enable(); + + if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT)) +- goto bail; ++ return; + + /* we don't implement logging of alignment exceptions */ + if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) From 6bb74174a1f70761fb7bdd7f71db17bf2e95aeb8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 10 Jun 2013 10:10:49 -0400 Subject: [PATCH 344/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index caf85006c..03cc5243b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2343,7 +2343,7 @@ fi # ||----w | # || || %changelog -* Mon Jun 10 2013 Josh Boyer +* Mon Jun 10 2013 Josh Boyer - 3.9.5-200 - Linux v3.9.5 * Fri Jun 07 2013 Josh Boyer From 2bd4b145657cf49c1826b2e0f08b05d916958dad Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Jun 2013 08:06:36 -0400 Subject: [PATCH 345/492] CVE-2013-2164 information leak in cdrom driver (rhbz 973100 973109) --- cdrom-use-kzalloc-for-failing-hardware.patch | 45 ++++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 cdrom-use-kzalloc-for-failing-hardware.patch diff --git a/cdrom-use-kzalloc-for-failing-hardware.patch b/cdrom-use-kzalloc-for-failing-hardware.patch new file mode 100644 index 000000000..6afb6c4d8 --- /dev/null +++ b/cdrom-use-kzalloc-for-failing-hardware.patch @@ -0,0 +1,45 @@ +From 050e4b8fb7cdd7096c987a9cd556029c622c7fe2 Mon Sep 17 00:00:00 2001 +From: Jonathan Salwan +Date: Thu, 06 Jun 2013 00:39:39 +0000 +Subject: drivers/cdrom/cdrom.c: use kzalloc() for failing hardware + +In drivers/cdrom/cdrom.c mmc_ioctl_cdrom_read_data() allocates a memory +area with kmalloc in line 2885. + +2885 cgc->buffer = kmalloc(blocksize, GFP_KERNEL); +2886 if (cgc->buffer == NULL) +2887 return -ENOMEM; + +In line 2908 we can find the copy_to_user function: + +2908 if (!ret && copy_to_user(arg, cgc->buffer, blocksize)) + +The cgc->buffer is never cleaned and initialized before this function. If +ret = 0 with the previous basic block, it's possible to display some +memory bytes in kernel space from userspace. + +When we read a block from the disk it normally fills the ->buffer but if +the drive is malfunctioning there is a chance that it would only be +partially filled. The result is an leak information to userspace. + +Signed-off-by: Dan Carpenter +Cc: Jens Axboe +Signed-off-by: Andrew Morton +--- +(limited to 'drivers/cdrom/cdrom.c') + +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index d620b44..8a3aff7 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2882,7 +2882,7 @@ static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, + if (lba < 0) + return -EINVAL; + +- cgc->buffer = kmalloc(blocksize, GFP_KERNEL); ++ cgc->buffer = kzalloc(blocksize, GFP_KERNEL); + if (cgc->buffer == NULL) + return -ENOMEM; + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 03cc5243b..c60ce975d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -780,6 +780,9 @@ Patch25035: block-do-not-pass-disk-names-as-format-strings.patch # Fix for build failure on powerpc in 3.9.5 Patch25037: powerpc-3.9.5-fix.patch +#CVE-2013-2164 rhbz 973100 973109 +Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch + # END OF PATCH DEFINITIONS %endif @@ -1498,6 +1501,9 @@ ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch # Fix for build failure on powerpc in 3.9.5 ApplyPatch powerpc-3.9.5-fix.patch +#CVE-2013-2164 rhbz 973100 973109 +ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch + # END OF PATCH APPLICATIONS %endif @@ -2343,6 +2349,9 @@ fi # ||----w | # || || %changelog +* Tue Jun 11 2013 Josh Boyer +- CVE-2013-2164 information leak in cdrom driver (rhbz 973100 973109) + * Mon Jun 10 2013 Josh Boyer - 3.9.5-200 - Linux v3.9.5 From ce5fae0641cc7b51f5dd43ce2c4b00572d6e5bd0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Jun 2013 09:26:41 -0400 Subject: [PATCH 346/492] Add two patches to fix issues with vhost_net and macvlan (rhbz 954181) --- kernel.spec | 10 ++++ ...p-set-SOCK_ZEROCOPY-flag-during-open.patch | 26 ++++++++ ...trol-for-non-zerocopy-case-during-tx.patch | 60 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch create mode 100644 vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch diff --git a/kernel.spec b/kernel.spec index c60ce975d..9ba763479 100644 --- a/kernel.spec +++ b/kernel.spec @@ -783,6 +783,11 @@ Patch25037: powerpc-3.9.5-fix.patch #CVE-2013-2164 rhbz 973100 973109 Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch +#rhbz 954181 +Patch25039: vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch +Patch25040: tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch + + # END OF PATCH DEFINITIONS %endif @@ -1504,6 +1509,10 @@ ApplyPatch powerpc-3.9.5-fix.patch #CVE-2013-2164 rhbz 973100 973109 ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch +#rhbz 954181 +ApplyPatch vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch +ApplyPatch tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch + # END OF PATCH APPLICATIONS %endif @@ -2350,6 +2359,7 @@ fi # || || %changelog * Tue Jun 11 2013 Josh Boyer +- Add two patches to fix issues with vhost_net and macvlan (rhbz 954181) - CVE-2013-2164 information leak in cdrom driver (rhbz 973100 973109) * Mon Jun 10 2013 Josh Boyer - 3.9.5-200 diff --git a/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch b/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch new file mode 100644 index 000000000..75de6ccce --- /dev/null +++ b/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch @@ -0,0 +1,26 @@ +tuntap: set SOCK_ZEROCOPY flag during open + +Commit 54f968d6efdbf7dec36faa44fc11f01b0e4d1990 +(tuntap: move socket to tun_file) forgets to set SOCK_ZEROCOPY flag, which will +prevent vhost_net from doing zercopy w/ tap. This patch fixes this by setting +it during file open. + +Cc: Michael S. Tsirkin +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin + +--- + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 89776c5..ff5312d 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -2159,6 +2159,8 @@ static int tun_chr_open(struct inode *inode, struct file * file) + set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); + INIT_LIST_HEAD(&tfile->next); + ++ sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); ++ + return 0; + } + diff --git a/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch b/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch new file mode 100644 index 000000000..4455bbc0b --- /dev/null +++ b/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch @@ -0,0 +1,60 @@ +From 3add6ae9e1b854a9ddbe0dc17ff4ec48a2dac9fe Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Wed, 5 Jun 2013 07:40:46 +0000 +Subject: [PATCH] vhost_net: clear msg.control for non-zerocopy case during tx + +When we decide not use zero-copy, msg.control should be set to NULL otherwise +macvtap/tap may set zerocopy callbacks which may decrease the kref of ubufs +wrongly. + +Bug were introduced by commit cedb9bdce099206290a2bdd02ce47a7b253b6a84 +(vhost-net: skip head management if no outstanding). + +This solves the following warnings: + +WARNING: at include/linux/kref.h:47 handle_tx+0x477/0x4b0 [vhost_net]() +Modules linked in: vhost_net macvtap macvlan tun nfsd exportfs bridge stp llc openvswitch kvm_amd kvm bnx2 megaraid_sas [last unloaded: tun] +CPU: 5 PID: 8670 Comm: vhost-8668 Not tainted 3.10.0-rc2+ #1566 +Hardware name: Dell Inc. PowerEdge R715/00XHKG, BIOS 1.5.2 04/19/2011 +ffffffffa0198323 ffff88007c9ebd08 ffffffff81796b73 ffff88007c9ebd48 +ffffffff8103d66b 000000007b773e20 ffff8800779f0000 ffff8800779f43f0 +ffff8800779f8418 000000000000015c 0000000000000062 ffff88007c9ebd58 +Call Trace: +[] dump_stack+0x19/0x1e +[] warn_slowpath_common+0x6b/0xa0 +[] warn_slowpath_null+0x15/0x20 +[] handle_tx+0x477/0x4b0 [vhost_net] +[] handle_tx_kick+0x10/0x20 [vhost_net] +[] vhost_worker+0xfe/0x1a0 [vhost_net] +[] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net] +[] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net] +[] kthread+0xc6/0xd0 +[] ? kthread_freezable_should_stop+0x70/0x70 +[] ret_from_fork+0x7c/0xb0 +[] ? kthread_freezable_should_stop+0x70/0x70 + +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +--- + drivers/vhost/net.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index ec6fb3f..3980e66 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -353,7 +353,9 @@ static void handle_tx(struct vhost_net *net) + kref_get(&ubufs->kref); + } + vq->upend_idx = (vq->upend_idx + 1) % UIO_MAXIOV; +- } ++ } else ++ msg.msg_control = NULL; ++ + /* TODO: Check specific error and bomb out unless ENOBUFS? */ + err = sock->ops->sendmsg(NULL, sock, &msg, len); + if (unlikely(err < 0)) { +-- +1.8.1.4 + From d6d68e331d2fb6bc0af7e92ae91f5869108823db Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Jun 2013 14:51:35 -0400 Subject: [PATCH 347/492] Add patches to fix MTRR issues in 3.9.5 (rhbz 973185) --- kernel.spec | 8 ++ ...inal-mtrr-range-get-for-mtrr_cleanup.patch | 63 ++++++++++++++++ x86-range-make-add_range-use-blank-slot.patch | 73 +++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch create mode 100644 x86-range-make-add_range-use-blank-slot.patch diff --git a/kernel.spec b/kernel.spec index 9ba763479..536ae44c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -787,6 +787,9 @@ Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch Patch25039: vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch Patch25040: tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch +#rhbz 973185 +Patch25041: x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch +Patch25042: x86-range-make-add_range-use-blank-slot.patch # END OF PATCH DEFINITIONS @@ -1513,6 +1516,10 @@ ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch ApplyPatch vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch ApplyPatch tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch +#rhbz 973185 +ApplyPatch x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch +ApplyPatch x86-range-make-add_range-use-blank-slot.patch + # END OF PATCH APPLICATIONS %endif @@ -2359,6 +2366,7 @@ fi # || || %changelog * Tue Jun 11 2013 Josh Boyer +- Add patches to fix MTRR issues in 3.9.5 (rhbz 973185) - Add two patches to fix issues with vhost_net and macvlan (rhbz 954181) - CVE-2013-2164 information leak in cdrom driver (rhbz 973100 973109) diff --git a/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch b/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch new file mode 100644 index 000000000..7c8b930f7 --- /dev/null +++ b/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch @@ -0,0 +1,63 @@ +Joshua reported: Commit cd7b304dfaf1 (x86, range: fix missing merge +during add range) broke mtrr cleanup on his setup in 3.9.5. +corresponding commit in upstream is fbe06b7bae7c. + + *BAD*gran_size: 64K chunk_size: 16M num_reg: 6 lose cover RAM: -0G + +https://bugzilla.kernel.org/show_bug.cgi?id=59491 + +So it rejects new var mtrr layout. + +It turns out we have some problem with initial mtrr range retrievel. +current sequence is: + x86_get_mtrr_mem_range + ==> bunchs of add_range_with_merge + ==> bunchs of subract_range + ==> clean_sort_range + add_range_with_merge for [0,1M) + sort_range() + +add_range_with_merge could have blank slots, so we can not just +sort only, that will have final result have extra blank slot in head. + +So move that calling add_range_with_merge for [0,1M), with that we +could avoid extra clean_sort_range calling. + +Reported-by: Joshua Covington +Tested-by: Joshua Covington +Signed-off-by: Yinghai Lu +Cc: v3.9 + +--- + arch/x86/kernel/cpu/mtrr/cleanup.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +Index: linux-2.6/arch/x86/kernel/cpu/mtrr/cleanup.c +=================================================================== +--- linux-2.6.orig/arch/x86/kernel/cpu/mtrr/cleanup.c ++++ linux-2.6/arch/x86/kernel/cpu/mtrr/cleanup.c +@@ -714,15 +714,15 @@ int __init mtrr_cleanup(unsigned address + if (mtrr_tom2) + x_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - x_remove_base; + +- nr_range = x86_get_mtrr_mem_range(range, 0, x_remove_base, x_remove_size); + /* + * [0, 1M) should always be covered by var mtrr with WB + * and fixed mtrrs should take effect before var mtrr for it: + */ +- nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0, ++ nr_range = add_range_with_merge(range, RANGE_NUM, 0, 0, + 1ULL<<(20 - PAGE_SHIFT)); +- /* Sort the ranges: */ +- sort_range(range, nr_range); ++ /* add from var mtrr at last */ ++ nr_range = x86_get_mtrr_mem_range(range, nr_range, ++ x_remove_base, x_remove_size); + + range_sums = sum_ranges(range, nr_range); + printk(KERN_INFO "total RAM covered: %ldM\n", +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file diff --git a/x86-range-make-add_range-use-blank-slot.patch b/x86-range-make-add_range-use-blank-slot.patch new file mode 100644 index 000000000..8a04f4f5c --- /dev/null +++ b/x86-range-make-add_range-use-blank-slot.patch @@ -0,0 +1,73 @@ +Now add_range_with_merge will generate blank slot as subtract_range. +we could reach the array limit because of blank slots. + +We can let add_range to have second try to use blank slot. + +Also use WARN_ONCE to print trace. + +Reported-by: Joshua Covington +Signed-off-by: Yinghai Lu +Cc: v3.9 +--- + kernel/range.c | 34 ++++++++++++++++++++++------------ + 1 file changed, 22 insertions(+), 12 deletions(-) + +diff --git a/kernel/range.c b/kernel/range.c +index 98883ed..8ca718a 100644 +--- a/kernel/range.c ++++ b/kernel/range.c +@@ -3,23 +3,34 @@ + */ + #include + #include ++#include + #include +- + #include + + int add_range(struct range *range, int az, int nr_range, u64 start, u64 end) + { +- if (start >= end) +- return nr_range; ++ int i; + +- /* Out of slots: */ +- if (nr_range >= az) ++ if (start >= end) + return nr_range; + +- range[nr_range].start = start; +- range[nr_range].end = end; ++ /* Out of slots ? */ ++ if (nr_range < az) { ++ i = nr_range; ++ nr_range++; ++ } else { ++ /* find blank slot */ ++ for (i = 0; i < az; i++) ++ if (!range[i].end) ++ break; ++ if (i == az) { ++ WARN_ONCE(1, "run out of slot in ranges\n"); ++ return az; ++ } ++ } + +- nr_range++; ++ range[i].start = start; ++ range[i].end = end; + + return nr_range; + } +@@ -99,7 +110,7 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) + range[i].end = range[j].end; + range[i].start = end; + } else { +- printk(KERN_ERR "run of slot in ranges\n"); ++ WARN_ONCE(1,"run of slot in ranges\n"); + } + range[j].end = start; + continue; +-- +1.8.1.4 + From 6bca20346138aac5737d2cf6f4f7e7038d66d395 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Jun 2013 15:21:06 -0400 Subject: [PATCH 348/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 536ae44c6..0411fef69 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2365,7 +2365,7 @@ fi # ||----w | # || || %changelog -* Tue Jun 11 2013 Josh Boyer +* Tue Jun 11 2013 Josh Boyer - 3.9.5-201 - Add patches to fix MTRR issues in 3.9.5 (rhbz 973185) - Add two patches to fix issues with vhost_net and macvlan (rhbz 954181) - CVE-2013-2164 information leak in cdrom driver (rhbz 973100 973109) From 729afc3f1a2ea5ab68e25f2caf13c0fed85d800e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Jun 2013 07:31:43 -0400 Subject: [PATCH 349/492] Add fix for rt5390/rt3290 regression (rhbz 950735) --- kernel.spec | 9 +++ ...-RT3290-TX-power-settings-regression.patch | 71 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch diff --git a/kernel.spec b/kernel.spec index 0411fef69..f45ef9d65 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch25040: tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch Patch25041: x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch Patch25042: x86-range-make-add_range-use-blank-slot.patch +#rhbz 950735 +Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch + # END OF PATCH DEFINITIONS %endif @@ -1520,6 +1523,9 @@ ApplyPatch tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch ApplyPatch x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch ApplyPatch x86-range-make-add_range-use-blank-slot.patch +#rhbz 950735 +ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch + # END OF PATCH APPLICATIONS %endif @@ -2365,6 +2371,9 @@ fi # ||----w | # || || %changelog +* Wed Jun 12 2013 Josh Boyer +- Add fix for rt5390/rt3290 regression (rhbz 950735) + * Tue Jun 11 2013 Josh Boyer - 3.9.5-201 - Add patches to fix MTRR issues in 3.9.5 (rhbz 973185) - Add two patches to fix issues with vhost_net and macvlan (rhbz 954181) diff --git a/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch b/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch new file mode 100644 index 000000000..354873950 --- /dev/null +++ b/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch @@ -0,0 +1,71 @@ +My change: + +commit cee2c7315f60beeff6137ee59e99acc77d636eeb +Author: Stanislaw Gruszka +Date: Fri Oct 5 13:44:09 2012 +0200 + + rt2800: use BBP_R1 for setting tx power + +unfortunately does not work well with RT5390 and RT3290 chips as they +require different temperature compensation TX power settings (TSSI +tuning). Since that commit make wireless connection very unstable on +those chips, restore previous behavior to fix regression. Once we +implement proper TSSI tuning on 5390/3290 we can restore back setting +TX power by BBP_R1 register for those chips. + +Reported-and-tested-by: Mike Romberg +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 29 ++++++++++++++++++----------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 92849e5..8b679df 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -2634,19 +2634,26 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, + * TODO: we do not use +6 dBm option to do not increase power beyond + * regulatory limit, however this could be utilized for devices with + * CAPABILITY_POWER_LIMIT. ++ * ++ * TODO: add different temperature compensation code for RT3290 & RT5390 ++ * to allow to use BBP_R1 for those chips. + */ +- rt2800_bbp_read(rt2x00dev, 1, &r1); +- if (delta <= -12) { +- power_ctrl = 2; +- delta += 12; +- } else if (delta <= -6) { +- power_ctrl = 1; +- delta += 6; +- } else { +- power_ctrl = 0; ++ if (!rt2x00_rt(rt2x00dev, RT3290) && ++ !rt2x00_rt(rt2x00dev, RT5390)) { ++ rt2800_bbp_read(rt2x00dev, 1, &r1); ++ if (delta <= -12) { ++ power_ctrl = 2; ++ delta += 12; ++ } else if (delta <= -6) { ++ power_ctrl = 1; ++ delta += 6; ++ } else { ++ power_ctrl = 0; ++ } ++ rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); ++ rt2800_bbp_write(rt2x00dev, 1, r1); + } +- rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); +- rt2800_bbp_write(rt2x00dev, 1, r1); ++ + offset = TX_PWR_CFG_0; + + for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { +-- +1.7.11.7 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From c98aa694c6040528621049d0ed9e7e9a183cbe7a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Jun 2013 07:37:50 -0400 Subject: [PATCH 350/492] Fix KVM divide by zero error (rhbz 969644) --- ...andle-idiv-overflow-at-kvm_write_tsc.patch | 45 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch diff --git a/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch b/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch new file mode 100644 index 000000000..678e82953 --- /dev/null +++ b/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -0,0 +1,45 @@ +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 094b5d9..64a4b03 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1194,20 +1194,37 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) + elapsed = ns - kvm->arch.last_tsc_nsec; + + if (vcpu->arch.virtual_tsc_khz) { ++ int faulted = 0; ++ + /* n.b - signed multiplication and division required */ + usdiff = data - kvm->arch.last_tsc_write; + #ifdef CONFIG_X86_64 + usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; + #else + /* do_div() only does unsigned */ +- asm("idivl %2; xor %%edx, %%edx" +- : "=A"(usdiff) +- : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); ++ asm("1: idivl %[divisor]\n" ++ "2: xor %%edx, %%edx\n" ++ " movl $0, %[faulted]\n" ++ "3:\n" ++ ".section .fixup,\"ax\"\n" ++ "4: movl $1, %[faulted]\n" ++ " jmp 3b\n" ++ ".previous\n" ++ ++ _ASM_EXTABLE(1b, 4b) ++ ++ : "=A"(usdiff), [faulted] "=r" (faulted) ++ : "A"(usdiff * 1000), [divisor] "rm"(vcpu->arch.virtual_tsc_khz)); ++ + #endif + do_div(elapsed, 1000); + usdiff -= elapsed; + if (usdiff < 0) + usdiff = -usdiff; ++ ++ /* idivl overflow => difference is larger than USEC_PER_SEC */ ++ if (faulted) ++ usdiff = USEC_PER_SEC; + } else + usdiff = USEC_PER_SEC; /* disable TSC match window below */ + diff --git a/kernel.spec b/kernel.spec index f45ef9d65..4b70af71e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -794,6 +794,9 @@ Patch25042: x86-range-make-add_range-use-blank-slot.patch #rhbz 950735 Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch +#rhbz 969644 +Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch + # END OF PATCH DEFINITIONS %endif @@ -1526,6 +1529,9 @@ ApplyPatch x86-range-make-add_range-use-blank-slot.patch #rhbz 950735 ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch +#rhbz 969644 +ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch + # END OF PATCH APPLICATIONS %endif @@ -2372,6 +2378,7 @@ fi # || || %changelog * Wed Jun 12 2013 Josh Boyer +- Fix KVM divide by zero error (rhbz 969644) - Add fix for rt5390/rt3290 regression (rhbz 950735) * Tue Jun 11 2013 Josh Boyer - 3.9.5-201 From 73be2dc284d363c12733cde91668c88a4abff10c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 13 Jun 2013 14:40:28 -0400 Subject: [PATCH 351/492] Linux v3.9.6 --- ...mi-fix-incorrect-rfkill-set-hw-state.patch | 13 ------------- kernel.spec | 19 +++++-------------- sources | 2 +- 3 files changed, 6 insertions(+), 28 deletions(-) delete mode 100644 hp-wmi-fix-incorrect-rfkill-set-hw-state.patch diff --git a/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch b/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch deleted file mode 100644 index 07f27b6c2..000000000 --- a/hp-wmi-fix-incorrect-rfkill-set-hw-state.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c -index 8df0c5a..d111c86 100644 ---- a/drivers/platform/x86/hp-wmi.c -+++ b/drivers/platform/x86/hp-wmi.c -@@ -703,7 +703,7 @@ static int hp_wmi_rfkill_setup(struct platform_device *device) - } - rfkill_init_sw_state(gps_rfkill, - hp_wmi_get_sw_state(HPWMI_GPS)); -- rfkill_set_hw_state(bluetooth_rfkill, -+ rfkill_set_hw_state(gps_rfkill, - hp_wmi_get_hw_state(HPWMI_GPS)); - err = rfkill_register(gps_rfkill); - if (err) diff --git a/kernel.spec b/kernel.spec index 4b70af71e..3491d21c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -753,9 +753,6 @@ Patch25001: i7300_edac_single_mode_fixup.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -#rhbz 964367 -Patch25023: hp-wmi-fix-incorrect-rfkill-set-hw-state.patch - #rhbz 948262 Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch @@ -777,9 +774,6 @@ Patch25034: b43-stop-format-string-leaking-into-error-msgs.patch #CVE-2013-2851 rhbz 969515 971662 Patch25035: block-do-not-pass-disk-names-as-format-strings.patch -# Fix for build failure on powerpc in 3.9.5 -Patch25037: powerpc-3.9.5-fix.patch - #CVE-2013-2164 rhbz 973100 973109 Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch @@ -1488,9 +1482,6 @@ ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -#rhbz 964367 -ApplyPatch hp-wmi-fix-incorrect-rfkill-set-hw-state.patch - #rhbz 948262 ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch @@ -1512,9 +1503,6 @@ ApplyPatch b43-stop-format-string-leaking-into-error-msgs.patch #CVE-2013-2851 rhbz 969515 971662 ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch -# Fix for build failure on powerpc in 3.9.5 -ApplyPatch powerpc-3.9.5-fix.patch - #CVE-2013-2164 rhbz 973100 973109 ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch @@ -2377,6 +2365,9 @@ fi # ||----w | # || || %changelog +* Thu Jun 13 2013 Josh Boyer - 3.9.6-200 +- Linux v3.9.6 + * Wed Jun 12 2013 Josh Boyer - Fix KVM divide by zero error (rhbz 969644) - Add fix for rt5390/rt3290 regression (rhbz 950735) diff --git a/sources b/sources index 2e345eb6b..803d88c2a 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -aa22187ae5cd482a69097e9e59244491 patch-3.9.5.xz +897cffc5167a561b38c6748e7f0a4215 patch-3.9.6.xz From 7c4fd19bb462defc869bc34fa6bc890d5a206c34 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 18 Jun 2013 13:05:51 -0400 Subject: [PATCH 352/492] Disable MTRR sanitizer by default. --- config-x86-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-x86-generic b/config-x86-generic index d8084b246..89bb5b0ef 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -29,7 +29,7 @@ CONFIG_PNP=y CONFIG_MTRR=y CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 CONFIG_X86_PAT=y CONFIG_X86_PM_TIMER=y diff --git a/kernel.spec b/kernel.spec index 3491d21c6..75b194477 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2365,6 +2365,9 @@ fi # ||----w | # || || %changelog +* Tue Jun 18 2013 Dave Jones +- Disable MTRR sanitizer by default. + * Thu Jun 13 2013 Josh Boyer - 3.9.6-200 - Linux v3.9.6 From c2c10b0fabdb35f6dc9f417f163750cea0e72c41 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 19 Jun 2013 14:43:29 -0300 Subject: [PATCH 353/492] Add support for nct677x sensors found on Asus Z77 motherboards Backport the existing driver found on Kernel 3.10-rc6, on those changesets: 169c05c hwmon: (nct6775) Do not create non-existing attributes 6445e66 hwmon: (nct6775) Fix coding style problems 6d4b362 hwmon: (nct6775) Constify strings c409fd4 hwmon: (nct6775) Use ARRAY_SIZE for loops where possible 573728c hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776 2c7fd30 hwmon: (nct6775) Expand scope of supported chips 236d903 hwmon: (nct6775) Drop read/write lock 0fc1f8f hwmon: (nct6775) Only report VID if supported and enabled 8e9285b hwmon: (nct6775) Detect and report additional temperature sources bbd8dec hwmon: (nct6775) Add support for weighted fan control cdcaece hwmon: (nct6775) Add support for automatic fan control 77eb5b3 hwmon: (nct6775) Add support for pwm, pwm_mode, and pwm_enable 84d19d9 hwmon: (nct6775) Add power management support 47ece96 hwmon: (nct6775) Add support for fan debounce module parameter 5c25d95 hwmon: (nct6775) Add support for fanX_pulses sysfs attribute 1c65dc3 hwmon: (nct6775) Add support for fan speed attributes aa136e5 hwmon: (nct6775) Add support for temperature sensors a6bd587 hwmon: (nct6775) Add case open detection 9de2e2e hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D Signed-off-by: Mauro Carvalho Chehab --- config-generic | 1 + drivers-hwmon-nct6775.patch | 6424 +++++++++++++++++++++++++++++++++++ kernel.spec | 9 + 3 files changed, 6434 insertions(+) create mode 100644 drivers-hwmon-nct6775.patch diff --git a/config-generic b/config-generic index 92827f15d..8b4cf7afd 100644 --- a/config-generic +++ b/config-generic @@ -2309,6 +2309,7 @@ CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m CONFIG_SENSORS_MAX6697=m CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_NCT6775=m CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m diff --git a/drivers-hwmon-nct6775.patch b/drivers-hwmon-nct6775.patch new file mode 100644 index 000000000..f6ee15c8c --- /dev/null +++ b/drivers-hwmon-nct6775.patch @@ -0,0 +1,6424 @@ +Add support for nct6775.c + +This driver is needed on modern Asus motherboards like P8Z77-M PRO, and +other motherboards based on Z77 chipset. + +This patch folds the changes found on those 3.10-rc6 changesets: + +169c05c hwmon: (nct6775) Do not create non-existing attributes +6445e66 hwmon: (nct6775) Fix coding style problems +6d4b362 hwmon: (nct6775) Constify strings +c409fd4 hwmon: (nct6775) Use ARRAY_SIZE for loops where possible +573728c hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776 +2c7fd30 hwmon: (nct6775) Expand scope of supported chips +236d903 hwmon: (nct6775) Drop read/write lock +0fc1f8f hwmon: (nct6775) Only report VID if supported and enabled +8e9285b hwmon: (nct6775) Detect and report additional temperature sources +bbd8dec hwmon: (nct6775) Add support for weighted fan control +cdcaece hwmon: (nct6775) Add support for automatic fan control +77eb5b3 hwmon: (nct6775) Add support for pwm, pwm_mode, and pwm_enable +84d19d9 hwmon: (nct6775) Add power management support +47ece96 hwmon: (nct6775) Add support for fan debounce module parameter +5c25d95 hwmon: (nct6775) Add support for fanX_pulses sysfs attribute +1c65dc3 hwmon: (nct6775) Add support for fan speed attributes +aa136e5 hwmon: (nct6775) Add support for temperature sensors +a6bd587 hwmon: (nct6775) Add case open detection +9de2e2e hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D + +- + +From 9de2e2e84e7d52e4c2a9e1a1e21ab6ac686233c0 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 20 May 2012 19:29:48 -0700 +Subject: [PATCH] hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D + +This driver will replace the w83627ehf driver for NCT6775F and NCT6776F, +and provides support for NCT6779D. + +This patch provides support for voltage monitor attributes. + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +new file mode 100644 +index 0000000..ccfd5cc +--- /dev/null ++++ b/Documentation/hwmon/nct6775 +@@ -0,0 +1,81 @@ ++Note ++==== ++ ++This driver supersedes the NCT6775F and NCT6776F support in the W83627EHF ++driver. ++ ++Kernel driver NCT6775 ++===================== ++ ++Supported chips: ++ * Nuvoton NCT6775F/W83667HG-I ++ Prefix: 'nct6775' ++ Addresses scanned: ISA address retrieved from Super I/O registers ++ Datasheet: Available from Nuvoton upon request ++ * Nuvoton NCT6776F ++ Prefix: 'nct6776' ++ Addresses scanned: ISA address retrieved from Super I/O registers ++ Datasheet: Available from Nuvoton upon request ++ * Nuvoton NCT6779D ++ Prefix: 'nct6779' ++ Addresses scanned: ISA address retrieved from Super I/O registers ++ Datasheet: Available from Nuvoton upon request ++ ++Authors: ++ Guenter Roeck ++ ++Description ++----------- ++ ++This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D ++super I/O chips. ++ ++The chips support up to 25 temperature monitoring sources. Up to 6 of those are ++direct temperature sensor inputs, the others are special sources such as PECI, ++PCH, and SMBUS. Depending on the chip type, 2 to 6 of the temperature sources ++can be monitored and compared against minimum, maximum, and critical ++temperatures. The driver reports up to 10 of the temperatures to the user. ++There are 4 to 5 fan rotation speed sensors, 8 to 15 analog voltage sensors, ++one VID, alarms with beep warnings (control unimplemented), and some automatic ++fan regulation strategies (plus manual fan control mode). ++ ++The temperature sensor sources on all chips are configurable. The configured ++source for each of the temperature sensors is provided in tempX_label. ++ ++Temperatures are measured in degrees Celsius and measurement resolution is ++either 1 degC or 0.5 degC, depending on the temperature source and ++configuration. An alarm is triggered when the temperature gets higher than ++the high limit; it stays on until the temperature falls below the hysteresis ++value. Alarms are only supported for temp1 to temp6, depending on the chip type. ++ ++Fan rotation speeds are reported in RPM (rotations per minute). An alarm is ++triggered if the rotation speed has dropped below a programmable limit. On ++NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8, ++16, 32, 64 or 128) to give the readings more range or accuracy; the other chips ++do not have a fan speed divider. The driver sets the most suitable fan divisor ++itself; specifically, it doubles the divider value each time a fan speed reading ++returns an invalid value. Some fans might not be present because they share pins ++with other functions. ++ ++Voltage sensors (also known as IN sensors) report their values in millivolts. ++An alarm is triggered if the voltage has crossed a programmable minimum ++or maximum limit. ++ ++The driver supports automatic fan control mode known as Thermal Cruise. ++In this mode, the chip attempts to keep the measured temperature in a ++predefined temperature range. If the temperature goes out of range, fan ++is driven slower/faster to reach the predefined range again. ++ ++The mode works for fan1-fan5. ++ ++Usage Notes ++----------- ++ ++On various ASUS boards with NCT6776F, it appears that CPUTIN is not really ++connected to anything and floats, or that it is connected to some non-standard ++temperature measurement device. As a result, the temperature reported on CPUTIN ++will not reflect a usable value. It often reports unreasonably high ++temperatures, and in some cases the reported temperature declines if the actual ++temperature increases (similar to the raw PECI temperature value - see PECI ++specification for details). CPUTIN should therefore be be ignored on ASUS ++boards. The CPU temperature on ASUS boards is reported from PECI 0. +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 47d2176..a0f1d6a 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -897,6 +897,19 @@ config SENSORS_MCP3021 + This driver can also be built as a module. If so, the module + will be called mcp3021. + ++config SENSORS_NCT6775 ++ tristate "Nuvoton NCT6775F, NCT6776F, NCT6779D" ++ depends on !PPC ++ select HWMON_VID ++ help ++ If you say yes here you get support for the hardware monitoring ++ functionality of the Nuvoton NCT6775F, NCT6776F, and NCT6779D ++ Super-I/O chips. This driver replaces the w83627ehf driver for ++ NCT6775F and NCT6776F. ++ ++ This driver can also be built as a module. If so, the module ++ will be called nct6775. ++ + config SENSORS_NTC_THERMISTOR + tristate "NTC thermistor support" + depends on (!OF && !IIO) || (OF && IIO) +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index 5d36a57..8297572 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -105,6 +105,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o + obj-$(CONFIG_SENSORS_MAX6697) += max6697.o + obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o + obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o ++obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o + obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o + obj-$(CONFIG_SENSORS_PC87360) += pc87360.o + obj-$(CONFIG_SENSORS_PC87427) += pc87427.o +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +new file mode 100644 +index 0000000..f75cd82 +--- /dev/null ++++ b/drivers/hwmon/nct6775.c +@@ -0,0 +1,1021 @@ ++/* ++ * nct6775 - Driver for the hardware monitoring functionality of ++ * Nuvoton NCT677x Super-I/O chips ++ * ++ * Copyright (C) 2012 Guenter Roeck ++ * ++ * Derived from w83627ehf driver ++ * Copyright (C) 2005-2012 Jean Delvare ++ * Copyright (C) 2006 Yuan Mu (Winbond), ++ * Rudolf Marek ++ * David Hubbard ++ * Daniel J Blueman ++ * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00) ++ * ++ * Shamelessly ripped from the w83627hf driver ++ * Copyright (C) 2003 Mark Studebaker ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * Supports the following chips: ++ * ++ * Chip #vin #fan #pwm #temp chip IDs man ID ++ * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3 ++ * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 ++ * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 ++ * ++ * #temp lists the number of monitored temperature sources (first value) plus ++ * the number of directly connectable temperature sensors (second value). ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lm75.h" ++ ++enum kinds { nct6775, nct6776, nct6779 }; ++ ++/* used to set data->name = nct6775_device_names[data->sio_kind] */ ++static const char * const nct6775_device_names[] = { ++ "nct6775", ++ "nct6776", ++ "nct6779", ++}; ++ ++static unsigned short force_id; ++module_param(force_id, ushort, 0); ++MODULE_PARM_DESC(force_id, "Override the detected device ID"); ++ ++#define DRVNAME "nct6775" ++ ++/* ++ * Super-I/O constants and functions ++ */ ++ ++#define NCT6775_LD_HWM 0x0b ++#define NCT6775_LD_VID 0x0d ++ ++#define SIO_REG_LDSEL 0x07 /* Logical device select */ ++#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ ++#define SIO_REG_ENABLE 0x30 /* Logical device enable */ ++#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ ++ ++#define SIO_NCT6775_ID 0xb470 ++#define SIO_NCT6776_ID 0xc330 ++#define SIO_NCT6779_ID 0xc560 ++#define SIO_ID_MASK 0xFFF0 ++ ++static inline void ++superio_outb(int ioreg, int reg, int val) ++{ ++ outb(reg, ioreg); ++ outb(val, ioreg + 1); ++} ++ ++static inline int ++superio_inb(int ioreg, int reg) ++{ ++ outb(reg, ioreg); ++ return inb(ioreg + 1); ++} ++ ++static inline void ++superio_select(int ioreg, int ld) ++{ ++ outb(SIO_REG_LDSEL, ioreg); ++ outb(ld, ioreg + 1); ++} ++ ++static inline int ++superio_enter(int ioreg) ++{ ++ /* ++ * Try to reserve and for exclusive access. ++ */ ++ if (!request_muxed_region(ioreg, 2, DRVNAME)) ++ return -EBUSY; ++ ++ outb(0x87, ioreg); ++ outb(0x87, ioreg); ++ ++ return 0; ++} ++ ++static inline void ++superio_exit(int ioreg) ++{ ++ outb(0xaa, ioreg); ++ outb(0x02, ioreg); ++ outb(0x02, ioreg + 1); ++ release_region(ioreg, 2); ++} ++ ++/* ++ * ISA constants ++ */ ++ ++#define IOREGION_ALIGNMENT (~7) ++#define IOREGION_OFFSET 5 ++#define IOREGION_LENGTH 2 ++#define ADDR_REG_OFFSET 0 ++#define DATA_REG_OFFSET 1 ++ ++#define NCT6775_REG_BANK 0x4E ++#define NCT6775_REG_CONFIG 0x40 ++ ++/* ++ * Not currently used: ++ * REG_MAN_ID has the value 0x5ca3 for all supported chips. ++ * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model. ++ * REG_MAN_ID is at port 0x4f ++ * REG_CHIP_ID is at port 0x58 ++ */ ++ ++#define NUM_REG_ALARM 4 /* Max number of alarm registers */ ++ ++/* Common and NCT6775 specific data */ ++ ++/* Voltage min/max registers for nr=7..14 are in bank 5 */ ++ ++static const u16 NCT6775_REG_IN_MAX[] = { ++ 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a, ++ 0x55c, 0x55e, 0x560, 0x562 }; ++static const u16 NCT6775_REG_IN_MIN[] = { ++ 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b, ++ 0x55d, 0x55f, 0x561, 0x563 }; ++static const u16 NCT6775_REG_IN[] = { ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552 ++}; ++ ++#define NCT6775_REG_VBAT 0x5D ++ ++static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; ++ ++/* 0..15 voltages, 16..23 fans, 24..31 temperatures */ ++ ++static const s8 NCT6775_ALARM_BITS[] = { ++ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ ++ 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ ++ -1, /* unused */ ++ 6, 7, 11, 10, 23, /* fan1..fan5 */ ++ -1, -1, -1, /* unused */ ++ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ ++ 12, -1 }; /* intrusion0, intrusion1 */ ++ ++/* NCT6776 specific data */ ++ ++static const s8 NCT6776_ALARM_BITS[] = { ++ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ ++ 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ ++ -1, /* unused */ ++ 6, 7, 11, 10, 23, /* fan1..fan5 */ ++ -1, -1, -1, /* unused */ ++ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ ++ 12, 9 }; /* intrusion0, intrusion1 */ ++ ++/* NCT6779 specific data */ ++ ++static const u16 NCT6779_REG_IN[] = { ++ 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, ++ 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e }; ++ ++static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = { ++ 0x459, 0x45A, 0x45B, 0x568 }; ++ ++static const s8 NCT6779_ALARM_BITS[] = { ++ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ ++ 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */ ++ -1, /* unused */ ++ 6, 7, 11, 10, 23, /* fan1..fan5 */ ++ -1, -1, -1, /* unused */ ++ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ ++ 12, 9 }; /* intrusion0, intrusion1 */ ++ ++/* ++ * Conversions ++ */ ++ ++/* ++ * Some of the voltage inputs have internal scaling, the tables below ++ * contain 8 (the ADC LSB in mV) * scaling factor * 100 ++ */ ++static const u16 scale_in[15] = { ++ 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800, ++ 800, 800 ++}; ++ ++static inline long in_from_reg(u8 reg, u8 nr) ++{ ++ return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100); ++} ++ ++static inline u8 in_to_reg(u32 val, u8 nr) ++{ ++ return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255); ++} ++ ++/* ++ * Data structures and manipulation thereof ++ */ ++ ++struct nct6775_data { ++ int addr; /* IO base of hw monitor block */ ++ enum kinds kind; ++ const char *name; ++ ++ struct device *hwmon_dev; ++ struct mutex lock; ++ ++ u16 REG_CONFIG; ++ u16 REG_VBAT; ++ ++ const s8 *ALARM_BITS; ++ ++ const u16 *REG_VIN; ++ const u16 *REG_IN_MINMAX[2]; ++ ++ const u16 *REG_ALARM; ++ ++ struct mutex update_lock; ++ bool valid; /* true if following fields are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ ++ /* Register values */ ++ u8 bank; /* current register bank */ ++ u8 in_num; /* number of in inputs we have */ ++ u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ ++ ++ u64 alarms; ++ ++ u8 vid; ++ u8 vrm; ++ ++ u16 have_in; ++}; ++ ++struct nct6775_sio_data { ++ int sioreg; ++ enum kinds kind; ++}; ++ ++static bool is_word_sized(struct nct6775_data *data, u16 reg) ++{ ++ switch (data->kind) { ++ case nct6775: ++ return (((reg & 0xff00) == 0x100 || ++ (reg & 0xff00) == 0x200) && ++ ((reg & 0x00ff) == 0x50 || ++ (reg & 0x00ff) == 0x53 || ++ (reg & 0x00ff) == 0x55)) || ++ (reg & 0xfff0) == 0x630 || ++ reg == 0x640 || reg == 0x642 || ++ reg == 0x662 || ++ ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) || ++ reg == 0x73 || reg == 0x75 || reg == 0x77; ++ case nct6776: ++ return (((reg & 0xff00) == 0x100 || ++ (reg & 0xff00) == 0x200) && ++ ((reg & 0x00ff) == 0x50 || ++ (reg & 0x00ff) == 0x53 || ++ (reg & 0x00ff) == 0x55)) || ++ (reg & 0xfff0) == 0x630 || ++ reg == 0x402 || ++ reg == 0x640 || reg == 0x642 || ++ ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) || ++ reg == 0x73 || reg == 0x75 || reg == 0x77; ++ case nct6779: ++ return reg == 0x150 || reg == 0x153 || reg == 0x155 || ++ ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) || ++ reg == 0x402 || ++ reg == 0x63a || reg == 0x63c || reg == 0x63e || ++ reg == 0x640 || reg == 0x642 || ++ reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 || ++ reg == 0x7b; ++ } ++ return false; ++} ++ ++/* ++ * On older chips, only registers 0x50-0x5f are banked. ++ * On more recent chips, all registers are banked. ++ * Assume that is the case and set the bank number for each access. ++ * Cache the bank number so it only needs to be set if it changes. ++ */ ++static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg) ++{ ++ u8 bank = reg >> 8; ++ if (data->bank != bank) { ++ outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET); ++ outb_p(bank, data->addr + DATA_REG_OFFSET); ++ data->bank = bank; ++ } ++} ++ ++static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) ++{ ++ int res, word_sized = is_word_sized(data, reg); ++ ++ mutex_lock(&data->lock); ++ ++ nct6775_set_bank(data, reg); ++ outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); ++ res = inb_p(data->addr + DATA_REG_OFFSET); ++ if (word_sized) { ++ outb_p((reg & 0xff) + 1, ++ data->addr + ADDR_REG_OFFSET); ++ res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET); ++ } ++ ++ mutex_unlock(&data->lock); ++ return res; ++} ++ ++static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) ++{ ++ int word_sized = is_word_sized(data, reg); ++ ++ mutex_lock(&data->lock); ++ ++ nct6775_set_bank(data, reg); ++ outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); ++ if (word_sized) { ++ outb_p(value >> 8, data->addr + DATA_REG_OFFSET); ++ outb_p((reg & 0xff) + 1, ++ data->addr + ADDR_REG_OFFSET); ++ } ++ outb_p(value & 0xff, data->addr + DATA_REG_OFFSET); ++ ++ mutex_unlock(&data->lock); ++ return 0; ++} ++ ++static struct nct6775_data *nct6775_update_device(struct device *dev) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ int i; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ/2) ++ || !data->valid) { ++ /* Measured voltages and limits */ ++ for (i = 0; i < data->in_num; i++) { ++ if (!(data->have_in & (1 << i))) ++ continue; ++ ++ data->in[i][0] = nct6775_read_value(data, ++ data->REG_VIN[i]); ++ data->in[i][1] = nct6775_read_value(data, ++ data->REG_IN_MINMAX[0][i]); ++ data->in[i][2] = nct6775_read_value(data, ++ data->REG_IN_MINMAX[1][i]); ++ } ++ ++ data->alarms = 0; ++ for (i = 0; i < NUM_REG_ALARM; i++) { ++ u8 alarm; ++ if (!data->REG_ALARM[i]) ++ continue; ++ alarm = nct6775_read_value(data, data->REG_ALARM[i]); ++ data->alarms |= ((u64)alarm) << (i << 3); ++ } ++ ++ data->last_updated = jiffies; ++ data->valid = true; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return data; ++} ++ ++/* ++ * Sysfs callback functions ++ */ ++static ssize_t ++show_in_reg(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr)); ++} ++ ++static ssize_t ++store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ unsigned long val; ++ int err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ mutex_lock(&data->update_lock); ++ data->in[nr][index] = in_to_reg(val, nr); ++ nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr], ++ data->in[nr][index]); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_alarm(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = data->ALARM_BITS[sattr->index]; ++ return sprintf(buf, "%u\n", ++ (unsigned int)((data->alarms >> nr) & 0x01)); ++} ++ ++static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0); ++static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0); ++static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0); ++static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0); ++static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0); ++static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0); ++static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0); ++static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0); ++static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0); ++static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0); ++static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0); ++static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0); ++static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0); ++static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0); ++static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0); ++ ++static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7); ++static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8); ++static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9); ++static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10); ++static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11); ++static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12); ++static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13); ++static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14); ++ ++static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 0, 1); ++static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 1, 1); ++static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 2, 1); ++static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 3, 1); ++static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 4, 1); ++static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 5, 1); ++static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 6, 1); ++static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 7, 1); ++static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 8, 1); ++static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 9, 1); ++static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 10, 1); ++static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 11, 1); ++static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 12, 1); ++static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 13, 1); ++static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 14, 1); ++ ++static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 0, 2); ++static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 1, 2); ++static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 2, 2); ++static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 3, 2); ++static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 4, 2); ++static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 5, 2); ++static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 6, 2); ++static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 7, 2); ++static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 8, 2); ++static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 9, 2); ++static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 10, 2); ++static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 11, 2); ++static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 12, 2); ++static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 13, 2); ++static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg, ++ store_in_reg, 14, 2); ++ ++static struct attribute *nct6775_attributes_in[15][5] = { ++ { ++ &sensor_dev_attr_in0_input.dev_attr.attr, ++ &sensor_dev_attr_in0_min.dev_attr.attr, ++ &sensor_dev_attr_in0_max.dev_attr.attr, ++ &sensor_dev_attr_in0_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in1_input.dev_attr.attr, ++ &sensor_dev_attr_in1_min.dev_attr.attr, ++ &sensor_dev_attr_in1_max.dev_attr.attr, ++ &sensor_dev_attr_in1_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in2_input.dev_attr.attr, ++ &sensor_dev_attr_in2_min.dev_attr.attr, ++ &sensor_dev_attr_in2_max.dev_attr.attr, ++ &sensor_dev_attr_in2_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in3_input.dev_attr.attr, ++ &sensor_dev_attr_in3_min.dev_attr.attr, ++ &sensor_dev_attr_in3_max.dev_attr.attr, ++ &sensor_dev_attr_in3_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in4_input.dev_attr.attr, ++ &sensor_dev_attr_in4_min.dev_attr.attr, ++ &sensor_dev_attr_in4_max.dev_attr.attr, ++ &sensor_dev_attr_in4_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in5_input.dev_attr.attr, ++ &sensor_dev_attr_in5_min.dev_attr.attr, ++ &sensor_dev_attr_in5_max.dev_attr.attr, ++ &sensor_dev_attr_in5_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in6_input.dev_attr.attr, ++ &sensor_dev_attr_in6_min.dev_attr.attr, ++ &sensor_dev_attr_in6_max.dev_attr.attr, ++ &sensor_dev_attr_in6_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in7_input.dev_attr.attr, ++ &sensor_dev_attr_in7_min.dev_attr.attr, ++ &sensor_dev_attr_in7_max.dev_attr.attr, ++ &sensor_dev_attr_in7_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in8_input.dev_attr.attr, ++ &sensor_dev_attr_in8_min.dev_attr.attr, ++ &sensor_dev_attr_in8_max.dev_attr.attr, ++ &sensor_dev_attr_in8_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in9_input.dev_attr.attr, ++ &sensor_dev_attr_in9_min.dev_attr.attr, ++ &sensor_dev_attr_in9_max.dev_attr.attr, ++ &sensor_dev_attr_in9_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in10_input.dev_attr.attr, ++ &sensor_dev_attr_in10_min.dev_attr.attr, ++ &sensor_dev_attr_in10_max.dev_attr.attr, ++ &sensor_dev_attr_in10_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in11_input.dev_attr.attr, ++ &sensor_dev_attr_in11_min.dev_attr.attr, ++ &sensor_dev_attr_in11_max.dev_attr.attr, ++ &sensor_dev_attr_in11_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in12_input.dev_attr.attr, ++ &sensor_dev_attr_in12_min.dev_attr.attr, ++ &sensor_dev_attr_in12_max.dev_attr.attr, ++ &sensor_dev_attr_in12_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in13_input.dev_attr.attr, ++ &sensor_dev_attr_in13_min.dev_attr.attr, ++ &sensor_dev_attr_in13_max.dev_attr.attr, ++ &sensor_dev_attr_in13_alarm.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_in14_input.dev_attr.attr, ++ &sensor_dev_attr_in14_min.dev_attr.attr, ++ &sensor_dev_attr_in14_max.dev_attr.attr, ++ &sensor_dev_attr_in14_alarm.dev_attr.attr, ++ NULL ++ }, ++}; ++ ++static const struct attribute_group nct6775_group_in[15] = { ++ { .attrs = nct6775_attributes_in[0] }, ++ { .attrs = nct6775_attributes_in[1] }, ++ { .attrs = nct6775_attributes_in[2] }, ++ { .attrs = nct6775_attributes_in[3] }, ++ { .attrs = nct6775_attributes_in[4] }, ++ { .attrs = nct6775_attributes_in[5] }, ++ { .attrs = nct6775_attributes_in[6] }, ++ { .attrs = nct6775_attributes_in[7] }, ++ { .attrs = nct6775_attributes_in[8] }, ++ { .attrs = nct6775_attributes_in[9] }, ++ { .attrs = nct6775_attributes_in[10] }, ++ { .attrs = nct6775_attributes_in[11] }, ++ { .attrs = nct6775_attributes_in[12] }, ++ { .attrs = nct6775_attributes_in[13] }, ++ { .attrs = nct6775_attributes_in[14] }, ++}; ++ ++static ssize_t ++show_name(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%s\n", data->name); ++} ++ ++static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); ++ ++static ssize_t ++show_vid(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); ++} ++ ++static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); ++ ++/* ++ * Driver and device management ++ */ ++ ++static void nct6775_device_remove_files(struct device *dev) ++{ ++ /* ++ * some entries in the following arrays may not have been used in ++ * device_create_file(), but device_remove_file() will ignore them ++ */ ++ int i; ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ ++ for (i = 0; i < data->in_num; i++) ++ sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); ++ ++ device_remove_file(dev, &dev_attr_name); ++ device_remove_file(dev, &dev_attr_cpu0_vid); ++} ++ ++/* Get the monitoring functions started */ ++static inline void nct6775_init_device(struct nct6775_data *data) ++{ ++ u8 tmp; ++ ++ /* Start monitoring if needed */ ++ if (data->REG_CONFIG) { ++ tmp = nct6775_read_value(data, data->REG_CONFIG); ++ if (!(tmp & 0x01)) ++ nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01); ++ } ++ ++ /* Enable VBAT monitoring if needed */ ++ tmp = nct6775_read_value(data, data->REG_VBAT); ++ if (!(tmp & 0x01)) ++ nct6775_write_value(data, data->REG_VBAT, tmp | 0x01); ++} ++ ++static int nct6775_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct nct6775_sio_data *sio_data = dev->platform_data; ++ struct nct6775_data *data; ++ struct resource *res; ++ int i, err = 0; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, ++ DRVNAME)) ++ return -EBUSY; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data), ++ GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->kind = sio_data->kind; ++ data->addr = res->start; ++ mutex_init(&data->lock); ++ mutex_init(&data->update_lock); ++ data->name = nct6775_device_names[data->kind]; ++ data->bank = 0xff; /* Force initial bank selection */ ++ platform_set_drvdata(pdev, data); ++ ++ switch (data->kind) { ++ case nct6775: ++ data->in_num = 9; ++ ++ data->ALARM_BITS = NCT6775_ALARM_BITS; ++ ++ data->REG_CONFIG = NCT6775_REG_CONFIG; ++ data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_VIN = NCT6775_REG_IN; ++ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; ++ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_ALARM = NCT6775_REG_ALARM; ++ break; ++ case nct6776: ++ data->in_num = 9; ++ ++ data->ALARM_BITS = NCT6776_ALARM_BITS; ++ ++ data->REG_CONFIG = NCT6775_REG_CONFIG; ++ data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_VIN = NCT6775_REG_IN; ++ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; ++ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_ALARM = NCT6775_REG_ALARM; ++ break; ++ case nct6779: ++ data->in_num = 15; ++ ++ data->ALARM_BITS = NCT6779_ALARM_BITS; ++ ++ data->REG_CONFIG = NCT6775_REG_CONFIG; ++ data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_VIN = NCT6779_REG_IN; ++ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; ++ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_ALARM = NCT6779_REG_ALARM; ++ break; ++ default: ++ return -ENODEV; ++ } ++ data->have_in = (1 << data->in_num) - 1; ++ ++ /* Initialize the chip */ ++ nct6775_init_device(data); ++ ++ data->vrm = vid_which_vrm(); ++ err = superio_enter(sio_data->sioreg); ++ if (err) ++ return err; ++ ++ /* ++ * Read VID value ++ * We can get the VID input values directly at logical device D 0xe3. ++ */ ++ superio_select(sio_data->sioreg, NCT6775_LD_VID); ++ data->vid = superio_inb(sio_data->sioreg, 0xe3); ++ superio_exit(sio_data->sioreg); ++ ++ err = device_create_file(dev, &dev_attr_cpu0_vid); ++ if (err) ++ return err; ++ ++ for (i = 0; i < data->in_num; i++) { ++ if (!(data->have_in & (1 << i))) ++ continue; ++ err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]); ++ if (err) ++ goto exit_remove; ++ } ++ ++ err = device_create_file(dev, &dev_attr_name); ++ if (err) ++ goto exit_remove; ++ ++ data->hwmon_dev = hwmon_device_register(dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ return 0; ++ ++exit_remove: ++ nct6775_device_remove_files(dev); ++ return err; ++} ++ ++static int nct6775_remove(struct platform_device *pdev) ++{ ++ struct nct6775_data *data = platform_get_drvdata(pdev); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ nct6775_device_remove_files(&pdev->dev); ++ ++ return 0; ++} ++ ++static struct platform_driver nct6775_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRVNAME, ++ }, ++ .probe = nct6775_probe, ++ .remove = nct6775_remove, ++}; ++ ++/* nct6775_find() looks for a '627 in the Super-I/O config space */ ++static int __init nct6775_find(int sioaddr, unsigned short *addr, ++ struct nct6775_sio_data *sio_data) ++{ ++ static const char sio_name_NCT6775[] __initconst = "NCT6775F"; ++ static const char sio_name_NCT6776[] __initconst = "NCT6776F"; ++ static const char sio_name_NCT6779[] __initconst = "NCT6779D"; ++ ++ u16 val; ++ const char *sio_name; ++ int err; ++ ++ err = superio_enter(sioaddr); ++ if (err) ++ return err; ++ ++ if (force_id) ++ val = force_id; ++ else ++ val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) ++ | superio_inb(sioaddr, SIO_REG_DEVID + 1); ++ switch (val & SIO_ID_MASK) { ++ case SIO_NCT6775_ID: ++ sio_data->kind = nct6775; ++ sio_name = sio_name_NCT6775; ++ break; ++ case SIO_NCT6776_ID: ++ sio_data->kind = nct6776; ++ sio_name = sio_name_NCT6776; ++ break; ++ case SIO_NCT6779_ID: ++ sio_data->kind = nct6779; ++ sio_name = sio_name_NCT6779; ++ break; ++ default: ++ if (val != 0xffff) ++ pr_debug("unsupported chip ID: 0x%04x\n", val); ++ superio_exit(sioaddr); ++ return -ENODEV; ++ } ++ ++ /* We have a known chip, find the HWM I/O address */ ++ superio_select(sioaddr, NCT6775_LD_HWM); ++ val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) ++ | superio_inb(sioaddr, SIO_REG_ADDR + 1); ++ *addr = val & IOREGION_ALIGNMENT; ++ if (*addr == 0) { ++ pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); ++ superio_exit(sioaddr); ++ return -ENODEV; ++ } ++ ++ /* Activate logical device if needed */ ++ val = superio_inb(sioaddr, SIO_REG_ENABLE); ++ if (!(val & 0x01)) { ++ pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); ++ superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); ++ } ++ ++ superio_exit(sioaddr); ++ pr_info("Found %s chip at %#x\n", sio_name, *addr); ++ sio_data->sioreg = sioaddr; ++ ++ return 0; ++} ++ ++/* ++ * when Super-I/O functions move to a separate file, the Super-I/O ++ * bus will manage the lifetime of the device and this module will only keep ++ * track of the nct6775 driver. But since we platform_device_alloc(), we ++ * must keep track of the device ++ */ ++static struct platform_device *pdev; ++ ++static int __init sensors_nct6775_init(void) ++{ ++ int err; ++ unsigned short address; ++ struct resource res; ++ struct nct6775_sio_data sio_data; ++ ++ /* ++ * initialize sio_data->kind and sio_data->sioreg. ++ * ++ * when Super-I/O functions move to a separate file, the Super-I/O ++ * driver will probe 0x2e and 0x4e and auto-detect the presence of a ++ * nct6775 hardware monitor, and call probe() ++ */ ++ if (nct6775_find(0x2e, &address, &sio_data) && ++ nct6775_find(0x4e, &address, &sio_data)) ++ return -ENODEV; ++ ++ err = platform_driver_register(&nct6775_driver); ++ if (err) ++ goto exit; ++ ++ pdev = platform_device_alloc(DRVNAME, address); ++ if (!pdev) { ++ err = -ENOMEM; ++ pr_err("Device allocation failed\n"); ++ goto exit_unregister; ++ } ++ ++ err = platform_device_add_data(pdev, &sio_data, ++ sizeof(struct nct6775_sio_data)); ++ if (err) { ++ pr_err("Platform data allocation failed\n"); ++ goto exit_device_put; ++ } ++ ++ memset(&res, 0, sizeof(res)); ++ res.name = DRVNAME; ++ res.start = address + IOREGION_OFFSET; ++ res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; ++ res.flags = IORESOURCE_IO; ++ ++ err = acpi_check_resource_conflict(&res); ++ if (err) ++ goto exit_device_put; ++ ++ err = platform_device_add_resources(pdev, &res, 1); ++ if (err) { ++ pr_err("Device resource addition failed (%d)\n", err); ++ goto exit_device_put; ++ } ++ ++ /* platform_device_add calls probe() */ ++ err = platform_device_add(pdev); ++ if (err) { ++ pr_err("Device addition failed (%d)\n", err); ++ goto exit_device_put; ++ } ++ ++ return 0; ++ ++exit_device_put: ++ platform_device_put(pdev); ++exit_unregister: ++ platform_driver_unregister(&nct6775_driver); ++exit: ++ return err; ++} ++ ++static void __exit sensors_nct6775_exit(void) ++{ ++ platform_device_unregister(pdev); ++ platform_driver_unregister(&nct6775_driver); ++} ++ ++MODULE_AUTHOR("Guenter Roeck "); ++MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(sensors_nct6775_init); ++module_exit(sensors_nct6775_exit); + +From a6bd587842772cd3e63a689c7ff4d64cf25284a3 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 03:13:34 -0800 +Subject: [PATCH] hwmon: (nct6775) Add case open detection + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index f75cd82..435691f 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -76,6 +76,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); + * Super-I/O constants and functions + */ + ++#define NCT6775_LD_ACPI 0x0a + #define NCT6775_LD_HWM 0x0b + #define NCT6775_LD_VID 0x0d + +@@ -186,6 +187,11 @@ static const s8 NCT6775_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, -1 }; /* intrusion0, intrusion1 */ + ++#define INTRUSION_ALARM_BASE 30 ++ ++static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; ++static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; ++ + /* NCT6776 specific data */ + + static const s8 NCT6776_ALARM_BITS[] = { +@@ -694,6 +700,56 @@ show_vid(struct device *dev, struct device_attribute *attr, char *buf) + + static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + ++/* Case open detection */ ++ ++static ssize_t ++clear_caseopen(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct nct6775_sio_data *sio_data = dev->platform_data; ++ int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE; ++ unsigned long val; ++ u8 reg; ++ int ret; ++ ++ if (kstrtoul(buf, 10, &val) || val != 0) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ /* ++ * Use CR registers to clear caseopen status. ++ * The CR registers are the same for all chips, and not all chips ++ * support clearing the caseopen status through "regular" registers. ++ */ ++ ret = superio_enter(sio_data->sioreg); ++ if (ret) { ++ count = ret; ++ goto error; ++ } ++ ++ superio_select(sio_data->sioreg, NCT6775_LD_ACPI); ++ reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]); ++ reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr]; ++ superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); ++ reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr]; ++ superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); ++ superio_exit(sio_data->sioreg); ++ ++ data->valid = false; /* Force cache refresh */ ++error: ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static struct sensor_device_attribute sda_caseopen[] = { ++ SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm, ++ clear_caseopen, INTRUSION_ALARM_BASE), ++ SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm, ++ clear_caseopen, INTRUSION_ALARM_BASE + 1), ++}; ++ + /* + * Driver and device management + */ +@@ -710,6 +766,9 @@ static void nct6775_device_remove_files(struct device *dev) + for (i = 0; i < data->in_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); + ++ device_remove_file(dev, &sda_caseopen[0].dev_attr); ++ device_remove_file(dev, &sda_caseopen[1].dev_attr); ++ + device_remove_file(dev, &dev_attr_name); + device_remove_file(dev, &dev_attr_cpu0_vid); + } +@@ -828,6 +887,14 @@ static int nct6775_probe(struct platform_device *pdev) + goto exit_remove; + } + ++ for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { ++ if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0) ++ continue; ++ err = device_create_file(dev, &sda_caseopen[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ + err = device_create_file(dev, &dev_attr_name); + if (err) + goto exit_remove; + +From aa136e5dad9fbec9e98867278555a81f2d75ea10 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 03:26:05 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for temperature sensors + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 435691f..fd0dd15 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -57,6 +57,8 @@ + #include + #include "lm75.h" + ++#define USE_ALTERNATE ++ + enum kinds { nct6775, nct6776, nct6779 }; + + /* used to set data->name = nct6775_device_names[data->sio_kind] */ +@@ -156,6 +158,9 @@ superio_exit(int ioreg) + * REG_CHIP_ID is at port 0x58 + */ + ++#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ ++#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */ ++ + #define NUM_REG_ALARM 4 /* Max number of alarm registers */ + + /* Common and NCT6775 specific data */ +@@ -173,6 +178,7 @@ static const u16 NCT6775_REG_IN[] = { + }; + + #define NCT6775_REG_VBAT 0x5D ++#define NCT6775_REG_DIODE 0x5E + + static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; + +@@ -187,11 +193,58 @@ static const s8 NCT6775_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, -1 }; /* intrusion0, intrusion1 */ + ++#define TEMP_ALARM_BASE 24 + #define INTRUSION_ALARM_BASE 30 + + static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; + static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; + ++static const u16 NCT6775_REG_TEMP[] = { ++ 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; ++ ++static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { ++ 0, 0x152, 0x252, 0x628, 0x629, 0x62A }; ++static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = { ++ 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D }; ++static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = { ++ 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C }; ++ ++static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { ++ 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; ++ ++static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; ++ ++static const char *const nct6775_temp_label[] = { ++ "", ++ "SYSTIN", ++ "CPUTIN", ++ "AUXTIN", ++ "AMD SB-TSI", ++ "PECI Agent 0", ++ "PECI Agent 1", ++ "PECI Agent 2", ++ "PECI Agent 3", ++ "PECI Agent 4", ++ "PECI Agent 5", ++ "PECI Agent 6", ++ "PECI Agent 7", ++ "PCH_CHIP_CPU_MAX_TEMP", ++ "PCH_CHIP_TEMP", ++ "PCH_CPU_TEMP", ++ "PCH_MCH_TEMP", ++ "PCH_DIM0_TEMP", ++ "PCH_DIM1_TEMP", ++ "PCH_DIM2_TEMP", ++ "PCH_DIM3_TEMP" ++}; ++ ++static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1] ++ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 }; ++ ++static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1] ++ = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06, ++ 0xa07 }; ++ + /* NCT6776 specific data */ + + static const s8 NCT6776_ALARM_BITS[] = { +@@ -203,6 +256,41 @@ static const s8 NCT6776_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { ++ 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; ++ ++static const char *const nct6776_temp_label[] = { ++ "", ++ "SYSTIN", ++ "CPUTIN", ++ "AUXTIN", ++ "SMBUSMASTER 0", ++ "SMBUSMASTER 1", ++ "SMBUSMASTER 2", ++ "SMBUSMASTER 3", ++ "SMBUSMASTER 4", ++ "SMBUSMASTER 5", ++ "SMBUSMASTER 6", ++ "SMBUSMASTER 7", ++ "PECI Agent 0", ++ "PECI Agent 1", ++ "PCH_CHIP_CPU_MAX_TEMP", ++ "PCH_CHIP_TEMP", ++ "PCH_CPU_TEMP", ++ "PCH_MCH_TEMP", ++ "PCH_DIM0_TEMP", ++ "PCH_DIM1_TEMP", ++ "PCH_DIM2_TEMP", ++ "PCH_DIM3_TEMP", ++ "BYTE_TEMP" ++}; ++ ++static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] ++ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 }; ++ ++static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] ++ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; ++ + /* NCT6779 specific data */ + + static const u16 NCT6779_REG_IN[] = { +@@ -221,6 +309,56 @@ static const s8 NCT6779_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; ++static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { ++ 0x18, 0x152 }; ++static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = { ++ 0x3a, 0x153 }; ++static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = { ++ 0x39, 0x155 }; ++ ++static const u16 NCT6779_REG_TEMP_OFFSET[] = { ++ 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c }; ++ ++static const char *const nct6779_temp_label[] = { ++ "", ++ "SYSTIN", ++ "CPUTIN", ++ "AUXTIN0", ++ "AUXTIN1", ++ "AUXTIN2", ++ "AUXTIN3", ++ "", ++ "SMBUSMASTER 0", ++ "SMBUSMASTER 1", ++ "SMBUSMASTER 2", ++ "SMBUSMASTER 3", ++ "SMBUSMASTER 4", ++ "SMBUSMASTER 5", ++ "SMBUSMASTER 6", ++ "SMBUSMASTER 7", ++ "PECI Agent 0", ++ "PECI Agent 1", ++ "PCH_CHIP_CPU_MAX_TEMP", ++ "PCH_CHIP_TEMP", ++ "PCH_CPU_TEMP", ++ "PCH_MCH_TEMP", ++ "PCH_DIM0_TEMP", ++ "PCH_DIM1_TEMP", ++ "PCH_DIM2_TEMP", ++ "PCH_DIM3_TEMP", ++ "BYTE_TEMP" ++}; ++ ++static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] ++ = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407, ++ 0x408, 0 }; ++ ++static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] ++ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; ++ + /* + * Conversions + */ +@@ -256,14 +394,27 @@ struct nct6775_data { + struct device *hwmon_dev; + struct mutex lock; + ++ u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, ++ * 3=temp_crit ++ */ ++ u8 temp_src[NUM_TEMP]; ++ u16 reg_temp_config[NUM_TEMP]; ++ const char * const *temp_label; ++ int temp_label_num; ++ + u16 REG_CONFIG; + u16 REG_VBAT; ++ u16 REG_DIODE; + + const s8 *ALARM_BITS; + + const u16 *REG_VIN; + const u16 *REG_IN_MINMAX[2]; + ++ const u16 *REG_TEMP_SOURCE; /* temp register sources */ ++ ++ const u16 *REG_TEMP_OFFSET; ++ + const u16 *REG_ALARM; + + struct mutex update_lock; +@@ -275,11 +426,18 @@ struct nct6775_data { + u8 in_num; /* number of in inputs we have */ + u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ + ++ u8 temp_fixed_num; /* 3 or 6 */ ++ u8 temp_type[NUM_TEMP_FIXED]; ++ s8 temp_offset[NUM_TEMP_FIXED]; ++ s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, ++ * 3=temp_crit */ + u64 alarms; + + u8 vid; + u8 vrm; + ++ u16 have_temp; ++ u16 have_temp_fixed; + u16 have_in; + }; + +@@ -379,10 +537,29 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) + return 0; + } + ++/* We left-align 8-bit temperature values to make the code simpler */ ++static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg) ++{ ++ u16 res; ++ ++ res = nct6775_read_value(data, reg); ++ if (!is_word_sized(data, reg)) ++ res <<= 8; ++ ++ return res; ++} ++ ++static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value) ++{ ++ if (!is_word_sized(data, reg)) ++ value >>= 8; ++ return nct6775_write_value(data, reg, value); ++} ++ + static struct nct6775_data *nct6775_update_device(struct device *dev) + { + struct nct6775_data *data = dev_get_drvdata(dev); +- int i; ++ int i, j; + + mutex_lock(&data->update_lock); + +@@ -401,6 +578,22 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + data->REG_IN_MINMAX[1][i]); + } + ++ /* Measured temperatures and limits */ ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ for (j = 0; j < 4; j++) { ++ if (data->reg_temp[j][i]) ++ data->temp[j][i] ++ = nct6775_read_temp(data, ++ data->reg_temp[j][i]); ++ } ++ if (!(data->have_temp_fixed & (1 << i))) ++ continue; ++ data->temp_offset[i] ++ = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]); ++ } ++ + data->alarms = 0; + for (i = 0; i < NUM_REG_ALARM; i++) { + u8 alarm; +@@ -682,6 +875,275 @@ static const struct attribute_group nct6775_group_in[15] = { + }; + + static ssize_t ++show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]); ++} ++ ++static ssize_t ++show_temp(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ ++ return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr])); ++} ++ ++static ssize_t ++store_temp(struct device *dev, struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ int err; ++ long val; ++ ++ err = kstrtol(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ mutex_lock(&data->update_lock); ++ data->temp[index][nr] = LM75_TEMP_TO_REG(val); ++ nct6775_write_temp(data, data->reg_temp[index][nr], ++ data->temp[index][nr]); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ ++ return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000); ++} ++ ++static ssize_t ++store_temp_offset(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ long val; ++ int err; ++ ++ err = kstrtol(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127); ++ ++ mutex_lock(&data->update_lock); ++ data->temp_offset[nr] = val; ++ nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t ++show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ return sprintf(buf, "%d\n", (int)data->temp_type[nr]); ++} ++ ++static ssize_t ++store_temp_type(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ u8 vbat, diode, bit; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ if (val != 1 && val != 3 && val != 4) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ data->temp_type[nr] = val; ++ vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr); ++ diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr); ++ bit = 0x02 << nr; ++ switch (val) { ++ case 1: /* CPU diode (diode, current mode) */ ++ vbat |= bit; ++ diode |= bit; ++ break; ++ case 3: /* diode, voltage mode */ ++ vbat |= bit; ++ break; ++ case 4: /* thermistor */ ++ break; ++ } ++ nct6775_write_value(data, data->REG_VBAT, vbat); ++ nct6775_write_value(data, data->REG_DIODE, diode); ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static struct sensor_device_attribute_2 sda_temp_input[] = { ++ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), ++ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0), ++ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0), ++ SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0), ++ SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0), ++ SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0), ++ SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0), ++ SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0), ++ SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0), ++ SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0), ++}; ++ ++static struct sensor_device_attribute sda_temp_label[] = { ++ SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0), ++ SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1), ++ SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2), ++ SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3), ++ SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4), ++ SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5), ++ SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6), ++ SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7), ++ SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8), ++ SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9), ++}; ++ ++static struct sensor_device_attribute_2 sda_temp_max[] = { ++ SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 0, 1), ++ SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 1, 1), ++ SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 2, 1), ++ SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 3, 1), ++ SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 4, 1), ++ SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 5, 1), ++ SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 6, 1), ++ SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 7, 1), ++ SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 8, 1), ++ SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 9, 1), ++}; ++ ++static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { ++ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 0, 2), ++ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 1, 2), ++ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 2, 2), ++ SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 3, 2), ++ SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 4, 2), ++ SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 5, 2), ++ SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 6, 2), ++ SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 7, 2), ++ SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 8, 2), ++ SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 9, 2), ++}; ++ ++static struct sensor_device_attribute_2 sda_temp_crit[] = { ++ SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 0, 3), ++ SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 1, 3), ++ SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 2, 3), ++ SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 3, 3), ++ SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 4, 3), ++ SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 5, 3), ++ SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 6, 3), ++ SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 7, 3), ++ SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 8, 3), ++ SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, ++ 9, 3), ++}; ++ ++static struct sensor_device_attribute sda_temp_offset[] = { ++ SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 0), ++ SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 1), ++ SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 2), ++ SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 3), ++ SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 4), ++ SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset, ++ store_temp_offset, 5), ++}; ++ ++static struct sensor_device_attribute sda_temp_type[] = { ++ SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 0), ++ SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 1), ++ SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 2), ++ SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 3), ++ SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 4), ++ SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type, ++ store_temp_type, 5), ++}; ++ ++static struct sensor_device_attribute sda_temp_alarm[] = { ++ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE), ++ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE + 1), ++ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE + 2), ++ SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE + 3), ++ SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE + 4), ++ SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, ++ TEMP_ALARM_BASE + 5), ++}; ++ ++#define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm) ++ ++static ssize_t + show_name(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = dev_get_drvdata(dev); +@@ -766,6 +1228,23 @@ static void nct6775_device_remove_files(struct device *dev) + for (i = 0; i < data->in_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); + ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ device_remove_file(dev, &sda_temp_input[i].dev_attr); ++ device_remove_file(dev, &sda_temp_label[i].dev_attr); ++ device_remove_file(dev, &sda_temp_max[i].dev_attr); ++ device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); ++ device_remove_file(dev, &sda_temp_crit[i].dev_attr); ++ if (!(data->have_temp_fixed & (1 << i))) ++ continue; ++ device_remove_file(dev, &sda_temp_type[i].dev_attr); ++ device_remove_file(dev, &sda_temp_offset[i].dev_attr); ++ if (i >= NUM_TEMP_ALARM) ++ continue; ++ device_remove_file(dev, &sda_temp_alarm[i].dev_attr); ++ } ++ + device_remove_file(dev, &sda_caseopen[0].dev_attr); + device_remove_file(dev, &sda_caseopen[1].dev_attr); + +@@ -776,7 +1255,8 @@ static void nct6775_device_remove_files(struct device *dev) + /* Get the monitoring functions started */ + static inline void nct6775_init_device(struct nct6775_data *data) + { +- u8 tmp; ++ int i; ++ u8 tmp, diode; + + /* Start monitoring if needed */ + if (data->REG_CONFIG) { +@@ -785,10 +1265,33 @@ static inline void nct6775_init_device(struct nct6775_data *data) + nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01); + } + ++ /* Enable temperature sensors if needed */ ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ if (!data->reg_temp_config[i]) ++ continue; ++ tmp = nct6775_read_value(data, data->reg_temp_config[i]); ++ if (tmp & 0x01) ++ nct6775_write_value(data, data->reg_temp_config[i], ++ tmp & 0xfe); ++ } ++ + /* Enable VBAT monitoring if needed */ + tmp = nct6775_read_value(data, data->REG_VBAT); + if (!(tmp & 0x01)) + nct6775_write_value(data, data->REG_VBAT, tmp | 0x01); ++ ++ diode = nct6775_read_value(data, data->REG_DIODE); ++ ++ for (i = 0; i < data->temp_fixed_num; i++) { ++ if (!(data->have_temp_fixed & (1 << i))) ++ continue; ++ if ((tmp & (0x02 << i))) /* diode */ ++ data->temp_type[i] = 3 - ((diode >> i) & 0x02); ++ else /* thermistor */ ++ data->temp_type[i] = 4; ++ } + } + + static int nct6775_probe(struct platform_device *pdev) +@@ -797,7 +1300,11 @@ static int nct6775_probe(struct platform_device *pdev) + struct nct6775_sio_data *sio_data = dev->platform_data; + struct nct6775_data *data; + struct resource *res; +- int i, err = 0; ++ int i, s, err = 0; ++ int src, mask, available; ++ const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config; ++ const u16 *reg_temp_alternate, *reg_temp_crit; ++ int num_reg_temp; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, +@@ -820,44 +1327,233 @@ static int nct6775_probe(struct platform_device *pdev) + switch (data->kind) { + case nct6775: + data->in_num = 9; ++ data->temp_fixed_num = 3; + + data->ALARM_BITS = NCT6775_ALARM_BITS; + ++ data->temp_label = nct6775_temp_label; ++ data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); ++ + data->REG_CONFIG = NCT6775_REG_CONFIG; + data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_DIODE = NCT6775_REG_DIODE; + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; ++ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; ++ ++ reg_temp = NCT6775_REG_TEMP; ++ num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); ++ reg_temp_over = NCT6775_REG_TEMP_OVER; ++ reg_temp_hyst = NCT6775_REG_TEMP_HYST; ++ reg_temp_config = NCT6775_REG_TEMP_CONFIG; ++ reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE; ++ reg_temp_crit = NCT6775_REG_TEMP_CRIT; ++ + break; + case nct6776: + data->in_num = 9; ++ data->temp_fixed_num = 3; + + data->ALARM_BITS = NCT6776_ALARM_BITS; + ++ data->temp_label = nct6776_temp_label; ++ data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); ++ + data->REG_CONFIG = NCT6775_REG_CONFIG; + data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_DIODE = NCT6775_REG_DIODE; + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; ++ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; ++ ++ reg_temp = NCT6775_REG_TEMP; ++ num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); ++ reg_temp_over = NCT6775_REG_TEMP_OVER; ++ reg_temp_hyst = NCT6775_REG_TEMP_HYST; ++ reg_temp_config = NCT6776_REG_TEMP_CONFIG; ++ reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE; ++ reg_temp_crit = NCT6776_REG_TEMP_CRIT; ++ + break; + case nct6779: + data->in_num = 15; ++ data->temp_fixed_num = 6; + + data->ALARM_BITS = NCT6779_ALARM_BITS; + ++ data->temp_label = nct6779_temp_label; ++ data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); ++ + data->REG_CONFIG = NCT6775_REG_CONFIG; + data->REG_VBAT = NCT6775_REG_VBAT; ++ data->REG_DIODE = NCT6775_REG_DIODE; + data->REG_VIN = NCT6779_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; ++ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6779_REG_ALARM; ++ ++ reg_temp = NCT6779_REG_TEMP; ++ num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP); ++ reg_temp_over = NCT6779_REG_TEMP_OVER; ++ reg_temp_hyst = NCT6779_REG_TEMP_HYST; ++ reg_temp_config = NCT6779_REG_TEMP_CONFIG; ++ reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE; ++ reg_temp_crit = NCT6779_REG_TEMP_CRIT; ++ + break; + default: + return -ENODEV; + } + data->have_in = (1 << data->in_num) - 1; ++ data->have_temp = 0; ++ ++ /* ++ * On some boards, not all available temperature sources are monitored, ++ * even though some of the monitoring registers are unused. ++ * Get list of unused monitoring registers, then detect if any fan ++ * controls are configured to use unmonitored temperature sources. ++ * If so, assign the unmonitored temperature sources to available ++ * monitoring registers. ++ */ ++ mask = 0; ++ available = 0; ++ for (i = 0; i < num_reg_temp; i++) { ++ if (reg_temp[i] == 0) ++ continue; ++ ++ src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; ++ if (!src || (mask & (1 << src))) ++ available |= 1 << i; ++ ++ mask |= 1 << src; ++ } ++ ++ mask = 0; ++ s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */ ++ for (i = 0; i < num_reg_temp; i++) { ++ if (reg_temp[i] == 0) ++ continue; ++ ++ src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; ++ if (!src || (mask & (1 << src))) ++ continue; ++ ++ if (src >= data->temp_label_num || ++ !strlen(data->temp_label[src])) { ++ dev_info(dev, ++ "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n", ++ src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]); ++ continue; ++ } ++ ++ mask |= 1 << src; ++ ++ /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */ ++ if (src <= data->temp_fixed_num) { ++ data->have_temp |= 1 << (src - 1); ++ data->have_temp_fixed |= 1 << (src - 1); ++ data->reg_temp[0][src - 1] = reg_temp[i]; ++ data->reg_temp[1][src - 1] = reg_temp_over[i]; ++ data->reg_temp[2][src - 1] = reg_temp_hyst[i]; ++ data->reg_temp_config[src - 1] = reg_temp_config[i]; ++ data->temp_src[src - 1] = src; ++ continue; ++ } ++ ++ if (s >= NUM_TEMP) ++ continue; ++ ++ /* Use dynamic index for other sources */ ++ data->have_temp |= 1 << s; ++ data->reg_temp[0][s] = reg_temp[i]; ++ data->reg_temp[1][s] = reg_temp_over[i]; ++ data->reg_temp[2][s] = reg_temp_hyst[i]; ++ data->reg_temp_config[s] = reg_temp_config[i]; ++ if (reg_temp_crit[src - 1]) ++ data->reg_temp[3][s] = reg_temp_crit[src - 1]; ++ ++ data->temp_src[s] = src; ++ s++; ++ } ++ ++#ifdef USE_ALTERNATE ++ /* ++ * Go through the list of alternate temp registers and enable ++ * if possible. ++ * The temperature is already monitored if the respective bit in ++ * is set. ++ */ ++ for (i = 0; i < data->temp_label_num - 1; i++) { ++ if (!reg_temp_alternate[i]) ++ continue; ++ if (mask & (1 << (i + 1))) ++ continue; ++ if (i < data->temp_fixed_num) { ++ if (data->have_temp & (1 << i)) ++ continue; ++ data->have_temp |= 1 << i; ++ data->have_temp_fixed |= 1 << i; ++ data->reg_temp[0][i] = reg_temp_alternate[i]; ++ data->reg_temp[1][i] = reg_temp_over[i]; ++ data->reg_temp[2][i] = reg_temp_hyst[i]; ++ data->temp_src[i] = i + 1; ++ continue; ++ } ++ ++ if (s >= NUM_TEMP) /* Abort if no more space */ ++ break; ++ ++ data->have_temp |= 1 << s; ++ data->reg_temp[0][s] = reg_temp_alternate[i]; ++ data->temp_src[s] = i + 1; ++ s++; ++ } ++#endif /* USE_ALTERNATE */ ++ ++ switch (data->kind) { ++ case nct6775: ++ break; ++ case nct6776: ++ /* ++ * On NCT6776, AUXTIN and VIN3 pins are shared. ++ * Only way to detect it is to check if AUXTIN is used ++ * as a temperature source, and if that source is ++ * enabled. ++ * ++ * If that is the case, disable in6, which reports VIN3. ++ * Otherwise disable temp3. ++ */ ++ if (data->have_temp & (1 << 2)) { ++ u8 reg = nct6775_read_value(data, ++ data->reg_temp_config[2]); ++ if (reg & 0x01) ++ data->have_temp &= ~(1 << 2); ++ else ++ data->have_in &= ~(1 << 6); ++ } ++ break; ++ case nct6779: ++ /* ++ * Shared pins: ++ * VIN4 / AUXTIN0 ++ * VIN5 / AUXTIN1 ++ * VIN6 / AUXTIN2 ++ * VIN7 / AUXTIN3 ++ * ++ * There does not seem to be a clean way to detect if VINx or ++ * AUXTINx is active, so for keep both sensor types enabled ++ * for now. ++ */ ++ break; ++ } + + /* Initialize the chip */ + nct6775_init_device(data); +@@ -887,6 +1583,52 @@ static int nct6775_probe(struct platform_device *pdev) + goto exit_remove; + } + ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ err = device_create_file(dev, &sda_temp_input[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ if (data->temp_label) { ++ err = device_create_file(dev, ++ &sda_temp_label[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (data->reg_temp[1][i]) { ++ err = device_create_file(dev, ++ &sda_temp_max[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (data->reg_temp[2][i]) { ++ err = device_create_file(dev, ++ &sda_temp_max_hyst[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (data->reg_temp[3][i]) { ++ err = device_create_file(dev, ++ &sda_temp_crit[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (!(data->have_temp_fixed & (1 << i))) ++ continue; ++ err = device_create_file(dev, &sda_temp_type[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ err = device_create_file(dev, &sda_temp_offset[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ if (i >= NUM_TEMP_ALARM || ++ data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0) ++ continue; ++ err = device_create_file(dev, &sda_temp_alarm[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ + for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { + if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0) + continue; + +From 1c65dc365ed38d6839fcc231ea38a6163fb9d343 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 07:56:24 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for fan speed attributes + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +index ccfd5cc..dcd56a3 100644 +--- a/Documentation/hwmon/nct6775 ++++ b/Documentation/hwmon/nct6775 +@@ -53,8 +53,9 @@ triggered if the rotation speed has dropped below a programmable limit. On + NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8, + 16, 32, 64 or 128) to give the readings more range or accuracy; the other chips + do not have a fan speed divider. The driver sets the most suitable fan divisor +-itself; specifically, it doubles the divider value each time a fan speed reading +-returns an invalid value. Some fans might not be present because they share pins ++itself; specifically, it increases the divider value each time a fan speed ++reading returns an invalid value, and it reduces it if the fan speed reading ++is lower than optimal. Some fans might not be present because they share pins + with other functions. + + Voltage sensors (also known as IN sensors) report their values in millivolts. +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index fd0dd15..bafcae5 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -180,6 +180,9 @@ static const u16 NCT6775_REG_IN[] = { + #define NCT6775_REG_VBAT 0x5D + #define NCT6775_REG_DIODE 0x5E + ++#define NCT6775_REG_FANDIV1 0x506 ++#define NCT6775_REG_FANDIV2 0x507 ++ + static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; + + /* 0..15 voltages, 16..23 fans, 24..31 temperatures */ +@@ -193,12 +196,16 @@ static const s8 NCT6775_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, -1 }; /* intrusion0, intrusion1 */ + ++#define FAN_ALARM_BASE 16 + #define TEMP_ALARM_BASE 24 + #define INTRUSION_ALARM_BASE 30 + + static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; + static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; + ++static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; ++static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; ++ + static const u16 NCT6775_REG_TEMP[] = { + 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; + +@@ -256,6 +263,8 @@ static const s8 NCT6776_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; ++ + static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; + +@@ -309,6 +318,8 @@ static const s8 NCT6779_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; ++ + static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; + static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { + 0x18, 0x152 }; +@@ -363,6 +374,44 @@ static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] + * Conversions + */ + ++static unsigned int fan_from_reg8(u16 reg, unsigned int divreg) ++{ ++ if (reg == 0 || reg == 255) ++ return 0; ++ return 1350000U / (reg << divreg); ++} ++ ++static unsigned int fan_from_reg13(u16 reg, unsigned int divreg) ++{ ++ if ((reg & 0xff1f) == 0xff1f) ++ return 0; ++ ++ reg = (reg & 0x1f) | ((reg & 0xff00) >> 3); ++ ++ if (reg == 0) ++ return 0; ++ ++ return 1350000U / reg; ++} ++ ++static unsigned int fan_from_reg16(u16 reg, unsigned int divreg) ++{ ++ if (reg == 0 || reg == 0xffff) ++ return 0; ++ ++ /* ++ * Even though the registers are 16 bit wide, the fan divisor ++ * still applies. ++ */ ++ return 1350000U / (reg << divreg); ++} ++ ++static inline unsigned int ++div_from_reg(u8 reg) ++{ ++ return 1 << reg; ++} ++ + /* + * Some of the voltage inputs have internal scaling, the tables below + * contain 8 (the ADC LSB in mV) * scaling factor * 100 +@@ -411,12 +460,17 @@ struct nct6775_data { + const u16 *REG_VIN; + const u16 *REG_IN_MINMAX[2]; + +- const u16 *REG_TEMP_SOURCE; /* temp register sources */ ++ const u16 *REG_FAN; ++ const u16 *REG_FAN_MIN; + ++ const u16 *REG_TEMP_SOURCE; /* temp register sources */ + const u16 *REG_TEMP_OFFSET; + + const u16 *REG_ALARM; + ++ unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg); ++ unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg); ++ + struct mutex update_lock; + bool valid; /* true if following fields are valid */ + unsigned long last_updated; /* In jiffies */ +@@ -425,6 +479,12 @@ struct nct6775_data { + u8 bank; /* current register bank */ + u8 in_num; /* number of in inputs we have */ + u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ ++ unsigned int rpm[5]; ++ u16 fan_min[5]; ++ u8 fan_div[5]; ++ u8 has_fan; /* some fan inputs can be disabled */ ++ u8 has_fan_min; /* some fans don't have min register */ ++ bool has_fan_div; + + u8 temp_fixed_num; /* 3 or 6 */ + u8 temp_type[NUM_TEMP_FIXED]; +@@ -556,6 +616,153 @@ static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value) + return nct6775_write_value(data, reg, value); + } + ++/* This function assumes that the caller holds data->update_lock */ ++static void nct6775_write_fan_div(struct nct6775_data *data, int nr) ++{ ++ u8 reg; ++ ++ switch (nr) { ++ case 0: ++ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70) ++ | (data->fan_div[0] & 0x7); ++ nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); ++ break; ++ case 1: ++ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7) ++ | ((data->fan_div[1] << 4) & 0x70); ++ nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); ++ break; ++ case 2: ++ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70) ++ | (data->fan_div[2] & 0x7); ++ nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); ++ break; ++ case 3: ++ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7) ++ | ((data->fan_div[3] << 4) & 0x70); ++ nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); ++ break; ++ } ++} ++ ++static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr) ++{ ++ if (data->kind == nct6775) ++ nct6775_write_fan_div(data, nr); ++} ++ ++static void nct6775_update_fan_div(struct nct6775_data *data) ++{ ++ u8 i; ++ ++ i = nct6775_read_value(data, NCT6775_REG_FANDIV1); ++ data->fan_div[0] = i & 0x7; ++ data->fan_div[1] = (i & 0x70) >> 4; ++ i = nct6775_read_value(data, NCT6775_REG_FANDIV2); ++ data->fan_div[2] = i & 0x7; ++ if (data->has_fan & (1<<3)) ++ data->fan_div[3] = (i & 0x70) >> 4; ++} ++ ++static void nct6775_update_fan_div_common(struct nct6775_data *data) ++{ ++ if (data->kind == nct6775) ++ nct6775_update_fan_div(data); ++} ++ ++static void nct6775_init_fan_div(struct nct6775_data *data) ++{ ++ int i; ++ ++ nct6775_update_fan_div_common(data); ++ /* ++ * For all fans, start with highest divider value if the divider ++ * register is not initialized. This ensures that we get a ++ * reading from the fan count register, even if it is not optimal. ++ * We'll compute a better divider later on. ++ */ ++ for (i = 0; i < 3; i++) { ++ if (!(data->has_fan & (1 << i))) ++ continue; ++ if (data->fan_div[i] == 0) { ++ data->fan_div[i] = 7; ++ nct6775_write_fan_div_common(data, i); ++ } ++ } ++} ++ ++static void nct6775_init_fan_common(struct device *dev, ++ struct nct6775_data *data) ++{ ++ int i; ++ u8 reg; ++ ++ if (data->has_fan_div) ++ nct6775_init_fan_div(data); ++ ++ /* ++ * If fan_min is not set (0), set it to 0xff to disable it. This ++ * prevents the unnecessary warning when fanX_min is reported as 0. ++ */ ++ for (i = 0; i < 5; i++) { ++ if (data->has_fan_min & (1 << i)) { ++ reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); ++ if (!reg) ++ nct6775_write_value(data, data->REG_FAN_MIN[i], ++ data->has_fan_div ? 0xff ++ : 0xff1f); ++ } ++ } ++} ++ ++static void nct6775_select_fan_div(struct device *dev, ++ struct nct6775_data *data, int nr, u16 reg) ++{ ++ u8 fan_div = data->fan_div[nr]; ++ u16 fan_min; ++ ++ if (!data->has_fan_div) ++ return; ++ ++ /* ++ * If we failed to measure the fan speed, or the reported value is not ++ * in the optimal range, and the clock divider can be modified, ++ * let's try that for next time. ++ */ ++ if (reg == 0x00 && fan_div < 0x07) ++ fan_div++; ++ else if (reg != 0x00 && reg < 0x30 && fan_div > 0) ++ fan_div--; ++ ++ if (fan_div != data->fan_div[nr]) { ++ dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n", ++ nr + 1, div_from_reg(data->fan_div[nr]), ++ div_from_reg(fan_div)); ++ ++ /* Preserve min limit if possible */ ++ if (data->has_fan_min & (1 << nr)) { ++ fan_min = data->fan_min[nr]; ++ if (fan_div > data->fan_div[nr]) { ++ if (fan_min != 255 && fan_min > 1) ++ fan_min >>= 1; ++ } else { ++ if (fan_min != 255) { ++ fan_min <<= 1; ++ if (fan_min > 254) ++ fan_min = 254; ++ } ++ } ++ if (fan_min != data->fan_min[nr]) { ++ data->fan_min[nr] = fan_min; ++ nct6775_write_value(data, data->REG_FAN_MIN[nr], ++ fan_min); ++ } ++ } ++ data->fan_div[nr] = fan_div; ++ nct6775_write_fan_div_common(data, nr); ++ } ++} ++ + static struct nct6775_data *nct6775_update_device(struct device *dev) + { + struct nct6775_data *data = dev_get_drvdata(dev); +@@ -565,6 +772,9 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + + if (time_after(jiffies, data->last_updated + HZ + HZ/2) + || !data->valid) { ++ /* Fan clock dividers */ ++ nct6775_update_fan_div_common(data); ++ + /* Measured voltages and limits */ + for (i = 0; i < data->in_num; i++) { + if (!(data->have_in & (1 << i))) +@@ -578,6 +788,24 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + data->REG_IN_MINMAX[1][i]); + } + ++ /* Measured fan speeds and limits */ ++ for (i = 0; i < 5; i++) { ++ u16 reg; ++ ++ if (!(data->has_fan & (1 << i))) ++ continue; ++ ++ reg = nct6775_read_value(data, data->REG_FAN[i]); ++ data->rpm[i] = data->fan_from_reg(reg, ++ data->fan_div[i]); ++ ++ if (data->has_fan_min & (1 << i)) ++ data->fan_min[i] = nct6775_read_value(data, ++ data->REG_FAN_MIN[i]); ++ ++ nct6775_select_fan_div(dev, data, i, reg); ++ } ++ + /* Measured temperatures and limits */ + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) +@@ -875,6 +1103,166 @@ static const struct attribute_group nct6775_group_in[15] = { + }; + + static ssize_t ++show_fan(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ return sprintf(buf, "%d\n", data->rpm[nr]); ++} ++ ++static ssize_t ++show_fan_min(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ return sprintf(buf, "%d\n", ++ data->fan_from_reg_min(data->fan_min[nr], ++ data->fan_div[nr])); ++} ++ ++static ssize_t ++show_fan_div(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); ++} ++ ++static ssize_t ++store_fan_min(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ unsigned int reg; ++ u8 new_div; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ mutex_lock(&data->update_lock); ++ if (!data->has_fan_div) { ++ /* NCT6776F or NCT6779D; we know this is a 13 bit register */ ++ if (!val) { ++ val = 0xff1f; ++ } else { ++ if (val > 1350000U) ++ val = 135000U; ++ val = 1350000U / val; ++ val = (val & 0x1f) | ((val << 3) & 0xff00); ++ } ++ data->fan_min[nr] = val; ++ goto write_min; /* Leave fan divider alone */ ++ } ++ if (!val) { ++ /* No min limit, alarm disabled */ ++ data->fan_min[nr] = 255; ++ new_div = data->fan_div[nr]; /* No change */ ++ dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1); ++ goto write_div; ++ } ++ reg = 1350000U / val; ++ if (reg >= 128 * 255) { ++ /* ++ * Speed below this value cannot possibly be represented, ++ * even with the highest divider (128) ++ */ ++ data->fan_min[nr] = 254; ++ new_div = 7; /* 128 == (1 << 7) */ ++ dev_warn(dev, ++ "fan%u low limit %lu below minimum %u, set to minimum\n", ++ nr + 1, val, data->fan_from_reg_min(254, 7)); ++ } else if (!reg) { ++ /* ++ * Speed above this value cannot possibly be represented, ++ * even with the lowest divider (1) ++ */ ++ data->fan_min[nr] = 1; ++ new_div = 0; /* 1 == (1 << 0) */ ++ dev_warn(dev, ++ "fan%u low limit %lu above maximum %u, set to maximum\n", ++ nr + 1, val, data->fan_from_reg_min(1, 0)); ++ } else { ++ /* ++ * Automatically pick the best divider, i.e. the one such ++ * that the min limit will correspond to a register value ++ * in the 96..192 range ++ */ ++ new_div = 0; ++ while (reg > 192 && new_div < 7) { ++ reg >>= 1; ++ new_div++; ++ } ++ data->fan_min[nr] = reg; ++ } ++ ++write_div: ++ /* ++ * Write both the fan clock divider (if it changed) and the new ++ * fan min (unconditionally) ++ */ ++ if (new_div != data->fan_div[nr]) { ++ dev_dbg(dev, "fan%u clock divider changed from %u to %u\n", ++ nr + 1, div_from_reg(data->fan_div[nr]), ++ div_from_reg(new_div)); ++ data->fan_div[nr] = new_div; ++ nct6775_write_fan_div_common(data, nr); ++ /* Give the chip time to sample a new speed value */ ++ data->last_updated = jiffies; ++ } ++ ++write_min: ++ nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static struct sensor_device_attribute sda_fan_input[] = { ++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), ++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), ++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), ++ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), ++ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), ++}; ++ ++static struct sensor_device_attribute sda_fan_alarm[] = { ++ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE), ++ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1), ++ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2), ++ SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3), ++ SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4), ++}; ++ ++static struct sensor_device_attribute sda_fan_min[] = { ++ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 0), ++ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 1), ++ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 2), ++ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 3), ++ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 4), ++}; ++ ++static struct sensor_device_attribute sda_fan_div[] = { ++ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), ++ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), ++ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), ++ SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), ++ SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), ++}; ++ ++static ssize_t + show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = nct6775_update_device(dev); +@@ -1228,6 +1616,12 @@ static void nct6775_device_remove_files(struct device *dev) + for (i = 0; i < data->in_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); + ++ for (i = 0; i < 5; i++) { ++ device_remove_file(dev, &sda_fan_input[i].dev_attr); ++ device_remove_file(dev, &sda_fan_alarm[i].dev_attr); ++ device_remove_file(dev, &sda_fan_div[i].dev_attr); ++ device_remove_file(dev, &sda_fan_min[i].dev_attr); ++ } + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) + continue; +@@ -1294,6 +1688,75 @@ static inline void nct6775_init_device(struct nct6775_data *data) + } + } + ++static int ++nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, ++ struct nct6775_data *data) ++{ ++ int regval; ++ bool fan3pin, fan3min, fan4pin, fan4min, fan5pin; ++ int ret; ++ ++ ret = superio_enter(sio_data->sioreg); ++ if (ret) ++ return ret; ++ ++ /* fan4 and fan5 share some pins with the GPIO and serial flash */ ++ if (data->kind == nct6775) { ++ regval = superio_inb(sio_data->sioreg, 0x2c); ++ ++ fan3pin = regval & (1 << 6); ++ fan3min = fan3pin; ++ ++ /* On NCT6775, fan4 shares pins with the fdc interface */ ++ fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); ++ fan4min = 0; ++ fan5pin = 0; ++ } else if (data->kind == nct6776) { ++ bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; ++ ++ superio_select(sio_data->sioreg, NCT6775_LD_HWM); ++ regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE); ++ ++ if (regval & 0x80) ++ fan3pin = gpok; ++ else ++ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); ++ ++ if (regval & 0x40) ++ fan4pin = gpok; ++ else ++ fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01; ++ ++ if (regval & 0x20) ++ fan5pin = gpok; ++ else ++ fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02; ++ ++ fan4min = fan4pin; ++ fan3min = fan3pin; ++ } else { /* NCT6779D */ ++ regval = superio_inb(sio_data->sioreg, 0x1c); ++ ++ fan3pin = !(regval & (1 << 5)); ++ fan4pin = !(regval & (1 << 6)); ++ fan5pin = !(regval & (1 << 7)); ++ ++ fan3min = fan3pin; ++ fan4min = fan4pin; ++ } ++ ++ superio_exit(sio_data->sioreg); ++ ++ data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */ ++ data->has_fan |= fan3pin << 2; ++ data->has_fan_min |= fan3min << 2; ++ ++ data->has_fan |= (fan4pin << 3) | (fan5pin << 4); ++ data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); ++ ++ return 0; ++} ++ + static int nct6775_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1327,10 +1790,14 @@ static int nct6775_probe(struct platform_device *pdev) + switch (data->kind) { + case nct6775: + data->in_num = 9; ++ data->has_fan_div = true; + data->temp_fixed_num = 3; + + data->ALARM_BITS = NCT6775_ALARM_BITS; + ++ data->fan_from_reg = fan_from_reg16; ++ data->fan_from_reg_min = fan_from_reg8; ++ + data->temp_label = nct6775_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); + +@@ -1340,6 +1807,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_FAN = NCT6775_REG_FAN; ++ data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1355,10 +1824,14 @@ static int nct6775_probe(struct platform_device *pdev) + break; + case nct6776: + data->in_num = 9; ++ data->has_fan_div = false; + data->temp_fixed_num = 3; + + data->ALARM_BITS = NCT6776_ALARM_BITS; + ++ data->fan_from_reg = fan_from_reg13; ++ data->fan_from_reg_min = fan_from_reg13; ++ + data->temp_label = nct6776_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); + +@@ -1368,6 +1841,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_FAN = NCT6775_REG_FAN; ++ data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1383,10 +1858,14 @@ static int nct6775_probe(struct platform_device *pdev) + break; + case nct6779: + data->in_num = 15; ++ data->has_fan_div = false; + data->temp_fixed_num = 6; + + data->ALARM_BITS = NCT6779_ALARM_BITS; + ++ data->fan_from_reg = fan_from_reg13; ++ data->fan_from_reg_min = fan_from_reg13; ++ + data->temp_label = nct6779_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); + +@@ -1396,6 +1875,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6779_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_FAN = NCT6779_REG_FAN; ++ data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6779_REG_ALARM; +@@ -1575,6 +2056,13 @@ static int nct6775_probe(struct platform_device *pdev) + if (err) + return err; + ++ err = nct6775_check_fan_inputs(sio_data, data); ++ if (err) ++ goto exit_remove; ++ ++ /* Read fan clock dividers immediately */ ++ nct6775_init_fan_common(dev, data); ++ + for (i = 0; i < data->in_num; i++) { + if (!(data->have_in & (1 << i))) + continue; +@@ -1583,6 +2071,32 @@ static int nct6775_probe(struct platform_device *pdev) + goto exit_remove; + } + ++ for (i = 0; i < 5; i++) { ++ if (data->has_fan & (1 << i)) { ++ err = device_create_file(dev, ++ &sda_fan_input[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ err = device_create_file(dev, ++ &sda_fan_alarm[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ if (data->kind != nct6776 && ++ data->kind != nct6779) { ++ err = device_create_file(dev, ++ &sda_fan_div[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (data->has_fan_min & (1 << i)) { ++ err = device_create_file(dev, ++ &sda_fan_min[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ } ++ } ++ + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) + continue; + +From 5c25d954d37b7c18606d7ef99122424552b86ef2 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 11 Dec 2012 07:29:06 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for fanX_pulses sysfs attribute + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index bafcae5..fea6ed7 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -205,6 +205,7 @@ static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; + + static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; + static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; ++static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; + + static const u16 NCT6775_REG_TEMP[] = { + 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; +@@ -264,6 +265,7 @@ static const s8 NCT6776_ALARM_BITS[] = { + 12, 9 }; /* intrusion0, intrusion1 */ + + static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; ++static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; + + static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; +@@ -319,6 +321,8 @@ static const s8 NCT6779_ALARM_BITS[] = { + 12, 9 }; /* intrusion0, intrusion1 */ + + static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; ++static const u16 NCT6779_REG_FAN_PULSES[] = { ++ 0x644, 0x645, 0x646, 0x647, 0x648 }; + + static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; + static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { +@@ -462,6 +466,7 @@ struct nct6775_data { + + const u16 *REG_FAN; + const u16 *REG_FAN_MIN; ++ const u16 *REG_FAN_PULSES; + + const u16 *REG_TEMP_SOURCE; /* temp register sources */ + const u16 *REG_TEMP_OFFSET; +@@ -481,6 +486,7 @@ struct nct6775_data { + u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ + unsigned int rpm[5]; + u16 fan_min[5]; ++ u8 fan_pulses[5]; + u8 fan_div[5]; + u8 has_fan; /* some fan inputs can be disabled */ + u8 has_fan_min; /* some fans don't have min register */ +@@ -802,6 +808,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + if (data->has_fan_min & (1 << i)) + data->fan_min[i] = nct6775_read_value(data, + data->REG_FAN_MIN[i]); ++ data->fan_pulses[i] = ++ nct6775_read_value(data, data->REG_FAN_PULSES[i]); + + nct6775_select_fan_div(dev, data, i, reg); + } +@@ -1225,6 +1233,41 @@ write_min: + return count; + } + ++static ssize_t ++show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int p = data->fan_pulses[sattr->index]; ++ ++ return sprintf(buf, "%d\n", p ? : 4); ++} ++ ++static ssize_t ++store_fan_pulses(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ if (val > 4) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->fan_pulses[nr] = val & 3; ++ nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ + static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), +@@ -1254,6 +1297,19 @@ static struct sensor_device_attribute sda_fan_min[] = { + store_fan_min, 4), + }; + ++static struct sensor_device_attribute sda_fan_pulses[] = { ++ SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, ++ store_fan_pulses, 0), ++ SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, ++ store_fan_pulses, 1), ++ SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, ++ store_fan_pulses, 2), ++ SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, ++ store_fan_pulses, 3), ++ SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, ++ store_fan_pulses, 4), ++}; ++ + static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), + SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), +@@ -1621,6 +1677,7 @@ static void nct6775_device_remove_files(struct device *dev) + device_remove_file(dev, &sda_fan_alarm[i].dev_attr); + device_remove_file(dev, &sda_fan_div[i].dev_attr); + device_remove_file(dev, &sda_fan_min[i].dev_attr); ++ device_remove_file(dev, &sda_fan_pulses[i].dev_attr); + } + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) +@@ -1809,6 +1866,7 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6775_REG_FAN; + data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; ++ data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1843,6 +1901,7 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6775_REG_FAN; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; ++ data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1877,6 +1936,7 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6779_REG_FAN; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; ++ data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6779_REG_ALARM; +@@ -2094,6 +2154,10 @@ static int nct6775_probe(struct platform_device *pdev) + if (err) + goto exit_remove; + } ++ err = device_create_file(dev, ++ &sda_fan_pulses[i].dev_attr); ++ if (err) ++ goto exit_remove; + } + } + + +From 47ece9645f288d46420d64dab90a182bde87bbbb Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 07:59:32 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for fan debounce module + parameter + +If set, fan debounce is enabled when loading the driver. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index fea6ed7..ffb56bb 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -72,6 +72,10 @@ static unsigned short force_id; + module_param(force_id, ushort, 0); + MODULE_PARM_DESC(force_id, "Override the detected device ID"); + ++static unsigned short fan_debounce; ++module_param(fan_debounce, ushort, 0); ++MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); ++ + #define DRVNAME "nct6775" + + /* +@@ -183,6 +187,8 @@ static const u16 NCT6775_REG_IN[] = { + #define NCT6775_REG_FANDIV1 0x506 + #define NCT6775_REG_FANDIV2 0x507 + ++#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0 ++ + static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; + + /* 0..15 voltages, 16..23 fans, 24..31 temperatures */ +@@ -2110,6 +2116,28 @@ static int nct6775_probe(struct platform_device *pdev) + */ + superio_select(sio_data->sioreg, NCT6775_LD_VID); + data->vid = superio_inb(sio_data->sioreg, 0xe3); ++ ++ if (fan_debounce) { ++ u8 tmp; ++ ++ superio_select(sio_data->sioreg, NCT6775_LD_HWM); ++ tmp = superio_inb(sio_data->sioreg, ++ NCT6775_REG_CR_FAN_DEBOUNCE); ++ switch (data->kind) { ++ case nct6775: ++ tmp |= 0x1e; ++ break; ++ case nct6776: ++ case nct6779: ++ tmp |= 0x3e; ++ break; ++ } ++ superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE, ++ tmp); ++ dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n", ++ data->name); ++ } ++ + superio_exit(sio_data->sioreg); + + err = device_create_file(dev, &dev_attr_cpu0_vid); + +From 84d19d92f78e10f8bdc1b3e1b5ddcaf5895edaf7 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 08:01:39 -0800 +Subject: [PATCH] hwmon: (nct6775) Add power management support + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index ffb56bb..56d7652 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -511,6 +511,12 @@ struct nct6775_data { + u16 have_temp; + u16 have_temp_fixed; + u16 have_in; ++#ifdef CONFIG_PM ++ /* Remember extra register values over suspend/resume */ ++ u8 vbat; ++ u8 fandiv1; ++ u8 fandiv2; ++#endif + }; + + struct nct6775_sio_data { +@@ -2270,10 +2276,90 @@ static int nct6775_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_PM ++static int nct6775_suspend(struct device *dev) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct nct6775_sio_data *sio_data = dev->platform_data; ++ ++ mutex_lock(&data->update_lock); ++ data->vbat = nct6775_read_value(data, data->REG_VBAT); ++ if (sio_data->kind == nct6775) { ++ data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1); ++ data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2); ++ } ++ mutex_unlock(&data->update_lock); ++ ++ return 0; ++} ++ ++static int nct6775_resume(struct device *dev) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct nct6775_sio_data *sio_data = dev->platform_data; ++ int i, j; ++ ++ mutex_lock(&data->update_lock); ++ data->bank = 0xff; /* Force initial bank selection */ ++ ++ /* Restore limits */ ++ for (i = 0; i < data->in_num; i++) { ++ if (!(data->have_in & (1 << i))) ++ continue; ++ ++ nct6775_write_value(data, data->REG_IN_MINMAX[0][i], ++ data->in[i][1]); ++ nct6775_write_value(data, data->REG_IN_MINMAX[1][i], ++ data->in[i][2]); ++ } ++ ++ for (i = 0; i < 5; i++) { ++ if (!(data->has_fan_min & (1 << i))) ++ continue; ++ ++ nct6775_write_value(data, data->REG_FAN_MIN[i], ++ data->fan_min[i]); ++ } ++ ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ ++ for (j = 1; j < 4; j++) ++ if (data->reg_temp[j][i]) ++ nct6775_write_temp(data, data->reg_temp[j][i], ++ data->temp[j][i]); ++ } ++ ++ /* Restore other settings */ ++ nct6775_write_value(data, data->REG_VBAT, data->vbat); ++ if (sio_data->kind == nct6775) { ++ nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1); ++ nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); ++ } ++ ++ /* Force re-reading all values */ ++ data->valid = false; ++ mutex_unlock(&data->update_lock); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops nct6775_dev_pm_ops = { ++ .suspend = nct6775_suspend, ++ .resume = nct6775_resume, ++}; ++ ++#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops) ++#else ++#define NCT6775_DEV_PM_OPS NULL ++#endif /* CONFIG_PM */ ++ + static struct platform_driver nct6775_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, ++ .pm = NCT6775_DEV_PM_OPS, + }, + .probe = nct6775_probe, + .remove = nct6775_remove, + +From 77eb5b3703d995e6c72ef4a1e5411821f81df7e4 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 08:30:54 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for pwm, pwm_mode, and + pwm_enable + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +index dcd56a3..7c9f1d3 100644 +--- a/Documentation/hwmon/nct6775 ++++ b/Documentation/hwmon/nct6775 +@@ -69,6 +69,24 @@ is driven slower/faster to reach the predefined range again. + + The mode works for fan1-fan5. + ++sysfs attributes ++---------------- ++ ++pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range: ++ 0 (lowest speed) to 255 (full) ++ ++pwm[1-5]_enable - this file controls mode of fan/temperature control: ++ * 0 Fan control disabled (fans set to maximum speed) ++ * 1 Manual mode, write to pwm[0-5] any value 0-255 ++ * 2 "Thermal Cruise" mode ++ * 3 "Fan Speed Cruise" mode ++ * 4 "Smart Fan III" mode (NCT6775F only) ++ * 5 "Smart Fan IV" mode ++ ++pwm[1-5]_mode - controls if output is PWM or DC level ++ * 0 DC output ++ * 1 PWM output ++ + Usage Notes + ----------- + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 56d7652..ad4ecc0 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -96,6 +96,8 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); + #define SIO_NCT6779_ID 0xc560 + #define SIO_ID_MASK 0xFFF0 + ++enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; ++ + static inline void + superio_outb(int ioreg, int reg, int val) + { +@@ -209,6 +211,15 @@ static const s8 NCT6775_ALARM_BITS[] = { + static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; + static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; + ++/* DC or PWM output fan configuration */ ++static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 }; ++static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 }; ++ ++static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; ++ ++static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; ++static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; ++ + static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; + static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; + static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; +@@ -270,6 +281,9 @@ static const s8 NCT6776_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; ++static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; ++ + static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; + static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; + +@@ -380,6 +394,20 @@ static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] + static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] + = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; + ++static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) ++{ ++ if (mode == 0 && pwm == 255) ++ return off; ++ return mode + 1; ++} ++ ++static int pwm_enable_to_reg(enum pwm_enable mode) ++{ ++ if (mode == off) ++ return 0; ++ return mode - 1; ++} ++ + /* + * Conversions + */ +@@ -471,9 +499,16 @@ struct nct6775_data { + const u16 *REG_IN_MINMAX[2]; + + const u16 *REG_FAN; ++ const u16 *REG_FAN_MODE; + const u16 *REG_FAN_MIN; + const u16 *REG_FAN_PULSES; + ++ const u8 *REG_PWM_MODE; ++ const u8 *PWM_MODE_MASK; ++ ++ const u16 *REG_PWM[1]; /* [0]=pwm */ ++ const u16 *REG_PWM_READ; ++ + const u16 *REG_TEMP_SOURCE; /* temp register sources */ + const u16 *REG_TEMP_OFFSET; + +@@ -494,6 +529,7 @@ struct nct6775_data { + u16 fan_min[5]; + u8 fan_pulses[5]; + u8 fan_div[5]; ++ u8 has_pwm; + u8 has_fan; /* some fan inputs can be disabled */ + u8 has_fan_min; /* some fans don't have min register */ + bool has_fan_div; +@@ -505,6 +541,18 @@ struct nct6775_data { + * 3=temp_crit */ + u64 alarms; + ++ u8 pwm_num; /* number of pwm */ ++ u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */ ++ enum pwm_enable pwm_enable[5]; ++ /* 0->off ++ * 1->manual ++ * 2->thermal cruise mode (also called SmartFan I) ++ * 3->fan speed cruise mode ++ * 4->SmartFan III ++ * 5->enhanced variable thermal cruise (SmartFan IV) ++ */ ++ u8 pwm[1][5]; /* [0]=pwm */ ++ + u8 vid; + u8 vrm; + +@@ -781,6 +829,36 @@ static void nct6775_select_fan_div(struct device *dev, + } + } + ++static void nct6775_update_pwm(struct device *dev) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ int i, j; ++ int fanmodecfg; ++ bool duty_is_dc; ++ ++ for (i = 0; i < data->pwm_num; i++) { ++ if (!(data->has_pwm & (1 << i))) ++ continue; ++ ++ duty_is_dc = data->REG_PWM_MODE[i] && ++ (nct6775_read_value(data, data->REG_PWM_MODE[i]) ++ & data->PWM_MODE_MASK[i]); ++ data->pwm_mode[i] = duty_is_dc; ++ ++ fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]); ++ for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) { ++ if (data->REG_PWM[j] && data->REG_PWM[j][i]) { ++ data->pwm[j][i] ++ = nct6775_read_value(data, ++ data->REG_PWM[j][i]); ++ } ++ } ++ ++ data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i], ++ (fanmodecfg >> 4) & 7); ++ } ++} ++ + static struct nct6775_data *nct6775_update_device(struct device *dev) + { + struct nct6775_data *data = dev_get_drvdata(dev); +@@ -826,6 +904,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + nct6775_select_fan_div(dev, data, i, reg); + } + ++ nct6775_update_pwm(dev); ++ + /* Measured temperatures and limits */ + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) +@@ -1600,6 +1680,170 @@ static struct sensor_device_attribute sda_temp_alarm[] = { + #define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm) + + static ssize_t ++show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ ++ return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]); ++} ++ ++static ssize_t ++store_pwm_mode(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ u8 reg; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ if (val > 1) ++ return -EINVAL; ++ ++ /* Setting DC mode is not supported for all chips/channels */ ++ if (data->REG_PWM_MODE[nr] == 0) { ++ if (val) ++ return -EINVAL; ++ return count; ++ } ++ ++ mutex_lock(&data->update_lock); ++ data->pwm_mode[nr] = val; ++ reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]); ++ reg &= ~data->PWM_MODE_MASK[nr]; ++ if (val) ++ reg |= data->PWM_MODE_MASK[nr]; ++ nct6775_write_value(data, data->REG_PWM_MODE[nr], reg); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_pwm(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ int pwm; ++ ++ /* ++ * For automatic fan control modes, show current pwm readings. ++ * Otherwise, show the configured value. ++ */ ++ if (index == 0 && data->pwm_enable[nr] > manual) ++ pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]); ++ else ++ pwm = data->pwm[index][nr]; ++ ++ return sprintf(buf, "%d\n", pwm); ++} ++ ++static ssize_t ++store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ val = clamp_val(val, 0, 255); ++ ++ mutex_lock(&data->update_lock); ++ data->pwm[index][nr] = val; ++ nct6775_write_value(data, data->REG_PWM[index][nr], val); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ ++ return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]); ++} ++ ++static ssize_t ++store_pwm_enable(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ u16 reg; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ if (val > sf4) ++ return -EINVAL; ++ ++ if (val == sf3 && data->kind != nct6775) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->pwm_enable[nr] = val; ++ if (val == off) { ++ /* ++ * turn off pwm control: select manual mode, set pwm to maximum ++ */ ++ data->pwm[0][nr] = 255; ++ nct6775_write_value(data, data->REG_PWM[0][nr], 255); ++ } ++ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); ++ reg &= 0x0f; ++ reg |= pwm_enable_to_reg(val) << 4; ++ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0); ++static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0); ++static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0); ++static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0); ++static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0); ++ ++static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, ++ store_pwm_mode, 0); ++static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, ++ store_pwm_mode, 1); ++static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode, ++ store_pwm_mode, 2); ++static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode, ++ store_pwm_mode, 3); ++static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode, ++ store_pwm_mode, 4); ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, ++ store_pwm_enable, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, ++ store_pwm_enable, 1); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable, ++ store_pwm_enable, 2); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, ++ store_pwm_enable, 3); ++static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable, ++ store_pwm_enable, 4); ++ ++static ssize_t + show_name(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = dev_get_drvdata(dev); +@@ -1609,6 +1853,47 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf) + + static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + ++static struct attribute *nct6775_attributes_pwm[5][4] = { ++ { ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm1_mode.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm2_mode.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm3_mode.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ &sensor_dev_attr_pwm4_mode.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ NULL ++ }, ++ { ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++ &sensor_dev_attr_pwm5_mode.dev_attr.attr, ++ &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ NULL ++ }, ++}; ++ ++static const struct attribute_group nct6775_group_pwm[5] = { ++ { .attrs = nct6775_attributes_pwm[0] }, ++ { .attrs = nct6775_attributes_pwm[1] }, ++ { .attrs = nct6775_attributes_pwm[2] }, ++ { .attrs = nct6775_attributes_pwm[3] }, ++ { .attrs = nct6775_attributes_pwm[4] }, ++}; ++ + static ssize_t + show_vid(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -1681,6 +1966,9 @@ static void nct6775_device_remove_files(struct device *dev) + int i; + struct nct6775_data *data = dev_get_drvdata(dev); + ++ for (i = 0; i < data->pwm_num; i++) ++ sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]); ++ + for (i = 0; i < data->in_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); + +@@ -1763,6 +2051,7 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + { + int regval; + bool fan3pin, fan3min, fan4pin, fan4min, fan5pin; ++ bool pwm3pin, pwm4pin, pwm5pin; + int ret; + + ret = superio_enter(sio_data->sioreg); +@@ -1775,11 +2064,14 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + + fan3pin = regval & (1 << 6); + fan3min = fan3pin; ++ pwm3pin = regval & (1 << 7); + + /* On NCT6775, fan4 shares pins with the fdc interface */ + fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); + fan4min = 0; + fan5pin = 0; ++ pwm4pin = 0; ++ pwm5pin = 0; + } else if (data->kind == nct6776) { + bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; + +@@ -1803,6 +2095,9 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + + fan4min = fan4pin; + fan3min = fan3pin; ++ pwm3pin = fan3pin; ++ pwm4pin = 0; ++ pwm5pin = 0; + } else { /* NCT6779D */ + regval = superio_inb(sio_data->sioreg, 0x1c); + +@@ -1810,6 +2105,10 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + fan4pin = !(regval & (1 << 6)); + fan5pin = !(regval & (1 << 7)); + ++ pwm3pin = !(regval & (1 << 0)); ++ pwm4pin = !(regval & (1 << 1)); ++ pwm5pin = !(regval & (1 << 2)); ++ + fan3min = fan3pin; + fan4min = fan4pin; + } +@@ -1823,6 +2122,8 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + data->has_fan |= (fan4pin << 3) | (fan5pin << 4); + data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); + ++ data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4); ++ + return 0; + } + +@@ -1859,6 +2160,7 @@ static int nct6775_probe(struct platform_device *pdev) + switch (data->kind) { + case nct6775: + data->in_num = 9; ++ data->pwm_num = 3; + data->has_fan_div = true; + data->temp_fixed_num = 3; + +@@ -1877,8 +2179,13 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6775_REG_FAN; ++ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; ++ data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM_READ = NCT6775_REG_PWM_READ; ++ data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; ++ data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1894,6 +2201,7 @@ static int nct6775_probe(struct platform_device *pdev) + break; + case nct6776: + data->in_num = 9; ++ data->pwm_num = 3; + data->has_fan_div = false; + data->temp_fixed_num = 3; + +@@ -1912,8 +2220,13 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6775_REG_FAN; ++ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; ++ data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM_READ = NCT6775_REG_PWM_READ; ++ data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; ++ data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6775_REG_ALARM; +@@ -1929,6 +2242,7 @@ static int nct6775_probe(struct platform_device *pdev) + break; + case nct6779: + data->in_num = 15; ++ data->pwm_num = 5; + data->has_fan_div = false; + data->temp_fixed_num = 6; + +@@ -1947,8 +2261,13 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_FAN = NCT6779_REG_FAN; ++ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; ++ data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM_READ = NCT6775_REG_PWM_READ; ++ data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; ++ data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_ALARM = NCT6779_REG_ALARM; +@@ -2157,6 +2476,16 @@ static int nct6775_probe(struct platform_device *pdev) + /* Read fan clock dividers immediately */ + nct6775_init_fan_common(dev, data); + ++ /* Register sysfs hooks */ ++ for (i = 0; i < data->pwm_num; i++) { ++ if (!(data->has_pwm & (1 << i))) ++ continue; ++ ++ err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]); ++ if (err) ++ goto exit_remove; ++ } ++ + for (i = 0; i < data->in_num; i++) { + if (!(data->have_in & (1 << i))) + continue; + +From cdcaeceb74ff3686eb25de6812870fbc765c3c39 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 09:04:52 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for automatic fan control + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +index 7c9f1d3..b4fe6bc 100644 +--- a/Documentation/hwmon/nct6775 ++++ b/Documentation/hwmon/nct6775 +@@ -87,6 +87,75 @@ pwm[1-5]_mode - controls if output is PWM or DC level + * 0 DC output + * 1 PWM output + ++Common fan control attributes ++----------------------------- ++ ++pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. ++ For example, select '1' for temp1_input. ++ ++Thermal Cruise mode (2) ++----------------------- ++ ++If the temperature is in the range defined by: ++ ++pwm[1-5]_target_temp Target temperature, unit millidegree Celsius ++ (range 0 - 127000) ++pwm[1-5]_temp_tolerance ++ Target temperature tolerance, unit millidegree Celsius ++ ++there are no changes to fan speed. Once the temperature leaves the interval, fan ++speed increases (if temperature is higher that desired) or decreases (if ++temperature is lower than desired), using the following limits and time ++intervals. ++ ++pwm[1-5]_start fan pwm start value (range 1 - 255), to start fan ++ when the temperature is above defined range. ++pwm[1-5]_floor lowest fan pwm (range 0 - 255) if temperature is below ++ the defined range. If set to 0, the fan is expected to ++ stop if the temperature is below the defined range. ++pwm[1-5]_step_up_time milliseconds before fan speed is increased ++pwm[1-5]_step_down_time milliseconds before fan speed is decreased ++pwm[1-5]_stop_time how many milliseconds must elapse to switch ++ corresponding fan off (when the temperature was below ++ defined range). ++ ++Speed Cruise mode (3) ++--------------------- ++ ++This modes tries to keep the fan speed constant. ++ ++fan[1-5]_target Target fan speed ++fan[1-5]_tolerance ++ Target speed tolerance ++ ++ ++Untested; use at your own risk. ++ ++Smart Fan IV mode (5) ++--------------------- ++ ++This mode offers multiple slopes to control the fan speed. The slopes can be ++controlled by setting the pwm and temperature attributes. When the temperature ++rises, the chip will calculate the DC/PWM output based on the current slope. ++There are up to seven data points depending on the chip type. Subsequent data ++points should be set to higher temperatures and higher pwm values to achieve ++higher fan speeds with increasing temperature. The last data point reflects ++critical temperature mode, in which the fans should run at full speed. ++ ++pwm[1-5]_auto_point[1-7]_pwm ++ pwm value to be set if temperature reaches matching ++ temperature range. ++pwm[1-5]_auto_point[1-7]_temp ++ Temperature over which the matching pwm is enabled. ++pwm[1-5]_temp_tolerance ++ Temperature tolerance, unit millidegree Celsius ++pwm[1-5]_crit_temp_tolerance ++ Temperature tolerance for critical temperature, ++ unit millidegree Celsius ++ ++pwm[1-5]_step_up_time milliseconds before fan speed is increased ++pwm[1-5]_step_down_time milliseconds before fan speed is decreased ++ + Usage Notes + ----------- + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index ad4ecc0..47b1d89 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -215,8 +215,23 @@ static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; + static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 }; + static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 }; + +-static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; ++/* Advanced Fan control, some values are common for all fans */ + ++static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 }; ++static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; ++static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = { ++ 0x103, 0x203, 0x303, 0x803, 0x903 }; ++static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = { ++ 0x104, 0x204, 0x304, 0x804, 0x904 }; ++static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { ++ 0x105, 0x205, 0x305, 0x805, 0x905 }; ++static const u16 NCT6775_REG_FAN_START_OUTPUT[] ++ = { 0x106, 0x206, 0x306, 0x806, 0x906 }; ++static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a }; ++static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b }; ++ ++static const u16 NCT6775_REG_FAN_STOP_TIME[] = { ++ 0x107, 0x207, 0x307, 0x807, 0x907 }; + static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; + static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; + +@@ -237,8 +252,26 @@ static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; + ++static const u16 NCT6775_REG_TEMP_SEL[] = { ++ 0x100, 0x200, 0x300, 0x800, 0x900 }; ++ + static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; + ++static const u16 NCT6775_REG_AUTO_TEMP[] = { ++ 0x121, 0x221, 0x321, 0x821, 0x921 }; ++static const u16 NCT6775_REG_AUTO_PWM[] = { ++ 0x127, 0x227, 0x327, 0x827, 0x927 }; ++ ++#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p)) ++#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p)) ++ ++static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 }; ++ ++static const u16 NCT6775_REG_CRITICAL_TEMP[] = { ++ 0x135, 0x235, 0x335, 0x835, 0x935 }; ++static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = { ++ 0x138, 0x238, 0x338, 0x838, 0x938 }; ++ + static const char *const nct6775_temp_label[] = { + "", + "SYSTIN", +@@ -281,6 +314,9 @@ static const s8 NCT6776_ALARM_BITS[] = { + 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ + 12, 9 }; /* intrusion0, intrusion1 */ + ++static const u16 NCT6776_REG_TOLERANCE_H[] = { ++ 0x10c, 0x20c, 0x30c, 0x80c, 0x90c }; ++ + static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; + static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; + +@@ -344,6 +380,11 @@ static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; + static const u16 NCT6779_REG_FAN_PULSES[] = { + 0x644, 0x645, 0x646, 0x647, 0x648 }; + ++static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { ++ 0x136, 0x236, 0x336, 0x836, 0x936 }; ++static const u16 NCT6779_REG_CRITICAL_PWM[] = { ++ 0x137, 0x237, 0x337, 0x837, 0x937 }; ++ + static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; + static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { + 0x18, 0x152 }; +@@ -412,6 +453,18 @@ static int pwm_enable_to_reg(enum pwm_enable mode) + * Conversions + */ + ++/* 1 is DC mode, output in ms */ ++static unsigned int step_time_from_reg(u8 reg, u8 mode) ++{ ++ return mode ? 400 * reg : 100 * reg; ++} ++ ++static u8 step_time_to_reg(unsigned int msec, u8 mode) ++{ ++ return clamp_val((mode ? (msec + 200) / 400 : ++ (msec + 50) / 100), 1, 255); ++} ++ + static unsigned int fan_from_reg8(u16 reg, unsigned int divreg) + { + if (reg == 0 || reg == 255) +@@ -444,6 +497,14 @@ static unsigned int fan_from_reg16(u16 reg, unsigned int divreg) + return 1350000U / (reg << divreg); + } + ++static u16 fan_to_reg(u32 fan, unsigned int divreg) ++{ ++ if (!fan) ++ return 0; ++ ++ return (1350000U / fan) >> divreg; ++} ++ + static inline unsigned int + div_from_reg(u8 reg) + { +@@ -498,18 +559,31 @@ struct nct6775_data { + const u16 *REG_VIN; + const u16 *REG_IN_MINMAX[2]; + ++ const u16 *REG_TARGET; + const u16 *REG_FAN; + const u16 *REG_FAN_MODE; + const u16 *REG_FAN_MIN; + const u16 *REG_FAN_PULSES; ++ const u16 *REG_FAN_TIME[3]; ++ ++ const u16 *REG_TOLERANCE_H; + + const u8 *REG_PWM_MODE; + const u8 *PWM_MODE_MASK; + +- const u16 *REG_PWM[1]; /* [0]=pwm */ ++ const u16 *REG_PWM[5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, ++ * [3]=pwm_max, [4]=pwm_step ++ */ + const u16 *REG_PWM_READ; + ++ const u16 *REG_AUTO_TEMP; ++ const u16 *REG_AUTO_PWM; ++ ++ const u16 *REG_CRITICAL_TEMP; ++ const u16 *REG_CRITICAL_TEMP_TOLERANCE; ++ + const u16 *REG_TEMP_SOURCE; /* temp register sources */ ++ const u16 *REG_TEMP_SEL; + const u16 *REG_TEMP_OFFSET; + + const u16 *REG_ALARM; +@@ -551,7 +625,26 @@ struct nct6775_data { + * 4->SmartFan III + * 5->enhanced variable thermal cruise (SmartFan IV) + */ +- u8 pwm[1][5]; /* [0]=pwm */ ++ u8 pwm[5][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, ++ * [3]=pwm_max, [4]=pwm_step ++ */ ++ ++ u8 target_temp[5]; ++ u8 target_temp_mask; ++ u32 target_speed[5]; ++ u32 target_speed_tolerance[5]; ++ u8 speed_tolerance_limit; ++ ++ u8 temp_tolerance[2][5]; ++ u8 tolerance_mask; ++ ++ u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */ ++ ++ /* Automatic fan speed control registers */ ++ int auto_pwm_num; ++ u8 auto_pwm[5][7]; ++ u8 auto_temp[5][7]; ++ u8 pwm_temp_sel[5]; + + u8 vid; + u8 vrm; +@@ -833,7 +926,7 @@ static void nct6775_update_pwm(struct device *dev) + { + struct nct6775_data *data = dev_get_drvdata(dev); + int i, j; +- int fanmodecfg; ++ int fanmodecfg, reg; + bool duty_is_dc; + + for (i = 0; i < data->pwm_num; i++) { +@@ -856,6 +949,96 @@ static void nct6775_update_pwm(struct device *dev) + + data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i], + (fanmodecfg >> 4) & 7); ++ ++ if (!data->temp_tolerance[0][i] || ++ data->pwm_enable[i] != speed_cruise) ++ data->temp_tolerance[0][i] = fanmodecfg & 0x0f; ++ if (!data->target_speed_tolerance[i] || ++ data->pwm_enable[i] == speed_cruise) { ++ u8 t = fanmodecfg & 0x0f; ++ if (data->REG_TOLERANCE_H) { ++ t |= (nct6775_read_value(data, ++ data->REG_TOLERANCE_H[i]) & 0x70) >> 1; ++ } ++ data->target_speed_tolerance[i] = t; ++ } ++ ++ data->temp_tolerance[1][i] = ++ nct6775_read_value(data, ++ data->REG_CRITICAL_TEMP_TOLERANCE[i]); ++ ++ reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]); ++ data->pwm_temp_sel[i] = reg & 0x1f; ++ /* If fan can stop, report floor as 0 */ ++ if (reg & 0x80) ++ data->pwm[2][i] = 0; ++ } ++} ++ ++static void nct6775_update_pwm_limits(struct device *dev) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ int i, j; ++ u8 reg; ++ u16 reg_t; ++ ++ for (i = 0; i < data->pwm_num; i++) { ++ if (!(data->has_pwm & (1 << i))) ++ continue; ++ ++ for (j = 0; j < 3; j++) { ++ data->fan_time[j][i] = ++ nct6775_read_value(data, data->REG_FAN_TIME[j][i]); ++ } ++ ++ reg_t = nct6775_read_value(data, data->REG_TARGET[i]); ++ /* Update only in matching mode or if never updated */ ++ if (!data->target_temp[i] || ++ data->pwm_enable[i] == thermal_cruise) ++ data->target_temp[i] = reg_t & data->target_temp_mask; ++ if (!data->target_speed[i] || ++ data->pwm_enable[i] == speed_cruise) { ++ if (data->REG_TOLERANCE_H) { ++ reg_t |= (nct6775_read_value(data, ++ data->REG_TOLERANCE_H[i]) & 0x0f) << 8; ++ } ++ data->target_speed[i] = reg_t; ++ } ++ ++ for (j = 0; j < data->auto_pwm_num; j++) { ++ data->auto_pwm[i][j] = ++ nct6775_read_value(data, ++ NCT6775_AUTO_PWM(data, i, j)); ++ data->auto_temp[i][j] = ++ nct6775_read_value(data, ++ NCT6775_AUTO_TEMP(data, i, j)); ++ } ++ ++ /* critical auto_pwm temperature data */ ++ data->auto_temp[i][data->auto_pwm_num] = ++ nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]); ++ ++ switch (data->kind) { ++ case nct6775: ++ reg = nct6775_read_value(data, ++ NCT6775_REG_CRITICAL_ENAB[i]); ++ data->auto_pwm[i][data->auto_pwm_num] = ++ (reg & 0x02) ? 0xff : 0x00; ++ break; ++ case nct6776: ++ data->auto_pwm[i][data->auto_pwm_num] = 0xff; ++ break; ++ case nct6779: ++ reg = nct6775_read_value(data, ++ NCT6779_REG_CRITICAL_PWM_ENABLE[i]); ++ if (reg & 1) ++ data->auto_pwm[i][data->auto_pwm_num] = ++ nct6775_read_value(data, ++ NCT6779_REG_CRITICAL_PWM[i]); ++ else ++ data->auto_pwm[i][data->auto_pwm_num] = 0xff; ++ break; ++ } + } + } + +@@ -905,6 +1088,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + } + + nct6775_update_pwm(dev); ++ nct6775_update_pwm_limits(dev); + + /* Measured temperatures and limits */ + for (i = 0; i < NUM_TEMP; i++) { +@@ -1754,20 +1938,91 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, + int nr = sattr->nr; + int index = sattr->index; + unsigned long val; ++ int minval[5] = { 0, 1, 1, data->pwm[2][nr], 0 }; ++ int maxval[5] ++ = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255 }; + int err; ++ u8 reg; + + err = kstrtoul(buf, 10, &val); + if (err < 0) + return err; +- val = clamp_val(val, 0, 255); ++ val = clamp_val(val, minval[index], maxval[index]); + + mutex_lock(&data->update_lock); + data->pwm[index][nr] = val; + nct6775_write_value(data, data->REG_PWM[index][nr], val); ++ if (index == 2) { /* floor: disable if val == 0 */ ++ reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); ++ reg &= 0x7f; ++ if (val) ++ reg |= 0x80; ++ nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); ++ } + mutex_unlock(&data->update_lock); + return count; + } + ++/* Returns 0 if OK, -EINVAL otherwise */ ++static int check_trip_points(struct nct6775_data *data, int nr) ++{ ++ int i; ++ ++ for (i = 0; i < data->auto_pwm_num - 1; i++) { ++ if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) ++ return -EINVAL; ++ } ++ for (i = 0; i < data->auto_pwm_num - 1; i++) { ++ if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) ++ return -EINVAL; ++ } ++ /* validate critical temperature and pwm if enabled (pwm > 0) */ ++ if (data->auto_pwm[nr][data->auto_pwm_num]) { ++ if (data->auto_temp[nr][data->auto_pwm_num - 1] > ++ data->auto_temp[nr][data->auto_pwm_num] || ++ data->auto_pwm[nr][data->auto_pwm_num - 1] > ++ data->auto_pwm[nr][data->auto_pwm_num]) ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void pwm_update_registers(struct nct6775_data *data, int nr) ++{ ++ u8 reg; ++ ++ switch (data->pwm_enable[nr]) { ++ case off: ++ case manual: ++ break; ++ case speed_cruise: ++ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); ++ reg = (reg & ~data->tolerance_mask) | ++ (data->target_speed_tolerance[nr] & data->tolerance_mask); ++ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); ++ nct6775_write_value(data, data->REG_TARGET[nr], ++ data->target_speed[nr] & 0xff); ++ if (data->REG_TOLERANCE_H) { ++ reg = (data->target_speed[nr] >> 8) & 0x0f; ++ reg |= (data->target_speed_tolerance[nr] & 0x38) << 1; ++ nct6775_write_value(data, ++ data->REG_TOLERANCE_H[nr], ++ reg); ++ } ++ break; ++ case thermal_cruise: ++ nct6775_write_value(data, data->REG_TARGET[nr], ++ data->target_temp[nr]); ++ /* intentional */ ++ default: ++ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); ++ reg = (reg & ~data->tolerance_mask) | ++ data->temp_tolerance[0][nr]; ++ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); ++ break; ++ } ++} ++ + static ssize_t + show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -1798,6 +2053,12 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, + if (val == sf3 && data->kind != nct6775) + return -EINVAL; + ++ if (val == sf4 && check_trip_points(data, nr)) { ++ dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n"); ++ dev_err(dev, "Adjust trip points and try again\n"); ++ return -EINVAL; ++ } ++ + mutex_lock(&data->update_lock); + data->pwm_enable[nr] = val; + if (val == off) { +@@ -1807,6 +2068,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, + data->pwm[0][nr] = 255; + nct6775_write_value(data, data->REG_PWM[0][nr], 255); + } ++ pwm_update_registers(data, nr); + reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); + reg &= 0x0f; + reg |= pwm_enable_to_reg(val) << 4; +@@ -1815,6 +2077,235 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, + return count; + } + ++static ssize_t ++show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int i, src, sel = 0; ++ ++ src = data->pwm_temp_sel[sattr->index]; ++ ++ for (i = 0; i < NUM_TEMP; i++) { ++ if (!(data->have_temp & (1 << i))) ++ continue; ++ if (src == data->temp_src[i]) { ++ sel = i + 1; ++ break; ++ } ++ } ++ ++ return sprintf(buf, "%d\n", sel); ++} ++ ++static ssize_t ++store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err, reg, src; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ if (val == 0 || val > NUM_TEMP) ++ return -EINVAL; ++ if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1]) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ src = data->temp_src[val - 1]; ++ data->pwm_temp_sel[nr] = src; ++ reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); ++ reg &= 0xe0; ++ reg |= src; ++ nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t ++show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ ++ return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000); ++} ++ ++static ssize_t ++store_target_temp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, ++ data->target_temp_mask); ++ ++ mutex_lock(&data->update_lock); ++ data->target_temp[nr] = val; ++ pwm_update_registers(data, nr); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_target_speed(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ ++ return sprintf(buf, "%d\n", ++ fan_from_reg16(data->target_speed[nr], ++ data->fan_div[nr])); ++} ++ ++static ssize_t ++store_target_speed(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ u16 speed; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ val = clamp_val(val, 0, 1350000U); ++ speed = fan_to_reg(val, data->fan_div[nr]); ++ ++ mutex_lock(&data->update_lock); ++ data->target_speed[nr] = speed; ++ pwm_update_registers(data, nr); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_temp_tolerance(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ ++ return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000); ++} ++ ++static ssize_t ++store_temp_tolerance(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ /* Limit tolerance as needed */ ++ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask); ++ ++ mutex_lock(&data->update_lock); ++ data->temp_tolerance[index][nr] = val; ++ if (index) ++ pwm_update_registers(data, nr); ++ else ++ nct6775_write_value(data, ++ data->REG_CRITICAL_TEMP_TOLERANCE[nr], ++ val); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++/* ++ * Fan speed tolerance is a tricky beast, since the associated register is ++ * a tick counter, but the value is reported and configured as rpm. ++ * Compute resulting low and high rpm values and report the difference. ++ */ ++static ssize_t ++show_speed_tolerance(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ int low = data->target_speed[nr] - data->target_speed_tolerance[nr]; ++ int high = data->target_speed[nr] + data->target_speed_tolerance[nr]; ++ int tolerance; ++ ++ if (low <= 0) ++ low = 1; ++ if (high > 0xffff) ++ high = 0xffff; ++ if (high < low) ++ high = low; ++ ++ tolerance = (fan_from_reg16(low, data->fan_div[nr]) ++ - fan_from_reg16(high, data->fan_div[nr])) / 2; ++ ++ return sprintf(buf, "%d\n", tolerance); ++} ++ ++static ssize_t ++store_speed_tolerance(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err; ++ int low, high; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ high = fan_from_reg16(data->target_speed[nr], ++ data->fan_div[nr]) + val; ++ low = fan_from_reg16(data->target_speed[nr], ++ data->fan_div[nr]) - val; ++ if (low <= 0) ++ low = 1; ++ if (high < low) ++ high = low; ++ ++ val = (fan_to_reg(low, data->fan_div[nr]) - ++ fan_to_reg(high, data->fan_div[nr])) / 2; ++ ++ /* Limit tolerance as needed */ ++ val = clamp_val(val, 0, data->speed_tolerance_limit); ++ ++ mutex_lock(&data->update_lock); ++ data->target_speed_tolerance[nr] = val; ++ pwm_update_registers(data, nr); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ + static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0); + static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0); + static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0); +@@ -1843,6 +2334,88 @@ static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, + static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable, + store_pwm_enable, 4); + ++static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_temp_sel, store_pwm_temp_sel, 0); ++static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_temp_sel, store_pwm_temp_sel, 1); ++static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_temp_sel, store_pwm_temp_sel, 2); ++static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_temp_sel, store_pwm_temp_sel, 3); ++static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_temp_sel, store_pwm_temp_sel, 4); ++ ++static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp, ++ store_target_temp, 0); ++static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp, ++ store_target_temp, 1); ++static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp, ++ store_target_temp, 2); ++static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp, ++ store_target_temp, 3); ++static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp, ++ store_target_temp, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed, ++ store_target_speed, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed, ++ store_target_speed, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed, ++ store_target_speed, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed, ++ store_target_speed, 3); ++static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed, ++ store_target_speed, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO, ++ show_speed_tolerance, store_speed_tolerance, 0); ++static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO, ++ show_speed_tolerance, store_speed_tolerance, 1); ++static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO, ++ show_speed_tolerance, store_speed_tolerance, 2); ++static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO, ++ show_speed_tolerance, store_speed_tolerance, 3); ++static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO, ++ show_speed_tolerance, store_speed_tolerance, 4); ++ ++/* Smart Fan registers */ ++ ++static ssize_t ++show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ ++ return sprintf(buf, "%d\n", ++ step_time_from_reg(data->fan_time[index][nr], ++ data->pwm_mode[nr])); ++} ++ ++static ssize_t ++store_fan_time(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ val = step_time_to_reg(val, data->pwm_mode[nr]); ++ mutex_lock(&data->update_lock); ++ data->fan_time[index][nr] = val; ++ nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ + static ssize_t + show_name(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -1853,35 +2426,190 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf) + + static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +-static struct attribute *nct6775_attributes_pwm[5][4] = { ++static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 0, 0); ++static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 1, 0); ++static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 2, 0); ++static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 3, 0); ++static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 4, 0); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 0, 1); ++static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 1, 1); ++static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 2, 1); ++static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 3, 1); ++static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, ++ store_fan_time, 4, 1); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO, ++ show_fan_time, store_fan_time, 0, 2); ++static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO, ++ show_fan_time, store_fan_time, 1, 2); ++static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO, ++ show_fan_time, store_fan_time, 2, 2); ++static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO, ++ show_fan_time, store_fan_time, 3, 2); ++static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO, ++ show_fan_time, store_fan_time, 4, 2); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 0, 1); ++static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 1, 1); ++static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 2, 1); ++static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 3, 1); ++static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 4, 1); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 0, 2); ++static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 1, 2); ++static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 2, 2); ++static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 3, 2); ++static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm, ++ store_pwm, 4, 2); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 0, 0); ++static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 1, 0); ++static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 2, 0); ++static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 3, 0); ++static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 4, 0); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 0, 1); ++static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 1, 1); ++static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 2, 1); ++static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 3, 1); ++static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO, ++ show_temp_tolerance, store_temp_tolerance, 4, 1); ++ ++/* pwm_max is not supported on all chips */ ++static struct sensor_device_attribute_2 sda_pwm_max[] = { ++ SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, ++ 0, 3), ++ SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, ++ 1, 3), ++ SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, ++ 2, 3), ++ SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, ++ 3, 3), ++ SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, ++ 4, 3), ++}; ++ ++/* pwm_step is not supported on all chips */ ++static struct sensor_device_attribute_2 sda_pwm_step[] = { ++ SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4), ++ SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4), ++ SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4), ++ SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4), ++ SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), ++}; ++ ++static struct attribute *nct6775_attributes_pwm[5][15] = { + { + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm1_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm1_target_temp.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm1_stop_time.dev_attr.attr, ++ &sensor_dev_attr_pwm1_step_up_time.dev_attr.attr, ++ &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, ++ &sensor_dev_attr_pwm1_start.dev_attr.attr, ++ &sensor_dev_attr_pwm1_floor.dev_attr.attr, + NULL + }, + { + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm2_mode.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm2_target_temp.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm2_stop_time.dev_attr.attr, ++ &sensor_dev_attr_pwm2_step_up_time.dev_attr.attr, ++ &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, ++ &sensor_dev_attr_pwm2_start.dev_attr.attr, ++ &sensor_dev_attr_pwm2_floor.dev_attr.attr, + NULL + }, + { + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm3_mode.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm3_target_temp.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm3_stop_time.dev_attr.attr, ++ &sensor_dev_attr_pwm3_step_up_time.dev_attr.attr, ++ &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, ++ &sensor_dev_attr_pwm3_start.dev_attr.attr, ++ &sensor_dev_attr_pwm3_floor.dev_attr.attr, + NULL + }, + { + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm4_mode.dev_attr.attr, + &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm4_target_temp.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm4_stop_time.dev_attr.attr, ++ &sensor_dev_attr_pwm4_step_up_time.dev_attr.attr, ++ &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, ++ &sensor_dev_attr_pwm4_start.dev_attr.attr, ++ &sensor_dev_attr_pwm4_floor.dev_attr.attr, + NULL + }, + { + &sensor_dev_attr_pwm5.dev_attr.attr, + &sensor_dev_attr_pwm5_mode.dev_attr.attr, + &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm5_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm5_target_temp.dev_attr.attr, ++ &sensor_dev_attr_fan5_target.dev_attr.attr, ++ &sensor_dev_attr_fan5_tolerance.dev_attr.attr, ++ &sensor_dev_attr_pwm5_stop_time.dev_attr.attr, ++ &sensor_dev_attr_pwm5_step_up_time.dev_attr.attr, ++ &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, ++ &sensor_dev_attr_pwm5_start.dev_attr.attr, ++ &sensor_dev_attr_pwm5_floor.dev_attr.attr, + NULL + }, + }; +@@ -1895,6 +2623,277 @@ static const struct attribute_group nct6775_group_pwm[5] = { + }; + + static ssize_t ++show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ ++ return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]); ++} ++ ++static ssize_t ++store_auto_pwm(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int point = sattr->index; ++ unsigned long val; ++ int err; ++ u8 reg; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ if (val > 255) ++ return -EINVAL; ++ ++ if (point == data->auto_pwm_num) { ++ if (data->kind != nct6775 && !val) ++ return -EINVAL; ++ if (data->kind != nct6779 && val) ++ val = 0xff; ++ } ++ ++ mutex_lock(&data->update_lock); ++ data->auto_pwm[nr][point] = val; ++ if (point < data->auto_pwm_num) { ++ nct6775_write_value(data, ++ NCT6775_AUTO_PWM(data, nr, point), ++ data->auto_pwm[nr][point]); ++ } else { ++ switch (data->kind) { ++ case nct6775: ++ /* disable if needed (pwm == 0) */ ++ reg = nct6775_read_value(data, ++ NCT6775_REG_CRITICAL_ENAB[nr]); ++ if (val) ++ reg |= 0x02; ++ else ++ reg &= ~0x02; ++ nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr], ++ reg); ++ break; ++ case nct6776: ++ break; /* always enabled, nothing to do */ ++ case nct6779: ++ nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr], ++ val); ++ reg = nct6775_read_value(data, ++ NCT6779_REG_CRITICAL_PWM_ENABLE[nr]); ++ if (val == 255) ++ reg &= ~0x01; ++ else ++ reg |= 0x01; ++ nct6775_write_value(data, ++ NCT6779_REG_CRITICAL_PWM_ENABLE[nr], ++ reg); ++ break; ++ } ++ } ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t ++show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int point = sattr->index; ++ ++ /* ++ * We don't know for sure if the temperature is signed or unsigned. ++ * Assume it is unsigned. ++ */ ++ return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000); ++} ++ ++static ssize_t ++store_auto_temp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int point = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err) ++ return err; ++ if (val > 255000) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000); ++ if (point < data->auto_pwm_num) { ++ nct6775_write_value(data, ++ NCT6775_AUTO_TEMP(data, nr, point), ++ data->auto_temp[nr][point]); ++ } else { ++ nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr], ++ data->auto_temp[nr][point]); ++ } ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++/* ++ * The number of auto-point trip points is chip dependent. ++ * Need to check support while generating/removing attribute files. ++ */ ++static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = { ++ SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 0), ++ SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 0), ++ SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 1), ++ SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 1), ++ SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 2), ++ SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 2), ++ SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 3), ++ SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 3), ++ SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 4), ++ SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 4), ++ SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 5), ++ SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 5), ++ SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 0, 6), ++ SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 0, 6), ++ ++ SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 0), ++ SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 0), ++ SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 1), ++ SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 1), ++ SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 2), ++ SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 2), ++ SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 3), ++ SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 3), ++ SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 4), ++ SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 4), ++ SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 5), ++ SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 5), ++ SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 1, 6), ++ SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 1, 6), ++ ++ SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 0), ++ SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 0), ++ SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 1), ++ SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 1), ++ SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 2), ++ SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 2), ++ SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 3), ++ SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 3), ++ SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 4), ++ SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 4), ++ SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 5), ++ SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 5), ++ SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 2, 6), ++ SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 2, 6), ++ ++ SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 0), ++ SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 0), ++ SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 1), ++ SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 1), ++ SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 2), ++ SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 2), ++ SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 3), ++ SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 3), ++ SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 4), ++ SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 4), ++ SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 5), ++ SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 5), ++ SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 3, 6), ++ SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 3, 6), ++ ++ SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 0), ++ SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 0), ++ SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 1), ++ SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 1), ++ SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 2), ++ SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 2), ++ SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 3), ++ SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 3), ++ SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 4), ++ SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 4), ++ SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 5), ++ SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 5), ++ SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO, ++ show_auto_pwm, store_auto_pwm, 4, 6), ++ SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO, ++ show_auto_temp, store_auto_temp, 4, 6), ++}; ++ ++static ssize_t + show_vid(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = dev_get_drvdata(dev); +@@ -1969,6 +2968,15 @@ static void nct6775_device_remove_files(struct device *dev) + for (i = 0; i < data->pwm_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]); + ++ for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++) ++ device_remove_file(dev, &sda_pwm_max[i].dev_attr); ++ ++ for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) ++ device_remove_file(dev, &sda_pwm_step[i].dev_attr); ++ ++ for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) ++ device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); ++ + for (i = 0; i < data->in_num; i++) + sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); + +@@ -2161,6 +3169,7 @@ static int nct6775_probe(struct platform_device *pdev) + case nct6775: + data->in_num = 9; + data->pwm_num = 3; ++ data->auto_pwm_num = 6; + data->has_fan_div = true; + data->temp_fixed_num = 3; + +@@ -2168,6 +3177,9 @@ static int nct6775_probe(struct platform_device *pdev) + + data->fan_from_reg = fan_from_reg16; + data->fan_from_reg_min = fan_from_reg8; ++ data->target_temp_mask = 0x7f; ++ data->tolerance_mask = 0x0f; ++ data->speed_tolerance_limit = 15; + + data->temp_label = nct6775_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); +@@ -2178,16 +3190,30 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TARGET = NCT6775_REG_TARGET; + data->REG_FAN = NCT6775_REG_FAN; + data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; ++ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; ++ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; + data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; ++ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; ++ data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; ++ data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; ++ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; ++ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; ++ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; ++ data->REG_CRITICAL_TEMP_TOLERANCE ++ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; ++ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; + data->REG_ALARM = NCT6775_REG_ALARM; + + reg_temp = NCT6775_REG_TEMP; +@@ -2202,6 +3228,7 @@ static int nct6775_probe(struct platform_device *pdev) + case nct6776: + data->in_num = 9; + data->pwm_num = 3; ++ data->auto_pwm_num = 4; + data->has_fan_div = false; + data->temp_fixed_num = 3; + +@@ -2209,6 +3236,9 @@ static int nct6775_probe(struct platform_device *pdev) + + data->fan_from_reg = fan_from_reg13; + data->fan_from_reg_min = fan_from_reg13; ++ data->target_temp_mask = 0xff; ++ data->tolerance_mask = 0x07; ++ data->speed_tolerance_limit = 63; + + data->temp_label = nct6776_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); +@@ -2219,16 +3249,29 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6775_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TARGET = NCT6775_REG_TARGET; + data->REG_FAN = NCT6775_REG_FAN; + data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; ++ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; ++ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; ++ data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; ++ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; ++ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; ++ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; ++ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; ++ data->REG_CRITICAL_TEMP_TOLERANCE ++ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; ++ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; + data->REG_ALARM = NCT6775_REG_ALARM; + + reg_temp = NCT6775_REG_TEMP; +@@ -2243,6 +3286,7 @@ static int nct6775_probe(struct platform_device *pdev) + case nct6779: + data->in_num = 15; + data->pwm_num = 5; ++ data->auto_pwm_num = 4; + data->has_fan_div = false; + data->temp_fixed_num = 6; + +@@ -2250,6 +3294,9 @@ static int nct6775_probe(struct platform_device *pdev) + + data->fan_from_reg = fan_from_reg13; + data->fan_from_reg_min = fan_from_reg13; ++ data->target_temp_mask = 0xff; ++ data->tolerance_mask = 0x07; ++ data->speed_tolerance_limit = 63; + + data->temp_label = nct6779_temp_label; + data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); +@@ -2260,16 +3307,29 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_VIN = NCT6779_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; ++ data->REG_TARGET = NCT6775_REG_TARGET; + data->REG_FAN = NCT6779_REG_FAN; + data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; ++ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; ++ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; ++ data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; ++ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; ++ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; ++ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; ++ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; ++ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; ++ data->REG_CRITICAL_TEMP_TOLERANCE ++ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; ++ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; + data->REG_ALARM = NCT6779_REG_ALARM; + + reg_temp = NCT6779_REG_TEMP; +@@ -2484,6 +3544,31 @@ static int nct6775_probe(struct platform_device *pdev) + err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]); + if (err) + goto exit_remove; ++ ++ if (data->REG_PWM[3]) { ++ err = device_create_file(dev, ++ &sda_pwm_max[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ if (data->REG_PWM[4]) { ++ err = device_create_file(dev, ++ &sda_pwm_step[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } ++ } ++ for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { ++ struct sensor_device_attribute_2 *attr = ++ &sda_auto_pwm_arrays[i]; ++ ++ if (!(data->has_pwm & (1 << attr->nr))) ++ continue; ++ if (attr->index > data->auto_pwm_num) ++ continue; ++ err = device_create_file(dev, &attr->dev_attr); ++ if (err) ++ goto exit_remove; + } + + for (i = 0; i < data->in_num; i++) { +@@ -2518,7 +3603,7 @@ static int nct6775_probe(struct platform_device *pdev) + goto exit_remove; + } + err = device_create_file(dev, +- &sda_fan_pulses[i].dev_attr); ++ &sda_fan_pulses[i].dev_attr); + if (err) + goto exit_remove; + } + +From bbd8decd4123648ddeba2be485bc7e1a3117bfe4 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 09:08:29 -0800 +Subject: [PATCH] hwmon: (nct6775) Add support for weighted fan control + +The NCT677X series support weighted fan control. In this mode, a secondary +temperature source is used in addition to the primary temperature source to +control fan speed. Add support for this feature. + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +index b4fe6bc..3f5587e 100644 +--- a/Documentation/hwmon/nct6775 ++++ b/Documentation/hwmon/nct6775 +@@ -92,6 +92,25 @@ Common fan control attributes + + pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. + For example, select '1' for temp1_input. ++pwm[1-5]_weight_temp_sel ++ Secondary temperature source. Value is temperature ++ sensor index. For example, select '1' for temp1_input. ++ Set to 0 to disable secondary temperature control. ++ ++If secondary temperature functionality is enabled, it is controlled with the ++following attributes. ++ ++pwm[1-5]_weight_duty_step ++ Duty step size. ++pwm[1-5]_weight_temp_step ++ Temperature step size. With each step over ++ temp_step_base, the value of weight_duty_step is added ++ to the current pwm value. ++pwm[1-5]_weight_temp_step_base ++ Temperature at which secondary temperature control kicks ++ in. ++pwm[1-5]_weight_temp_step_tol ++ Temperature step tolerance. + + Thermal Cruise mode (2) + ----------------------- +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 47b1d89..f80ff82 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -255,6 +255,17 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + static const u16 NCT6775_REG_TEMP_SEL[] = { + 0x100, 0x200, 0x300, 0x800, 0x900 }; + ++static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { ++ 0x139, 0x239, 0x339, 0x839, 0x939 }; ++static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { ++ 0x13a, 0x23a, 0x33a, 0x83a, 0x93a }; ++static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { ++ 0x13b, 0x23b, 0x33b, 0x83b, 0x93b }; ++static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { ++ 0x13c, 0x23c, 0x33c, 0x83c, 0x93c }; ++static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { ++ 0x13d, 0x23d, 0x33d, 0x83d, 0x93d }; ++ + static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; + + static const u16 NCT6775_REG_AUTO_TEMP[] = { +@@ -323,6 +334,9 @@ static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; + static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; + static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; + ++static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { ++ 0x13e, 0x23e, 0x33e, 0x83e, 0x93e }; ++ + static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { + 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; + +@@ -571,8 +585,9 @@ struct nct6775_data { + const u8 *REG_PWM_MODE; + const u8 *PWM_MODE_MASK; + +- const u16 *REG_PWM[5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, +- * [3]=pwm_max, [4]=pwm_step ++ const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, ++ * [3]=pwm_max, [4]=pwm_step, ++ * [5]=weight_duty_step, [6]=weight_duty_base + */ + const u16 *REG_PWM_READ; + +@@ -584,6 +599,9 @@ struct nct6775_data { + + const u16 *REG_TEMP_SOURCE; /* temp register sources */ + const u16 *REG_TEMP_SEL; ++ const u16 *REG_WEIGHT_TEMP_SEL; ++ const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */ ++ + const u16 *REG_TEMP_OFFSET; + + const u16 *REG_ALARM; +@@ -625,8 +643,9 @@ struct nct6775_data { + * 4->SmartFan III + * 5->enhanced variable thermal cruise (SmartFan IV) + */ +- u8 pwm[5][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, +- * [3]=pwm_max, [4]=pwm_step ++ u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, ++ * [3]=pwm_max, [4]=pwm_step, ++ * [5]=weight_duty_step, [6]=weight_duty_base + */ + + u8 target_temp[5]; +@@ -645,6 +664,10 @@ struct nct6775_data { + u8 auto_pwm[5][7]; + u8 auto_temp[5][7]; + u8 pwm_temp_sel[5]; ++ u8 pwm_weight_temp_sel[5]; ++ u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol, ++ * 2->temp_base ++ */ + + u8 vid; + u8 vrm; +@@ -972,6 +995,19 @@ static void nct6775_update_pwm(struct device *dev) + /* If fan can stop, report floor as 0 */ + if (reg & 0x80) + data->pwm[2][i] = 0; ++ ++ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]); ++ data->pwm_weight_temp_sel[i] = reg & 0x1f; ++ /* If weight is disabled, report weight source as 0 */ ++ if (j == 1 && !(reg & 0x80)) ++ data->pwm_weight_temp_sel[i] = 0; ++ ++ /* Weight temp data */ ++ for (j = 0; j < 3; j++) { ++ data->weight_temp[j][i] ++ = nct6775_read_value(data, ++ data->REG_WEIGHT_TEMP[j][i]); ++ } + } + } + +@@ -1938,9 +1974,9 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, + int nr = sattr->nr; + int index = sattr->index; + unsigned long val; +- int minval[5] = { 0, 1, 1, data->pwm[2][nr], 0 }; +- int maxval[5] +- = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255 }; ++ int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 }; ++ int maxval[7] ++ = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 }; + int err; + u8 reg; + +@@ -2078,13 +2114,9 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, + } + + static ssize_t +-show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) ++show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src) + { +- struct nct6775_data *data = nct6775_update_device(dev); +- struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); +- int i, src, sel = 0; +- +- src = data->pwm_temp_sel[sattr->index]; ++ int i, sel = 0; + + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) +@@ -2099,6 +2131,16 @@ show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) + } + + static ssize_t ++show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int index = sattr->index; ++ ++ return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]); ++} ++ ++static ssize_t + store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { +@@ -2129,6 +2171,56 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, + } + + static ssize_t ++show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int index = sattr->index; ++ ++ return show_pwm_temp_sel_common(data, buf, ++ data->pwm_weight_temp_sel[index]); ++} ++ ++static ssize_t ++store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); ++ int nr = sattr->index; ++ unsigned long val; ++ int err, reg, src; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ if (val > NUM_TEMP) ++ return -EINVAL; ++ if (val && (!(data->have_temp & (1 << (val - 1))) || ++ !data->temp_src[val - 1])) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ if (val) { ++ src = data->temp_src[val - 1]; ++ data->pwm_weight_temp_sel[nr] = src; ++ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); ++ reg &= 0xe0; ++ reg |= (src | 0x80); ++ nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); ++ } else { ++ data->pwm_weight_temp_sel[nr] = 0; ++ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); ++ reg &= 0x7f; ++ nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); ++ } ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t + show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = nct6775_update_device(dev); +@@ -2381,6 +2473,115 @@ static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO, + /* Smart Fan registers */ + + static ssize_t ++show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct nct6775_data *data = nct6775_update_device(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ ++ return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000); ++} ++ ++static ssize_t ++store_weight_temp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct nct6775_data *data = dev_get_drvdata(dev); ++ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); ++ int nr = sattr->nr; ++ int index = sattr->index; ++ unsigned long val; ++ int err; ++ ++ err = kstrtoul(buf, 10, &val); ++ if (err < 0) ++ return err; ++ ++ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255); ++ ++ mutex_lock(&data->update_lock); ++ data->weight_temp[index][nr] = val; ++ nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, ++ 0); ++static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, ++ 1); ++static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, ++ 2); ++static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, ++ 3); ++static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO, ++ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, ++ 4); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 0, 0); ++static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 1, 0); ++static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 2, 0); ++static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 3, 0); ++static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 4, 0); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 0, 1); ++static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 1, 1); ++static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 2, 1); ++static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 3, 1); ++static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 4, 1); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 0, 2); ++static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 1, 2); ++static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 2, 2); ++static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 3, 2); ++static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO, ++ show_weight_temp, store_weight_temp, 4, 2); ++ ++static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 0, 5); ++static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 1, 5); ++static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 2, 5); ++static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 3, 5); ++static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 4, 5); ++ ++/* duty_base is not supported on all chips */ ++static struct sensor_device_attribute_2 sda_weight_duty_base[] = { ++ SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 0, 6), ++ SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 1, 6), ++ SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 2, 6), ++ SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 3, 6), ++ SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO, ++ show_pwm, store_pwm, 4, 6), ++}; ++ ++static ssize_t + show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) + { + struct nct6775_data *data = nct6775_update_device(dev); +@@ -2526,7 +2727,7 @@ static struct sensor_device_attribute_2 sda_pwm_step[] = { + SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), + }; + +-static struct attribute *nct6775_attributes_pwm[5][15] = { ++static struct attribute *nct6775_attributes_pwm[5][20] = { + { + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, +@@ -2542,6 +2743,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { + &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, + &sensor_dev_attr_pwm1_start.dev_attr.attr, + &sensor_dev_attr_pwm1_floor.dev_attr.attr, ++ &sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr, ++ &sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr, ++ &sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr, ++ &sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr, + NULL + }, + { +@@ -2559,6 +2765,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { + &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, + &sensor_dev_attr_pwm2_start.dev_attr.attr, + &sensor_dev_attr_pwm2_floor.dev_attr.attr, ++ &sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr, ++ &sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr, ++ &sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr, ++ &sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr, + NULL + }, + { +@@ -2576,6 +2787,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { + &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, + &sensor_dev_attr_pwm3_start.dev_attr.attr, + &sensor_dev_attr_pwm3_floor.dev_attr.attr, ++ &sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr, ++ &sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr, ++ &sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr, ++ &sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr, + NULL + }, + { +@@ -2593,6 +2809,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { + &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, + &sensor_dev_attr_pwm4_start.dev_attr.attr, + &sensor_dev_attr_pwm4_floor.dev_attr.attr, ++ &sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr, ++ &sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr, ++ &sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr, ++ &sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr, + NULL + }, + { +@@ -2610,6 +2831,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { + &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, + &sensor_dev_attr_pwm5_start.dev_attr.attr, + &sensor_dev_attr_pwm5_floor.dev_attr.attr, ++ &sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr, ++ &sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr, ++ &sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr, ++ &sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr, ++ &sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr, + NULL + }, + }; +@@ -2974,6 +3200,9 @@ static void nct6775_device_remove_files(struct device *dev) + for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) + device_remove_file(dev, &sda_pwm_step[i].dev_attr); + ++ for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++) ++ device_remove_file(dev, &sda_weight_duty_base[i].dev_attr); ++ + for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) + device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); + +@@ -3203,6 +3432,7 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; + data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; + data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; ++ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; +@@ -3214,6 +3444,10 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; ++ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; ++ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; ++ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; ++ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; + data->REG_ALARM = NCT6775_REG_ALARM; + + reg_temp = NCT6775_REG_TEMP; +@@ -3261,6 +3495,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; + data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; ++ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; ++ data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; +@@ -3272,6 +3508,10 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; ++ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; ++ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; ++ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; ++ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; + data->REG_ALARM = NCT6775_REG_ALARM; + + reg_temp = NCT6775_REG_TEMP; +@@ -3319,6 +3559,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; + data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; ++ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; ++ data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; +@@ -3330,6 +3572,10 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; + data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; ++ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; ++ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; ++ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; ++ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; + data->REG_ALARM = NCT6779_REG_ALARM; + + reg_temp = NCT6779_REG_TEMP; +@@ -3557,6 +3803,12 @@ static int nct6775_probe(struct platform_device *pdev) + if (err) + goto exit_remove; + } ++ if (data->REG_PWM[6]) { ++ err = device_create_file(dev, ++ &sda_weight_duty_base[i].dev_attr); ++ if (err) ++ goto exit_remove; ++ } + } + for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { + struct sensor_device_attribute_2 *attr = + +From 8e9285b0bb2ab48924032147baa29699c0bbee7c Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 4 Dec 2012 08:03:37 -0800 +Subject: [PATCH] hwmon: (nct6775) Detect and report additional temperature + sources + +Scan all temperature sources used for fan control and report if additional +monitoring registers are available. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index f80ff82..6d58597 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -3364,6 +3364,32 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, + return 0; + } + ++static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, ++ int *available, int *mask) ++{ ++ int i; ++ u8 src; ++ ++ for (i = 0; i < data->pwm_num && *available; i++) { ++ int index; ++ ++ if (!regp[i]) ++ continue; ++ src = nct6775_read_value(data, regp[i]); ++ src &= 0x1f; ++ if (!src || (*mask & (1 << src))) ++ continue; ++ if (src >= data->temp_label_num || ++ !strlen(data->temp_label[src])) ++ continue; ++ ++ index = __ffs(*available); ++ nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src); ++ *available &= ~(1 << index); ++ *mask |= 1 << src; ++ } ++} ++ + static int nct6775_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -3614,6 +3640,13 @@ static int nct6775_probe(struct platform_device *pdev) + mask |= 1 << src; + } + ++ /* ++ * Now find unmonitored temperature registers and enable monitoring ++ * if additional monitoring registers are available. ++ */ ++ add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask); ++ add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask); ++ + mask = 0; + s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */ + for (i = 0; i < num_reg_temp; i++) { + +From 0fc1f8fc614ca0fef78011b34ef8da638eb9acea Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 26 Feb 2013 09:43:50 -0800 +Subject: [PATCH] hwmon: (nct6775) Only report VID if supported and enabled + +VID is not always enabled (NCT6775, NCT6776) or supported (NCT6779). + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 6d58597..752fbd7 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -3401,6 +3401,8 @@ static int nct6775_probe(struct platform_device *pdev) + const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config; + const u16 *reg_temp_alternate, *reg_temp_crit; + int num_reg_temp; ++ bool have_vid = false; ++ u8 cr2a; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, +@@ -3769,17 +3771,31 @@ static int nct6775_probe(struct platform_device *pdev) + /* Initialize the chip */ + nct6775_init_device(data); + +- data->vrm = vid_which_vrm(); + err = superio_enter(sio_data->sioreg); + if (err) + return err; + ++ cr2a = superio_inb(sio_data->sioreg, 0x2a); ++ switch (data->kind) { ++ case nct6775: ++ have_vid = (cr2a & 0x40); ++ break; ++ case nct6776: ++ have_vid = (cr2a & 0x60) == 0x40; ++ break; ++ case nct6779: ++ break; ++ } ++ + /* + * Read VID value + * We can get the VID input values directly at logical device D 0xe3. + */ +- superio_select(sio_data->sioreg, NCT6775_LD_VID); +- data->vid = superio_inb(sio_data->sioreg, 0xe3); ++ if (have_vid) { ++ superio_select(sio_data->sioreg, NCT6775_LD_VID); ++ data->vid = superio_inb(sio_data->sioreg, 0xe3); ++ data->vrm = vid_which_vrm(); ++ } + + if (fan_debounce) { + u8 tmp; +@@ -3804,9 +3820,11 @@ static int nct6775_probe(struct platform_device *pdev) + + superio_exit(sio_data->sioreg); + +- err = device_create_file(dev, &dev_attr_cpu0_vid); +- if (err) +- return err; ++ if (have_vid) { ++ err = device_create_file(dev, &dev_attr_cpu0_vid); ++ if (err) ++ return err; ++ } + + err = nct6775_check_fan_inputs(sio_data, data); + if (err) + +From 236d9039480059f97dc9d3cd75e3651582b62997 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Fri, 8 Mar 2013 07:42:00 -0800 +Subject: [PATCH] hwmon: (nct6775) Drop read/write lock + +The read/write lock is acquired for each read/write operation from/to the chip. +This occurs either during initialization, when it is not needed, or during +updates, when the update_lock is held as well, and it is not needed either. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 752fbd7..2269bb2 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -554,7 +554,6 @@ struct nct6775_data { + const char *name; + + struct device *hwmon_dev; +- struct mutex lock; + + u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, + * 3=temp_crit +@@ -745,8 +744,6 @@ static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) + { + int res, word_sized = is_word_sized(data, reg); + +- mutex_lock(&data->lock); +- + nct6775_set_bank(data, reg); + outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); + res = inb_p(data->addr + DATA_REG_OFFSET); +@@ -755,8 +752,6 @@ static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) + data->addr + ADDR_REG_OFFSET); + res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET); + } +- +- mutex_unlock(&data->lock); + return res; + } + +@@ -764,8 +759,6 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) + { + int word_sized = is_word_sized(data, reg); + +- mutex_lock(&data->lock); +- + nct6775_set_bank(data, reg); + outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); + if (word_sized) { +@@ -774,8 +767,6 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) + data->addr + ADDR_REG_OFFSET); + } + outb_p(value & 0xff, data->addr + DATA_REG_OFFSET); +- +- mutex_unlock(&data->lock); + return 0; + } + +@@ -3416,7 +3407,6 @@ static int nct6775_probe(struct platform_device *pdev) + + data->kind = sio_data->kind; + data->addr = res->start; +- mutex_init(&data->lock); + mutex_init(&data->update_lock); + data->name = nct6775_device_names[data->kind]; + data->bank = 0xff; /* Force initial bank selection */ + +From 2c7fd30da21bf6bda12d7a0f678e4fd8ed362c96 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 2 Apr 2013 08:53:19 -0700 +Subject: [PATCH] hwmon: (nct6775) Expand scope of supported chips + +NCT6775, NCT6776, and NCT6779 have a number of variants with the same +chip ID but different chip labels. Add text "or compatible" to the +message displayed when the driver is loaded and rephrase the Kconfig +entry to reflect that it also supports compatible chips. + +Signed-off-by: Guenter Roeck + +diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 +index 3f5587e..4e9ef60 100644 +--- a/Documentation/hwmon/nct6775 ++++ b/Documentation/hwmon/nct6775 +@@ -8,15 +8,15 @@ Kernel driver NCT6775 + ===================== + + Supported chips: +- * Nuvoton NCT6775F/W83667HG-I ++ * Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I + Prefix: 'nct6775' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: Available from Nuvoton upon request +- * Nuvoton NCT6776F ++ * Nuvoton NCT5577D/NCT6776D/NCT6776F + Prefix: 'nct6776' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: Available from Nuvoton upon request +- * Nuvoton NCT6779D ++ * Nuvoton NCT5532D/NCT6779D + Prefix: 'nct6779' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: Available from Nuvoton upon request +@@ -28,7 +28,7 @@ Description + ----------- + + This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D +-super I/O chips. ++and compatible super I/O chips. + + The chips support up to 25 temperature monitoring sources. Up to 6 of those are + direct temperature sensor inputs, the others are special sources such as PECI, +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 4986961..26ebff0 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -908,14 +908,14 @@ config SENSORS_MCP3021 + will be called mcp3021. + + config SENSORS_NCT6775 +- tristate "Nuvoton NCT6775F, NCT6776F, NCT6779D" ++ tristate "Nuvoton NCT6775F and compatibles" + depends on !PPC + select HWMON_VID + help + If you say yes here you get support for the hardware monitoring +- functionality of the Nuvoton NCT6775F, NCT6776F, and NCT6779D +- Super-I/O chips. This driver replaces the w83627ehf driver for +- NCT6775F and NCT6776F. ++ functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D ++ and compatible Super-I/O chips. This driver replaces the ++ w83627ehf driver for NCT6775F and NCT6776F. + + This driver can also be built as a module. If so, the module + will be called nct6775. +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 2269bb2..d05a700 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -4072,16 +4072,17 @@ static struct platform_driver nct6775_driver = { + .remove = nct6775_remove, + }; + ++static const char *nct6775_sio_names[] __initconst = { ++ "NCT6775F", ++ "NCT6776D/F", ++ "NCT6779D", ++}; ++ + /* nct6775_find() looks for a '627 in the Super-I/O config space */ + static int __init nct6775_find(int sioaddr, unsigned short *addr, + struct nct6775_sio_data *sio_data) + { +- static const char sio_name_NCT6775[] __initconst = "NCT6775F"; +- static const char sio_name_NCT6776[] __initconst = "NCT6776F"; +- static const char sio_name_NCT6779[] __initconst = "NCT6779D"; +- + u16 val; +- const char *sio_name; + int err; + + err = superio_enter(sioaddr); +@@ -4096,15 +4097,12 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr, + switch (val & SIO_ID_MASK) { + case SIO_NCT6775_ID: + sio_data->kind = nct6775; +- sio_name = sio_name_NCT6775; + break; + case SIO_NCT6776_ID: + sio_data->kind = nct6776; +- sio_name = sio_name_NCT6776; + break; + case SIO_NCT6779_ID: + sio_data->kind = nct6779; +- sio_name = sio_name_NCT6779; + break; + default: + if (val != 0xffff) +@@ -4132,7 +4130,8 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr, + } + + superio_exit(sioaddr); +- pr_info("Found %s chip at %#x\n", sio_name, *addr); ++ pr_info("Found %s or compatible chip at %#x\n", ++ nct6775_sio_names[sio_data->kind], *addr); + sio_data->sioreg = sioaddr; + + return 0; + +From 573728c647fb991ec7be6408a4975413d2ace6c3 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Fri, 5 Apr 2013 23:15:53 -0700 +Subject: [PATCH] hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776 + +Per datasheet, VIN3 and AUXTIN share the same external pin. However, there +is no clean way to detect this condition. Furthermore, both are reported +by the BIOS on Supermicro C7H61. It may thus be possible that chip revisions +exist where both attributes are supported at the same time. +Better play safe and report both. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index d05a700..8d0e4c4 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -3721,43 +3721,6 @@ static int nct6775_probe(struct platform_device *pdev) + } + #endif /* USE_ALTERNATE */ + +- switch (data->kind) { +- case nct6775: +- break; +- case nct6776: +- /* +- * On NCT6776, AUXTIN and VIN3 pins are shared. +- * Only way to detect it is to check if AUXTIN is used +- * as a temperature source, and if that source is +- * enabled. +- * +- * If that is the case, disable in6, which reports VIN3. +- * Otherwise disable temp3. +- */ +- if (data->have_temp & (1 << 2)) { +- u8 reg = nct6775_read_value(data, +- data->reg_temp_config[2]); +- if (reg & 0x01) +- data->have_temp &= ~(1 << 2); +- else +- data->have_in &= ~(1 << 6); +- } +- break; +- case nct6779: +- /* +- * Shared pins: +- * VIN4 / AUXTIN0 +- * VIN5 / AUXTIN1 +- * VIN6 / AUXTIN2 +- * VIN7 / AUXTIN3 +- * +- * There does not seem to be a clean way to detect if VINx or +- * AUXTINx is active, so for keep both sensor types enabled +- * for now. +- */ +- break; +- } +- + /* Initialize the chip */ + nct6775_init_device(data); + + +From c409fd43bdea705799d21531600b8f305b120009 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 9 Apr 2013 05:04:00 -0700 +Subject: [PATCH] hwmon: (nct6775) Use ARRAY_SIZE for loops where possible + +This ensures that the loop iterations are correct even if/when +the number of elements in an array changes. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 8d0e4c4..04ccfff 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -854,7 +854,7 @@ static void nct6775_init_fan_div(struct nct6775_data *data) + * reading from the fan count register, even if it is not optimal. + * We'll compute a better divider later on. + */ +- for (i = 0; i < 3; i++) { ++ for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) { + if (!(data->has_fan & (1 << i))) + continue; + if (data->fan_div[i] == 0) { +@@ -877,7 +877,7 @@ static void nct6775_init_fan_common(struct device *dev, + * If fan_min is not set (0), set it to 0xff to disable it. This + * prevents the unnecessary warning when fanX_min is reported as 0. + */ +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { + if (data->has_fan_min & (1 << i)) { + reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); + if (!reg) +@@ -994,7 +994,7 @@ static void nct6775_update_pwm(struct device *dev) + data->pwm_weight_temp_sel[i] = 0; + + /* Weight temp data */ +- for (j = 0; j < 3; j++) { ++ for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) { + data->weight_temp[j][i] + = nct6775_read_value(data, + data->REG_WEIGHT_TEMP[j][i]); +@@ -1013,7 +1013,7 @@ static void nct6775_update_pwm_limits(struct device *dev) + if (!(data->has_pwm & (1 << i))) + continue; + +- for (j = 0; j < 3; j++) { ++ for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) { + data->fan_time[j][i] = + nct6775_read_value(data, data->REG_FAN_TIME[j][i]); + } +@@ -1095,7 +1095,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + } + + /* Measured fan speeds and limits */ +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < ARRAY_SIZE(data->rpm); i++) { + u16 reg; + + if (!(data->has_fan & (1 << i))) +@@ -1121,7 +1121,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + for (i = 0; i < NUM_TEMP; i++) { + if (!(data->have_temp & (1 << i))) + continue; +- for (j = 0; j < 4; j++) { ++ for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) { + if (data->reg_temp[j][i]) + data->temp[j][i] + = nct6775_read_temp(data, +@@ -3983,7 +3983,7 @@ static int nct6775_resume(struct device *dev) + data->in[i][2]); + } + +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { + if (!(data->has_fan_min & (1 << i))) + continue; + +@@ -3995,7 +3995,7 @@ static int nct6775_resume(struct device *dev) + if (!(data->have_temp & (1 << i))) + continue; + +- for (j = 1; j < 4; j++) ++ for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++) + if (data->reg_temp[j][i]) + nct6775_write_temp(data, data->reg_temp[j][i], + data->temp[j][i]); + +From 6d4b3621bb613da51ae7474c50f5cb37465b6f37 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 21 Apr 2013 09:08:11 -0700 +Subject: [PATCH] hwmon: (nct6775) Constify strings + +nct6775_sio_names should be a constant pointer to an array of +constant strings. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 04ccfff..14da90e 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -4035,7 +4035,7 @@ static struct platform_driver nct6775_driver = { + .remove = nct6775_remove, + }; + +-static const char *nct6775_sio_names[] __initconst = { ++static const char * const nct6775_sio_names[] __initconst = { + "NCT6775F", + "NCT6776D/F", + "NCT6779D", + +From 6445e6600fa632448cac64e71119310378464ad9 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 21 Apr 2013 09:13:28 -0700 +Subject: [PATCH] hwmon: (nct6775) Fix coding style problems + +Add space around binary operators (CodingStyle, chapter 3.1). + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 14da90e..f43f5e5 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -833,7 +833,7 @@ static void nct6775_update_fan_div(struct nct6775_data *data) + data->fan_div[1] = (i & 0x70) >> 4; + i = nct6775_read_value(data, NCT6775_REG_FANDIV2); + data->fan_div[2] = i & 0x7; +- if (data->has_fan & (1<<3)) ++ if (data->has_fan & (1 << 3)) + data->fan_div[3] = (i & 0x70) >> 4; + } + +@@ -1076,7 +1076,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) + + mutex_lock(&data->update_lock); + +- if (time_after(jiffies, data->last_updated + HZ + HZ/2) ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + /* Fan clock dividers */ + nct6775_update_fan_div_common(data); +@@ -1177,7 +1177,7 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, + return err; + mutex_lock(&data->update_lock); + data->in[nr][index] = in_to_reg(val, nr); +- nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr], ++ nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], + data->in[nr][index]); + mutex_unlock(&data->update_lock); + return count; + +From 169c05cd54473ba4cc37bf4d22e7631395d14f68 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Thu, 9 May 2013 10:40:01 -0700 +Subject: [PATCH] hwmon: (nct6775) Do not create non-existing attributes + +Overtemperature and hysteresis registers only exist for primary +temperature registers, not for alternates, so do not assign +those registers when initializing alternates. + +Signed-off-by: Guenter Roeck + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index f43f5e5..04638ae 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -3705,8 +3705,10 @@ static int nct6775_probe(struct platform_device *pdev) + data->have_temp |= 1 << i; + data->have_temp_fixed |= 1 << i; + data->reg_temp[0][i] = reg_temp_alternate[i]; +- data->reg_temp[1][i] = reg_temp_over[i]; +- data->reg_temp[2][i] = reg_temp_hyst[i]; ++ if (i < num_reg_temp) { ++ data->reg_temp[1][i] = reg_temp_over[i]; ++ data->reg_temp[2][i] = reg_temp_hyst[i]; ++ } + data->temp_src[i] = i + 1; + continue; + } diff --git a/kernel.spec b/kernel.spec index 75b194477..c45d10c53 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch #rhbz 969644 Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch +#rhbz 975995 +Patch25047: drivers-hwmon-nct6775.patch + # END OF PATCH DEFINITIONS %endif @@ -1520,6 +1523,9 @@ ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch #rhbz 969644 ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch +#rhbz 975995 +ApplyPatch drivers-hwmon-nct6775.patch + # END OF PATCH APPLICATIONS %endif @@ -2365,6 +2371,9 @@ fi # ||----w | # || || %changelog +* Wed Jun 19 2013 Mauro Carvalho Chehab +- Add and enable upstream kernel driver for nct6775 sensors + * Tue Jun 18 2013 Dave Jones - Disable MTRR sanitizer by default. From 0d22b061e28a41badcdc452818472c02416cf1ca Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 20 Jun 2013 16:46:56 -0500 Subject: [PATCH 354/492] Linux v3.9.7 --- ...or-dmesg_restrict-sysctl-on-dev-kmsg.patch | 228 ----------- Modify-UEFI-anti-bricking-code.patch | 371 ------------------ ...ormat-string-leaking-into-error-msgs.patch | 32 -- config-generic | 2 +- kernel.spec | 23 +- sources | 2 +- 6 files changed, 6 insertions(+), 652 deletions(-) delete mode 100644 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch delete mode 100644 Modify-UEFI-anti-bricking-code.patch delete mode 100644 b43-stop-format-string-leaking-into-error-msgs.patch diff --git a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch b/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch deleted file mode 100644 index 7197f7f7a..000000000 --- a/0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch +++ /dev/null @@ -1,228 +0,0 @@ -To fix /dev/kmsg, let's compare the existing interfaces and what they allow: - -- /proc/kmsg allows: - - open (SYSLOG_ACTION_OPEN) if CAP_SYSLOG since it uses a destructive - single-reader interface (SYSLOG_ACTION_READ). - - everything, after an open. - -- syslog syscall allows: - - anything, if CAP_SYSLOG. - - SYSLOG_ACTION_READ_ALL and SYSLOG_ACTION_SIZE_BUFFER, if dmesg_restrict==0. - - nothing else (EPERM). - -The use-cases were: -- dmesg(1) needs to do non-destructive SYSLOG_ACTION_READ_ALLs. -- sysklog(1) needs to open /proc/kmsg, drop privs, and still issue the - destructive SYSLOG_ACTION_READs. - -AIUI, dmesg(1) is moving to /dev/kmsg, and systemd-journald doesn't -clear the ring buffer. - -Based on the comments in devkmsg_llseek, it sounds like actions besides -reading aren't going to be supported by /dev/kmsg (i.e. SYSLOG_ACTION_CLEAR), -so we have a strict subset of the non-destructive syslog syscall actions. - -To this end, move the check as Josh had done, but also rename the constants -to reflect their new uses (SYSLOG_FROM_CALL becomes SYSLOG_FROM_READER, and -SYSLOG_FROM_FILE becomes SYSLOG_FROM_PROC). SYSLOG_FROM_READER allows -non-destructive actions, and SYSLOG_FROM_PROC allows destructive actions -after a capabilities-constrained SYSLOG_ACTION_OPEN check. - -- /dev/kmsg allows: - - open if CAP_SYSLOG or dmesg_restrict==0 - - reading/polling, after open - -Signed-off-by: Kees Cook -Reported-by: Christian Kujau -Cc: Josh Boyer -Cc: Kay Sievers -Cc: stable@vger.kernel.org ---- - fs/proc/kmsg.c | 10 +++--- - include/linux/syslog.h | 4 +-- - kernel/printk.c | 91 ++++++++++++++++++++++++++---------------------- - 3 files changed, 57 insertions(+), 48 deletions(-) - -diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c -index bd4b5a7..bdfabda 100644 ---- a/fs/proc/kmsg.c -+++ b/fs/proc/kmsg.c -@@ -21,12 +21,12 @@ extern wait_queue_head_t log_wait; - - static int kmsg_open(struct inode * inode, struct file * file) - { -- return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE); -+ return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC); - } - - static int kmsg_release(struct inode * inode, struct file * file) - { -- (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE); -+ (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_PROC); - return 0; - } - -@@ -34,15 +34,15 @@ static ssize_t kmsg_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) - { - if ((file->f_flags & O_NONBLOCK) && -- !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) -+ !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) - return -EAGAIN; -- return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE); -+ return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_PROC); - } - - static unsigned int kmsg_poll(struct file *file, poll_table *wait) - { - poll_wait(file, &log_wait, wait); -- if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) -+ if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) - return POLLIN | POLLRDNORM; - return 0; - } -diff --git a/include/linux/syslog.h b/include/linux/syslog.h -index 3891139..98a3153 100644 ---- a/include/linux/syslog.h -+++ b/include/linux/syslog.h -@@ -44,8 +44,8 @@ - /* Return size of the log buffer */ - #define SYSLOG_ACTION_SIZE_BUFFER 10 - --#define SYSLOG_FROM_CALL 0 --#define SYSLOG_FROM_FILE 1 -+#define SYSLOG_FROM_READER 0 -+#define SYSLOG_FROM_PROC 1 - - int do_syslog(int type, char __user *buf, int count, bool from_file); - -diff --git a/kernel/printk.c b/kernel/printk.c -index abbdd9e..53b5c5e 100644 ---- a/kernel/printk.c -+++ b/kernel/printk.c -@@ -368,6 +368,53 @@ static void log_store(int facility, int level, - log_next_seq++; - } - -+#ifdef CONFIG_SECURITY_DMESG_RESTRICT -+int dmesg_restrict = 1; -+#else -+int dmesg_restrict; -+#endif -+ -+static int syslog_action_restricted(int type) -+{ -+ if (dmesg_restrict) -+ return 1; -+ /* -+ * Unless restricted, we allow "read all" and "get buffer size" -+ * for everybody. -+ */ -+ return type != SYSLOG_ACTION_READ_ALL && -+ type != SYSLOG_ACTION_SIZE_BUFFER; -+} -+ -+static int check_syslog_permissions(int type, bool from_file) -+{ -+ /* -+ * If this is from /proc/kmsg and we've already opened it, then we've -+ * already done the capabilities checks at open time. -+ */ -+ if (from_file && type != SYSLOG_ACTION_OPEN) -+ return 0; -+ -+ if (syslog_action_restricted(type)) { -+ if (capable(CAP_SYSLOG)) -+ return 0; -+ /* -+ * For historical reasons, accept CAP_SYS_ADMIN too, with -+ * a warning. -+ */ -+ if (capable(CAP_SYS_ADMIN)) { -+ printk_once(KERN_WARNING "%s (%d): " -+ "Attempt to access syslog with CAP_SYS_ADMIN " -+ "but no CAP_SYSLOG (deprecated).\n", -+ current->comm, task_pid_nr(current)); -+ return 0; -+ } -+ return -EPERM; -+ } -+ return security_syslog(type); -+} -+ -+ - /* /dev/kmsg - userspace message inject/listen interface */ - struct devkmsg_user { - u64 seq; -@@ -624,7 +671,8 @@ static int devkmsg_open(struct inode *inode, struct file *file) - if ((file->f_flags & O_ACCMODE) == O_WRONLY) - return 0; - -- err = security_syslog(SYSLOG_ACTION_READ_ALL); -+ err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, -+ SYSLOG_FROM_READER); - if (err) - return err; - -@@ -817,45 +865,6 @@ static inline void boot_delay_msec(int level) - } - #endif - --#ifdef CONFIG_SECURITY_DMESG_RESTRICT --int dmesg_restrict = 1; --#else --int dmesg_restrict; --#endif -- --static int syslog_action_restricted(int type) --{ -- if (dmesg_restrict) -- return 1; -- /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ -- return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; --} -- --static int check_syslog_permissions(int type, bool from_file) --{ -- /* -- * If this is from /proc/kmsg and we've already opened it, then we've -- * already done the capabilities checks at open time. -- */ -- if (from_file && type != SYSLOG_ACTION_OPEN) -- return 0; -- -- if (syslog_action_restricted(type)) { -- if (capable(CAP_SYSLOG)) -- return 0; -- /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ -- if (capable(CAP_SYS_ADMIN)) { -- printk_once(KERN_WARNING "%s (%d): " -- "Attempt to access syslog with CAP_SYS_ADMIN " -- "but no CAP_SYSLOG (deprecated).\n", -- current->comm, task_pid_nr(current)); -- return 0; -- } -- return -EPERM; -- } -- return 0; --} -- - #if defined(CONFIG_PRINTK_TIME) - static bool printk_time = 1; - #else -@@ -1253,7 +1262,7 @@ out: - - SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) - { -- return do_syslog(type, buf, len, SYSLOG_FROM_CALL); -+ return do_syslog(type, buf, len, SYSLOG_FROM_READER); - } - - /* --- -1.7.9.5 - - --- -Kees Cook -Chrome OS Security diff --git a/Modify-UEFI-anti-bricking-code.patch b/Modify-UEFI-anti-bricking-code.patch deleted file mode 100644 index 862574556..000000000 --- a/Modify-UEFI-anti-bricking-code.patch +++ /dev/null @@ -1,371 +0,0 @@ -From 2380baac8b96f6e93ef72135d1b60d686d7f82e6 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Sat, 1 Jun 2013 16:06:20 -0400 -Subject: [PATCH] Modify UEFI anti-bricking code - -This patch reworks the UEFI anti-bricking code, including an effective -reversion of cc5a080c and 31ff2f20. It turns out that calling -QueryVariableInfo() from boot services results in some firmware -implementations jumping to physical addresses even after entering virtual -mode, so until we have 1:1 mappings for UEFI runtime space this isn't -going to work so well. - -Reverting these gets us back to the situation where we'd refuse to create -variables on some systems because they classify deleted variables as "used" -until the firmware triggers a garbage collection run, which they won't do -until they reach a lower threshold. This results in it being impossible to -install a bootloader, which is unhelpful. - -Feedback from Samsung indicates that the firmware doesn't need more than -5KB of storage space for its own purposes, so that seems like a reasonable -threshold. However, there's still no guarantee that a platform will attempt -garbage collection merely because it drops below this threshold. It seems -that this is often only triggered if an attempt to write generates a -genuine EFI_OUT_OF_RESOURCES error. We can force that by attempting to -create a variable larger than the remaining space. This should fail, but if -it somehow succeeds we can then immediately delete it. - -I've tested this on the UEFI machines I have available, but I don't have -a Samsung and so can't verify that it avoids the bricking problem. - -Signed-off-by: Matthew Garrett ---- - arch/x86/boot/compressed/eboot.c | 47 ---------- - arch/x86/include/asm/efi.h | 7 -- - arch/x86/include/uapi/asm/bootparam.h | 1 - - arch/x86/platform/efi/efi.c | 167 +++++++++------------------------- - 4 files changed, 44 insertions(+), 178 deletions(-) - -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 35ee62f..c205035 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -251,51 +251,6 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size) - *size = len; - } - --static efi_status_t setup_efi_vars(struct boot_params *params) --{ -- struct setup_data *data; -- struct efi_var_bootdata *efidata; -- u64 store_size, remaining_size, var_size; -- efi_status_t status; -- -- if (sys_table->runtime->hdr.revision < EFI_2_00_SYSTEM_TABLE_REVISION) -- return EFI_UNSUPPORTED; -- -- data = (struct setup_data *)(unsigned long)params->hdr.setup_data; -- -- while (data && data->next) -- data = (struct setup_data *)(unsigned long)data->next; -- -- status = efi_call_phys4((void *)sys_table->runtime->query_variable_info, -- EFI_VARIABLE_NON_VOLATILE | -- EFI_VARIABLE_BOOTSERVICE_ACCESS | -- EFI_VARIABLE_RUNTIME_ACCESS, &store_size, -- &remaining_size, &var_size); -- -- if (status != EFI_SUCCESS) -- return status; -- -- status = efi_call_phys3(sys_table->boottime->allocate_pool, -- EFI_LOADER_DATA, sizeof(*efidata), &efidata); -- -- if (status != EFI_SUCCESS) -- return status; -- -- efidata->data.type = SETUP_EFI_VARS; -- efidata->data.len = sizeof(struct efi_var_bootdata) - -- sizeof(struct setup_data); -- efidata->data.next = 0; -- efidata->store_size = store_size; -- efidata->remaining_size = remaining_size; -- efidata->max_var_size = var_size; -- -- if (data) -- data->next = (unsigned long)efidata; -- else -- params->hdr.setup_data = (unsigned long)efidata; -- --} -- - static efi_status_t setup_efi_pci(struct boot_params *params) - { - efi_pci_io_protocol *pci; -@@ -1202,8 +1157,6 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, - - setup_graphics(boot_params); - -- setup_efi_vars(boot_params); -- - setup_efi_pci(boot_params); - - status = efi_call_phys3(sys_table->boottime->allocate_pool, -diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h -index 2fb5d58..60c89f3 100644 ---- a/arch/x86/include/asm/efi.h -+++ b/arch/x86/include/asm/efi.h -@@ -102,13 +102,6 @@ extern void efi_call_phys_epilog(void); - extern void efi_unmap_memmap(void); - extern void efi_memory_uc(u64 addr, unsigned long size); - --struct efi_var_bootdata { -- struct setup_data data; -- u64 store_size; -- u64 remaining_size; -- u64 max_var_size; --}; -- - #ifdef CONFIG_EFI - - static inline bool efi_is_native(void) -diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h -index 0874424..c15ddaf 100644 ---- a/arch/x86/include/uapi/asm/bootparam.h -+++ b/arch/x86/include/uapi/asm/bootparam.h -@@ -6,7 +6,6 @@ - #define SETUP_E820_EXT 1 - #define SETUP_DTB 2 - #define SETUP_PCI 3 --#define SETUP_EFI_VARS 4 - - /* ram_size flags */ - #define RAMDISK_IMAGE_START_MASK 0x07FF -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index e4a86a6..beb5d5f 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -41,7 +41,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -52,13 +51,6 @@ - - #define EFI_DEBUG 1 - --/* -- * There's some additional metadata associated with each -- * variable. Intel's reference implementation is 60 bytes - bump that -- * to account for potential alignment constraints -- */ --#define VAR_METADATA_SIZE 64 -- - struct efi __read_mostly efi = { - .mps = EFI_INVALID_TABLE_ADDR, - .acpi = EFI_INVALID_TABLE_ADDR, -@@ -77,13 +69,6 @@ struct efi_memory_map memmap; - static struct efi efi_phys __initdata; - static efi_system_table_t efi_systab __initdata; - --static u64 efi_var_store_size; --static u64 efi_var_remaining_size; --static u64 efi_var_max_var_size; --static u64 boot_used_size; --static u64 boot_var_size; --static u64 active_size; -- - unsigned long x86_efi_facility; - - /* -@@ -186,53 +171,8 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, - efi_char16_t *name, - efi_guid_t *vendor) - { -- efi_status_t status; -- static bool finished = false; -- static u64 var_size; -- -- status = efi_call_virt3(get_next_variable, -+ return efi_call_virt3(get_next_variable, - name_size, name, vendor); -- -- if (status == EFI_NOT_FOUND) { -- finished = true; -- if (var_size < boot_used_size) { -- boot_var_size = boot_used_size - var_size; -- active_size += boot_var_size; -- } else { -- printk(KERN_WARNING FW_BUG "efi: Inconsistent initial sizes\n"); -- } -- } -- -- if (boot_used_size && !finished) { -- unsigned long size; -- u32 attr; -- efi_status_t s; -- void *tmp; -- -- s = virt_efi_get_variable(name, vendor, &attr, &size, NULL); -- -- if (s != EFI_BUFFER_TOO_SMALL || !size) -- return status; -- -- tmp = kmalloc(size, GFP_ATOMIC); -- -- if (!tmp) -- return status; -- -- s = virt_efi_get_variable(name, vendor, &attr, &size, tmp); -- -- if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) { -- var_size += size; -- var_size += ucs2_strsize(name, 1024); -- active_size += size; -- active_size += VAR_METADATA_SIZE; -- active_size += ucs2_strsize(name, 1024); -- } -- -- kfree(tmp); -- } -- -- return status; - } - - static efi_status_t virt_efi_set_variable(efi_char16_t *name, -@@ -241,34 +181,9 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, - unsigned long data_size, - void *data) - { -- efi_status_t status; -- u32 orig_attr = 0; -- unsigned long orig_size = 0; -- -- status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size, -- NULL); -- -- if (status != EFI_BUFFER_TOO_SMALL) -- orig_size = 0; -- -- status = efi_call_virt5(set_variable, -- name, vendor, attr, -- data_size, data); -- -- if (status == EFI_SUCCESS) { -- if (orig_size) { -- active_size -= orig_size; -- active_size -= ucs2_strsize(name, 1024); -- active_size -= VAR_METADATA_SIZE; -- } -- if (data_size) { -- active_size += data_size; -- active_size += ucs2_strsize(name, 1024); -- active_size += VAR_METADATA_SIZE; -- } -- } -- -- return status; -+ return efi_call_virt5(set_variable, -+ name, vendor, attr, -+ data_size, data); - } - - static efi_status_t virt_efi_query_variable_info(u32 attr, -@@ -776,9 +691,6 @@ void __init efi_init(void) - char vendor[100] = "unknown"; - int i = 0; - void *tmp; -- struct setup_data *data; -- struct efi_var_bootdata *efi_var_data; -- u64 pa_data; - - #ifdef CONFIG_X86_32 - if (boot_params.efi_info.efi_systab_hi || -@@ -796,22 +708,6 @@ void __init efi_init(void) - if (efi_systab_init(efi_phys.systab)) - return; - -- pa_data = boot_params.hdr.setup_data; -- while (pa_data) { -- data = early_ioremap(pa_data, sizeof(*efi_var_data)); -- if (data->type == SETUP_EFI_VARS) { -- efi_var_data = (struct efi_var_bootdata *)data; -- -- efi_var_store_size = efi_var_data->store_size; -- efi_var_remaining_size = efi_var_data->remaining_size; -- efi_var_max_var_size = efi_var_data->max_var_size; -- } -- pa_data = data->next; -- early_iounmap(data, sizeof(*efi_var_data)); -- } -- -- boot_used_size = efi_var_store_size - efi_var_remaining_size; -- - set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); - - /* -@@ -1131,28 +1027,53 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) - if (status != EFI_SUCCESS) - return status; - -- if (!max_size && remaining_size > size) -- printk_once(KERN_ERR FW_BUG "Broken EFI implementation" -- " is returning MaxVariableSize=0\n"); - /* - * Some firmware implementations refuse to boot if there's insufficient - * space in the variable store. We account for that by refusing the - * write if permitting it would reduce the available space to under -- * 50%. However, some firmware won't reclaim variable space until -- * after the used (not merely the actively used) space drops below -- * a threshold. We can approximate that case with the value calculated -- * above. If both the firmware and our calculations indicate that the -- * available space would drop below 50%, refuse the write. -+ * 5KB. This figure was provided by Samsung, so should be safe. - */ -+ if ((remaining_size - size < 5120) && !efi_no_storage_paranoia) { -+ /* -+ * Triggering garbage collection may require that the firmware -+ * generate a real EFI_OUT_OF_RESOURCES error. We can force -+ * that by attempting to use more space than is available. -+ */ -+ unsigned long dummy_size = remaining_size + 1024; -+ void *dummy = kmalloc(dummy_size, GFP_ATOMIC); -+ efi_char16_t efi_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; -+ efi_guid_t guid = EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, -+ 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, -+ 0xa9); -+ -+ status = efi.set_variable(efi_name, &guid, attributes, -+ dummy_size, dummy); -+ -+ if (status == EFI_SUCCESS) { -+ /* -+ * This should have failed, so if it didn't make sure -+ * that we delete it... -+ */ -+ efi.set_variable(efi_name, &guid, attributes, 0, -+ dummy); -+ } - -- if (!storage_size || size > remaining_size || -- (max_size && size > max_size)) -- return EFI_OUT_OF_RESOURCES; -+ /* -+ * The runtime code may now have triggered a garbage collection -+ * run, so check the variable info again -+ */ -+ status = efi.query_variable_info(attributes, &storage_size, -+ &remaining_size, &max_size); - -- if (!efi_no_storage_paranoia && -- ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) && -- (remaining_size - size < storage_size / 2))) -- return EFI_OUT_OF_RESOURCES; -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ /* -+ * There still isn't enough room, so return an error -+ */ -+ if (remaining_size - size < 5120) -+ return EFI_OUT_OF_RESOURCES; -+ } - - return EFI_SUCCESS; - } --- -1.8.1.4 - diff --git a/b43-stop-format-string-leaking-into-error-msgs.patch b/b43-stop-format-string-leaking-into-error-msgs.patch deleted file mode 100644 index 84249e5eb..000000000 --- a/b43-stop-format-string-leaking-into-error-msgs.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 9538cbaab6e8b8046039b4b2eb6c9d614dc782bd Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Fri, 10 May 2013 21:48:21 +0000 -Subject: b43: stop format string leaking into error msgs - -The module parameter "fwpostfix" is userspace controllable, unfiltered, -and is used to define the firmware filename. b43_do_request_fw() populates -ctx->errors[] on error, containing the firmware filename. b43err() -parses its arguments as a format string. For systems with b43 hardware, -this could lead to a uid-0 to ring-0 escalation. - -CVE-2013-2852 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Signed-off-by: John W. Linville ---- -diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c -index 6dd07e2..a95b77a 100644 ---- a/drivers/net/wireless/b43/main.c -+++ b/drivers/net/wireless/b43/main.c -@@ -2458,7 +2458,7 @@ static void b43_request_firmware(struct work_struct *work) - for (i = 0; i < B43_NR_FWTYPES; i++) { - errmsg = ctx->errors[i]; - if (strlen(errmsg)) -- b43err(dev->wl, errmsg); -+ b43err(dev->wl, "%s", errmsg); - } - b43_print_fw_helptext(dev->wl, 1); - goto out; --- -cgit v0.9.2 diff --git a/config-generic b/config-generic index 8b4cf7afd..eeb6eea70 100644 --- a/config-generic +++ b/config-generic @@ -1533,7 +1533,7 @@ CONFIG_ATH9K_DEBUGFS=y CONFIG_ATH9K_HTC=m CONFIG_ATH9K_BTCOEX_SUPPORT=y # CONFIG_ATH9K_HTC_DEBUGFS is not set -CONFIG_ATH9K_RATE_CONTROL=y +CONFIG_ATH9K_LEGACY_RATE_CONTROL=y CONFIG_WIL6210=m CONFIG_WIL6210_ISR_COR=y CONFIG_CARL9170=m diff --git a/kernel.spec b/kernel.spec index c45d10c53..47ecfe39c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -738,9 +738,6 @@ Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch -#rhbz 903192 -Patch22261: 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch - #rhbz 916544 Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch @@ -756,9 +753,6 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 948262 Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#rhbz 964335 -Patch25026: Modify-UEFI-anti-bricking-code.patch - #CVE-2013-2140 rhbz 971146 971148 Patch25031: xen-blkback-Check-device-permissions-before-allowing.patch @@ -768,9 +762,6 @@ Patch25032: cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 Patch25033: fanotify-info-leak-in-copy_event_to_user.patch -#CVE-2013-2852 rhbz 969518 971665 -Patch25034: b43-stop-format-string-leaking-into-error-msgs.patch - #CVE-2013-2851 rhbz 969515 971662 Patch25035: block-do-not-pass-disk-names-as-format-strings.patch @@ -1470,9 +1461,6 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch -#rhbz 903192 -ApplyPatch 0001-kmsg-Honor-dmesg_restrict-sysctl-on-dev-kmsg.patch - #rhbz 916544 ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch @@ -1488,9 +1476,6 @@ ApplyPatch fix-child-thread-introspection.patch #rhbz 948262 ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#rhbz 964335 -ApplyPatch Modify-UEFI-anti-bricking-code.patch - #CVE-2013-2140 rhbz 971146 971148 ApplyPatch xen-blkback-Check-device-permissions-before-allowing.patch @@ -1500,9 +1485,6 @@ ApplyPatch cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch -#CVE-2013-2852 rhbz 969518 971665 -ApplyPatch b43-stop-format-string-leaking-into-error-msgs.patch - #CVE-2013-2851 rhbz 969515 971662 ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch @@ -2371,6 +2353,9 @@ fi # ||----w | # || || %changelog +* Thu Jun 20 2013 Justin M. Forbes - 3.9.7-200 +- Linux v3.9.7 + * Wed Jun 19 2013 Mauro Carvalho Chehab - Add and enable upstream kernel driver for nct6775 sensors diff --git a/sources b/sources index 803d88c2a..6a7aeb8b7 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -897cffc5167a561b38c6748e7f0a4215 patch-3.9.6.xz +74005c469fbd309ab631d981e2d3a6e7 patch-3.9.7.xz From f08e8e175c45a8dc552c8c0e804071fdc0a4b11d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 21 Jun 2013 09:07:54 -0400 Subject: [PATCH 355/492] Add patch to fix carl9170 oops (rhbz 967271) --- ...me-drop-and-WARN-due-to-minstrel_ht-.patch | 160 ++++++++++++++++++ kernel.spec | 9 + 2 files changed, 169 insertions(+) create mode 100644 carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch diff --git a/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch b/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch new file mode 100644 index 000000000..a360731bd --- /dev/null +++ b/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch @@ -0,0 +1,160 @@ +From 5f34608fa2acbfef5a06d0072a978c9943c28a2d Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 22 Feb 2013 01:30:44 +0100 +Subject: [PATCH] carl9170: fix frame drop and WARN due to minstrel_ht change + +With "mac80211/minstrel_ht: add support for using CCK rates" +minstrel_ht selects legacy CCK rates as viable rates for +outgoing frames which might be sent as part of an A-MPDU +[IEEE80211_TX_CTL_AMPDU is set]. + +This behavior triggered the following WARN_ON in the driver: +> WARNING: at carl9170/tx.c:995 carl9170_op_tx+0x1dd/0x6fd +The driver assumed that the rate control algorithm made a +mistake and dropped the frame. + +This patch removes the noisy warning altogether and allows +said A-MPDU frames with CCK sample and/or fallback rates to +be transmitted seamlessly. + +Signed-off-by: Christian Lamparter +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/carl9170/tx.c | 69 ++++++++++++++-------------------- + 1 file changed, 28 insertions(+), 41 deletions(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 9c0b150..c61cafa 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, + u8 tid; + + if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || +- txinfo->flags & IEEE80211_TX_CTL_INJECTED || +- (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) ++ txinfo->flags & IEEE80211_TX_CTL_INJECTED) + return; + + rcu_read_lock(); +@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, + + SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, + txc->s.ampdu_settings, factor); +- +- for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { +- txrate = &info->control.rates[i]; +- if (txrate->idx >= 0) { +- txc->s.ri[i] = +- CARL9170_TX_SUPER_RI_AMPDU; +- +- if (WARN_ON(!(txrate->flags & +- IEEE80211_TX_RC_MCS))) { +- /* +- * Not sure if it's even possible +- * to aggregate non-ht rates with +- * this HW. +- */ +- goto err_out; +- } +- continue; +- } +- +- txrate->idx = 0; +- txrate->count = ar->hw->max_rate_tries; +- } +- +- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); + } + + /* +@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar, + * taken from mac_control. For all fallback rate, the firmware + * updates the mac_control flags from the rate info field. + */ +- for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { ++ for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { ++ __le32 phy_set; + txrate = &info->control.rates[i]; + if (txrate->idx < 0) + break; + ++ phy_set = carl9170_tx_physet(ar, info, txrate); ++ if (i == 0) { ++ /* first rate - part of the hw's frame header */ ++ txc->f.phy_control = phy_set; ++ ++ if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) ++ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); ++ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) ++ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); ++ else if (carl9170_tx_cts_check(ar, txrate)) ++ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); ++ ++ } else { ++ /* fallback rates are stored in the firmware's ++ * retry rate set array. ++ */ ++ txc->s.rr[i - 1] = phy_set; ++ } ++ + SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], + txrate->count); + +@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar, + txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << + CARL9170_TX_SUPER_RI_ERP_PROT_S); + +- txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); ++ if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) ++ txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; + } + +- txrate = &info->control.rates[0]; +- SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); +- +- if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) +- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); +- else if (carl9170_tx_cts_check(ar, txrate)) +- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); +- + txc->s.len = cpu_to_le16(skb->len); + txc->f.length = cpu_to_le16(len + FCS_LEN); + txc->f.mac_control = mac_tmp; +- txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); + + arinfo = (void *)info->rate_driver_data; + arinfo->timeout = jiffies; +@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar) + } + + static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, +- struct ieee80211_sta *sta, struct sk_buff *skb) ++ struct ieee80211_sta *sta, struct sk_buff *skb, ++ struct ieee80211_tx_info *txinfo) + { +- struct _carl9170_tx_superframe *super = (void *) skb->data; + struct carl9170_sta_info *sta_info; + struct carl9170_sta_tid *agg; + struct sk_buff *iter; +@@ -1450,7 +1437,7 @@ err_unlock: + + err_unlock_rcu: + rcu_read_unlock(); +- super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); ++ txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; + carl9170_tx_status(ar, skb, false); + ar->tx_dropped++; + return false; +@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, + * sta == NULL checks are redundant in this + * special case. + */ +- run = carl9170_tx_ampdu_queue(ar, sta, skb); ++ run = carl9170_tx_ampdu_queue(ar, sta, skb, info); + if (run) + carl9170_tx_ampdu(ar); + +-- +1.7.11.7 + diff --git a/kernel.spec b/kernel.spec index 47ecfe39c..a31ff7b39 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,9 @@ Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch #rhbz 975995 Patch25047: drivers-hwmon-nct6775.patch +#rhbz 967271 +Patch25049: carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch + # END OF PATCH DEFINITIONS %endif @@ -1508,6 +1511,9 @@ ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch #rhbz 975995 ApplyPatch drivers-hwmon-nct6775.patch +#rhbz 967271 +ApplyPatch carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch + # END OF PATCH APPLICATIONS %endif @@ -2353,6 +2359,9 @@ fi # ||----w | # || || %changelog +* Fri Jun 21 2013 Josh Boyer +- Add patch to fix carl9170 oops (rhbz 967271) + * Thu Jun 20 2013 Justin M. Forbes - 3.9.7-200 - Linux v3.9.7 From 78b9117565832a185f05e7b74b5ea4dce8ab8ff3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 21 Jun 2013 09:33:25 -0400 Subject: [PATCH 356/492] Add two patches to fix iwlwifi issues in unmapping - Add patch to fix carl9170 oops (rhbz 967271) --- ...ifi-pcie-fix-race-in-queue-unmapping.patch | 56 +++++++++++++++++++ ...queue-if-stopped-when-being-unmapped.patch | 35 ++++++++++++ kernel.spec | 7 +++ 3 files changed, 98 insertions(+) create mode 100644 iwlwifi-pcie-fix-race-in-queue-unmapping.patch create mode 100644 iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch diff --git a/iwlwifi-pcie-fix-race-in-queue-unmapping.patch b/iwlwifi-pcie-fix-race-in-queue-unmapping.patch new file mode 100644 index 000000000..ad9194af3 --- /dev/null +++ b/iwlwifi-pcie-fix-race-in-queue-unmapping.patch @@ -0,0 +1,56 @@ +From: Emmanuel Grumbach + +When a queue is disabled, it frees all its entries. Later, +the op_mode might still get notifications from the firmware +that triggers to free entries in the tx queue. The transport +should be prepared for these races and know to ignore +reclaim calls on queues that have been disabled and whose +entries have been freed. + +Cc: stable@vger.kernel.org +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- + drivers/net/wireless/iwlwifi/pcie/tx.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index cb5c679..faaf77c 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -578,9 +578,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) + + spin_lock_bh(&txq->lock); + while (q->write_ptr != q->read_ptr) { ++ IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", ++ txq_id, q->read_ptr); + iwl_pcie_txq_free_tfd(trans, txq); + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); + } ++ txq->active = false; + spin_unlock_bh(&txq->lock); + } + +@@ -929,6 +932,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, + + spin_lock_bh(&txq->lock); + ++ if (!txq->active) { ++ IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n", ++ txq_id, ssn); ++ goto out; ++ } ++ + if (txq->q.read_ptr == tfd_num) + goto out; + +@@ -1105,6 +1114,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, + (fifo << SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << SCD_QUEUE_STTS_REG_POS_WSL) | + SCD_QUEUE_STTS_REG_MSK); ++ trans_pcie->txq[txq_id].active = true; + IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", + txq_id, fifo, ssn & 0xff); + } +-- +1.7.11.7 diff --git a/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch b/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch new file mode 100644 index 000000000..661fc5035 --- /dev/null +++ b/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch @@ -0,0 +1,35 @@ +From: Emmanuel Grumbach + +When the queue is unmapped while it was so loaded that +mac80211's was stopped, we need to wake the queue after +having freed all the packets in the queue. +Not doing so can result in weird stuff like: + +* run lots of traffic (mac80211's queue gets stopped) +* RFKILL +* de-assert RFKILL +* no traffic + +Cc: stable@vger.kernel.org +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- + drivers/net/wireless/iwlwifi/pcie/tx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index faaf77c..4e7b8d4 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -585,6 +585,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) + } + txq->active = false; + spin_unlock_bh(&txq->lock); ++ ++ /* just in case - this queue may have been stopped */ ++ iwl_wake_queue(trans, txq); + } + + /* +-- +1.7.11.7 diff --git a/kernel.spec b/kernel.spec index a31ff7b39..1ea7b55eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,9 @@ Patch25047: drivers-hwmon-nct6775.patch #rhbz 967271 Patch25049: carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch +Patch25050: iwlwifi-pcie-fix-race-in-queue-unmapping.patch +Patch25051: iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch + # END OF PATCH DEFINITIONS %endif @@ -1514,6 +1517,9 @@ ApplyPatch drivers-hwmon-nct6775.patch #rhbz 967271 ApplyPatch carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch +ApplyPatch iwlwifi-pcie-fix-race-in-queue-unmapping.patch +ApplyPatch iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch + # END OF PATCH APPLICATIONS %endif @@ -2360,6 +2366,7 @@ fi # || || %changelog * Fri Jun 21 2013 Josh Boyer +- Add two patches to fix iwlwifi issues in unmapping - Add patch to fix carl9170 oops (rhbz 967271) * Thu Jun 20 2013 Justin M. Forbes - 3.9.7-200 From d09da5dea4435b4e2b0bf1433877fa7f51d4592f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Jun 2013 10:24:19 -0400 Subject: [PATCH 357/492] Fix battery issue with bluetooth keyboards (rhbz 903741) --- ...ODATA-if-reading-battery-attrs-fails.patch | 55 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 64 insertions(+) create mode 100644 HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch diff --git a/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch b/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch new file mode 100644 index 000000000..acdd66d48 --- /dev/null +++ b/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch @@ -0,0 +1,55 @@ +From d0a934b764c67b4bf626f5b7cf725a6e3066afd2 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Mon, 13 May 2013 15:01:30 +0000 +Subject: HID: input: return ENODATA if reading battery attrs fails + +power_supply core has the bad habit of calling our battery callbacks +from within power_supply_register(). Furthermore, if the callbacks +fail with an unhandled error code, it will skip any uevent that it +might currently process. +So if HID-core registers battery devices, an "add" uevent is generated +and the battery callbacks are called. These will gracefully fail due +to timeouts as they might still hold locks on event processing. One +could argue that this should be fixed in power_supply core, but the +least we can do is to signal ENODATA so power_supply core will just +skip the property and continue with the uevent. + +This fixes a bug where "add" and "remove" uevents are skipped for +battery devices. upower is unable to track these devices and currently +needs to ignore them. + +This patch also overwrites any other error code. I cannot see any reason +why we should forward protocol- or I/O-errors to the power_supply core. +We handle these errors in hid_ll_driver later, anyway, so just skip +them. power_supply core cannot do anything useful with them, anyway, +and we avoid skipping important uevents and confusing user-space. + +Thanks a lot to Daniel Nicoletti for pushing and investigating +on this. + +Cc: Jiri Kosina +Cc: Anton Vorontsov +Cc: David Woodhouse +Reported-by: Daniel Nicoletti +Signed-off-by: David Herrmann +Signed-off-by: Jiri Kosina +--- +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 945b815..c526a3c 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -354,10 +354,10 @@ static int hidinput_get_battery_property(struct power_supply *psy, + dev->battery_report_type); + + if (ret != 2) { +- if (ret >= 0) +- ret = -EINVAL; ++ ret = -ENODATA; + break; + } ++ ret = 0; + + if (dev->battery_min < dev->battery_max && + buf[1] >= dev->battery_min && +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 1ea7b55eb..2ec466947 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch25049: carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch Patch25050: iwlwifi-pcie-fix-race-in-queue-unmapping.patch Patch25051: iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch +#rhbz 903741 +Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch + # END OF PATCH DEFINITIONS %endif @@ -1520,6 +1523,9 @@ ApplyPatch carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch ApplyPatch iwlwifi-pcie-fix-race-in-queue-unmapping.patch ApplyPatch iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch +#rhbz 903741 +ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch + # END OF PATCH APPLICATIONS %endif @@ -2365,6 +2371,9 @@ fi # ||----w | # || || %changelog +* Mon Jun 24 2013 Josh Boyer +- Fix battery issue with bluetooth keyboards (rhbz 903741) + * Fri Jun 21 2013 Josh Boyer - Add two patches to fix iwlwifi issues in unmapping - Add patch to fix carl9170 oops (rhbz 967271) From e7af4730ae00cb1713bbb8e8488f2f99fcd5f9a0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Jun 2013 07:50:55 -0400 Subject: [PATCH 358/492] Add two patches to fix bridge networking issues (rhbz 880035) --- ...the-mdb-entry-when-query-is-received.patch | 159 ++++++++++++++++++ ...d-query-as-soon-as-leave-is-received.patch | 57 +++++++ kernel.spec | 11 ++ 3 files changed, 227 insertions(+) create mode 100644 bridge-only-expire-the-mdb-entry-when-query-is-received.patch create mode 100644 bridge-send-query-as-soon-as-leave-is-received.patch diff --git a/bridge-only-expire-the-mdb-entry-when-query-is-received.patch b/bridge-only-expire-the-mdb-entry-when-query-is-received.patch new file mode 100644 index 000000000..b58b57083 --- /dev/null +++ b/bridge-only-expire-the-mdb-entry-when-query-is-received.patch @@ -0,0 +1,159 @@ +From 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Tue, 21 May 2013 21:52:55 +0000 +Subject: bridge: only expire the mdb entry when query is received + +Currently we arm the expire timer when the mdb entry is added, +however, this causes problem when there is no querier sent +out after that. + +So we should only arm the timer when a corresponding query is +received, as suggested by Herbert. + +And he also mentioned "if there is no querier then group +subscriptions shouldn't expire. There has to be at least one querier +in the network for this thing to work. Otherwise it just degenerates +into a non-snooping switch, which is OK." + +Cc: Herbert Xu +Cc: Stephen Hemminger +Cc: "David S. Miller" +Cc: Adam Baker +Signed-off-by: Cong Wang +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- +(limited to 'net/bridge') + +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 2475147..40bda80 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -617,8 +617,6 @@ rehash: + + mp->br = br; + mp->addr = *group; +- setup_timer(&mp->timer, br_multicast_group_expired, +- (unsigned long)mp); + + hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); + mdb->size++; +@@ -656,7 +654,6 @@ static int br_multicast_add_group(struct net_bridge *br, + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *p; + struct net_bridge_port_group __rcu **pp; +- unsigned long now = jiffies; + int err; + + spin_lock(&br->multicast_lock); +@@ -671,7 +668,6 @@ static int br_multicast_add_group(struct net_bridge *br, + + if (!port) { + mp->mglist = true; +- mod_timer(&mp->timer, now + br->multicast_membership_interval); + goto out; + } + +@@ -679,7 +675,7 @@ static int br_multicast_add_group(struct net_bridge *br, + (p = mlock_dereference(*pp, br)) != NULL; + pp = &p->next) { + if (p->port == port) +- goto found; ++ goto out; + if ((unsigned long)p->port < (unsigned long)port) + break; + } +@@ -690,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br, + rcu_assign_pointer(*pp, p); + br_mdb_notify(br->dev, port, group, RTM_NEWMDB); + +-found: +- mod_timer(&p->timer, now + br->multicast_membership_interval); + out: + err = 0; + +@@ -1131,6 +1125,10 @@ static int br_ip4_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + ++ setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); ++ mod_timer(&mp->timer, now + br->multicast_membership_interval); ++ mp->timer_armed = true; ++ + max_delay *= br->multicast_last_member_count; + + if (mp->mglist && +@@ -1205,6 +1203,10 @@ static int br_ip6_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + ++ setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); ++ mod_timer(&mp->timer, now + br->multicast_membership_interval); ++ mp->timer_armed = true; ++ + max_delay *= br->multicast_last_member_count; + if (mp->mglist && + (timer_pending(&mp->timer) ? +@@ -1263,7 +1265,7 @@ static void br_multicast_leave_group(struct net_bridge *br, + call_rcu_bh(&p->rcu, br_multicast_free_pg); + br_mdb_notify(br->dev, port, group, RTM_DELMDB); + +- if (!mp->ports && !mp->mglist && ++ if (!mp->ports && !mp->mglist && mp->timer_armed && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + } +@@ -1275,30 +1277,12 @@ static void br_multicast_leave_group(struct net_bridge *br, + br->multicast_last_member_interval; + + if (!port) { +- if (mp->mglist && ++ if (mp->mglist && mp->timer_armed && + (timer_pending(&mp->timer) ? + time_after(mp->timer.expires, time) : + try_to_del_timer_sync(&mp->timer) >= 0)) { + mod_timer(&mp->timer, time); + } +- +- goto out; +- } +- +- for (p = mlock_dereference(mp->ports, br); +- p != NULL; +- p = mlock_dereference(p->next, br)) { +- if (p->port != port) +- continue; +- +- if (!hlist_unhashed(&p->mglist) && +- (timer_pending(&p->timer) ? +- time_after(p->timer.expires, time) : +- try_to_del_timer_sync(&p->timer) >= 0)) { +- mod_timer(&p->timer, time); +- } +- +- break; + } + + out: +@@ -1674,6 +1658,7 @@ void br_multicast_stop(struct net_bridge *br) + hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], + hlist[ver]) { + del_timer(&mp->timer); ++ mp->timer_armed = false; + call_rcu_bh(&mp->rcu, br_multicast_free_group); + } + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index e260710..1b0ac95 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -112,6 +112,7 @@ struct net_bridge_mdb_entry + struct timer_list timer; + struct br_ip addr; + bool mglist; ++ bool timer_armed; + }; + + struct net_bridge_mdb_htable +-- +cgit v0.9.2 diff --git a/bridge-send-query-as-soon-as-leave-is-received.patch b/bridge-send-query-as-soon-as-leave-is-received.patch new file mode 100644 index 000000000..8b6652e7e --- /dev/null +++ b/bridge-send-query-as-soon-as-leave-is-received.patch @@ -0,0 +1,57 @@ +From 6b7df111ece130fa979a0c4f58e53674c1e47d3e Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Tue, 21 May 2013 21:52:56 +0000 +Subject: bridge: send query as soon as leave is received + +Continue sending queries when leave is received if the user marks +it as a querier. + +Cc: Herbert Xu +Cc: Stephen Hemminger +Cc: "David S. Miller" +Cc: Adam Baker +Signed-off-by: Cong Wang +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- +(limited to 'net/bridge') + +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 40bda80..37a4676 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1250,6 +1250,32 @@ static void br_multicast_leave_group(struct net_bridge *br, + if (!mp) + goto out; + ++ if (br->multicast_querier && ++ !timer_pending(&br->multicast_querier_timer)) { ++ __br_multicast_send_query(br, port, &mp->addr); ++ ++ time = jiffies + br->multicast_last_member_count * ++ br->multicast_last_member_interval; ++ mod_timer(port ? &port->multicast_query_timer : ++ &br->multicast_query_timer, time); ++ ++ for (p = mlock_dereference(mp->ports, br); ++ p != NULL; ++ p = mlock_dereference(p->next, br)) { ++ if (p->port != port) ++ continue; ++ ++ if (!hlist_unhashed(&p->mglist) && ++ (timer_pending(&p->timer) ? ++ time_after(p->timer.expires, time) : ++ try_to_del_timer_sync(&p->timer) >= 0)) { ++ mod_timer(&p->timer, time); ++ } ++ ++ break; ++ } ++ } ++ + if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { + struct net_bridge_port_group __rcu **pp; + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 2ec466947..c9e85b2b3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -794,6 +794,10 @@ Patch25051: iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch #rhbz 903741 Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch +#rhbz 880035 +Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch +Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch + # END OF PATCH DEFINITIONS %endif @@ -1526,6 +1530,10 @@ ApplyPatch iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch #rhbz 903741 ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch +#rhbz 880035 +ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch +ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch + # END OF PATCH APPLICATIONS %endif @@ -2371,6 +2379,9 @@ fi # ||----w | # || || %changelog +* Wed Jun 26 2013 Josh Boyer +- Add two patches to fix bridge networking issues (rhbz 880035) + * Mon Jun 24 2013 Josh Boyer - Fix battery issue with bluetooth keyboards (rhbz 903741) From 35140946fbc95ac2c4434c8a4f5ad7cc9b1534b9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 27 Jun 2013 09:36:48 -0400 Subject: [PATCH 359/492] Fix stack memory usage for DMA in ath3k (rhbz 977558) --- ath3k-dont-use-stack-memory-for-DMA.patch | 72 +++++++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 81 insertions(+) create mode 100644 ath3k-dont-use-stack-memory-for-DMA.patch diff --git a/ath3k-dont-use-stack-memory-for-DMA.patch b/ath3k-dont-use-stack-memory-for-DMA.patch new file mode 100644 index 000000000..610a00067 --- /dev/null +++ b/ath3k-dont-use-stack-memory-for-DMA.patch @@ -0,0 +1,72 @@ +Memory allocated by vmalloc (including stack) can not be used for DMA, +i.e. data pointer on usb_control_msg() should not point to stack memory. + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=977558 + +Reported-and-tested-by: Andy Lawrence +Signed-off-by: Stanislaw Gruszka +--- + drivers/bluetooth/ath3k.c | 38 +++++++++++++++++++++++++++++--------- + 1 file changed, 29 insertions(+), 9 deletions(-) + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 11f467c..81b636c 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -193,24 +193,44 @@ error: + + static int ath3k_get_state(struct usb_device *udev, unsigned char *state) + { +- int pipe = 0; ++ int ret, pipe = 0; ++ char *buf; ++ ++ buf = kmalloc(1, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + + pipe = usb_rcvctrlpipe(udev, 0); +- return usb_control_msg(udev, pipe, ATH3K_GETSTATE, +- USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +- state, 0x01, USB_CTRL_SET_TIMEOUT); ++ ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE, ++ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, ++ buf, 1, USB_CTRL_SET_TIMEOUT); ++ ++ *state = *buf; ++ kfree(buf); ++ ++ return ret; + } + + static int ath3k_get_version(struct usb_device *udev, + struct ath3k_version *version) + { +- int pipe = 0; ++ int ret, pipe = 0; ++ char *buf; ++ const int size = sizeof(struct ath3k_version); ++ ++ buf = kmalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + + pipe = usb_rcvctrlpipe(udev, 0); +- return usb_control_msg(udev, pipe, ATH3K_GETVERSION, +- USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, +- sizeof(struct ath3k_version), +- USB_CTRL_SET_TIMEOUT); ++ ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION, ++ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, ++ buf, size, USB_CTRL_SET_TIMEOUT); ++ ++ memcpy(version, buf, size); ++ kfree(buf); ++ ++ return ret; + } + + static int ath3k_load_fwfile(struct usb_device *udev, +-- +1.7.11.7 diff --git a/kernel.spec b/kernel.spec index c9e85b2b3..572289f98 100644 --- a/kernel.spec +++ b/kernel.spec @@ -798,6 +798,9 @@ Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch +#rhbz 977558 +Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch + # END OF PATCH DEFINITIONS %endif @@ -1534,6 +1537,9 @@ ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch +#rhbz 977558 +ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch + # END OF PATCH APPLICATIONS %endif @@ -2379,6 +2385,9 @@ fi # ||----w | # || || %changelog +* Thu Jun 27 2013 Josh Boyer +- Fix stack memory usage for DMA in ath3k (rhbz 977558) + * Wed Jun 26 2013 Josh Boyer - Add two patches to fix bridge networking issues (rhbz 880035) From 7ac2c9df5f0b889e61650cdacddf7c3c1deb514e Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 27 Jun 2013 14:10:36 -0500 Subject: [PATCH 360/492] Linux v3.9.8 --- ...me-drop-and-WARN-due-to-minstrel_ht-.patch | 160 ------------------ config-armv7-generic | 1 + kernel.spec | 27 +-- sources | 2 +- ...p-set-SOCK_ZEROCOPY-flag-during-open.patch | 26 --- ...trol-for-non-zerocopy-case-during-tx.patch | 60 ------- ...inal-mtrr-range-get-for-mtrr_cleanup.patch | 63 ------- x86-range-make-add_range-use-blank-slot.patch | 73 -------- 8 files changed, 6 insertions(+), 406 deletions(-) delete mode 100644 carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch delete mode 100644 tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch delete mode 100644 vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch delete mode 100644 x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch delete mode 100644 x86-range-make-add_range-use-blank-slot.patch diff --git a/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch b/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch deleted file mode 100644 index a360731bd..000000000 --- a/carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 5f34608fa2acbfef5a06d0072a978c9943c28a2d Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Fri, 22 Feb 2013 01:30:44 +0100 -Subject: [PATCH] carl9170: fix frame drop and WARN due to minstrel_ht change - -With "mac80211/minstrel_ht: add support for using CCK rates" -minstrel_ht selects legacy CCK rates as viable rates for -outgoing frames which might be sent as part of an A-MPDU -[IEEE80211_TX_CTL_AMPDU is set]. - -This behavior triggered the following WARN_ON in the driver: -> WARNING: at carl9170/tx.c:995 carl9170_op_tx+0x1dd/0x6fd -The driver assumed that the rate control algorithm made a -mistake and dropped the frame. - -This patch removes the noisy warning altogether and allows -said A-MPDU frames with CCK sample and/or fallback rates to -be transmitted seamlessly. - -Signed-off-by: Christian Lamparter -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/carl9170/tx.c | 69 ++++++++++++++-------------------- - 1 file changed, 28 insertions(+), 41 deletions(-) - -diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c -index 9c0b150..c61cafa 100644 ---- a/drivers/net/wireless/ath/carl9170/tx.c -+++ b/drivers/net/wireless/ath/carl9170/tx.c -@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, - u8 tid; - - if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || -- txinfo->flags & IEEE80211_TX_CTL_INJECTED || -- (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) -+ txinfo->flags & IEEE80211_TX_CTL_INJECTED) - return; - - rcu_read_lock(); -@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, - - SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, - txc->s.ampdu_settings, factor); -- -- for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { -- txrate = &info->control.rates[i]; -- if (txrate->idx >= 0) { -- txc->s.ri[i] = -- CARL9170_TX_SUPER_RI_AMPDU; -- -- if (WARN_ON(!(txrate->flags & -- IEEE80211_TX_RC_MCS))) { -- /* -- * Not sure if it's even possible -- * to aggregate non-ht rates with -- * this HW. -- */ -- goto err_out; -- } -- continue; -- } -- -- txrate->idx = 0; -- txrate->count = ar->hw->max_rate_tries; -- } -- -- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); - } - - /* -@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar, - * taken from mac_control. For all fallback rate, the firmware - * updates the mac_control flags from the rate info field. - */ -- for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { -+ for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { -+ __le32 phy_set; - txrate = &info->control.rates[i]; - if (txrate->idx < 0) - break; - -+ phy_set = carl9170_tx_physet(ar, info, txrate); -+ if (i == 0) { -+ /* first rate - part of the hw's frame header */ -+ txc->f.phy_control = phy_set; -+ -+ if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) -+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); -+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) -+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); -+ else if (carl9170_tx_cts_check(ar, txrate)) -+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); -+ -+ } else { -+ /* fallback rates are stored in the firmware's -+ * retry rate set array. -+ */ -+ txc->s.rr[i - 1] = phy_set; -+ } -+ - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], - txrate->count); - -@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar, - txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << - CARL9170_TX_SUPER_RI_ERP_PROT_S); - -- txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); -+ if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) -+ txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; - } - -- txrate = &info->control.rates[0]; -- SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); -- -- if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) -- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); -- else if (carl9170_tx_cts_check(ar, txrate)) -- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); -- - txc->s.len = cpu_to_le16(skb->len); - txc->f.length = cpu_to_le16(len + FCS_LEN); - txc->f.mac_control = mac_tmp; -- txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); - - arinfo = (void *)info->rate_driver_data; - arinfo->timeout = jiffies; -@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar) - } - - static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, -- struct ieee80211_sta *sta, struct sk_buff *skb) -+ struct ieee80211_sta *sta, struct sk_buff *skb, -+ struct ieee80211_tx_info *txinfo) - { -- struct _carl9170_tx_superframe *super = (void *) skb->data; - struct carl9170_sta_info *sta_info; - struct carl9170_sta_tid *agg; - struct sk_buff *iter; -@@ -1450,7 +1437,7 @@ err_unlock: - - err_unlock_rcu: - rcu_read_unlock(); -- super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); -+ txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; - carl9170_tx_status(ar, skb, false); - ar->tx_dropped++; - return false; -@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, - * sta == NULL checks are redundant in this - * special case. - */ -- run = carl9170_tx_ampdu_queue(ar, sta, skb); -+ run = carl9170_tx_ampdu_queue(ar, sta, skb, info); - if (run) - carl9170_tx_ampdu(ar); - --- -1.7.11.7 - diff --git a/config-armv7-generic b/config-armv7-generic index 7b4d546c7..c005a4efc 100644 --- a/config-armv7-generic +++ b/config-armv7-generic @@ -54,6 +54,7 @@ CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set # Cortex-A9 +CONFIG_ARM_ERRATA_643719=y CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_742230=y CONFIG_ARM_ERRATA_742231=y diff --git a/kernel.spec b/kernel.spec index 572289f98..12f148010 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -768,14 +768,6 @@ Patch25035: block-do-not-pass-disk-names-as-format-strings.patch #CVE-2013-2164 rhbz 973100 973109 Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch -#rhbz 954181 -Patch25039: vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch -Patch25040: tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch - -#rhbz 973185 -Patch25041: x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch -Patch25042: x86-range-make-add_range-use-blank-slot.patch - #rhbz 950735 Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch @@ -785,9 +777,6 @@ Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch #rhbz 975995 Patch25047: drivers-hwmon-nct6775.patch -#rhbz 967271 -Patch25049: carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch - Patch25050: iwlwifi-pcie-fix-race-in-queue-unmapping.patch Patch25051: iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch @@ -1507,14 +1496,6 @@ ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch #CVE-2013-2164 rhbz 973100 973109 ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch -#rhbz 954181 -ApplyPatch vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch -ApplyPatch tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch - -#rhbz 973185 -ApplyPatch x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch -ApplyPatch x86-range-make-add_range-use-blank-slot.patch - #rhbz 950735 ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch @@ -1524,9 +1505,6 @@ ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch #rhbz 975995 ApplyPatch drivers-hwmon-nct6775.patch -#rhbz 967271 -ApplyPatch carl9170-fix-frame-drop-and-WARN-due-to-minstrel_ht-.patch - ApplyPatch iwlwifi-pcie-fix-race-in-queue-unmapping.patch ApplyPatch iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch @@ -2385,6 +2363,9 @@ fi # ||----w | # || || %changelog +* Thu Jun 27 2013 Justin M. Forbes - 3.9.8-200 +- Linux v3.9.8 + * Thu Jun 27 2013 Josh Boyer - Fix stack memory usage for DMA in ath3k (rhbz 977558) diff --git a/sources b/sources index 6a7aeb8b7..607da4fb5 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -74005c469fbd309ab631d981e2d3a6e7 patch-3.9.7.xz +c5f2166686a913abf550bfed8b77df27 patch-3.9.8.xz diff --git a/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch b/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch deleted file mode 100644 index 75de6ccce..000000000 --- a/tuntap-set-SOCK_ZEROCOPY-flag-during-open.patch +++ /dev/null @@ -1,26 +0,0 @@ -tuntap: set SOCK_ZEROCOPY flag during open - -Commit 54f968d6efdbf7dec36faa44fc11f01b0e4d1990 -(tuntap: move socket to tun_file) forgets to set SOCK_ZEROCOPY flag, which will -prevent vhost_net from doing zercopy w/ tap. This patch fixes this by setting -it during file open. - -Cc: Michael S. Tsirkin -Signed-off-by: Jason Wang -Acked-by: Michael S. Tsirkin - ---- - -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index 89776c5..ff5312d 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -2159,6 +2159,8 @@ static int tun_chr_open(struct inode *inode, struct file * file) - set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); - INIT_LIST_HEAD(&tfile->next); - -+ sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); -+ - return 0; - } - diff --git a/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch b/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch deleted file mode 100644 index 4455bbc0b..000000000 --- a/vhost_net-clear-msg.control-for-non-zerocopy-case-during-tx.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 3add6ae9e1b854a9ddbe0dc17ff4ec48a2dac9fe Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Wed, 5 Jun 2013 07:40:46 +0000 -Subject: [PATCH] vhost_net: clear msg.control for non-zerocopy case during tx - -When we decide not use zero-copy, msg.control should be set to NULL otherwise -macvtap/tap may set zerocopy callbacks which may decrease the kref of ubufs -wrongly. - -Bug were introduced by commit cedb9bdce099206290a2bdd02ce47a7b253b6a84 -(vhost-net: skip head management if no outstanding). - -This solves the following warnings: - -WARNING: at include/linux/kref.h:47 handle_tx+0x477/0x4b0 [vhost_net]() -Modules linked in: vhost_net macvtap macvlan tun nfsd exportfs bridge stp llc openvswitch kvm_amd kvm bnx2 megaraid_sas [last unloaded: tun] -CPU: 5 PID: 8670 Comm: vhost-8668 Not tainted 3.10.0-rc2+ #1566 -Hardware name: Dell Inc. PowerEdge R715/00XHKG, BIOS 1.5.2 04/19/2011 -ffffffffa0198323 ffff88007c9ebd08 ffffffff81796b73 ffff88007c9ebd48 -ffffffff8103d66b 000000007b773e20 ffff8800779f0000 ffff8800779f43f0 -ffff8800779f8418 000000000000015c 0000000000000062 ffff88007c9ebd58 -Call Trace: -[] dump_stack+0x19/0x1e -[] warn_slowpath_common+0x6b/0xa0 -[] warn_slowpath_null+0x15/0x20 -[] handle_tx+0x477/0x4b0 [vhost_net] -[] handle_tx_kick+0x10/0x20 [vhost_net] -[] vhost_worker+0xfe/0x1a0 [vhost_net] -[] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net] -[] ? vhost_attach_cgroups_work+0x30/0x30 [vhost_net] -[] kthread+0xc6/0xd0 -[] ? kthread_freezable_should_stop+0x70/0x70 -[] ret_from_fork+0x7c/0xb0 -[] ? kthread_freezable_should_stop+0x70/0x70 - -Signed-off-by: Jason Wang -Acked-by: Michael S. Tsirkin -Signed-off-by: David S. Miller ---- - drivers/vhost/net.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c -index ec6fb3f..3980e66 100644 ---- a/drivers/vhost/net.c -+++ b/drivers/vhost/net.c -@@ -353,7 +353,9 @@ static void handle_tx(struct vhost_net *net) - kref_get(&ubufs->kref); - } - vq->upend_idx = (vq->upend_idx + 1) % UIO_MAXIOV; -- } -+ } else -+ msg.msg_control = NULL; -+ - /* TODO: Check specific error and bomb out unless ENOBUFS? */ - err = sock->ops->sendmsg(NULL, sock, &msg, len); - if (unlikely(err < 0)) { --- -1.8.1.4 - diff --git a/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch b/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch deleted file mode 100644 index 7c8b930f7..000000000 --- a/x86-mtrr-Fix-original-mtrr-range-get-for-mtrr_cleanup.patch +++ /dev/null @@ -1,63 +0,0 @@ -Joshua reported: Commit cd7b304dfaf1 (x86, range: fix missing merge -during add range) broke mtrr cleanup on his setup in 3.9.5. -corresponding commit in upstream is fbe06b7bae7c. - - *BAD*gran_size: 64K chunk_size: 16M num_reg: 6 lose cover RAM: -0G - -https://bugzilla.kernel.org/show_bug.cgi?id=59491 - -So it rejects new var mtrr layout. - -It turns out we have some problem with initial mtrr range retrievel. -current sequence is: - x86_get_mtrr_mem_range - ==> bunchs of add_range_with_merge - ==> bunchs of subract_range - ==> clean_sort_range - add_range_with_merge for [0,1M) - sort_range() - -add_range_with_merge could have blank slots, so we can not just -sort only, that will have final result have extra blank slot in head. - -So move that calling add_range_with_merge for [0,1M), with that we -could avoid extra clean_sort_range calling. - -Reported-by: Joshua Covington -Tested-by: Joshua Covington -Signed-off-by: Yinghai Lu -Cc: v3.9 - ---- - arch/x86/kernel/cpu/mtrr/cleanup.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -Index: linux-2.6/arch/x86/kernel/cpu/mtrr/cleanup.c -=================================================================== ---- linux-2.6.orig/arch/x86/kernel/cpu/mtrr/cleanup.c -+++ linux-2.6/arch/x86/kernel/cpu/mtrr/cleanup.c -@@ -714,15 +714,15 @@ int __init mtrr_cleanup(unsigned address - if (mtrr_tom2) - x_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - x_remove_base; - -- nr_range = x86_get_mtrr_mem_range(range, 0, x_remove_base, x_remove_size); - /* - * [0, 1M) should always be covered by var mtrr with WB - * and fixed mtrrs should take effect before var mtrr for it: - */ -- nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0, -+ nr_range = add_range_with_merge(range, RANGE_NUM, 0, 0, - 1ULL<<(20 - PAGE_SHIFT)); -- /* Sort the ranges: */ -- sort_range(range, nr_range); -+ /* add from var mtrr at last */ -+ nr_range = x86_get_mtrr_mem_range(range, nr_range, -+ x_remove_base, x_remove_size); - - range_sums = sum_ranges(range, nr_range); - printk(KERN_INFO "total RAM covered: %ldM\n", --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file diff --git a/x86-range-make-add_range-use-blank-slot.patch b/x86-range-make-add_range-use-blank-slot.patch deleted file mode 100644 index 8a04f4f5c..000000000 --- a/x86-range-make-add_range-use-blank-slot.patch +++ /dev/null @@ -1,73 +0,0 @@ -Now add_range_with_merge will generate blank slot as subtract_range. -we could reach the array limit because of blank slots. - -We can let add_range to have second try to use blank slot. - -Also use WARN_ONCE to print trace. - -Reported-by: Joshua Covington -Signed-off-by: Yinghai Lu -Cc: v3.9 ---- - kernel/range.c | 34 ++++++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 12 deletions(-) - -diff --git a/kernel/range.c b/kernel/range.c -index 98883ed..8ca718a 100644 ---- a/kernel/range.c -+++ b/kernel/range.c -@@ -3,23 +3,34 @@ - */ - #include - #include -+#include - #include -- - #include - - int add_range(struct range *range, int az, int nr_range, u64 start, u64 end) - { -- if (start >= end) -- return nr_range; -+ int i; - -- /* Out of slots: */ -- if (nr_range >= az) -+ if (start >= end) - return nr_range; - -- range[nr_range].start = start; -- range[nr_range].end = end; -+ /* Out of slots ? */ -+ if (nr_range < az) { -+ i = nr_range; -+ nr_range++; -+ } else { -+ /* find blank slot */ -+ for (i = 0; i < az; i++) -+ if (!range[i].end) -+ break; -+ if (i == az) { -+ WARN_ONCE(1, "run out of slot in ranges\n"); -+ return az; -+ } -+ } - -- nr_range++; -+ range[i].start = start; -+ range[i].end = end; - - return nr_range; - } -@@ -99,7 +110,7 @@ void subtract_range(struct range *range, int az, u64 start, u64 end) - range[i].end = range[j].end; - range[i].start = end; - } else { -- printk(KERN_ERR "run of slot in ranges\n"); -+ WARN_ONCE(1,"run of slot in ranges\n"); - } - range[j].end = start; - continue; --- -1.8.1.4 - From 82b878e48961689aafa8844b3c8ff1ecf5985dce Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Jul 2013 08:29:53 -0400 Subject: [PATCH 361/492] Add patches to fix iwl skb managment (rhbz 977040) --- ...945-better-skb-management-in-rx-path.patch | 97 +++++++++++++++++++ ...965-better-skb-management-in-rx-path.patch | 66 +++++++++++++ kernel.spec | 11 +++ 3 files changed, 174 insertions(+) create mode 100644 iwl3945-better-skb-management-in-rx-path.patch create mode 100644 iwl4965-better-skb-management-in-rx-path.patch diff --git a/iwl3945-better-skb-management-in-rx-path.patch b/iwl3945-better-skb-management-in-rx-path.patch new file mode 100644 index 000000000..5d85af7d4 --- /dev/null +++ b/iwl3945-better-skb-management-in-rx-path.patch @@ -0,0 +1,97 @@ +From: Eric Dumazet + +Steinar reported reallocations of skb->head with IPv6, leading to +a warning in skb_try_coalesce() + +It turns out iwl3945 has several problems : + +1) skb->truesize is underestimated. + We really consume PAGE_SIZE bytes for a fragment, + not the frame length. +2) 128 bytes of initial headroom is a bit low and forces reallocations. +3) We can avoid consuming a full page for small enough frames. + +Reported-by: Steinar H. Gunderson +Signed-off-by: Eric Dumazet +Cc: Paul Stewart +--- +v3: use regular memcpy(skb_put(...),...) +v2: SMALL_PACKET_SIZE define + + drivers/net/wireless/iwlegacy/3945.c | 31 +++++++++++++++---------- + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c +index c092033..f09e257 100644 +--- a/drivers/net/wireless/iwlegacy/3945.c ++++ b/drivers/net/wireless/iwlegacy/3945.c +@@ -475,6 +475,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header) + } + } + ++#define SMALL_PACKET_SIZE 256 ++ + static void + il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, + struct ieee80211_rx_status *stats) +@@ -483,14 +485,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt); + struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt); + struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt); +- u16 len = le16_to_cpu(rx_hdr->len); ++ u32 len = le16_to_cpu(rx_hdr->len); + struct sk_buff *skb; + __le16 fc = hdr->frame_control; ++ u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order; + + /* We received data from the HW, so stop the watchdog */ +- if (unlikely +- (len + IL39_RX_FRAME_SIZE > +- PAGE_SIZE << il->hw_params.rx_page_order)) { ++ if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) { + D_DROP("Corruption detected!\n"); + return; + } +@@ -506,26 +507,32 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, + D_INFO("Woke queues - frame received on passive channel\n"); + } + +- skb = dev_alloc_skb(128); ++ skb = dev_alloc_skb(SMALL_PACKET_SIZE); + if (!skb) { + IL_ERR("dev_alloc_skb failed\n"); + return; + } + + if (!il3945_mod_params.sw_crypto) +- il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb), ++ il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt, + le32_to_cpu(rx_end->status), stats); + +- skb_add_rx_frag(skb, 0, rxb->page, +- (void *)rx_hdr->payload - (void *)pkt, len, +- len); +- ++ /* If frame is small enough to fit into skb->head, copy it ++ * and do not consume a full page ++ */ ++ if (len <= SMALL_PACKET_SIZE) { ++ memcpy(skb_put(skb, len), rx_hdr->payload, len); ++ } else { ++ skb_add_rx_frag(skb, 0, rxb->page, ++ (void *)rx_hdr->payload - (void *)pkt, len, ++ fraglen); ++ il->alloc_rxb_page--; ++ rxb->page = NULL; ++ } + il_update_stats(il, false, fc, len); + memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); + + ieee80211_rx(il->hw, skb); +- il->alloc_rxb_page--; +- rxb->page = NULL; + } + + #define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) + + diff --git a/iwl4965-better-skb-management-in-rx-path.patch b/iwl4965-better-skb-management-in-rx-path.patch new file mode 100644 index 000000000..b5d987900 --- /dev/null +++ b/iwl4965-better-skb-management-in-rx-path.patch @@ -0,0 +1,66 @@ +4965 version of Eric patch "iwl3945: better skb management in rx path". +It fixes several problems : + +1) skb->truesize is underestimated. + We really consume PAGE_SIZE bytes for a fragment, + not the frame length. +2) 128 bytes of initial headroom is a bit low and forces reallocations. +3) We can avoid consuming a full page for small enough frames. + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/4965-mac.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c +index d287fd2..4e5d408 100644 +--- a/drivers/net/wireless/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/iwlegacy/4965-mac.c +@@ -574,9 +574,11 @@ il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in) + return decrypt_out; + } + ++#define SMALL_PACKET_SIZE 256 ++ + static void + il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, +- u16 len, u32 ampdu_status, struct il_rx_buf *rxb, ++ u32 len, u32 ampdu_status, struct il_rx_buf *rxb, + struct ieee80211_rx_status *stats) + { + struct sk_buff *skb; +@@ -598,21 +600,25 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, + il_set_decrypted_flag(il, hdr, ampdu_status, stats)) + return; + +- skb = dev_alloc_skb(128); ++ skb = dev_alloc_skb(SMALL_PACKET_SIZE); + if (!skb) { + IL_ERR("dev_alloc_skb failed\n"); + return; + } + +- skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len, +- len); ++ if (len <= SMALL_PACKET_SIZE) { ++ memcpy(skb_put(skb, len), hdr, len); ++ } else { ++ skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), ++ len, PAGE_SIZE << il->hw_params.rx_page_order); ++ il->alloc_rxb_page--; ++ rxb->page = NULL; ++ } + + il_update_stats(il, false, fc, len); + memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); + + ieee80211_rx(il->hw, skb); +- il->alloc_rxb_page--; +- rxb->page = NULL; + } + + /* Called for N_RX (legacy ABG frames), or +-- +1.7.11.7 + + diff --git a/kernel.spec b/kernel.spec index 12f148010..0fe86c7c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -790,6 +790,10 @@ Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch #rhbz 977558 Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch +#rhbz 977040 +Patch25056: iwl3945-better-skb-management-in-rx-path.patch +Patch25057: iwl4965-better-skb-management-in-rx-path.patch + # END OF PATCH DEFINITIONS %endif @@ -1518,6 +1522,10 @@ ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch #rhbz 977558 ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch +#rhbz 977040 +ApplyPatch iwl3945-better-skb-management-in-rx-path.patch +ApplyPatch iwl4965-better-skb-management-in-rx-path.patch + # END OF PATCH APPLICATIONS %endif @@ -2363,6 +2371,9 @@ fi # ||----w | # || || %changelog +* Wed Jul 03 2013 Josh Boyer +- Add patches to fix iwl skb managment (rhbz 977040) + * Thu Jun 27 2013 Justin M. Forbes - 3.9.8-200 - Linux v3.9.8 From 1afd520f13c150c4b86459b33147dc138747e75e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Jul 2013 14:48:32 -0400 Subject: [PATCH 362/492] Linux v3.9.9 --- kernel.spec | 13 ++-- ...-RT3290-TX-power-settings-regression.patch | 71 ------------------- sources | 2 +- 3 files changed, 6 insertions(+), 80 deletions(-) delete mode 100644 rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch diff --git a/kernel.spec b/kernel.spec index 0fe86c7c3..cc9c0fbd8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -768,9 +768,6 @@ Patch25035: block-do-not-pass-disk-names-as-format-strings.patch #CVE-2013-2164 rhbz 973100 973109 Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch -#rhbz 950735 -Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch - #rhbz 969644 Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -1500,9 +1497,6 @@ ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch #CVE-2013-2164 rhbz 973100 973109 ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch -#rhbz 950735 -ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch - #rhbz 969644 ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -2371,6 +2365,9 @@ fi # ||----w | # || || %changelog +* Wed Jul 03 2013 Josh Boyer +- Linux v3.9.9 + * Wed Jul 03 2013 Josh Boyer - Add patches to fix iwl skb managment (rhbz 977040) @@ -2555,7 +2552,7 @@ fi * Thu Apr 11 2013 Josh Boyer - Fix ALPS backport patch (rhbz 812111) -* Mon Apr 09 2013 Josh Boyer - 3.8.6-203 +* Tue Apr 09 2013 Josh Boyer - 3.8.6-203 - Temporarily work around pci device assignment issues (rhbz 908888) - CVE-2013-1929 tg3: len overflow in VPD firmware parsing (rhbz 949932 949946) - Backport intel brightness quirk for emachines (rhbz 871932) diff --git a/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch b/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch deleted file mode 100644 index 354873950..000000000 --- a/rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch +++ /dev/null @@ -1,71 +0,0 @@ -My change: - -commit cee2c7315f60beeff6137ee59e99acc77d636eeb -Author: Stanislaw Gruszka -Date: Fri Oct 5 13:44:09 2012 +0200 - - rt2800: use BBP_R1 for setting tx power - -unfortunately does not work well with RT5390 and RT3290 chips as they -require different temperature compensation TX power settings (TSSI -tuning). Since that commit make wireless connection very unstable on -those chips, restore previous behavior to fix regression. Once we -implement proper TSSI tuning on 5390/3290 we can restore back setting -TX power by BBP_R1 register for those chips. - -Reported-and-tested-by: Mike Romberg -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rt2x00/rt2800lib.c | 29 ++++++++++++++++++----------- - 1 file changed, 18 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c -index 92849e5..8b679df 100644 ---- a/drivers/net/wireless/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -2634,19 +2634,26 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, - * TODO: we do not use +6 dBm option to do not increase power beyond - * regulatory limit, however this could be utilized for devices with - * CAPABILITY_POWER_LIMIT. -+ * -+ * TODO: add different temperature compensation code for RT3290 & RT5390 -+ * to allow to use BBP_R1 for those chips. - */ -- rt2800_bbp_read(rt2x00dev, 1, &r1); -- if (delta <= -12) { -- power_ctrl = 2; -- delta += 12; -- } else if (delta <= -6) { -- power_ctrl = 1; -- delta += 6; -- } else { -- power_ctrl = 0; -+ if (!rt2x00_rt(rt2x00dev, RT3290) && -+ !rt2x00_rt(rt2x00dev, RT5390)) { -+ rt2800_bbp_read(rt2x00dev, 1, &r1); -+ if (delta <= -12) { -+ power_ctrl = 2; -+ delta += 12; -+ } else if (delta <= -6) { -+ power_ctrl = 1; -+ delta += 6; -+ } else { -+ power_ctrl = 0; -+ } -+ rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); -+ rt2800_bbp_write(rt2x00dev, 1, r1); - } -- rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); -- rt2800_bbp_write(rt2x00dev, 1, r1); -+ - offset = TX_PWR_CFG_0; - - for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { --- -1.7.11.7 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/sources b/sources index 607da4fb5..372d198c3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -c5f2166686a913abf550bfed8b77df27 patch-3.9.8.xz +41f350c2fd6aa14414bf39f173a8e6a3 patch-3.9.9.xz From d85f8a309c890aa14f7808d4bed5869ca719ec68 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Jul 2013 15:36:22 -0400 Subject: [PATCH 363/492] CVE-2013-2234 net: information leak in AF_KEY notify (rhbz 980995 981007) --- ...ey-fix-info-leaks-in-notify-messages.patch | 37 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 44 insertions(+) create mode 100644 af_key-fix-info-leaks-in-notify-messages.patch diff --git a/af_key-fix-info-leaks-in-notify-messages.patch b/af_key-fix-info-leaks-in-notify-messages.patch new file mode 100644 index 000000000..9d20aec0f --- /dev/null +++ b/af_key-fix-info-leaks-in-notify-messages.patch @@ -0,0 +1,37 @@ +From a5cc68f3d63306d0d288f31edfc2ae6ef8ecd887 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Wed, 26 Jun 2013 21:52:30 +0000 +Subject: af_key: fix info leaks in notify messages + +key_notify_sa_flush() and key_notify_policy_flush() miss to initialize +the sadb_msg_reserved member of the broadcasted message and thereby +leak 2 bytes of heap memory to listeners. Fix that. + +Signed-off-by: Mathias Krause +Cc: Steffen Klassert +Cc: "David S. Miller" +Cc: Herbert Xu +Signed-off-by: David S. Miller +--- +diff --git a/net/key/af_key.c b/net/key/af_key.c +index c5fbd75..9da8620 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -1710,6 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c) + hdr->sadb_msg_version = PF_KEY_V2; + hdr->sadb_msg_errno = (uint8_t) 0; + hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); ++ hdr->sadb_msg_reserved = 0; + + pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); + +@@ -2699,6 +2700,7 @@ static int key_notify_policy_flush(const struct km_event *c) + hdr->sadb_msg_errno = (uint8_t) 0; + hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; + hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); ++ hdr->sadb_msg_reserved = 0; + pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); + return 0; + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index cc9c0fbd8..25f5be57e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch Patch25056: iwl3945-better-skb-management-in-rx-path.patch Patch25057: iwl4965-better-skb-management-in-rx-path.patch +#CVE-2013-2234 rhbz 980995 981007 +Patch25058: af_key-fix-info-leaks-in-notify-messages.patch + # END OF PATCH DEFINITIONS %endif @@ -1520,6 +1523,9 @@ ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch ApplyPatch iwl3945-better-skb-management-in-rx-path.patch ApplyPatch iwl4965-better-skb-management-in-rx-path.patch +#CVE-2013-2234 rhbz 980995 981007 +ApplyPatch af_key-fix-info-leaks-in-notify-messages.patch + # END OF PATCH APPLICATIONS %endif @@ -2366,6 +2372,7 @@ fi # || || %changelog * Wed Jul 03 2013 Josh Boyer +- CVE-2013-2234 net: information leak in AF_KEY notify (rhbz 980995 981007) - Linux v3.9.9 * Wed Jul 03 2013 Josh Boyer From a80f0d14d250d3b9150c90ee092c3ef2143452ef Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Jul 2013 16:10:09 -0400 Subject: [PATCH 364/492] CVE-2013-1059 libceph: Fix NULL pointer dereference in auth client code (rhbz 977356 980341) --- ceph-fix.patch | 24 ++++++++++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 31 insertions(+) create mode 100644 ceph-fix.patch diff --git a/ceph-fix.patch b/ceph-fix.patch new file mode 100644 index 000000000..6515e758d --- /dev/null +++ b/ceph-fix.patch @@ -0,0 +1,24 @@ +diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c +index 925ca58..0ef2458 100644 +--- a/net/ceph/auth_none.c ++++ b/net/ceph/auth_none.c +@@ -39,6 +39,11 @@ static int should_authenticate(struct ceph_auth_client *ac) + return xi->starting; + } + ++static int build_request(struct ceph_auth_client *ac, void *buf, void *end) ++{ ++ return 0; ++} ++ + /* + * the generic auth code decode the global_id, and we carry no actual + * authenticate state, so nothing happens here. +@@ -106,6 +111,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = { + .destroy = destroy, + .is_authenticated = is_authenticated, + .should_authenticate = should_authenticate, ++ .build_request = build_request, + .handle_reply = handle_reply, + .create_authorizer = ceph_auth_none_create_authorizer, + .destroy_authorizer = ceph_auth_none_destroy_authorizer, diff --git a/kernel.spec b/kernel.spec index 25f5be57e..28e8f1619 100644 --- a/kernel.spec +++ b/kernel.spec @@ -794,6 +794,9 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #CVE-2013-2234 rhbz 980995 981007 Patch25058: af_key-fix-info-leaks-in-notify-messages.patch +#CVE-2013-1059 rhbz 977356 980341 +Patch25059: ceph-fix.patch + # END OF PATCH DEFINITIONS %endif @@ -1526,6 +1529,9 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #CVE-2013-2234 rhbz 980995 981007 ApplyPatch af_key-fix-info-leaks-in-notify-messages.patch +#CVE-2013-1059 rhbz 977356 980341 +ApplyPatch ceph-fix.patch + # END OF PATCH APPLICATIONS %endif @@ -2372,6 +2378,7 @@ fi # || || %changelog * Wed Jul 03 2013 Josh Boyer +- CVE-2013-1059 libceph: Fix NULL pointer dereference in auth client code (rhbz 977356 980341) - CVE-2013-2234 net: information leak in AF_KEY notify (rhbz 980995 981007) - Linux v3.9.9 From 3e6b75eafbb059480a49f5b7fcb273afcca19a07 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 4 Jul 2013 08:42:27 -0400 Subject: [PATCH 365/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 28e8f1619..71964aec9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2377,7 +2377,7 @@ fi # ||----w | # || || %changelog -* Wed Jul 03 2013 Josh Boyer +* Wed Jul 03 2013 Josh Boyer - 3.9.9-200 - CVE-2013-1059 libceph: Fix NULL pointer dereference in auth client code (rhbz 977356 980341) - CVE-2013-2234 net: information leak in AF_KEY notify (rhbz 980995 981007) - Linux v3.9.9 From b3110537eca9d689554789ec3073c1bc963b161f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Jul 2013 08:01:24 -0400 Subject: [PATCH 366/492] CVE-2013-2232 ipv6: using ipv4 vs ipv6 structure during routing lookup in sendmsg (rhbz 981552 981564) --- ...k_dst_check-must-not-assume-ipv6-dst.patch | 52 +++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 61 insertions(+) create mode 100644 ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch diff --git a/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch b/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch new file mode 100644 index 000000000..8f6c41d28 --- /dev/null +++ b/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch @@ -0,0 +1,52 @@ +From a963a37d384d71ad43b3e9e79d68d42fbe0901f3 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 26 Jun 2013 04:15:07 -0700 +Subject: [PATCH] ipv6: ip6_sk_dst_check() must not assume ipv6 dst + +It's possible to use AF_INET6 sockets and to connect to an IPv4 +destination. After this, socket dst cache is a pointer to a rtable, +not rt6_info. + +ip6_sk_dst_check() should check the socket dst cache is IPv6, or else +various corruptions/crashes can happen. + +Dave Jones can reproduce immediate crash with +trinity -q -l off -n -c sendmsg -c connect + +With help from Hannes Frederic Sowa + +Reported-by: Dave Jones +Reported-by: Hannes Frederic Sowa +Signed-off-by: Eric Dumazet +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 95703ba..d5d20cd 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -821,11 +821,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, + const struct flowi6 *fl6) + { + struct ipv6_pinfo *np = inet6_sk(sk); +- struct rt6_info *rt = (struct rt6_info *)dst; ++ struct rt6_info *rt; + + if (!dst) + goto out; + ++ if (dst->ops->family != AF_INET6) { ++ dst_release(dst); ++ return NULL; ++ } ++ ++ rt = (struct rt6_info *)dst; + /* Yes, checking route validity in not connected + * case is not very simple. Take into account, + * that we do not support routing by source, TOS, +-- +1.8.2.1 + diff --git a/kernel.spec b/kernel.spec index 71964aec9..8704e16a6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,9 @@ Patch25058: af_key-fix-info-leaks-in-notify-messages.patch #CVE-2013-1059 rhbz 977356 980341 Patch25059: ceph-fix.patch +#CVE-2013-2232 rhbz 981552 981564 +Patch25060: ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch + # END OF PATCH DEFINITIONS %endif @@ -1532,6 +1535,9 @@ ApplyPatch af_key-fix-info-leaks-in-notify-messages.patch #CVE-2013-1059 rhbz 977356 980341 ApplyPatch ceph-fix.patch +#CVE-2013-2232 rhbz 981552 981564 +ApplyPatch ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch + # END OF PATCH APPLICATIONS %endif @@ -2377,6 +2383,9 @@ fi # ||----w | # || || %changelog +* Fri Jul 05 2013 Josh Boyer +- CVE-2013-2232 ipv6: using ipv4 vs ipv6 structure during routing lookup in sendmsg (rhbz 981552 981564) + * Wed Jul 03 2013 Josh Boyer - 3.9.9-200 - CVE-2013-1059 libceph: Fix NULL pointer dereference in auth client code (rhbz 977356 980341) - CVE-2013-2234 net: information leak in AF_KEY notify (rhbz 980995 981007) From e7d7a620ab1debe3bc0b97c5184bfcd50ddbaedc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Jul 2013 08:57:12 -0400 Subject: [PATCH 367/492] Add fix for timer issue in bridge code (rhbz 980254) --- bridge-timer-fix.patch | 13 +++++++++++++ kernel.spec | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 bridge-timer-fix.patch diff --git a/bridge-timer-fix.patch b/bridge-timer-fix.patch new file mode 100644 index 000000000..888a6f009 --- /dev/null +++ b/bridge-timer-fix.patch @@ -0,0 +1,13 @@ +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index d6448e3..aadb596 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -269,7 +269,7 @@ static void br_multicast_del_pg(struct net_bridge *br, + del_timer(&p->timer); + call_rcu_bh(&p->rcu, br_multicast_free_pg); + +- if (!mp->ports && !mp->mglist && ++ if (!mp->ports && !mp->mglist && mp->timer_armed && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + diff --git a/kernel.spec b/kernel.spec index 8704e16a6..8fdc61290 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -783,6 +783,8 @@ Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch #rhbz 880035 Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch +#rhbz 980254 +Patch25061: bridge-timer-fix.patch #rhbz 977558 Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch @@ -1521,6 +1523,7 @@ ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch #rhbz 880035 ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch +ApplyPatch bridge-timer-fix.patch #rhbz 977558 ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch @@ -2384,6 +2387,7 @@ fi # || || %changelog * Fri Jul 05 2013 Josh Boyer +- Add fix for timer issue in bridge code (rhbz 980254) - CVE-2013-2232 ipv6: using ipv4 vs ipv6 structure during routing lookup in sendmsg (rhbz 981552 981564) * Wed Jul 03 2013 Josh Boyer - 3.9.9-200 From 15eecb868abaf60b15d3471843c8bd33ec9bdade Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Jul 2013 09:01:24 -0400 Subject: [PATCH 368/492] Add vhost-net use-after-free fix (rhbz 976789 980643) --- kernel.spec | 7 ++ ...ix-use-after-free-in-vhost_net_flush.patch | 76 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 vhost-net-fix-use-after-free-in-vhost_net_flush.patch diff --git a/kernel.spec b/kernel.spec index 8fdc61290..36c407631 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,6 +802,9 @@ Patch25059: ceph-fix.patch #CVE-2013-2232 rhbz 981552 981564 Patch25060: ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch +#rhbz 976789 980643 +Patch25062: vhost-net-fix-use-after-free-in-vhost_net_flush.patch + # END OF PATCH DEFINITIONS %endif @@ -1541,6 +1544,9 @@ ApplyPatch ceph-fix.patch #CVE-2013-2232 rhbz 981552 981564 ApplyPatch ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch +#rhbz 976789 980643 +ApplyPatch vhost-net-fix-use-after-free-in-vhost_net_flush.patch + # END OF PATCH APPLICATIONS %endif @@ -2387,6 +2393,7 @@ fi # || || %changelog * Fri Jul 05 2013 Josh Boyer +- Add vhost-net use-after-free fix (rhbz 976789 980643) - Add fix for timer issue in bridge code (rhbz 980254) - CVE-2013-2232 ipv6: using ipv4 vs ipv6 structure during routing lookup in sendmsg (rhbz 981552 981564) diff --git a/vhost-net-fix-use-after-free-in-vhost_net_flush.patch b/vhost-net-fix-use-after-free-in-vhost_net_flush.patch new file mode 100644 index 000000000..f9a6a7b9f --- /dev/null +++ b/vhost-net-fix-use-after-free-in-vhost_net_flush.patch @@ -0,0 +1,76 @@ +From 0c9d7f6ea817d5328a09a78e901b16e1836ca4d7 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Tue, 25 Jun 2013 17:29:46 +0300 +Subject: [PATCH] vhost-net: fix use-after-free in vhost_net_flush + +vhost_net_ubuf_put_and_wait has a confusing name: +it will actually also free it's argument. +Thus since commit 1280c27f8e29acf4af2da914e80ec27c3dbd5c01 + "vhost-net: flush outstanding DMAs on memory change" +vhost_net_flush tries to use the argument after passing it +to vhost_net_ubuf_put_and_wait, this results +in use after free. +To fix, don't free the argument in vhost_net_ubuf_put_and_wait, +add an new API for callers that want to free ubufs. + +Acked-by: Asias He +Acked-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +--- + drivers/vhost/net.c | 4 ++-- + drivers/vhost/vhost.c | 5 +++++ + drivers/vhost/vhost.h | 1 + + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index dfff647..d8d4f57 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -857,7 +857,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) + mutex_unlock(&vq->mutex); + + if (oldubufs) { +- vhost_ubuf_put_and_wait(oldubufs); ++ vhost_ubuf_put_wait_and_free(oldubufs); + mutex_lock(&vq->mutex); + vhost_zerocopy_signal_used(n, vq); + mutex_unlock(&vq->mutex); +@@ -875,7 +875,7 @@ err_used: + rcu_assign_pointer(vq->private_data, oldsock); + vhost_net_enable_vq(n, vq); + if (ubufs) +- vhost_ubuf_put_and_wait(ubufs); ++ vhost_ubuf_put_wait_and_free(ubufs); + err_ubufs: + fput(sock->file); + err_vq: +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 9759249..ff53c9e 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -1581,5 +1581,10 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) + { + kref_put(&ubufs->kref, vhost_zerocopy_done_signal); + wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); ++} ++ ++void vhost_ubuf_put_wait_and_free(struct vhost_ubuf_ref *ubufs) ++{ ++ vhost_ubuf_put_and_wait(ubufs); + kfree(ubufs); + } +diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h +index 17261e2..dd63b35 100644 +--- a/drivers/vhost/vhost.h ++++ b/drivers/vhost/vhost.h +@@ -63,6 +63,7 @@ struct vhost_ubuf_ref { + struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy); + void vhost_ubuf_put(struct vhost_ubuf_ref *); + void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *); ++void vhost_ubuf_put_wait_and_free(struct vhost_ubuf_ref *); + + struct ubuf_info; + +-- +1.8.2.1 + From b9f0d980bc818e2df0a51d308eb1926963c482b8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Jul 2013 09:17:32 -0400 Subject: [PATCH 369/492] Add report fixup for Genius Gila mouse from Benjamin Tissoires (rhbz 959721) --- ...t-fixup-for-Genius-Gila-Gaming-mouse.patch | 98 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 105 insertions(+) create mode 100644 HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch diff --git a/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch b/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch new file mode 100644 index 000000000..6913eb520 --- /dev/null +++ b/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch @@ -0,0 +1,98 @@ +From 3685c18e17f12438d0a83331c1b6a5b00fade7a1 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Tue, 02 Jul 2013 16:10:09 +0000 +Subject: HID: kye: Add report fixup for Genius Gila Gaming mouse + +Genius Gila Gaming Mouse presents an obviously wrong report descriptor. +the Consumer control (report ID 3) is the following: +0x05, 0x0c, // Usage Page (Consumer Devices) 105 +0x09, 0x01, // Usage (Consumer Control) 107 +0xa1, 0x01, // Collection (Application) 109 +0x85, 0x03, // Report ID (3) 111 +0x19, 0x00, // Usage Minimum (0) 113 +0x2a, 0xff, 0x7f, // Usage Maximum (32767) 115 +0x15, 0x00, // Logical Minimum (0) 118 +0x26, 0xff, 0x7f, // Logical Maximum (32767) 120 +0x75, 0x10, // Report Size (16) 123 +0x95, 0x03, // Report Count (3) 125 +0x81, 0x00, // Input (Data,Arr,Abs) 127 +0x75, 0x08, // Report Size (8) 129 +0x95, 0x01, // Report Count (1) 131 +0x81, 0x01, // Input (Cnst,Arr,Abs) 133 +0xc0, // End Collection 135 + +So the first input whithin this report has a count of 3 but a usage range +of 32768. So this value is obviously wrong as it should not be greater than +the report count. + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=959721 + +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +--- +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 8f616bd..27aa7c7 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1589,6 +1589,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 3da75dd..b2b692e 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -474,6 +474,7 @@ + + #define USB_VENDOR_ID_KYE 0x0458 + #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 ++#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 + #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 + #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 +diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c +index 6af90db..1e2ee2aa 100644 +--- a/drivers/hid/hid-kye.c ++++ b/drivers/hid/hid-kye.c +@@ -314,6 +314,25 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + *rsize = sizeof(easypen_m610x_rdesc_fixed); + } + break; ++ case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: ++ /* ++ * the fixup that need to be done: ++ * - change Usage Maximum in the Comsumer Control ++ * (report ID 3) to a reasonable value ++ */ ++ if (*rsize >= 135 && ++ /* Usage Page (Consumer Devices) */ ++ rdesc[104] == 0x05 && rdesc[105] == 0x0c && ++ /* Usage (Consumer Control) */ ++ rdesc[106] == 0x09 && rdesc[107] == 0x01 && ++ /* Usage Maximum > 12287 */ ++ rdesc[114] == 0x2a && rdesc[116] > 0x2f) { ++ hid_info(hdev, ++ "fixing up Genius Gila Gaming Mouse " ++ "report descriptor\n"); ++ rdesc[116] = 0x2f; ++ } ++ break; + } + return rdesc; + } +@@ -407,6 +426,8 @@ static const struct hid_device_id kye_devices[] = { + USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_KYE_EASYPEN_M610X) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, ++ USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, + { } + }; + MODULE_DEVICE_TABLE(hid, kye_devices); +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 36c407631..f50864ae0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -805,6 +805,9 @@ Patch25060: ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch #rhbz 976789 980643 Patch25062: vhost-net-fix-use-after-free-in-vhost_net_flush.patch +#rhbz 959721 +Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch + # END OF PATCH DEFINITIONS %endif @@ -1547,6 +1550,9 @@ ApplyPatch ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch #rhbz 976789 980643 ApplyPatch vhost-net-fix-use-after-free-in-vhost_net_flush.patch +#rhbz 959721 +ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch + # END OF PATCH APPLICATIONS %endif @@ -2393,6 +2399,7 @@ fi # || || %changelog * Fri Jul 05 2013 Josh Boyer +- Add report fixup for Genius Gila mouse from Benjamin Tissoires (rhbz 959721) - Add vhost-net use-after-free fix (rhbz 976789 980643) - Add fix for timer issue in bridge code (rhbz 980254) - CVE-2013-2232 ipv6: using ipv4 vs ipv6 structure during routing lookup in sendmsg (rhbz 981552 981564) From 6c78bc0a359dbd80bf1e118f42afa514ff5e3917 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 12 Jul 2013 07:47:24 -0400 Subject: [PATCH 370/492] Add iwlwifi fix for connection issue (rhbz 885407) --- ...nd-BT_CONFIG-on-devices-wo-Bluetooth.patch | 32 +++++++++++++++++++ kernel.spec | 11 ++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch diff --git a/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch b/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch new file mode 100644 index 000000000..fa4320763 --- /dev/null +++ b/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch @@ -0,0 +1,32 @@ +From 7b29fdb8cd8f92e31f550611a8c031986dba2e8f Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 03 May 2013 16:58:16 +0000 +Subject: iwlwifi: dvm: don't send BT_CONFIG on devices w/o Bluetooth + +The BT_CONFIG command that is sent to the device during +startup will enable BT coex unless the module parameter +turns it off, but on devices without Bluetooth this may +cause problems, as reported in Redhat BZ 885407. + +Fix this by sending the BT_CONFIG command only when the +device has Bluetooth. + +Cc: stable@vger.kernel.org +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- +diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c +index 3952ddf..1531a4f 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/main.c ++++ b/drivers/net/wireless/iwlwifi/dvm/main.c +@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv) + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; +- } else { ++ } else if (priv->lib->bt_params) { + /* + * default is 2-wire BT coexexistence support + */ +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index f50864ae0..5e7241e81 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 202 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -808,6 +808,9 @@ Patch25062: vhost-net-fix-use-after-free-in-vhost_net_flush.patch #rhbz 959721 Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch +#rhbz 885407 +Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch + # END OF PATCH DEFINITIONS %endif @@ -1553,6 +1556,9 @@ ApplyPatch vhost-net-fix-use-after-free-in-vhost_net_flush.patch #rhbz 959721 ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch +#rhbz 885407 +ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch + # END OF PATCH APPLICATIONS %endif @@ -2398,6 +2404,9 @@ fi # ||----w | # || || %changelog +* Fri Jul 12 2013 Josh Boyer +- Add iwlwifi fix for connection issue (rhbz 885407) + * Fri Jul 05 2013 Josh Boyer - Add report fixup for Genius Gila mouse from Benjamin Tissoires (rhbz 959721) - Add vhost-net use-after-free fix (rhbz 976789 980643) From 8c58af14b872f99423dad59fe1b08a3cd0c98aec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 12 Jul 2013 09:34:36 -0400 Subject: [PATCH 371/492] Fix various overflow issues in ext4 (rhbz 976837) --- fix-ext4-overflows.patch | 207 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 214 insertions(+) create mode 100644 fix-ext4-overflows.patch diff --git a/fix-ext4-overflows.patch b/fix-ext4-overflows.patch new file mode 100644 index 000000000..f2a08ebc8 --- /dev/null +++ b/fix-ext4-overflows.patch @@ -0,0 +1,207 @@ +From 93f6b57df5d9dd8c0327cebc01f6c00dbcd6d2ff Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:33:42 -0400 +Subject: [PATCH 1/4] ext4: fix data offset overflow on 32-bit archs in + ext4_inline_data_fiemap() + +On 32-bit archs when sector_t is defined as 32-bit the logic computing +data offset in ext4_inline_data_fiemap(). Fix that by properly typing +the shifted value. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/inline.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index c0fd1a1..c46a01e 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1702,7 +1702,7 @@ int ext4_inline_data_fiemap(struct inode *inode, + if (error) + goto out; + +- physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; ++ physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; + physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; + physical += offsetof(struct ext4_inode, i_block); + length = i_size_read(inode); +-- +1.8.3.1 + + +From 4d2cedb535bae3ada76a335540657e948f99d9c0 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:37:56 -0400 +Subject: [PATCH 2/4] ext4: fix overflows in SEEK_HOLE, SEEK_DATA + implementations + +ext4_lblk_t is just u32 so multiplying it by blocksize can easily +overflow for files larger than 4 GB. Fix that by properly typing the +block offsets before shifting. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Reviewed-by: Zheng Liu +--- + fs/ext4/file.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 64848b5..b47ccf9 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -311,7 +311,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, + blkbits = inode->i_sb->s_blocksize_bits; + startoff = *offset; + lastoff = startoff; +- endoff = (map->m_lblk + map->m_len) << blkbits; ++ endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits; + + index = startoff >> PAGE_CACHE_SHIFT; + end = endoff >> PAGE_CACHE_SHIFT; +@@ -456,7 +456,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) + ret = ext4_map_blocks(NULL, inode, &map, 0); + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { + if (last != start) +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + break; + } + +@@ -467,7 +467,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) + ext4_es_find_delayed_extent(inode, last, &es); + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { + if (last != start) +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + break; + } + +@@ -485,7 +485,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) + } + + last++; +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + } while (last <= end); + + mutex_unlock(&inode->i_mutex); +@@ -539,7 +539,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) + ret = ext4_map_blocks(NULL, inode, &map, 0); + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { + last += ret; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + +@@ -550,7 +550,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) + ext4_es_find_delayed_extent(inode, last, &es); + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { + last = es.es_lblk + es.es_len; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + +@@ -565,7 +565,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) + &map, &holeoff); + if (!unwritten) { + last += ret; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + } +-- +1.8.3.1 + + +From 114fe3b7fc9ca3ca00f774dd8705e8c802f39f14 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:38:56 -0400 +Subject: [PATCH 3/4] ext4: fix data offset overflow in ext4_xattr_fiemap() on + 32-bit archs + +On 32-bit architectures with 32-bit sector_t computation of data offset +in ext4_xattr_fiemap() can overflow resulting in reporting bogus data +location. Fix the problem by typing block number to proper type before +shifting. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/extents.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 9c6d06d..6bb303c 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4605,7 +4605,7 @@ static int ext4_xattr_fiemap(struct inode *inode, + error = ext4_get_inode_loc(inode, &iloc); + if (error) + return error; +- physical = iloc.bh->b_blocknr << blockbits; ++ physical = (__u64)iloc.bh->b_blocknr << blockbits; + offset = EXT4_GOOD_OLD_INODE_SIZE + + EXT4_I(inode)->i_extra_isize; + physical += offset; +@@ -4613,7 +4613,7 @@ static int ext4_xattr_fiemap(struct inode *inode, + flags |= FIEMAP_EXTENT_DATA_INLINE; + brelse(iloc.bh); + } else { /* external block */ +- physical = EXT4_I(inode)->i_file_acl << blockbits; ++ physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits; + length = inode->i_sb->s_blocksize; + } + +-- +1.8.3.1 + + +From aeb72ff4b7fe084b4373d4a91d77d3bea8089627 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:39:56 -0400 +Subject: [PATCH 4/4] ext4: fix overflow when counting used blocks on 32-bit + architectures + +The arithmetics adding delalloc blocks to the number of used blocks in +ext4_getattr() can easily overflow on 32-bit archs as we first multiply +number of blocks by blocksize and then divide back by 512. Make the +arithmetics more clever and also use proper type (unsigned long long +instead of unsigned long). + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index d69e954..e33e2d2 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4616,7 +4616,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) + { + struct inode *inode; +- unsigned long delalloc_blocks; ++ unsigned long long delalloc_blocks; + + inode = dentry->d_inode; + generic_fillattr(inode, stat); +@@ -4634,7 +4634,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, + delalloc_blocks = EXT4_C2B(EXT4_SB(inode->i_sb), + EXT4_I(inode)->i_reserved_data_blocks); + +- stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9; ++ stat->blocks += delalloc_blocks << (inode->i_sb->s_blocksize_bits-9); + return 0; + } + +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 5e7241e81..ace74477f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -811,6 +811,9 @@ Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch +#rhbz 976837 +Patch25065: fix-ext4-overflows.patch + # END OF PATCH DEFINITIONS %endif @@ -1559,6 +1562,9 @@ ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch +#rhbz 976837 +ApplyPatch fix-ext4-overflows.patch + # END OF PATCH APPLICATIONS %endif @@ -2405,6 +2411,7 @@ fi # || || %changelog * Fri Jul 12 2013 Josh Boyer +- Fix various overflow issues in ext4 (rhbz 976837) - Add iwlwifi fix for connection issue (rhbz 885407) * Fri Jul 05 2013 Josh Boyer From 16dbebbb4bec15bd2d48d449616dccb08f131bf8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 12 Jul 2013 12:18:59 -0400 Subject: [PATCH 372/492] Disable LATENCYTOP/SCHEDSTATS in non-debug builds. --- config-debug | 2 ++ config-generic | 2 -- config-nodebug | 2 ++ kernel.spec | 5 ++++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/config-debug b/config-debug index 43655a1a1..ad06116c7 100644 --- a/config-debug +++ b/config-debug @@ -115,3 +115,5 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y CONFIG_MAC80211_MESSAGE_TRACING=y CONFIG_EDAC_DEBUG=y +CONFIG_LATENCYTOP=y +CONFIG_SCHEDSTATS=y diff --git a/config-generic b/config-generic index eeb6eea70..77d8e89ce 100644 --- a/config-generic +++ b/config-generic @@ -3958,7 +3958,6 @@ CONFIG_HWPOISON_INJECT=m CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_DEBUG_SECTION_MISMATCH is not set # CONFIG_BACKTRACE_SELF_TEST is not set -CONFIG_LATENCYTOP=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_COMPAT_BRK is not set # CONFIG_DEBUG_VIRTUAL is not set @@ -4125,7 +4124,6 @@ CONFIG_BACKLIGHT_LP855X=m CONFIG_LCD_CLASS_DEVICE=m CONFIG_LCD_PLATFORM=m -CONFIG_SCHEDSTATS=y CONFIG_SCHED_DEBUG=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y diff --git a/config-nodebug b/config-nodebug index aa7568c82..6db2dde22 100644 --- a/config-nodebug +++ b/config-nodebug @@ -117,3 +117,5 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y # CONFIG_EDAC_DEBUG is not set # CONFIG_SPI_DEBUG is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SCHEDSTATS is not set diff --git a/kernel.spec b/kernel.spec index ace74477f..f0b54a4fd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2410,6 +2410,9 @@ fi # ||----w | # || || %changelog +* Fri Jul 12 2013 Dave Jones - 3.9.9-203 +- Disable LATENCYTOP/SCHEDSTATS in non-debug builds. + * Fri Jul 12 2013 Josh Boyer - Fix various overflow issues in ext4 (rhbz 976837) - Add iwlwifi fix for connection issue (rhbz 885407) From 7eabed422781b75233a75ac2109a938678bd22e7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 13 Jul 2013 21:00:19 -0400 Subject: [PATCH 373/492] Linux v3.9.10 --- ...ot-pass-disk-names-as-format-strings.patch | 64 ------------------- cdrom-use-kzalloc-for-failing-hardware.patch | 45 ------------- ceph-fix.patch | 24 ------- kernel.spec | 25 ++------ sources | 2 +- 5 files changed, 6 insertions(+), 154 deletions(-) delete mode 100644 block-do-not-pass-disk-names-as-format-strings.patch delete mode 100644 cdrom-use-kzalloc-for-failing-hardware.patch delete mode 100644 ceph-fix.patch diff --git a/block-do-not-pass-disk-names-as-format-strings.patch b/block-do-not-pass-disk-names-as-format-strings.patch deleted file mode 100644 index 496111dcd..000000000 --- a/block-do-not-pass-disk-names-as-format-strings.patch +++ /dev/null @@ -1,64 +0,0 @@ -Disk names may contain arbitrary strings, so they must not be interpreted -as format strings. It seems that only md allows arbitrary strings to be -used for disk names, but this could allow for a local memory corruption -from uid 0 into ring 0. - -CVE-2013-2851 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Cc: Jens Axboe ---- - block/genhd.c | 2 +- - drivers/block/nbd.c | 3 ++- - drivers/scsi/osd/osd_uld.c | 2 +- - 3 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/block/genhd.c b/block/genhd.c -index 20625ee..cdeb527 100644 ---- a/block/genhd.c -+++ b/block/genhd.c -@@ -512,7 +512,7 @@ static void register_disk(struct gendisk *disk) - - ddev->parent = disk->driverfs_dev; - -- dev_set_name(ddev, disk->disk_name); -+ dev_set_name(ddev, "%s", disk->disk_name); - - /* delay uevents, until we scanned partition table */ - dev_set_uevent_suppress(ddev, 1); -diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c -index 037288e..46b35f7 100644 ---- a/drivers/block/nbd.c -+++ b/drivers/block/nbd.c -@@ -714,7 +714,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, - else - blk_queue_flush(nbd->disk->queue, 0); - -- thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name); -+ thread = kthread_create(nbd_thread, nbd, "%s", -+ nbd->disk->disk_name); - if (IS_ERR(thread)) { - mutex_lock(&nbd->tx_lock); - return PTR_ERR(thread); -diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c -index 0fab6b5..9d86947 100644 ---- a/drivers/scsi/osd/osd_uld.c -+++ b/drivers/scsi/osd/osd_uld.c -@@ -485,7 +485,7 @@ static int osd_probe(struct device *dev) - oud->class_dev.class = &osd_uld_class; - oud->class_dev.parent = dev; - oud->class_dev.release = __remove; -- error = dev_set_name(&oud->class_dev, disk->disk_name); -+ error = dev_set_name(&oud->class_dev, "%s", disk->disk_name); - if (error) { - OSD_ERR("dev_set_name failed => %d\n", error); - goto err_put_cdev; --- -1.7.9.5 - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file diff --git a/cdrom-use-kzalloc-for-failing-hardware.patch b/cdrom-use-kzalloc-for-failing-hardware.patch deleted file mode 100644 index 6afb6c4d8..000000000 --- a/cdrom-use-kzalloc-for-failing-hardware.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 050e4b8fb7cdd7096c987a9cd556029c622c7fe2 Mon Sep 17 00:00:00 2001 -From: Jonathan Salwan -Date: Thu, 06 Jun 2013 00:39:39 +0000 -Subject: drivers/cdrom/cdrom.c: use kzalloc() for failing hardware - -In drivers/cdrom/cdrom.c mmc_ioctl_cdrom_read_data() allocates a memory -area with kmalloc in line 2885. - -2885 cgc->buffer = kmalloc(blocksize, GFP_KERNEL); -2886 if (cgc->buffer == NULL) -2887 return -ENOMEM; - -In line 2908 we can find the copy_to_user function: - -2908 if (!ret && copy_to_user(arg, cgc->buffer, blocksize)) - -The cgc->buffer is never cleaned and initialized before this function. If -ret = 0 with the previous basic block, it's possible to display some -memory bytes in kernel space from userspace. - -When we read a block from the disk it normally fills the ->buffer but if -the drive is malfunctioning there is a chance that it would only be -partially filled. The result is an leak information to userspace. - -Signed-off-by: Dan Carpenter -Cc: Jens Axboe -Signed-off-by: Andrew Morton ---- -(limited to 'drivers/cdrom/cdrom.c') - -diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c -index d620b44..8a3aff7 100644 ---- a/drivers/cdrom/cdrom.c -+++ b/drivers/cdrom/cdrom.c -@@ -2882,7 +2882,7 @@ static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, - if (lba < 0) - return -EINVAL; - -- cgc->buffer = kmalloc(blocksize, GFP_KERNEL); -+ cgc->buffer = kzalloc(blocksize, GFP_KERNEL); - if (cgc->buffer == NULL) - return -ENOMEM; - --- -cgit v0.9.2 diff --git a/ceph-fix.patch b/ceph-fix.patch deleted file mode 100644 index 6515e758d..000000000 --- a/ceph-fix.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c -index 925ca58..0ef2458 100644 ---- a/net/ceph/auth_none.c -+++ b/net/ceph/auth_none.c -@@ -39,6 +39,11 @@ static int should_authenticate(struct ceph_auth_client *ac) - return xi->starting; - } - -+static int build_request(struct ceph_auth_client *ac, void *buf, void *end) -+{ -+ return 0; -+} -+ - /* - * the generic auth code decode the global_id, and we carry no actual - * authenticate state, so nothing happens here. -@@ -106,6 +111,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = { - .destroy = destroy, - .is_authenticated = is_authenticated, - .should_authenticate = should_authenticate, -+ .build_request = build_request, - .handle_reply = handle_reply, - .create_authorizer = ceph_auth_none_create_authorizer, - .destroy_authorizer = ceph_auth_none_destroy_authorizer, diff --git a/kernel.spec b/kernel.spec index f0b54a4fd..2f6e1f6d7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 203 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -762,12 +762,6 @@ Patch25032: cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 Patch25033: fanotify-info-leak-in-copy_event_to_user.patch -#CVE-2013-2851 rhbz 969515 971662 -Patch25035: block-do-not-pass-disk-names-as-format-strings.patch - -#CVE-2013-2164 rhbz 973100 973109 -Patch25038: cdrom-use-kzalloc-for-failing-hardware.patch - #rhbz 969644 Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -796,9 +790,6 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #CVE-2013-2234 rhbz 980995 981007 Patch25058: af_key-fix-info-leaks-in-notify-messages.patch -#CVE-2013-1059 rhbz 977356 980341 -Patch25059: ceph-fix.patch - #CVE-2013-2232 rhbz 981552 981564 Patch25060: ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch @@ -1514,12 +1505,6 @@ ApplyPatch cve-2013-2147-ciss-info-leak.patch #CVE-2013-2148 rhbz 971258 971261 ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch -#CVE-2013-2851 rhbz 969515 971662 -ApplyPatch block-do-not-pass-disk-names-as-format-strings.patch - -#CVE-2013-2164 rhbz 973100 973109 -ApplyPatch cdrom-use-kzalloc-for-failing-hardware.patch - #rhbz 969644 ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -1547,9 +1532,6 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #CVE-2013-2234 rhbz 980995 981007 ApplyPatch af_key-fix-info-leaks-in-notify-messages.patch -#CVE-2013-1059 rhbz 977356 980341 -ApplyPatch ceph-fix.patch - #CVE-2013-2232 rhbz 981552 981564 ApplyPatch ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch @@ -2410,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Sat Jul 13 2013 Josh Boyer - 3.9.10-200 +- Linux v3.9.10 + * Fri Jul 12 2013 Dave Jones - 3.9.9-203 - Disable LATENCYTOP/SCHEDSTATS in non-debug builds. diff --git a/sources b/sources index 372d198c3..7bd5308bc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -41f350c2fd6aa14414bf39f173a8e6a3 patch-3.9.9.xz +9ceaca9b18b47e126858900bd7502672 patch-3.9.10.xz From 72ed3660725e268ce9cd515adffc8dfcbb3d9ab8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 13 Jul 2013 21:19:41 -0400 Subject: [PATCH 374/492] Fix wrong structure in iwlwifi dvm patch --- iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch b/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch index fa4320763..aa2ca7035 100644 --- a/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch +++ b/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch @@ -24,7 +24,7 @@ index 3952ddf..1531a4f 100644 if (ret) return ret; - } else { -+ } else if (priv->lib->bt_params) { ++ } else if (priv->cfg->bt_params) { /* * default is 2-wire BT coexexistence support */ From 2667cae3eaee3595a06a0305d230bbb9822d79db Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 19 Jul 2013 12:36:41 -0400 Subject: [PATCH 375/492] CVE-2013-4125 ipv6: BUG_ON in fib6_add_rt2node() (rhbz 984664) --- cve-2013-4125.patch | 79 +++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 86 insertions(+) create mode 100644 cve-2013-4125.patch diff --git a/cve-2013-4125.patch b/cve-2013-4125.patch new file mode 100644 index 000000000..25b7eca42 --- /dev/null +++ b/cve-2013-4125.patch @@ -0,0 +1,79 @@ +From 307f2fb95e9b96b3577916e73d92e104f8f26494 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Fri, 12 Jul 2013 21:46:33 +0000 +Subject: ipv6: only static routes qualify for equal cost multipathing + +Static routes in this case are non-expiring routes which did not get +configured by autoconf or by icmpv6 redirects. + +To make sure we actually get an ecmp route while searching for the first +one in this fib6_node's leafs, also make sure it matches the ecmp route +assumptions. + +v2: +a) Removed RTF_EXPIRE check in dst.from chain. The check of RTF_ADDRCONF + already ensures that this route, even if added again without + RTF_EXPIRES (in case of a RA announcement with infinite timeout), + does not cause the rt6i_nsiblings logic to go wrong if a later RA + updates the expiration time later. + +v3: +a) Allow RTF_EXPIRES routes to enter the ecmp route set. We have to do so, + because an pmtu event could update the RTF_EXPIRES flag and we would + not count this route, if another route joins this set. We now filter + only for RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC, which are flags that + don't get changed after rt6_info construction. + +Cc: Nicolas Dichtel +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 192dd1a..5fc9c7a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -632,6 +632,12 @@ insert_above: + return ln; + } + ++static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) ++{ ++ return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) == ++ RTF_GATEWAY; ++} ++ + /* + * Insert routing information in a node. + */ +@@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + int add = (!info->nlh || + (info->nlh->nlmsg_flags & NLM_F_CREATE)); + int found = 0; ++ bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); + + ins = &fn->leaf; + +@@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + * To avoid long list, we only had siblings if the + * route have a gateway. + */ +- if (rt->rt6i_flags & RTF_GATEWAY && +- !(rt->rt6i_flags & RTF_EXPIRES) && +- !(iter->rt6i_flags & RTF_EXPIRES)) ++ if (rt_can_ecmp && ++ rt6_qualify_for_ecmp(iter)) + rt->rt6i_nsiblings++; + } + +@@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + /* Find the first route that have the same metric */ + sibling = fn->leaf; + while (sibling) { +- if (sibling->rt6i_metric == rt->rt6i_metric) { ++ if (sibling->rt6i_metric == rt->rt6i_metric && ++ rt6_qualify_for_ecmp(sibling)) { + list_add_tail(&rt->rt6i_siblings, + &sibling->rt6i_siblings); + break; +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 2f6e1f6d7..37bd6848b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -805,6 +805,8 @@ Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch #rhbz 976837 Patch25065: fix-ext4-overflows.patch +Patch26000: cve-2013-4125.patch + # END OF PATCH DEFINITIONS %endif @@ -1547,6 +1549,8 @@ ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch #rhbz 976837 ApplyPatch fix-ext4-overflows.patch +ApplyPatch cve-2013-4125.patch + # END OF PATCH APPLICATIONS %endif @@ -2392,6 +2396,9 @@ fi # ||----w | # || || %changelog +* Fri Jul 19 2013 Dave Jones +- CVE-2013-4125 ipv6: BUG_ON in fib6_add_rt2node() (rhbz 984664) + * Sat Jul 13 2013 Josh Boyer - 3.9.10-200 - Linux v3.9.10 From 53399c5a894b34cd5617c8b994a1ca88c3eece7f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Jul 2013 08:47:40 -0400 Subject: [PATCH 376/492] Linux v3.9.11 --- fix-ext4-overflows.patch | 207 --------------------------------------- kernel.spec | 11 +-- sources | 2 +- 3 files changed, 5 insertions(+), 215 deletions(-) delete mode 100644 fix-ext4-overflows.patch diff --git a/fix-ext4-overflows.patch b/fix-ext4-overflows.patch deleted file mode 100644 index f2a08ebc8..000000000 --- a/fix-ext4-overflows.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 93f6b57df5d9dd8c0327cebc01f6c00dbcd6d2ff Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Fri, 31 May 2013 19:33:42 -0400 -Subject: [PATCH 1/4] ext4: fix data offset overflow on 32-bit archs in - ext4_inline_data_fiemap() - -On 32-bit archs when sector_t is defined as 32-bit the logic computing -data offset in ext4_inline_data_fiemap(). Fix that by properly typing -the shifted value. - -Signed-off-by: Jan Kara -Signed-off-by: Theodore Ts'o ---- - fs/ext4/inline.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c -index c0fd1a1..c46a01e 100644 ---- a/fs/ext4/inline.c -+++ b/fs/ext4/inline.c -@@ -1702,7 +1702,7 @@ int ext4_inline_data_fiemap(struct inode *inode, - if (error) - goto out; - -- physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; -+ physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; - physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; - physical += offsetof(struct ext4_inode, i_block); - length = i_size_read(inode); --- -1.8.3.1 - - -From 4d2cedb535bae3ada76a335540657e948f99d9c0 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Fri, 31 May 2013 19:37:56 -0400 -Subject: [PATCH 2/4] ext4: fix overflows in SEEK_HOLE, SEEK_DATA - implementations - -ext4_lblk_t is just u32 so multiplying it by blocksize can easily -overflow for files larger than 4 GB. Fix that by properly typing the -block offsets before shifting. - -Signed-off-by: Jan Kara -Signed-off-by: Theodore Ts'o -Reviewed-by: Zheng Liu ---- - fs/ext4/file.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 64848b5..b47ccf9 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -311,7 +311,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, - blkbits = inode->i_sb->s_blocksize_bits; - startoff = *offset; - lastoff = startoff; -- endoff = (map->m_lblk + map->m_len) << blkbits; -+ endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits; - - index = startoff >> PAGE_CACHE_SHIFT; - end = endoff >> PAGE_CACHE_SHIFT; -@@ -456,7 +456,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) - ret = ext4_map_blocks(NULL, inode, &map, 0); - if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { - if (last != start) -- dataoff = last << blkbits; -+ dataoff = (loff_t)last << blkbits; - break; - } - -@@ -467,7 +467,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) - ext4_es_find_delayed_extent(inode, last, &es); - if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { - if (last != start) -- dataoff = last << blkbits; -+ dataoff = (loff_t)last << blkbits; - break; - } - -@@ -485,7 +485,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) - } - - last++; -- dataoff = last << blkbits; -+ dataoff = (loff_t)last << blkbits; - } while (last <= end); - - mutex_unlock(&inode->i_mutex); -@@ -539,7 +539,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) - ret = ext4_map_blocks(NULL, inode, &map, 0); - if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { - last += ret; -- holeoff = last << blkbits; -+ holeoff = (loff_t)last << blkbits; - continue; - } - -@@ -550,7 +550,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) - ext4_es_find_delayed_extent(inode, last, &es); - if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { - last = es.es_lblk + es.es_len; -- holeoff = last << blkbits; -+ holeoff = (loff_t)last << blkbits; - continue; - } - -@@ -565,7 +565,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) - &map, &holeoff); - if (!unwritten) { - last += ret; -- holeoff = last << blkbits; -+ holeoff = (loff_t)last << blkbits; - continue; - } - } --- -1.8.3.1 - - -From 114fe3b7fc9ca3ca00f774dd8705e8c802f39f14 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Fri, 31 May 2013 19:38:56 -0400 -Subject: [PATCH 3/4] ext4: fix data offset overflow in ext4_xattr_fiemap() on - 32-bit archs - -On 32-bit architectures with 32-bit sector_t computation of data offset -in ext4_xattr_fiemap() can overflow resulting in reporting bogus data -location. Fix the problem by typing block number to proper type before -shifting. - -Signed-off-by: Jan Kara -Signed-off-by: Theodore Ts'o ---- - fs/ext4/extents.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 9c6d06d..6bb303c 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4605,7 +4605,7 @@ static int ext4_xattr_fiemap(struct inode *inode, - error = ext4_get_inode_loc(inode, &iloc); - if (error) - return error; -- physical = iloc.bh->b_blocknr << blockbits; -+ physical = (__u64)iloc.bh->b_blocknr << blockbits; - offset = EXT4_GOOD_OLD_INODE_SIZE + - EXT4_I(inode)->i_extra_isize; - physical += offset; -@@ -4613,7 +4613,7 @@ static int ext4_xattr_fiemap(struct inode *inode, - flags |= FIEMAP_EXTENT_DATA_INLINE; - brelse(iloc.bh); - } else { /* external block */ -- physical = EXT4_I(inode)->i_file_acl << blockbits; -+ physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits; - length = inode->i_sb->s_blocksize; - } - --- -1.8.3.1 - - -From aeb72ff4b7fe084b4373d4a91d77d3bea8089627 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Fri, 31 May 2013 19:39:56 -0400 -Subject: [PATCH 4/4] ext4: fix overflow when counting used blocks on 32-bit - architectures - -The arithmetics adding delalloc blocks to the number of used blocks in -ext4_getattr() can easily overflow on 32-bit archs as we first multiply -number of blocks by blocksize and then divide back by 512. Make the -arithmetics more clever and also use proper type (unsigned long long -instead of unsigned long). - -Signed-off-by: Jan Kara -Signed-off-by: Theodore Ts'o ---- - fs/ext4/inode.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index d69e954..e33e2d2 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -4616,7 +4616,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) - { - struct inode *inode; -- unsigned long delalloc_blocks; -+ unsigned long long delalloc_blocks; - - inode = dentry->d_inode; - generic_fillattr(inode, stat); -@@ -4634,7 +4634,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, - delalloc_blocks = EXT4_C2B(EXT4_SB(inode->i_sb), - EXT4_I(inode)->i_reserved_data_blocks); - -- stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9; -+ stat->blocks += delalloc_blocks << (inode->i_sb->s_blocksize_bits-9); - return 0; - } - --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index 37bd6848b..4985470b7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -802,9 +802,6 @@ Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch -#rhbz 976837 -Patch25065: fix-ext4-overflows.patch - Patch26000: cve-2013-4125.patch # END OF PATCH DEFINITIONS @@ -1546,9 +1543,6 @@ ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch -#rhbz 976837 -ApplyPatch fix-ext4-overflows.patch - ApplyPatch cve-2013-4125.patch # END OF PATCH APPLICATIONS @@ -2396,6 +2390,9 @@ fi # ||----w | # || || %changelog +* Mon Jul 22 2013 Josh Boyer +- Linux v3.9.11 + * Fri Jul 19 2013 Dave Jones - CVE-2013-4125 ipv6: BUG_ON in fib6_add_rt2node() (rhbz 984664) diff --git a/sources b/sources index 7bd5308bc..5947c8bcb 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -9ceaca9b18b47e126858900bd7502672 patch-3.9.10.xz +552146435b7ecc414bf8e3cd8bb6ac4a patch-3.9.11.xz From 833d99d8693f4499ec8d095528de48cd2f411619 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Jul 2013 14:51:38 -0400 Subject: [PATCH 377/492] Add patch for iwlwifi 6x35 devices (rhbz 986538) --- iwlwifi-add-new-pci-id-for-6x35-series.patch | 29 ++++++++++++++++++++ kernel.spec | 7 +++++ 2 files changed, 36 insertions(+) create mode 100644 iwlwifi-add-new-pci-id-for-6x35-series.patch diff --git a/iwlwifi-add-new-pci-id-for-6x35-series.patch b/iwlwifi-add-new-pci-id-for-6x35-series.patch new file mode 100644 index 000000000..ba616400f --- /dev/null +++ b/iwlwifi-add-new-pci-id-for-6x35-series.patch @@ -0,0 +1,29 @@ +From 20ecf9fd3bebc4147e2996c08a75d6f0229b90df Mon Sep 17 00:00:00 2001 +From: Shuduo Sang +Date: Sat, 30 Mar 2013 06:26:37 +0000 +Subject: iwlwifi: add new pci id for 6x35 series + +some new thinkpad laptops use intel chip with new pci id need be added +lspci -vnn output: + Network controller [0280]: Intel Corporation Centrino Advanced-N 6235 + [8086:088f] (rev 24) + Subsystem: Intel Corporation Device [8086:5260] + +Signed-off-by: Shuduo Sang +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- +diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c +index 46ca91f..0016bb2 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c +@@ -241,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, ++ {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)}, + + /* 105 Series */ + {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 4985470b7..a3763fc8c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,6 +802,9 @@ Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch +#rhbz 986538 +Patch25065: iwlwifi-add-new-pci-id-for-6x35-series.patch + Patch26000: cve-2013-4125.patch # END OF PATCH DEFINITIONS @@ -1545,6 +1548,9 @@ ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch ApplyPatch cve-2013-4125.patch +#rhbz 986538 +ApplyPatch iwlwifi-add-new-pci-id-for-6x35-series.patch + # END OF PATCH APPLICATIONS %endif @@ -2391,6 +2397,7 @@ fi # || || %changelog * Mon Jul 22 2013 Josh Boyer +- Add patch for iwlwifi 6x35 devices (rhbz 986538) - Linux v3.9.11 * Fri Jul 19 2013 Dave Jones From 6dcbc3634e45bbaae9397b90a318af6f6921fe46 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Jul 2013 14:55:50 -0400 Subject: [PATCH 378/492] Fix timer issue in bridge code (rhbz 980254) --- ...-not-call-setup_timer-multiple-times.patch | 50 +++++++++++++++++++ kernel.spec | 4 ++ 2 files changed, 54 insertions(+) create mode 100644 bridge-do-not-call-setup_timer-multiple-times.patch diff --git a/bridge-do-not-call-setup_timer-multiple-times.patch b/bridge-do-not-call-setup_timer-multiple-times.patch new file mode 100644 index 000000000..c8c7bf747 --- /dev/null +++ b/bridge-do-not-call-setup_timer-multiple-times.patch @@ -0,0 +1,50 @@ +From 1faabf2aab1fdaa1ace4e8c829d1b9cf7bfec2f1 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 20 Jul 2013 03:07:16 +0000 +Subject: bridge: do not call setup_timer() multiple times + +commit 9f00b2e7cf24 ("bridge: only expire the mdb entry when query is +received") added a nasty bug as an active timer can be reinitialized. + +setup_timer() must be done once, no matter how many time mod_timer() +is called. br_multicast_new_group() is the right place to do this. + +Reported-by: Srivatsa S. Bhat +Diagnosed-by: Thomas Gleixner +Signed-off-by: Eric Dumazet +Tested-by: Srivatsa S. Bhat +Cc: Cong Wang +Signed-off-by: David S. Miller +--- +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 69af490..4b99c9a 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -619,6 +619,9 @@ rehash: + mp->br = br; + mp->addr = *group; + ++ setup_timer(&mp->timer, br_multicast_group_expired, ++ (unsigned long)mp); ++ + hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); + mdb->size++; + +@@ -1126,7 +1129,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + +- setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); + mod_timer(&mp->timer, now + br->multicast_membership_interval); + mp->timer_armed = true; + +@@ -1204,7 +1206,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + +- setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); + mod_timer(&mp->timer, now + br->multicast_membership_interval); + mp->timer_armed = true; + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index a3763fc8c..8b4ae8b5c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,7 @@ Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch #rhbz 980254 Patch25061: bridge-timer-fix.patch +Patch25066: bridge-do-not-call-setup_timer-multiple-times.patch #rhbz 977558 Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch @@ -1522,7 +1523,9 @@ ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch #rhbz 880035 ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch +#rhbz 980254 ApplyPatch bridge-timer-fix.patch +ApplyPatch bridge-do-not-call-setup_timer-multiple-times.patch #rhbz 977558 ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch @@ -2397,6 +2400,7 @@ fi # || || %changelog * Mon Jul 22 2013 Josh Boyer +- Fix timer issue in bridge code (rhbz 980254) - Add patch for iwlwifi 6x35 devices (rhbz 986538) - Linux v3.9.11 From 5596f3ea40c8b3ba3cd5a164f9471b3fa0142042 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Jul 2013 16:45:59 -0400 Subject: [PATCH 379/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 8b4ae8b5c..9b935f577 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2399,7 +2399,7 @@ fi # ||----w | # || || %changelog -* Mon Jul 22 2013 Josh Boyer +* Mon Jul 22 2013 Josh Boyer - 3.9.11-200 - Fix timer issue in bridge code (rhbz 980254) - Add patch for iwlwifi 6x35 devices (rhbz 986538) - Linux v3.9.11 From a4d36187f54300b7b9d3f9eb7b637b4503d95dd2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Jul 2013 08:23:36 -0400 Subject: [PATCH 380/492] CVE-2013-4163 net: panic while appending data to a corked IPv6 socket in ip6_append_data_mtu (rhbz 987633 987639) --- ...ot-care-about-pmtudisc-and_frag_size.patch | 137 ++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 146 insertions(+) create mode 100644 ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch diff --git a/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch b/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch new file mode 100644 index 000000000..97c3b1981 --- /dev/null +++ b/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch @@ -0,0 +1,137 @@ +From 1fcbda94eb3ababc95eff46548962ceb14de638e Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Tue, 2 Jul 2013 08:04:05 +0200 +Subject: [PATCH 12/40] ipv6: ip6_append_data_mtu did not care about pmtudisc + and frag_size + +[ Upstream commit 75a493e60ac4bbe2e977e7129d6d8cbb0dd236be ] + +If the socket had an IPV6_MTU value set, ip6_append_data_mtu lost track +of this when appending the second frame on a corked socket. This results +in the following splat: + +[37598.993962] ------------[ cut here ]------------ +[37598.994008] kernel BUG at net/core/skbuff.c:2064! +[37598.994008] invalid opcode: 0000 [#1] SMP +[37598.994008] Modules linked in: tcp_lp uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core videodev media vfat fat usb_storage fuse ebtable_nat xt_CHECKSUM bridge stp llc ipt_MASQUERADE nf_conntrack_netbios_ns nf_conntrack_broadcast ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat ++nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp libiscsi ++scsi_transport_iscsi rfcomm bnep iTCO_wdt iTCO_vendor_support snd_hda_codec_conexant arc4 iwldvm mac80211 snd_hda_intel acpi_cpufreq mperf coretemp snd_hda_codec microcode cdc_wdm cdc_acm +[37598.994008] snd_hwdep cdc_ether snd_seq snd_seq_device usbnet mii joydev btusb snd_pcm bluetooth i2c_i801 e1000e lpc_ich mfd_core ptp iwlwifi pps_core snd_page_alloc mei cfg80211 snd_timer thinkpad_acpi snd tpm_tis soundcore rfkill tpm tpm_bios vhost_net tun macvtap macvlan kvm_intel kvm uinput binfmt_misc ++dm_crypt i915 i2c_algo_bit drm_kms_helper drm i2c_core wmi video +[37598.994008] CPU 0 +[37598.994008] Pid: 27320, comm: t2 Not tainted 3.9.6-200.fc18.x86_64 #1 LENOVO 27744PG/27744PG +[37598.994008] RIP: 0010:[] [] skb_copy_and_csum_bits+0x325/0x330 +[37598.994008] RSP: 0018:ffff88003670da18 EFLAGS: 00010202 +[37598.994008] RAX: ffff88018105c018 RBX: 0000000000000004 RCX: 00000000000006c0 +[37598.994008] RDX: ffff88018105a6c0 RSI: ffff88018105a000 RDI: ffff8801e1b0aa00 +[37598.994008] RBP: ffff88003670da78 R08: 0000000000000000 R09: ffff88018105c040 +[37598.994008] R10: ffff8801e1b0aa00 R11: 0000000000000000 R12: 000000000000fff8 +[37598.994008] R13: 00000000000004fc R14: 00000000ffff0504 R15: 0000000000000000 +[37598.994008] FS: 00007f28eea59740(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000 +[37598.994008] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +[37598.994008] CR2: 0000003d935789e0 CR3: 00000000365cb000 CR4: 00000000000407f0 +[37598.994008] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[37598.994008] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +[37598.994008] Process t2 (pid: 27320, threadinfo ffff88003670c000, task ffff88022c162ee0) +[37598.994008] Stack: +[37598.994008] ffff88022e098a00 ffff88020f973fc0 0000000000000008 00000000000004c8 +[37598.994008] ffff88020f973fc0 00000000000004c4 ffff88003670da78 ffff8801e1b0a200 +[37598.994008] 0000000000000018 00000000000004c8 ffff88020f973fc0 00000000000004c4 +[37598.994008] Call Trace: +[37598.994008] [] ip6_append_data+0xccf/0xfe0 +[37598.994008] [] ? ip_copy_metadata+0x1a0/0x1a0 +[37598.994008] [] ? _raw_spin_lock_bh+0x16/0x40 +[37598.994008] [] udpv6_sendmsg+0x1ed/0xc10 +[37598.994008] [] ? sock_has_perm+0x75/0x90 +[37598.994008] [] inet_sendmsg+0x63/0xb0 +[37598.994008] [] ? selinux_socket_sendmsg+0x23/0x30 +[37598.994008] [] sock_sendmsg+0xb0/0xe0 +[37598.994008] [] ? __switch_to+0x181/0x4a0 +[37598.994008] [] sys_sendto+0x12d/0x180 +[37598.994008] [] ? __audit_syscall_entry+0x94/0xf0 +[37598.994008] [] ? syscall_trace_enter+0x231/0x240 +[37598.994008] [] tracesys+0xdd/0xe2 +[37598.994008] Code: fe 07 00 00 48 c7 c7 04 28 a6 81 89 45 a0 4c 89 4d b8 44 89 5d a8 e8 1b ac b1 ff 44 8b 5d a8 4c 8b 4d b8 8b 45 a0 e9 cf fe ff ff <0f> 0b 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 48 +[37598.994008] RIP [] skb_copy_and_csum_bits+0x325/0x330 +[37598.994008] RSP +[37599.007323] ---[ end trace d69f6a17f8ac8eee ]--- + +While there, also check if path mtu discovery is activated for this +socket. The logic was adapted from ip6_append_data when first writing +on the corked socket. + +This bug was introduced with commit +0c1833797a5a6ec23ea9261d979aa18078720b74 ("ipv6: fix incorrect ipsec +fragment"). + +v2: +a) Replace IPV6_PMTU_DISC_DO with IPV6_PMTUDISC_PROBE. +b) Don't pass ipv6_pinfo to ip6_append_data_mtu (suggestion by Gao + feng, thanks!). +c) Change mtu to unsigned int, else we get a warning about + non-matching types because of the min()-macro type-check. + +Acked-by: Gao feng +Cc: YOSHIFUJI Hideaki +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index d5d20cd..6e3ddf8 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1098,11 +1098,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; + } + +-static void ip6_append_data_mtu(int *mtu, ++static void ip6_append_data_mtu(unsigned int *mtu, + int *maxfraglen, + unsigned int fragheaderlen, + struct sk_buff *skb, +- struct rt6_info *rt) ++ struct rt6_info *rt, ++ bool pmtuprobe) + { + if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { + if (skb == NULL) { +@@ -1114,7 +1115,9 @@ static void ip6_append_data_mtu(int *mtu, + * this fragment is not first, the headers + * space is regarded as data space. + */ +- *mtu = dst_mtu(rt->dst.path); ++ *mtu = min(*mtu, pmtuprobe ? ++ rt->dst.dev->mtu : ++ dst_mtu(rt->dst.path)); + } + *maxfraglen = ((*mtu - fragheaderlen) & ~7) + + fragheaderlen - sizeof(struct frag_hdr); +@@ -1131,11 +1134,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + struct ipv6_pinfo *np = inet6_sk(sk); + struct inet_cork *cork; + struct sk_buff *skb, *skb_prev = NULL; +- unsigned int maxfraglen, fragheaderlen; ++ unsigned int maxfraglen, fragheaderlen, mtu; + int exthdrlen; + int dst_exthdrlen; + int hh_len; +- int mtu; + int copy; + int err; + int offset = 0; +@@ -1292,7 +1294,9 @@ alloc_new_skb: + /* update mtu and maxfraglen if necessary */ + if (skb == NULL || skb_prev == NULL) + ip6_append_data_mtu(&mtu, &maxfraglen, +- fragheaderlen, skb, rt); ++ fragheaderlen, skb, rt, ++ np->pmtudisc == ++ IPV6_PMTUDISC_PROBE); + + skb_prev = skb; + +-- +1.7.11.7 diff --git a/kernel.spec b/kernel.spec index 9b935f577..6640df60e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -806,6 +806,9 @@ Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch #rhbz 986538 Patch25065: iwlwifi-add-new-pci-id-for-6x35-series.patch +#CVE-2013-4163 rhbz 987633 987639 +Patch25067: ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch + Patch26000: cve-2013-4125.patch # END OF PATCH DEFINITIONS @@ -1554,6 +1557,9 @@ ApplyPatch cve-2013-4125.patch #rhbz 986538 ApplyPatch iwlwifi-add-new-pci-id-for-6x35-series.patch +#CVE-2013-4163 rhbz 987633 987639 +ApplyPatch ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch + # END OF PATCH APPLICATIONS %endif @@ -2399,6 +2405,9 @@ fi # ||----w | # || || %changelog +* Wed Jul 24 2013 Josh Boyer +- CVE-2013-4163 net: panic while appending data to a corked IPv6 socket in ip6_append_data_mtu (rhbz 987633 987639) + * Mon Jul 22 2013 Josh Boyer - 3.9.11-200 - Fix timer issue in bridge code (rhbz 980254) - Add patch for iwlwifi 6x35 devices (rhbz 986538) From 80774789b1cb3b0de0a08e4ff30bbef2acd58665 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Jul 2013 08:27:51 -0400 Subject: [PATCH 381/492] CVE-2013-4162 net: panic while pushing pending data out of a IPv6 socket with UDP_CORK enabled (rhbz 987627 987656) --- ...g-a-socket-with-AF_INET-pending-data.patch | 128 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 135 insertions(+) create mode 100644 ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch diff --git a/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch b/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch new file mode 100644 index 000000000..8f37348e9 --- /dev/null +++ b/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch @@ -0,0 +1,128 @@ +From 0e3f585c132e7716b8b96c20c59b15a24ec2790e Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Mon, 1 Jul 2013 20:21:30 +0200 +Subject: [PATCH 11/40] ipv6: call udp_push_pending_frames when uncorking a + socket with AF_INET pending data + +[ Upstream commit 8822b64a0fa64a5dd1dfcf837c5b0be83f8c05d1 ] + +We accidentally call down to ip6_push_pending_frames when uncorking +pending AF_INET data on a ipv6 socket. This results in the following +splat (from Dave Jones): + +skbuff: skb_under_panic: text:ffffffff816765f6 len:48 put:40 head:ffff88013deb6df0 data:ffff88013deb6dec tail:0x2c end:0xc0 dev: +------------[ cut here ]------------ +kernel BUG at net/core/skbuff.c:126! +invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC +Modules linked in: dccp_ipv4 dccp 8021q garp bridge stp dlci mpoa snd_seq_dummy sctp fuse hidp tun bnep nfnetlink scsi_transport_iscsi rfcomm can_raw can_bcm af_802154 appletalk caif_socket can caif ipt_ULOG x25 rose af_key pppoe pppox ipx phonet irda llc2 ppp_generic slhc p8023 psnap p8022 llc crc_ccitt atm bluetooth ++netrom ax25 nfc rfkill rds af_rxrpc coretemp hwmon kvm_intel kvm crc32c_intel snd_hda_codec_realtek ghash_clmulni_intel microcode pcspkr snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep usb_debug snd_seq snd_seq_device snd_pcm e1000e snd_page_alloc snd_timer ptp snd pps_core soundcore xfs libcrc32c +CPU: 2 PID: 8095 Comm: trinity-child2 Not tainted 3.10.0-rc7+ #37 +task: ffff8801f52c2520 ti: ffff8801e6430000 task.ti: ffff8801e6430000 +RIP: 0010:[] [] skb_panic+0x63/0x65 +RSP: 0018:ffff8801e6431de8 EFLAGS: 00010282 +RAX: 0000000000000086 RBX: ffff8802353d3cc0 RCX: 0000000000000006 +RDX: 0000000000003b90 RSI: ffff8801f52c2ca0 RDI: ffff8801f52c2520 +RBP: ffff8801e6431e08 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000001 R11: 0000000000000001 R12: ffff88022ea0c800 +R13: ffff88022ea0cdf8 R14: ffff8802353ecb40 R15: ffffffff81cc7800 +FS: 00007f5720a10740(0000) GS:ffff880244c00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000005862000 CR3: 000000022843c000 CR4: 00000000001407e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000600 +Stack: + ffff88013deb6dec 000000000000002c 00000000000000c0 ffffffff81a3f6e4 + ffff8801e6431e18 ffffffff8159a9aa ffff8801e6431e90 ffffffff816765f6 + ffffffff810b756b 0000000700000002 ffff8801e6431e40 0000fea9292aa8c0 +Call Trace: + [] skb_push+0x3a/0x40 + [] ip6_push_pending_frames+0x1f6/0x4d0 + [] ? mark_held_locks+0xbb/0x140 + [] udp_v6_push_pending_frames+0x2b9/0x3d0 + [] ? udplite_getfrag+0x20/0x20 + [] udp_lib_setsockopt+0x1aa/0x1f0 + [] ? fget_light+0x387/0x4f0 + [] udpv6_setsockopt+0x34/0x40 + [] sock_common_setsockopt+0x14/0x20 + [] SyS_setsockopt+0x71/0xd0 + [] tracesys+0xdd/0xe2 +Code: 00 00 48 89 44 24 10 8b 87 d8 00 00 00 48 89 44 24 08 48 8b 87 e8 00 00 00 48 c7 c7 c0 04 aa 81 48 89 04 24 31 c0 e8 e1 7e ff ff <0f> 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 +RIP [] skb_panic+0x63/0x65 + RSP + +This patch adds a check if the pending data is of address family AF_INET +and directly calls udp_push_ending_frames from udp_v6_push_pending_frames +if that is the case. + +This bug was found by Dave Jones with trinity. + +(Also move the initialization of fl6 below the AF_INET check, even if +not strictly necessary.) + +Cc: Dave Jones +Cc: YOSHIFUJI Hideaki +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/udp.h | 1 + + net/ipv4/udp.c | 3 ++- + net/ipv6/udp.c | 7 ++++++- + 3 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/include/net/udp.h b/include/net/udp.h +index 065f379..ad99eed 100644 +--- a/include/net/udp.h ++++ b/include/net/udp.h +@@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum, + extern void udp_err(struct sk_buff *, u32); + extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len); ++extern int udp_push_pending_frames(struct sock *sk); + extern void udp_flush_pending_frames(struct sock *sk); + extern int udp_rcv(struct sk_buff *skb); + extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 0bf5d39..93b731d 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -799,7 +799,7 @@ send: + /* + * Push out all pending data as one UDP datagram. Socket is locked. + */ +-static int udp_push_pending_frames(struct sock *sk) ++int udp_push_pending_frames(struct sock *sk) + { + struct udp_sock *up = udp_sk(sk); + struct inet_sock *inet = inet_sk(sk); +@@ -818,6 +818,7 @@ out: + up->pending = 0; + return err; + } ++EXPORT_SYMBOL(udp_push_pending_frames); + + int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 42923b1..e7b28f9 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -955,11 +955,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) + struct udphdr *uh; + struct udp_sock *up = udp_sk(sk); + struct inet_sock *inet = inet_sk(sk); +- struct flowi6 *fl6 = &inet->cork.fl.u.ip6; ++ struct flowi6 *fl6; + int err = 0; + int is_udplite = IS_UDPLITE(sk); + __wsum csum = 0; + ++ if (up->pending == AF_INET) ++ return udp_push_pending_frames(sk); ++ ++ fl6 = &inet->cork.fl.u.ip6; ++ + /* Grab the skbuff where UDP header space exists. */ + if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) + goto out; +-- +1.7.11.7 diff --git a/kernel.spec b/kernel.spec index 6640df60e..71ef438ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -809,6 +809,9 @@ Patch25065: iwlwifi-add-new-pci-id-for-6x35-series.patch #CVE-2013-4163 rhbz 987633 987639 Patch25067: ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch +#CVE-2013-4162 rhbz 987627 987656 +Patch25068: ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch + Patch26000: cve-2013-4125.patch # END OF PATCH DEFINITIONS @@ -1560,6 +1563,9 @@ ApplyPatch iwlwifi-add-new-pci-id-for-6x35-series.patch #CVE-2013-4163 rhbz 987633 987639 ApplyPatch ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch +#CVE-2013-4162 rhbz 987627 987656 +ApplyPatch ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch + # END OF PATCH APPLICATIONS %endif @@ -2406,6 +2412,7 @@ fi # || || %changelog * Wed Jul 24 2013 Josh Boyer +- CVE-2013-4162 net: panic while pushing pending data out of a IPv6 socket with UDP_CORK enabled (rhbz 987627 987656) - CVE-2013-4163 net: panic while appending data to a corked IPv6 socket in ip6_append_data_mtu (rhbz 987633 987639) * Mon Jul 22 2013 Josh Boyer - 3.9.11-200 From 131f0a40e01f2fe59d7be4e7927a7159415cafd4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Jul 2013 10:43:52 -0400 Subject: [PATCH 382/492] Add patch to fix NULL deref in iwlwifi (rhbz 979581) --- ...ng-ieee80211_chswitch_done-with-NULL.patch | 58 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 67 insertions(+) create mode 100644 iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch diff --git a/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch b/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch new file mode 100644 index 000000000..84d6aa06d --- /dev/null +++ b/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch @@ -0,0 +1,58 @@ +If channel switch is pending and we remove interface we can +crash like showed below due to passing NULL vif to mac80211: + +BUG: unable to handle kernel paging request at fffffffffffff8cc +IP: [] strnlen+0xd/0x40 +Call Trace: + [] string.isra.3+0x3e/0xd0 + [] vsnprintf+0x219/0x640 + [] vscnprintf+0x11/0x30 + [] vprintk_emit+0x115/0x4f0 + [] printk+0x61/0x63 + [] ieee80211_chswitch_done+0xaf/0xd0 [mac80211] + [] iwl_chswitch_done+0x34/0x40 [iwldvm] + [] iwlagn_commit_rxon+0x2a3/0xdc0 [iwldvm] + [] ? iwlagn_set_rxon_chain+0x180/0x2c0 [iwldvm] + [] iwl_set_mode+0x36/0x40 [iwldvm] + [] iwlagn_mac_remove_interface+0x8d/0x1b0 [iwldvm] + [] ieee80211_do_stop+0x29d/0x7f0 [mac80211] + +This is because we nulify ctx->vif in iwlagn_mac_remove_interface() +before calling some other functions that teardown interface. To fix +just check ctx->vif on iwl_chswitch_done(). We should not call +ieee80211_chswitch_done() as channel switch works were already canceled +by mac80211 in ieee80211_do_stop() -> ieee80211_mgd_stop(). + +Resolve: +https://bugzilla.redhat.com/show_bug.cgi?id=979581 + +Cc: stable@vger.kernel.org +Reported-by: Lukasz Jagiello +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/dvm/mac80211.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c +index 323e4a3..9a817df 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c +@@ -1046,7 +1046,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + +- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ++ if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ++ return; ++ ++ if (ctx->vif) + ieee80211_chswitch_done(ctx->vif, is_success); + } + +-- +1.7.11.7 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 71ef438ce..e2661375d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -814,6 +814,9 @@ Patch25068: ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_IN Patch26000: cve-2013-4125.patch +#rhbz 979581 +Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch + # END OF PATCH DEFINITIONS %endif @@ -1566,6 +1569,9 @@ ApplyPatch ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.pa #CVE-2013-4162 rhbz 987627 987656 ApplyPatch ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch +#rhbz 979581 +ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch + # END OF PATCH APPLICATIONS %endif @@ -2411,6 +2417,9 @@ fi # ||----w | # || || %changelog +* Fri Jul 26 2013 Josh Boyer +- Add patch to fix NULL deref in iwlwifi (rhbz 979581) + * Wed Jul 24 2013 Josh Boyer - CVE-2013-4162 net: panic while pushing pending data out of a IPv6 socket with UDP_CORK enabled (rhbz 987627 987656) - CVE-2013-4163 net: panic while appending data to a corked IPv6 socket in ip6_append_data_mtu (rhbz 987633 987639) From 0a6c27ad881a9b41848346a9e39edce1a252f168 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 29 Jul 2013 08:29:29 -0400 Subject: [PATCH 383/492] Add support for elantech v7 devices (rhbz 969473) --- ...h-fix-for-newer-hardware-versions-v7.patch | 70 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 79 insertions(+) create mode 100644 Input-elantech-fix-for-newer-hardware-versions-v7.patch diff --git a/Input-elantech-fix-for-newer-hardware-versions-v7.patch b/Input-elantech-fix-for-newer-hardware-versions-v7.patch new file mode 100644 index 000000000..b9495d75d --- /dev/null +++ b/Input-elantech-fix-for-newer-hardware-versions-v7.patch @@ -0,0 +1,70 @@ +From 9eebed7de660c0b5ab129a9de4f89d20b60de68c Mon Sep 17 00:00:00 2001 +From: Matteo Delfino +Date: Sat, 6 Jul 2013 21:52:26 -0700 +Subject: [PATCH] Input: elantech - fix for newer hardware versions (v7) + +* Fix version recognition in elantech_set_properties + + The new hardware reports itself as v7 but the packets' + structure is unaltered. + +* Fix packet type recognition in elantech_packet_check_v4 + + The bitmask used for v6 is too wide, only the last three bits of + the third byte in a packet (packet[3] & 0x03) are actually used to + distinguish between packet types. + Starting from v7, additional information (to be interpreted) is + stored in the remaining bits (packets[3] & 0x1c). + In addition, the value stored in (packet[0] & 0x0c) is no longer + a constant but contains additional information yet to be deciphered. + This change should be backwards compatible with v6 hardware. + +Additional-author: Giovanni Frigione +Signed-off-by: Matteo Delfino +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 1e8e42f..57b2637 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -694,18 +694,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) + static int elantech_packet_check_v4(struct psmouse *psmouse) + { + unsigned char *packet = psmouse->packet; ++ unsigned char packet_type = packet[3] & 0x03; + +- if ((packet[0] & 0x0c) == 0x04 && +- (packet[3] & 0x1f) == 0x11) ++ switch (packet_type) { ++ case 0: ++ return PACKET_V4_STATUS; ++ ++ case 1: + return PACKET_V4_HEAD; + +- if ((packet[0] & 0x0c) == 0x04 && +- (packet[3] & 0x1f) == 0x12) ++ case 2: + return PACKET_V4_MOTION; +- +- if ((packet[0] & 0x0c) == 0x04 && +- (packet[3] & 0x1f) == 0x10) +- return PACKET_V4_STATUS; ++ } + + return PACKET_UNKNOWN; + } +@@ -1282,6 +1282,7 @@ static int elantech_set_properties(struct elantech_data *etd) + etd->hw_version = 3; + break; + case 6: ++ case 7: + etd->hw_version = 4; + break; + default: +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index e2661375d..8fba9fed6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -817,6 +817,9 @@ Patch26000: cve-2013-4125.patch #rhbz 979581 Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch +#rhbz 969473 +Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch + # END OF PATCH DEFINITIONS %endif @@ -1572,6 +1575,9 @@ ApplyPatch ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INE #rhbz 979581 ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch +#rhbz 969473 +ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch + # END OF PATCH APPLICATIONS %endif @@ -2417,6 +2423,9 @@ fi # ||----w | # || || %changelog +* Mon Jul 29 2013 Josh Boyer +- Add support for elantech v7 devices (rhbz 969473) + * Fri Jul 26 2013 Josh Boyer - Add patch to fix NULL deref in iwlwifi (rhbz 979581) From 652a694987f87d454e9ae29520d8983e6fa88868 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Aug 2013 08:34:36 -0400 Subject: [PATCH 384/492] Fix firmware issues with iwl4965 and rfkill (rhbz 977053) --- iwl4965-reset-firmware-after-rfkill-off.patch | 56 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 iwl4965-reset-firmware-after-rfkill-off.patch diff --git a/iwl4965-reset-firmware-after-rfkill-off.patch b/iwl4965-reset-firmware-after-rfkill-off.patch new file mode 100644 index 000000000..08b360d10 --- /dev/null +++ b/iwl4965-reset-firmware-after-rfkill-off.patch @@ -0,0 +1,56 @@ +Using rfkill switch can make firmware unstable, what cause various +Microcode errors and kernel warnings. Reseting firmware just after +rfkill off (radio on) helped with that. + +Resolve: +https://bugzilla.redhat.com/show_bug.cgi?id=977053 + +Reported-and-tested-by: Justin Pearce +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/4965-mac.c | 10 +++++----- + drivers/net/wireless/iwlegacy/common.c | 1 + + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c +index f0b7794..f2ed62e 100644 +--- a/drivers/net/wireless/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/iwlegacy/4965-mac.c +@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il) + * is killed. Hence update the killswitch state here. The + * rfkill handler will care about restarting if needed. + */ +- if (!test_bit(S_ALIVE, &il->status)) { +- if (hw_rf_kill) +- set_bit(S_RFKILL, &il->status); +- else +- clear_bit(S_RFKILL, &il->status); ++ if (hw_rf_kill) { ++ set_bit(S_RFKILL, &il->status); ++ } else { ++ clear_bit(S_RFKILL, &il->status); + wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); ++ il_force_reset(il, true); + } + + handled |= CSR_INT_BIT_RF_KILL; +diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c +index 3195aad..b03e22e 100644 +--- a/drivers/net/wireless/iwlegacy/common.c ++++ b/drivers/net/wireless/iwlegacy/common.c +@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external) + + return 0; + } ++EXPORT_SYMBOL(il_force_reset); + + int + il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +-- +1.7.11.7 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 8fba9fed6..aa21d654e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -820,6 +820,9 @@ Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch +#rhbz 977053 +Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch + # END OF PATCH DEFINITIONS %endif @@ -1578,6 +1581,9 @@ ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch +#rhbz 977053 +ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch + # END OF PATCH APPLICATIONS %endif @@ -2423,6 +2429,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 01 2013 Josh Boyer +- Fix firmware issues with iwl4965 and rfkill (rhbz 977053) + * Mon Jul 29 2013 Josh Boyer - Add support for elantech v7 devices (rhbz 969473) From 5499ee0c2be4635263c064fc1e717747bec9d013 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Aug 2013 08:49:55 -0400 Subject: [PATCH 385/492] Fix mac80211 connection issues (rhbz 981445) --- kernel.spec | 11 ++ ...ng-disabled-channels-while-connected.patch | 43 +++++++ ...loop-in-ieee80211_determine_chantype.patch | 32 +++++ ...e-HT-primary-channel-while-connected.patch | 121 ++++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 mac80211-continue-using-disabled-channels-while-connected.patch create mode 100644 mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch create mode 100644 mac80211-ignore-HT-primary-channel-while-connected.patch diff --git a/kernel.spec b/kernel.spec index aa21d654e..517280272 100644 --- a/kernel.spec +++ b/kernel.spec @@ -823,6 +823,11 @@ Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 977053 Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch +#rhbz 981445 +Patch25074: mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch +Patch25075: mac80211-ignore-HT-primary-channel-while-connected.patch +Patch25076: mac80211-continue-using-disabled-channels-while-connected.patch + # END OF PATCH DEFINITIONS %endif @@ -1584,6 +1589,11 @@ ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 977053 ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch +#rhbz 981445 +ApplyPatch mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch +ApplyPatch mac80211-ignore-HT-primary-channel-while-connected.patch +ApplyPatch mac80211-continue-using-disabled-channels-while-connected.patch + # END OF PATCH APPLICATIONS %endif @@ -2430,6 +2440,7 @@ fi # || || %changelog * Thu Aug 01 2013 Josh Boyer +- Fix mac80211 connection issues (rhbz 981445) - Fix firmware issues with iwl4965 and rfkill (rhbz 977053) * Mon Jul 29 2013 Josh Boyer diff --git a/mac80211-continue-using-disabled-channels-while-connected.patch b/mac80211-continue-using-disabled-channels-while-connected.patch new file mode 100644 index 000000000..91dd1d7db --- /dev/null +++ b/mac80211-continue-using-disabled-channels-while-connected.patch @@ -0,0 +1,43 @@ +From ddfe49b42d8ad4bfdf92d63d4a74f162660d878d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 31 Jul 2013 18:52:03 +0000 +Subject: mac80211: continue using disabled channels while connected + +In case the AP has different regulatory information than we do, +it can happen that we connect to an AP based on e.g. the world +roaming regulatory data, and then update our database with the +AP's country information disables the channel the AP is using. +If this happens on an HT AP, the bandwidth tracking code will +hit the WARN_ON() and disconnect. Since that's not very useful, +ignore the channel-disable flag in bandwidth tracking. + +Cc: stable@vger.kernel.org +Reported-by: Chris Wright +Tested-by: Chris Wright +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 077a953..cc9e02d 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -335,8 +335,17 @@ out: + if (ret & IEEE80211_STA_DISABLE_VHT) + vht_chandef = *chandef; + ++ /* ++ * Ignore the DISABLED flag when we're already connected and only ++ * tracking the APs beacon for bandwidth changes - otherwise we ++ * might get disconnected here if we connect to an AP, update our ++ * regulatory information based on the AP's country IE and the ++ * information we have is wrong/outdated and disables the channel ++ * that we're actually using for the connection to the AP. ++ */ + while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, +- IEEE80211_CHAN_DISABLED)) { ++ tracking ? 0 : ++ IEEE80211_CHAN_DISABLED)) { + if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT; +-- +cgit v0.9.2 diff --git a/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch b/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch new file mode 100644 index 000000000..49115f969 --- /dev/null +++ b/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch @@ -0,0 +1,32 @@ +From b56e4b857c5210e848bfb80e074e5756a36cd523 Mon Sep 17 00:00:00 2001 +From: Chris Wright +Date: Wed, 31 Jul 2013 19:12:24 +0000 +Subject: mac80211: fix infinite loop in ieee80211_determine_chantype + +Commit "3d9646d mac80211: fix channel selection bug" introduced a possible +infinite loop by moving the out target above the chandef_downgrade +while loop. When we downgrade to NL80211_CHAN_WIDTH_20_NOHT, we jump +back up to re-run the while loop...indefinitely. Replace goto with +break and carry on. This may not be sufficient to connect to the AP, +but will at least keep the cpu from livelocking. Thanks to Derek Atkins +as an extra pair of debugging eyes. + +Cc: stable@kernel.org +Signed-off-by: Chris Wright +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ae31968..e3e7d2b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -338,7 +338,7 @@ out: + if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT; +- goto out; ++ break; + } + + ret |= chandef_downgrade(chandef); +-- +cgit v0.9.2 diff --git a/mac80211-ignore-HT-primary-channel-while-connected.patch b/mac80211-ignore-HT-primary-channel-while-connected.patch new file mode 100644 index 000000000..ba5d2a478 --- /dev/null +++ b/mac80211-ignore-HT-primary-channel-while-connected.patch @@ -0,0 +1,121 @@ +From 5cdaed1e878d723d56d04ae0be1738124acf9f46 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 31 Jul 2013 09:23:06 +0000 +Subject: mac80211: ignore HT primary channel while connected + +While we're connected, the AP shouldn't change the primary channel +in the HT information. We checked this, and dropped the connection +if it did change it. + +Unfortunately, this is causing problems on some APs, e.g. on the +Netgear WRT610NL: the beacons seem to always contain a bad channel +and if we made a connection using a probe response (correct data) +we drop the connection immediately and can basically not connect +properly at all. + +Work around this by ignoring the HT primary channel information in +beacons if we're already connected. + +Also print out more verbose messages in the other situations to +help diagnose similar bugs quicker in the future. + +Cc: stable@vger.kernel.org [3.10] +Acked-by: Andy Isaacson +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e5c3cf4..077a953 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -211,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *channel, + const struct ieee80211_ht_operation *ht_oper, + const struct ieee80211_vht_operation *vht_oper, +- struct cfg80211_chan_def *chandef, bool verbose) ++ struct cfg80211_chan_def *chandef, bool tracking) + { ++ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct cfg80211_chan_def vht_chandef; + u32 ht_cfreq, ret; + +@@ -231,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, + channel->band); + /* check that channel matches the right operating channel */ +- if (channel->center_freq != ht_cfreq) { ++ if (!tracking && channel->center_freq != ht_cfreq) { + /* + * It's possible that some APs are confused here; + * Netgear WNDR3700 sometimes reports 4 higher than +@@ -239,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + * since we look at probe response/beacon data here + * it should be OK. + */ +- if (verbose) +- sdata_info(sdata, +- "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", +- channel->center_freq, ht_cfreq, +- ht_oper->primary_chan, channel->band); ++ sdata_info(sdata, ++ "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", ++ channel->center_freq, ht_cfreq, ++ ht_oper->primary_chan, channel->band); + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; + goto out; + } +@@ -297,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + channel->band); + break; + default: +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT operation IE has invalid channel width (%d), disable VHT\n", + vht_oper->chan_width); +@@ -306,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + } + + if (!cfg80211_chandef_valid(&vht_chandef)) { +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT information is invalid, disable VHT\n"); + ret = IEEE80211_STA_DISABLE_VHT; +@@ -319,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + } + + if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT information doesn't match HT, disable VHT\n"); + ret = IEEE80211_STA_DISABLE_VHT; +@@ -346,7 +346,7 @@ out: + ret |= chandef_downgrade(chandef); + } + +- if (chandef->width != vht_chandef.width && verbose) ++ if (chandef->width != vht_chandef.width && !tracking) + sdata_info(sdata, + "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); + +@@ -386,7 +386,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, + + /* calculate new channel (type) based on HT/VHT operation IEs */ + flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, +- vht_oper, &chandef, false); ++ vht_oper, &chandef, true); + + /* + * Downgrade the new channel if we associated with restricted +@@ -3838,7 +3838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, + cbss->channel, + ht_oper, vht_oper, +- &chandef, true); ++ &chandef, false); + + sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), + local->rx_chains); +-- +cgit v0.9.2 From 85ccd6f5760b52ff47e5ee04848a0306d4aa1d30 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 1 Aug 2013 11:13:25 -0500 Subject: [PATCH 386/492] Rebase to 3.10.4 --- ...x-fix-init-race-alignmasks-and-GCM-b.patch | 83 - ...-handle-host-TSC-calibration-failure.patch | 58 - ...ey-fix-info-leaks-in-notify-messages.patch | 37 - arm-omap-ehci-fix.patch | 190 - arm-tegra-fixclk.patch | 28 - config-debug | 4 + config-generic | 62 +- config-nodebug | 4 + config-powerpc-generic | 2 + config-powerpc64 | 3 + config-powerpc64p7 | 3 + config-x86-generic | 13 + config-x86_64-generic | 11 + cve-2013-4125.patch | 79 - debug-bad-pte-dmi.patch | 66 - debug-bad-pte-modules.patch | 21 - devel-pekey-secure-boot-20130502.patch | 5912 +++++++++++++++ drivers-hwmon-nct6775.patch | 6424 ----------------- ...ly-restore-fences-with-objects-attac.patch | 113 + drm-i915-dp-stfu.patch | 24 +- i7300_edac_single_mode_fixup.patch | 108 - ...g-a-socket-with-AF_INET-pending-data.patch | 128 - ...ot-care-about-pmtudisc-and_frag_size.patch | 137 - ...k_dst_check-must-not-assume-ipv6-dst.patch | 52 - iwlwifi-add-new-pci-id-for-6x35-series.patch | 29 - ...ifi-pcie-fix-race-in-queue-unmapping.patch | 56 - ...queue-if-stopped-when-being-unmapped.patch | 35 - kernel.spec | 117 +- secure-boot-20130506.patch | 1474 ---- sources | 4 +- ...ix-use-after-free-in-vhost_net_flush.patch | 76 - 31 files changed, 6170 insertions(+), 9183 deletions(-) delete mode 100644 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch delete mode 100644 VMX-x86-handle-host-TSC-calibration-failure.patch delete mode 100644 af_key-fix-info-leaks-in-notify-messages.patch delete mode 100644 arm-omap-ehci-fix.patch delete mode 100644 arm-tegra-fixclk.patch delete mode 100644 cve-2013-4125.patch delete mode 100644 debug-bad-pte-dmi.patch delete mode 100644 debug-bad-pte-modules.patch create mode 100644 devel-pekey-secure-boot-20130502.patch delete mode 100644 drivers-hwmon-nct6775.patch create mode 100644 drm-i915-correctly-restore-fences-with-objects-attac.patch delete mode 100644 i7300_edac_single_mode_fixup.patch delete mode 100644 ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch delete mode 100644 ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch delete mode 100644 ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch delete mode 100644 iwlwifi-add-new-pci-id-for-6x35-series.patch delete mode 100644 iwlwifi-pcie-fix-race-in-queue-unmapping.patch delete mode 100644 iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch delete mode 100644 secure-boot-20130506.patch delete mode 100644 vhost-net-fix-use-after-free-in-vhost_net_flush.patch diff --git a/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch b/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch deleted file mode 100644 index c8d30455e..000000000 --- a/0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch +++ /dev/null @@ -1,83 +0,0 @@ -From b05ceba560e094d27ff716f6df1e2d5ef670d4d3 Mon Sep 17 00:00:00 2001 -From: Kent Yoder -Date: Wed, 27 Feb 2013 15:50:27 -0600 -Subject: [PATCH] drivers/crypto/nx: fix init race, alignmasks and GCM bug - - Fixes a race on driver init with registering algorithms where the -driver status flag wasn't being set before self testing started. - - Added the cra_alignmask field for CBC and ECB modes. - - Fixed a bug in GCM where AES block size was being used instead of -authsize. - -Signed-off-by: Kent Yoder ---- - drivers/crypto/nx/nx-aes-cbc.c | 1 + - drivers/crypto/nx/nx-aes-ecb.c | 1 + - drivers/crypto/nx/nx-aes-gcm.c | 2 +- - drivers/crypto/nx/nx.c | 4 ++-- - 4 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c -index a76d4c4..35d483f 100644 ---- a/drivers/crypto/nx/nx-aes-cbc.c -+++ b/drivers/crypto/nx/nx-aes-cbc.c -@@ -126,6 +126,7 @@ struct crypto_alg nx_cbc_aes_alg = { - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct nx_crypto_ctx), - .cra_type = &crypto_blkcipher_type, -+ .cra_alignmask = 0xf, - .cra_module = THIS_MODULE, - .cra_init = nx_crypto_ctx_aes_cbc_init, - .cra_exit = nx_crypto_ctx_exit, -diff --git a/drivers/crypto/nx/nx-aes-ecb.c b/drivers/crypto/nx/nx-aes-ecb.c -index ba5f161..7bbc9a8 100644 ---- a/drivers/crypto/nx/nx-aes-ecb.c -+++ b/drivers/crypto/nx/nx-aes-ecb.c -@@ -123,6 +123,7 @@ struct crypto_alg nx_ecb_aes_alg = { - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_alignmask = 0xf, - .cra_ctxsize = sizeof(struct nx_crypto_ctx), - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, -diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c -index c8109ed..6cca6c3 100644 ---- a/drivers/crypto/nx/nx-aes-gcm.c -+++ b/drivers/crypto/nx/nx-aes-gcm.c -@@ -219,7 +219,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc) - if (enc) - NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; - else -- nbytes -= AES_BLOCK_SIZE; -+ nbytes -= crypto_aead_authsize(crypto_aead_reqtfm(req)); - - csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8; - -diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c -index c767f23..7621d05 100644 ---- a/drivers/crypto/nx/nx.c -+++ b/drivers/crypto/nx/nx.c -@@ -454,6 +454,8 @@ static int nx_register_algs(void) - if (rc) - goto out; - -+ nx_driver.of.status = NX_OKAY; -+ - rc = crypto_register_alg(&nx_ecb_aes_alg); - if (rc) - goto out; -@@ -498,8 +500,6 @@ static int nx_register_algs(void) - if (rc) - goto out_unreg_s512; - -- nx_driver.of.status = NX_OKAY; -- - goto out; - - out_unreg_s512: --- -1.7.11.7 - diff --git a/VMX-x86-handle-host-TSC-calibration-failure.patch b/VMX-x86-handle-host-TSC-calibration-failure.patch deleted file mode 100644 index 6b6ddd2d2..000000000 --- a/VMX-x86-handle-host-TSC-calibration-failure.patch +++ /dev/null @@ -1,58 +0,0 @@ -@@ -, +, @@ - VMX: x86: handle host TSC calibration failure - - If the host TSC calibration fails, tsc_khz is zero (see tsc_init.c). - Handle such case properly in KVM (instead of dividing by zero). - - https://bugzilla.redhat.com/show_bug.cgi?id=859282 - - Signed-off-by: Marcelo Tosatti - Signed-off-by: Gleb Natapov ---- a/arch/x86/kvm/x86.c -+++ a/arch/x86/kvm/x86.c -@@ -1079,6 +1079,10 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz) - u32 thresh_lo, thresh_hi; - int use_scaling = 0; - -+ /* tsc_khz can be zero if TSC calibration fails */ -+ if (this_tsc_khz == 0) -+ return; -+ - /* Compute a scale to convert nanoseconds in TSC cycles */ - kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000, - &vcpu->arch.virtual_tsc_shift, -@@ -1156,20 +1160,23 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) - ns = get_kernel_ns(); - elapsed = ns - kvm->arch.last_tsc_nsec; - -- /* n.b - signed multiplication and division required */ -- usdiff = data - kvm->arch.last_tsc_write; -+ if (vcpu->arch.virtual_tsc_khz) { -+ /* n.b - signed multiplication and division required */ -+ usdiff = data - kvm->arch.last_tsc_write; - #ifdef CONFIG_X86_64 -- usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; -+ usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; - #else -- /* do_div() only does unsigned */ -- asm("idivl %2; xor %%edx, %%edx" -- : "=A"(usdiff) -- : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); -+ /* do_div() only does unsigned */ -+ asm("idivl %2; xor %%edx, %%edx" -+ : "=A"(usdiff) -+ : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); - #endif -- do_div(elapsed, 1000); -- usdiff -= elapsed; -- if (usdiff < 0) -- usdiff = -usdiff; -+ do_div(elapsed, 1000); -+ usdiff -= elapsed; -+ if (usdiff < 0) -+ usdiff = -usdiff; -+ } else -+ usdiff = USEC_PER_SEC; /* disable TSC match window below */ - - /* - * Special case: TSC write with a small delta (1 second) of virtual diff --git a/af_key-fix-info-leaks-in-notify-messages.patch b/af_key-fix-info-leaks-in-notify-messages.patch deleted file mode 100644 index 9d20aec0f..000000000 --- a/af_key-fix-info-leaks-in-notify-messages.patch +++ /dev/null @@ -1,37 +0,0 @@ -From a5cc68f3d63306d0d288f31edfc2ae6ef8ecd887 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Wed, 26 Jun 2013 21:52:30 +0000 -Subject: af_key: fix info leaks in notify messages - -key_notify_sa_flush() and key_notify_policy_flush() miss to initialize -the sadb_msg_reserved member of the broadcasted message and thereby -leak 2 bytes of heap memory to listeners. Fix that. - -Signed-off-by: Mathias Krause -Cc: Steffen Klassert -Cc: "David S. Miller" -Cc: Herbert Xu -Signed-off-by: David S. Miller ---- -diff --git a/net/key/af_key.c b/net/key/af_key.c -index c5fbd75..9da8620 100644 ---- a/net/key/af_key.c -+++ b/net/key/af_key.c -@@ -1710,6 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c) - hdr->sadb_msg_version = PF_KEY_V2; - hdr->sadb_msg_errno = (uint8_t) 0; - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); -+ hdr->sadb_msg_reserved = 0; - - pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); - -@@ -2699,6 +2700,7 @@ static int key_notify_policy_flush(const struct km_event *c) - hdr->sadb_msg_errno = (uint8_t) 0; - hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); -+ hdr->sadb_msg_reserved = 0; - pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); - return 0; - --- -cgit v0.9.2 diff --git a/arm-omap-ehci-fix.patch b/arm-omap-ehci-fix.patch deleted file mode 100644 index f6fc0a934..000000000 --- a/arm-omap-ehci-fix.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 54a419668b0f27b7982807fb2376d237e0a0ce05 Mon Sep 17 00:00:00 2001 -From: Alan Stern -Date: Tue, 12 Mar 2013 10:44:39 +0000 -Subject: USB: EHCI: split ehci-omap out to a separate driver - -This patch (as1645) converts ehci-omap over to the new "ehci-hcd is a -library" approach, so that it can coexist peacefully with other EHCI -platform drivers and can make use of the private area allocated at -the end of struct ehci_hcd. - -Signed-off-by: Alan Stern -Signed-off-by: Greg Kroah-Hartman ---- -diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index c59a112..62f4e9a 100644 ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -155,7 +155,7 @@ config USB_EHCI_MXC - Variation of ARC USB block used in some Freescale chips. - - config USB_EHCI_HCD_OMAP -- bool "EHCI support for OMAP3 and later chips" -+ tristate "EHCI support for OMAP3 and later chips" - depends on USB_EHCI_HCD && ARCH_OMAP - default y - ---help--- -diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index 001fbff..56de410 100644 ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o - obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o - obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o - obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o -+obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o - - obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o - obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o -diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c -index b416a3f..303b022 100644 ---- a/drivers/usb/host/ehci-hcd.c -+++ b/drivers/usb/host/ehci-hcd.c -@@ -1252,11 +1252,6 @@ MODULE_LICENSE ("GPL"); - #define PLATFORM_DRIVER ehci_hcd_sh_driver - #endif - --#ifdef CONFIG_USB_EHCI_HCD_OMAP --#include "ehci-omap.c" --#define PLATFORM_DRIVER ehci_hcd_omap_driver --#endif -- - #ifdef CONFIG_PPC_PS3 - #include "ehci-ps3.c" - #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver -@@ -1346,6 +1341,7 @@ MODULE_LICENSE ("GPL"); - !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ - !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ - !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ -+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ - !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && \ - !defined(OF_PLATFORM_DRIVER) && \ -diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c -index 0555ee4..fa66757 100644 ---- a/drivers/usb/host/ehci-omap.c -+++ b/drivers/usb/host/ehci-omap.c -@@ -36,6 +36,9 @@ - * - convert to use hwmod and runtime PM - */ - -+#include -+#include -+#include - #include - #include - #include -@@ -43,6 +46,10 @@ - #include - #include - #include -+#include -+#include -+ -+#include "ehci.h" - - #include - -@@ -57,9 +64,11 @@ - #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 - #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 - --/*-------------------------------------------------------------------------*/ -+#define DRIVER_DESC "OMAP-EHCI Host Controller driver" - --static const struct hc_driver ehci_omap_hc_driver; -+static const char hcd_name[] = "ehci-omap"; -+ -+/*-------------------------------------------------------------------------*/ - - - static inline void ehci_write(void __iomem *base, u32 reg, u32 val) -@@ -166,6 +175,12 @@ static void disable_put_regulator( - /* configure so an HC device and id are always provided */ - /* always called with process context; sleeping is OK */ - -+static struct hc_driver __read_mostly ehci_omap_hc_driver; -+ -+static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { -+ .reset = omap_ehci_init, -+}; -+ - /** - * ehci_hcd_omap_probe - initialize TI-based HCDs - * -@@ -315,56 +330,33 @@ static struct platform_driver ehci_hcd_omap_driver = { - /*.suspend = ehci_hcd_omap_suspend, */ - /*.resume = ehci_hcd_omap_resume, */ - .driver = { -- .name = "ehci-omap", -+ .name = hcd_name, - } - }; - - /*-------------------------------------------------------------------------*/ - --static const struct hc_driver ehci_omap_hc_driver = { -- .description = hcd_name, -- .product_desc = "OMAP-EHCI Host Controller", -- .hcd_priv_size = sizeof(struct ehci_hcd), -- -- /* -- * generic hardware linkage -- */ -- .irq = ehci_irq, -- .flags = HCD_MEMORY | HCD_USB2, -- -- /* -- * basic lifecycle operations -- */ -- .reset = omap_ehci_init, -- .start = ehci_run, -- .stop = ehci_stop, -- .shutdown = ehci_shutdown, -- -- /* -- * managing i/o requests and associated device resources -- */ -- .urb_enqueue = ehci_urb_enqueue, -- .urb_dequeue = ehci_urb_dequeue, -- .endpoint_disable = ehci_endpoint_disable, -- .endpoint_reset = ehci_endpoint_reset, -+static int __init ehci_omap_init(void) -+{ -+ if (usb_disabled()) -+ return -ENODEV; - -- /* -- * scheduling support -- */ -- .get_frame_number = ehci_get_frame, -+ pr_info("%s: " DRIVER_DESC "\n", hcd_name); - -- /* -- * root hub support -- */ -- .hub_status_data = ehci_hub_status_data, -- .hub_control = ehci_hub_control, -- .bus_suspend = ehci_bus_suspend, -- .bus_resume = ehci_bus_resume, -+ ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); -+ return platform_driver_register(&ehci_hcd_omap_driver); -+} -+module_init(ehci_omap_init); - -- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, --}; -+static void __exit ehci_omap_cleanup(void) -+{ -+ platform_driver_unregister(&ehci_hcd_omap_driver); -+} -+module_exit(ehci_omap_cleanup); - - MODULE_ALIAS("platform:ehci-omap"); - MODULE_AUTHOR("Texas Instruments, Inc."); - MODULE_AUTHOR("Felipe Balbi "); - -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE("GPL"); --- -cgit v0.9.1 diff --git a/arm-tegra-fixclk.patch b/arm-tegra-fixclk.patch deleted file mode 100644 index df0991293..000000000 --- a/arm-tegra-fixclk.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c -index 788486e..2f4d0e3 100644 ---- a/drivers/clk/tegra/clk-periph.c -+++ b/drivers/clk/tegra/clk-periph.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include "clk.h" - -@@ -128,6 +129,7 @@ void tegra_periph_reset_deassert(struct clk *c) - - tegra_periph_reset(gate, 0); - } -+EXPORT_SYMBOL_GPL(tegra_periph_reset_deassert); - - void tegra_periph_reset_assert(struct clk *c) - { -@@ -147,6 +149,7 @@ void tegra_periph_reset_assert(struct clk *c) - - tegra_periph_reset(gate, 1); - } -+EXPORT_SYMBOL_GPL(tegra_periph_reset_assert); - - const struct clk_ops tegra_clk_periph_ops = { - .get_parent = clk_periph_get_parent, diff --git a/config-debug b/config-debug index ad06116c7..e7f7ce147 100644 --- a/config-debug +++ b/config-debug @@ -117,3 +117,7 @@ CONFIG_MAC80211_MESSAGE_TRACING=y CONFIG_EDAC_DEBUG=y CONFIG_LATENCYTOP=y CONFIG_SCHEDSTATS=y + +CONFIG_TEST_STRING_HELPERS=m +CONFIG_XFS_WARN=y + diff --git a/config-generic b/config-generic index 77d8e89ce..e80eb3172 100644 --- a/config-generic +++ b/config-generic @@ -188,6 +188,7 @@ CONFIG_FW_LOADER=y # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_EXTRA_FIRMWARE="" +# Give this a try in rawhide for now # CONFIG_FW_LOADER_USER_HELPER is not set # CONFIG_CMA is not set @@ -2309,7 +2310,6 @@ CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m CONFIG_SENSORS_MAX6697=m CONFIG_SENSORS_MCP3021=m -CONFIG_SENSORS_NCT6775=m CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m @@ -3999,7 +3999,8 @@ CONFIG_SECURITY_SELINUX_AVC_STATS=y # CONFIG_SECURITY_YAMA is not set CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y -# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set +# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004125.html +CONFIG_AUDIT_LOGINUID_IMMUTABLE=y # # Cryptographic options @@ -4712,3 +4713,60 @@ CONFIG_IOMMU_SUPPORT=y # CONFIG_CRYPTO_KEY_TYPE is not set # CONFIG_PGP_LIBRARY is not set # CONFIG_PGP_PRELOAD is not set + + +# F18 3.10 rebase options below + +# CONFIG_ATH6KL_TRACING is not set +CONFIG_BATMAN_ADV_NC=y +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_EDEBUG is not set +CONFIG_BCACHE=m +CONFIG_BINFMT_SCRIPT=y +CONFIG_BOUNCE=y +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +CONFIG_CRYPTO_CMAC=m +# CONFIG_DUMMY_IRQ is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_GPIO_GRGPIO is not set +CONFIG_HID_APPLEIR=m +# CONFIG_INPUT_IMS_PCU is not set +CONFIG_LEDS_LP5562=m +CONFIG_LEDS_TRIGGER_CAMERA=m +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_SI476X_CORE is not set +CONFIG_NETLINK_DIAG=m +CONFIG_NETLINK_MMAP=y +CONFIG_NET_TEAM_MODE_RANDOM=m +# CONFIG_RCU_USER_QS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +CONFIG_RT2800USB_RT55XX=y +# CONFIG_SCSI_UFSHCD_PLATFORM is not set +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_NCT6775=m +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SMS_SIANO_DEBUGFS is not set +# CONFIG_SRAM is not set +# CONFIG_SSBI is not set +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set +CONFIG_USB_DEFAULT_PERSIST=y +CONFIG_USB_PHY=y +CONFIG_USB_RTL8152=m +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_W1_SLAVE_DS2408_READBACK is not set +# CONFIG_SAMSUNG_USB2PHY is not set +# CONFIG_SAMSUNG_USB3PHY is not set +CONFIG_ALX=m +CONFIG_INFINIBAND_ISERT=m +CONFIG_QLCNIC_SRIOV=y +CONFIG_RTL8188EE=m +# CONFIG_SAMSUNG_USBPHY is not set +# CONFIG_TIPC_MEDIA_IB is not set +# CONFIG_USB_DWC2 is not set +CONFIG_VHOST_SCSI=m +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_SYSCON is not set diff --git a/config-nodebug b/config-nodebug index 6db2dde22..12ecfcc29 100644 --- a/config-nodebug +++ b/config-nodebug @@ -119,3 +119,7 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y # CONFIG_SPI_DEBUG is not set # CONFIG_LATENCYTOP is not set # CONFIG_SCHEDSTATS is not set + +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_XFS_WARN is not set + diff --git a/config-powerpc-generic b/config-powerpc-generic index b6df88ea8..e8617230e 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -392,3 +392,5 @@ CONFIG_BACKLIGHT_PWM=m CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=n CONFIG_XZ_DEC_POWERPC=y + +# CONFIG_POWERNV_MSI is not set diff --git a/config-powerpc64 b/config-powerpc64 index d0e0aab5b..02a44d888 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -181,3 +181,6 @@ CONFIG_BPF_JIT=y # CONFIG_PPC_TRANSACTIONAL_MEM is not set # CONFIG_SND_HDA_INTEL is not set CONFIG_BLK_DEV_RSXX=m + +CONFIG_POWERNV_MSI=y +CONFIG_KVM_XICS=y diff --git a/config-powerpc64p7 b/config-powerpc64p7 index 285d9fff9..ff4471037 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -171,3 +171,6 @@ CONFIG_BPF_JIT=y # CONFIG_PCIEPORTBUS is not set # CONFIG_SND_HDA_INTEL is not set CONFIG_BLK_DEV_RSXX=m + +CONFIG_POWERNV_MSI=y +CONFIG_KVM_XICS=y diff --git a/config-x86-generic b/config-x86-generic index 89bb5b0ef..911455e40 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -448,14 +448,27 @@ CONFIG_XZ_DEC_X86=y CONFIG_MPILIB=y CONFIG_PKCS7_MESSAGE_PARSER=y CONFIG_EFI_SIGNATURE_LIST_PARSER=y +CONFIG_PE_FILE_PARSER=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_ALL=y # CONFIG_MODULE_SIG_SHA1 is not set CONFIG_MODULE_SIG_SHA256=y # CONFIG_MODULE_SIG_FORCE is not set CONFIG_MODULE_SIG_BLACKLIST=y +CONFIG_SYSTEM_BLACKLIST_KEYRING=y CONFIG_MODULE_SIG_UEFI=y CONFIG_VMXNET3=m CONFIG_VFIO_PCI_VGA=y + +CONFIG_EFIVAR_FS=y +CONFIG_HYPERVISOR_GUEST=y +CONFIG_KVM_DEVICE_ASSIGNMENT=y +CONFIG_NFC_MEI_PHY=m +CONFIG_PVPANIC=m +CONFIG_X86_AMD_FREQ_SENSITIVITY=m +CONFIG_FB_HYPERV=m +CONFIG_NFC_MICROREAD_MEI=m +CONFIG_NFC_PN544_MEI=m + diff --git a/config-x86_64-generic b/config-x86_64-generic index 67ac161f3..0c460722f 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -97,6 +97,7 @@ CONFIG_XEN_MAX_DOMAIN_MEMORY=128 CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y # CONFIG_XEN_MCE_LOG is not set +# CONFIG_XEN_STUB is not set CONFIG_PROVIDE_OHCI1394_DMA_INIT=y @@ -133,6 +134,11 @@ CONFIG_BPF_JIT=y CONFIG_NTB=m CONFIG_NTB_NETDEV=m +CONFIG_SFC=m +CONFIG_SFC_MCDI_MON=y +CONFIG_SFC_SRIOV=y +CONFIG_SFC_PTP=y + # 10GigE # CONFIG_IP1000=m @@ -148,3 +154,8 @@ CONFIG_SFC_MTD=y CONFIG_MTD_CHAR=m CONFIG_MTD_BLOCK=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m +CONFIG_CRYPTO_SHA256_SSSE3=m +CONFIG_CRYPTO_SHA512_SSSE3=m + diff --git a/cve-2013-4125.patch b/cve-2013-4125.patch deleted file mode 100644 index 25b7eca42..000000000 --- a/cve-2013-4125.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 307f2fb95e9b96b3577916e73d92e104f8f26494 Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Fri, 12 Jul 2013 21:46:33 +0000 -Subject: ipv6: only static routes qualify for equal cost multipathing - -Static routes in this case are non-expiring routes which did not get -configured by autoconf or by icmpv6 redirects. - -To make sure we actually get an ecmp route while searching for the first -one in this fib6_node's leafs, also make sure it matches the ecmp route -assumptions. - -v2: -a) Removed RTF_EXPIRE check in dst.from chain. The check of RTF_ADDRCONF - already ensures that this route, even if added again without - RTF_EXPIRES (in case of a RA announcement with infinite timeout), - does not cause the rt6i_nsiblings logic to go wrong if a later RA - updates the expiration time later. - -v3: -a) Allow RTF_EXPIRES routes to enter the ecmp route set. We have to do so, - because an pmtu event could update the RTF_EXPIRES flag and we would - not count this route, if another route joins this set. We now filter - only for RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC, which are flags that - don't get changed after rt6_info construction. - -Cc: Nicolas Dichtel -Signed-off-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- -diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c -index 192dd1a..5fc9c7a 100644 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -632,6 +632,12 @@ insert_above: - return ln; - } - -+static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) -+{ -+ return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) == -+ RTF_GATEWAY; -+} -+ - /* - * Insert routing information in a node. - */ -@@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - int add = (!info->nlh || - (info->nlh->nlmsg_flags & NLM_F_CREATE)); - int found = 0; -+ bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); - - ins = &fn->leaf; - -@@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - * To avoid long list, we only had siblings if the - * route have a gateway. - */ -- if (rt->rt6i_flags & RTF_GATEWAY && -- !(rt->rt6i_flags & RTF_EXPIRES) && -- !(iter->rt6i_flags & RTF_EXPIRES)) -+ if (rt_can_ecmp && -+ rt6_qualify_for_ecmp(iter)) - rt->rt6i_nsiblings++; - } - -@@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - /* Find the first route that have the same metric */ - sibling = fn->leaf; - while (sibling) { -- if (sibling->rt6i_metric == rt->rt6i_metric) { -+ if (sibling->rt6i_metric == rt->rt6i_metric && -+ rt6_qualify_for_ecmp(sibling)) { - list_add_tail(&rt->rt6i_siblings, - &sibling->rt6i_siblings); - break; --- -cgit v0.9.2 diff --git a/debug-bad-pte-dmi.patch b/debug-bad-pte-dmi.patch deleted file mode 100644 index eddd595b0..000000000 --- a/debug-bad-pte-dmi.patch +++ /dev/null @@ -1,66 +0,0 @@ ---- linux.orig/include/asm-generic/bug.h -+++ linux/include/asm-generic/bug.h -@@ -55,6 +55,8 @@ struct bug_entry { - #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) - #endif - -+void print_hardware_dmi_name(void); -+ - /* - * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report - * significant issues that need prompt attention if they should ever ---- linux.orig/kernel/panic.c -+++ linux/kernel/panic.c -@@ -391,6 +391,15 @@ void oops_exit(void) - kmsg_dump(KMSG_DUMP_OOPS); - } - -+void print_hardware_dmi_name(void) -+{ -+ const char *board; -+ -+ board = dmi_get_system_info(DMI_PRODUCT_NAME); -+ if (board) -+ printk(KERN_WARNING "Hardware name: %s\n", board); -+} -+ - #ifdef WANT_WARN_ON_SLOWPATH - struct slowpath_args { - const char *fmt; -@@ -400,13 +409,10 @@ struct slowpath_args { - static void warn_slowpath_common(const char *file, int line, void *caller, - unsigned taint, struct slowpath_args *args) - { -- const char *board; -- - printk(KERN_WARNING "------------[ cut here ]------------\n"); - printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); -- board = dmi_get_system_info(DMI_PRODUCT_NAME); -- if (board) -- printk(KERN_WARNING "Hardware name: %s\n", board); -+ -+ print_hardware_dmi_name(); - - if (args) - vprintk(args->fmt, args->args); ---- linux.orig/mm/memory.c -+++ linux/mm/memory.c -@@ -706,6 +706,8 @@ static void print_bad_pte(struct vm_area - "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", - current->comm, - (long long)pte_val(pte), (long long)pmd_val(*pmd)); -+ print_hardware_dmi_name(); -+ - if (page) - dump_page(page); - printk(KERN_ALERT ---- linux.orig/mm/page_alloc.c -+++ linux/mm/page_alloc.c -@@ -321,6 +321,7 @@ static void bad_page(struct page *page) - current->comm, page_to_pfn(page)); - dump_page(page); - -+ print_hardware_dmi_name(); - print_modules(); - dump_stack(); - out: diff --git a/debug-bad-pte-modules.patch b/debug-bad-pte-modules.patch deleted file mode 100644 index 0cc7d550e..000000000 --- a/debug-bad-pte-modules.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -durpN '--exclude-from=/home/davej/.exclude' /home/davej/src/kernel/git-trees/linux/mm/memory.c linux-dj/mm/memory.c ---- /home/davej/src/kernel/git-trees/linux/mm/memory.c 2013-02-26 14:41:18.591116577 -0500 -+++ linux-dj/mm/memory.c 2013-02-28 20:04:37.678304092 -0500 -@@ -57,6 +57,7 @@ - #include - #include - #include -+#include - #include - #include - ---- linux-3.9.0-200.fc18.x86_64/mm/memory.c~ 2013-05-06 15:04:30.324416922 -0400 -+++ linux-3.9.0-200.fc18.x86_64/mm/memory.c 2013-05-06 15:04:43.933398227 -0400 -@@ -723,6 +723,7 @@ static void print_bad_pte(struct vm_area - if (vma->vm_file && vma->vm_file->f_op) - print_symbol(KERN_ALERT "vma->vm_file->f_op->mmap: %s\n", - (unsigned long)vma->vm_file->f_op->mmap); -+ print_modules(); - dump_stack(); - add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); - } diff --git a/devel-pekey-secure-boot-20130502.patch b/devel-pekey-secure-boot-20130502.patch new file mode 100644 index 000000000..703bbf5ad --- /dev/null +++ b/devel-pekey-secure-boot-20130502.patch @@ -0,0 +1,5912 @@ +From 888c361d20210d39863ba6f2b71adb84e0a926a7 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 Jan 2013 13:53:35 +0000 +Subject: [PATCH 01/47] KEYS: Load *.x509 files into kernel keyring + +Load all the files matching the pattern "*.x509" that are to be found in kernel +base source dir and base build dir into the module signing keyring. + +The "extra_certificates" file is then redundant. + +Signed-off-by: David Howells +--- + kernel/Makefile | 35 +++++++++++++++++++++++++++++------ + kernel/modsign_certificate.S | 3 +-- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index d1574d4..64c97da 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -141,17 +141,40 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE + $(call if_changed,bc) + + ifeq ($(CONFIG_MODULE_SIG),y) ++############################################################################### + # +-# Pull the signing certificate and any extra certificates into the kernel ++# Roll all the X.509 certificates that we can find together and pull ++# them into the kernel. + # ++############################################################################### ++X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) ++X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 ++X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) ++ ++ifeq ($(X509_CERTIFICATES),) ++$(warning *** No X.509 certificates found ***) ++endif ++ ++ifneq ($(wildcard $(obj)/.x509.list),) ++ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES)) ++$(info X.509 certificate list changed) ++$(shell rm $(obj)/.x509.list) ++endif ++endif ++ ++kernel/modsign_certificate.o: $(obj)/x509_certificate_list + +-quiet_cmd_touch = TOUCH $@ +- cmd_touch = touch $@ ++quiet_cmd_x509certs = CERTS $@ ++ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ ++targets += $(obj)/x509_certificate_list ++$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list ++ $(call if_changed,x509certs) + +-extra_certificates: +- $(call cmd,touch) ++targets += $(obj)/.x509.list ++$(obj)/.x509.list: ++ @echo $(X509_CERTIFICATES) >$@ + +-kernel/modsign_certificate.o: signing_key.x509 extra_certificates ++clean-files := x509_certificate_list .x509.list + + ############################################################################### + # +diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S +index 246b4c6..0a60203 100644 +--- a/kernel/modsign_certificate.S ++++ b/kernel/modsign_certificate.S +@@ -14,6 +14,5 @@ + .section ".init.data","aw" + + GLOBAL(modsign_certificate_list) +- .incbin "signing_key.x509" +- .incbin "extra_certificates" ++ .incbin "kernel/x509_certificate_list" + GLOBAL(modsign_certificate_list_end) +-- +1.8.1.4 + + +From 26a6bf8ffbe82d706c6de06746d760d9bc425ee5 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 18:39:54 +0000 +Subject: [PATCH 02/47] KEYS: Separate the kernel signature checking keyring + from module signing + +Separate the kernel signature checking keyring from module signing so that it +can be used by code other than the module-signing code. + +Signed-off-by: David Howells +--- + include/keys/system_keyring.h | 23 ++++++++++ + init/Kconfig | 13 ++++++ + kernel/Makefile | 17 ++++--- + kernel/modsign_pubkey.c | 104 ------------------------------------------ + kernel/module-internal.h | 2 - + kernel/module_signing.c | 3 +- + kernel/system_certificates.S | 18 ++++++++ + kernel/system_keyring.c | 101 ++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 168 insertions(+), 113 deletions(-) + create mode 100644 include/keys/system_keyring.h + delete mode 100644 kernel/modsign_pubkey.c + create mode 100644 kernel/system_certificates.S + create mode 100644 kernel/system_keyring.c + +diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h +new file mode 100644 +index 0000000..8dabc39 +--- /dev/null ++++ b/include/keys/system_keyring.h +@@ -0,0 +1,23 @@ ++/* System keyring containing trusted public keys. ++ * ++ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifndef _KEYS_SYSTEM_KEYRING_H ++#define _KEYS_SYSTEM_KEYRING_H ++ ++#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING ++ ++#include ++ ++extern struct key *system_trusted_keyring; ++ ++#endif ++ ++#endif /* _KEYS_SYSTEM_KEYRING_H */ +diff --git a/init/Kconfig b/init/Kconfig +index a76d131..b9d8870 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1615,6 +1615,18 @@ config BASE_SMALL + default 0 if BASE_FULL + default 1 if !BASE_FULL + ++config SYSTEM_TRUSTED_KEYRING ++ bool "Provide system-wide ring of trusted keys" ++ depends on KEYS ++ help ++ Provide a system keyring to which trusted keys can be added. Keys in ++ the keyring are considered to be trusted. Keys may be added at will ++ by the kernel from compiled-in data and from hardware key stores, but ++ userspace may only add extra keys if those keys can be verified by ++ keys already in the keyring. ++ ++ Keys in this keyring are used by module signature checking. ++ + menuconfig MODULES + bool "Enable loadable module support" + help +@@ -1687,6 +1699,7 @@ config MODULE_SRCVERSION_ALL + config MODULE_SIG + bool "Module signature verification" + depends on MODULES ++ select SYSTEM_TRUSTED_KEYRING + select KEYS + select CRYPTO + select ASYMMETRIC_KEY_TYPE +diff --git a/kernel/Makefile b/kernel/Makefile +index 64c97da..ecff938 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -52,8 +52,9 @@ obj-$(CONFIG_SMP) += spinlock.o + obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o ++obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o + obj-$(CONFIG_MODULES) += module.o +-obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -140,13 +141,14 @@ targets += timeconst.h + $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE + $(call if_changed,bc) + +-ifeq ($(CONFIG_MODULE_SIG),y) + ############################################################################### + # +-# Roll all the X.509 certificates that we can find together and pull +-# them into the kernel. ++# Roll all the X.509 certificates that we can find together and pull them into ++# the kernel so that they get loaded into the system trusted keyring during ++# boot. + # + ############################################################################### ++ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) + X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) + X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 + X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) +@@ -162,10 +164,11 @@ $(shell rm $(obj)/.x509.list) + endif + endif + +-kernel/modsign_certificate.o: $(obj)/x509_certificate_list ++kernel/system_certificates.o: $(obj)/x509_certificate_list + + quiet_cmd_x509certs = CERTS $@ +- cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ ++ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") ++ + targets += $(obj)/x509_certificate_list + $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list + $(call if_changed,x509certs) +@@ -175,7 +178,9 @@ $(obj)/.x509.list: + @echo $(X509_CERTIFICATES) >$@ + + clean-files := x509_certificate_list .x509.list ++endif + ++ifeq ($(CONFIG_MODULE_SIG),y) + ############################################################################### + # + # If module signing is requested, say by allyesconfig, but a key has not been +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +deleted file mode 100644 +index 2b6e699..0000000 +--- a/kernel/modsign_pubkey.c ++++ /dev/null +@@ -1,104 +0,0 @@ +-/* Public keys for module signature verification +- * +- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. +- * Written by David Howells (dhowells@redhat.com) +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public Licence +- * as published by the Free Software Foundation; either version +- * 2 of the Licence, or (at your option) any later version. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include "module-internal.h" +- +-struct key *modsign_keyring; +- +-extern __initdata const u8 modsign_certificate_list[]; +-extern __initdata const u8 modsign_certificate_list_end[]; +- +-/* +- * We need to make sure ccache doesn't cache the .o file as it doesn't notice +- * if modsign.pub changes. +- */ +-static __initdata const char annoy_ccache[] = __TIME__ "foo"; +- +-/* +- * Load the compiled-in keys +- */ +-static __init int module_verify_init(void) +-{ +- pr_notice("Initialise module verification\n"); +- +- modsign_keyring = keyring_alloc(".module_sign", +- KUIDT_INIT(0), KGIDT_INIT(0), +- current_cred(), +- ((KEY_POS_ALL & ~KEY_POS_SETATTR) | +- KEY_USR_VIEW | KEY_USR_READ), +- KEY_ALLOC_NOT_IN_QUOTA, NULL); +- if (IS_ERR(modsign_keyring)) +- panic("Can't allocate module signing keyring\n"); +- +- return 0; +-} +- +-/* +- * Must be initialised before we try and load the keys into the keyring. +- */ +-device_initcall(module_verify_init); +- +-/* +- * Load the compiled-in keys +- */ +-static __init int load_module_signing_keys(void) +-{ +- key_ref_t key; +- const u8 *p, *end; +- size_t plen; +- +- pr_notice("Loading module verification certificates\n"); +- +- end = modsign_certificate_list_end; +- p = modsign_certificate_list; +- while (p < end) { +- /* Each cert begins with an ASN.1 SEQUENCE tag and must be more +- * than 256 bytes in size. +- */ +- if (end - p < 4) +- goto dodgy_cert; +- if (p[0] != 0x30 && +- p[1] != 0x82) +- goto dodgy_cert; +- plen = (p[2] << 8) | p[3]; +- plen += 4; +- if (plen > end - p) +- goto dodgy_cert; +- +- key = key_create_or_update(make_key_ref(modsign_keyring, 1), +- "asymmetric", +- NULL, +- p, +- plen, +- (KEY_POS_ALL & ~KEY_POS_SETATTR) | +- KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA); +- if (IS_ERR(key)) +- pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", +- PTR_ERR(key)); +- else +- pr_notice("MODSIGN: Loaded cert '%s'\n", +- key_ref_to_ptr(key)->description); +- p += plen; +- } +- +- return 0; +- +-dodgy_cert: +- pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); +- return 0; +-} +-late_initcall(load_module_signing_keys); +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 24f9247..915e123 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -9,6 +9,4 @@ + * 2 of the Licence, or (at your option) any later version. + */ + +-extern struct key *modsign_keyring; +- + extern int mod_verify_sig(const void *mod, unsigned long *_modlen); +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index f2970bd..0034e36 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include "module-internal.h" + + /* +@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + +- key = keyring_search(make_key_ref(modsign_keyring, 1), ++ key = keyring_search(make_key_ref(system_trusted_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) + pr_warn("Request for unknown module key '%s' err %ld\n", +diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S +new file mode 100644 +index 0000000..86240df +--- /dev/null ++++ b/kernel/system_certificates.S +@@ -0,0 +1,18 @@ ++/* SYMBOL_PREFIX defined on commandline from CONFIG_SYMBOL_PREFIX */ ++#ifndef SYMBOL_PREFIX ++#define ASM_SYMBOL(sym) sym ++#else ++#define PASTE2(x,y) x##y ++#define PASTE(x,y) PASTE2(x,y) ++#define ASM_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym) ++#endif ++ ++#define GLOBAL(name) \ ++ .globl ASM_SYMBOL(name); \ ++ ASM_SYMBOL(name): ++ ++ .section ".init.data","aw" ++ ++GLOBAL(system_certificate_list) ++ .incbin "kernel/x509_certificate_list" ++GLOBAL(system_certificate_list_end) +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +new file mode 100644 +index 0000000..a3ca76f +--- /dev/null ++++ b/kernel/system_keyring.c +@@ -0,0 +1,101 @@ ++/* System trusted keyring for trusted public keys ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++struct key *system_trusted_keyring; ++EXPORT_SYMBOL_GPL(system_trusted_keyring); ++ ++extern __initdata const u8 system_certificate_list[]; ++extern __initdata const u8 system_certificate_list_end[]; ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int system_trusted_keyring_init(void) ++{ ++ pr_notice("Initialise system trusted keyring\n"); ++ ++ system_trusted_keyring = ++ keyring_alloc(".system_keyring", ++ KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ++ ((KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ), ++ KEY_ALLOC_NOT_IN_QUOTA, NULL); ++ if (IS_ERR(system_trusted_keyring)) ++ panic("Can't allocate system trusted keyring\n"); ++ ++ return 0; ++} ++ ++/* ++ * Must be initialised before we try and load the keys into the keyring. ++ */ ++device_initcall(system_trusted_keyring_init); ++ ++/* ++ * Load the compiled-in list of X.509 certificates. ++ */ ++static __init int load_system_certificate_list(void) ++{ ++ key_ref_t key; ++ const u8 *p, *end; ++ size_t plen; ++ ++ pr_notice("Loading compiled-in X.509 certificates\n"); ++ ++ end = system_certificate_list_end; ++ p = system_certificate_list; ++ while (p < end) { ++ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more ++ * than 256 bytes in size. ++ */ ++ if (end - p < 4) ++ goto dodgy_cert; ++ if (p[0] != 0x30 && ++ p[1] != 0x82) ++ goto dodgy_cert; ++ plen = (p[2] << 8) | p[3]; ++ plen += 4; ++ if (plen > end - p) ++ goto dodgy_cert; ++ ++ key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), ++ "asymmetric", ++ NULL, ++ p, ++ plen, ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(key)) ++ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("Loaded X.509 cert '%s'\n", ++ key_ref_to_ptr(key)->description); ++ p += plen; ++ } ++ ++ return 0; ++ ++dodgy_cert: ++ pr_err("Problem parsing in-kernel X.509 certificate list\n"); ++ return 0; ++} ++late_initcall(load_system_certificate_list); +-- +1.8.1.4 + + +From 4e2b0f425d73360fc40b8719b36e6e3ca94d458e Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 17 Jan 2013 16:25:00 +0000 +Subject: [PATCH 03/47] KEYS: Add a 'trusted' flag and a 'trusted only' flag + +Add KEY_FLAG_TRUSTED to indicate that a key either comes from a trusted source +or had a cryptographic signature chain that led back to a trusted key the +kernel already possessed. + +Add KEY_FLAGS_TRUSTED_ONLY to indicate that a keyring will only accept links to +keys marked with KEY_FLAGS_TRUSTED. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + include/linux/key-type.h | 1 + + include/linux/key.h | 3 +++ + kernel/system_keyring.c | 4 +++- + security/keys/key.c | 8 ++++++++ + security/keys/keyring.c | 4 ++++ + 5 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/include/linux/key-type.h b/include/linux/key-type.h +index 518a53a..f942b2d 100644 +--- a/include/linux/key-type.h ++++ b/include/linux/key-type.h +@@ -45,6 +45,7 @@ struct key_preparsed_payload { + const void *data; /* Raw data */ + size_t datalen; /* Raw datalen */ + size_t quotalen; /* Quota length for proposed payload */ ++ bool trusted; /* True if key is trusted */ + }; + + typedef int (*request_key_actor_t)(struct key_construction *key, +diff --git a/include/linux/key.h b/include/linux/key.h +index 4dfde11..0b32a09 100644 +--- a/include/linux/key.h ++++ b/include/linux/key.h +@@ -162,6 +162,8 @@ struct key { + #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ + #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ + #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ ++#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ ++#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ + + /* the description string + * - this is used to match a key against search criteria +@@ -203,6 +205,7 @@ extern struct key *key_alloc(struct key_type *type, + #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ + #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ + #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ ++#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ + + extern void key_revoke(struct key *key); + extern void key_invalidate(struct key *key); +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +index a3ca76f..dae8778 100644 +--- a/kernel/system_keyring.c ++++ b/kernel/system_keyring.c +@@ -40,6 +40,7 @@ static __init int system_trusted_keyring_init(void) + if (IS_ERR(system_trusted_keyring)) + panic("Can't allocate system trusted keyring\n"); + ++ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); + return 0; + } + +@@ -82,7 +83,8 @@ static __init int load_system_certificate_list(void) + plen, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA); ++ KEY_ALLOC_NOT_IN_QUOTA | ++ KEY_ALLOC_TRUSTED); + if (IS_ERR(key)) + pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", + PTR_ERR(key)); +diff --git a/security/keys/key.c b/security/keys/key.c +index 8fb7c7b..f3de9e4 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -299,6 +299,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, + + if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) + key->flags |= 1 << KEY_FLAG_IN_QUOTA; ++ if (flags & KEY_ALLOC_TRUSTED) ++ key->flags |= 1 << KEY_FLAG_TRUSTED; + + memset(&key->type_data, 0, sizeof(key->type_data)); + +@@ -813,6 +815,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + prep.data = payload; + prep.datalen = plen; + prep.quotalen = ktype->def_datalen; ++ prep.trusted = flags & KEY_ALLOC_TRUSTED; + if (ktype->preparse) { + ret = ktype->preparse(&prep); + if (ret < 0) { +@@ -826,6 +829,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + goto error_free_prep; + } + ++ key_ref = ERR_PTR(-EPERM); ++ if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) ++ goto error_free_prep; ++ flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; ++ + ret = __key_link_begin(keyring, ktype, description, &prealloc); + if (ret < 0) { + key_ref = ERR_PTR(ret); +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 6ece7f2..f18d7ff 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -1006,6 +1006,10 @@ int key_link(struct key *keyring, struct key *key) + key_check(keyring); + key_check(key); + ++ if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && ++ !test_bit(KEY_FLAG_TRUSTED, &key->flags)) ++ return -EPERM; ++ + ret = __key_link_begin(keyring, key->type, key->description, &prealloc); + if (ret == 0) { + ret = __key_link_check_live_key(keyring, key); +-- +1.8.1.4 + + +From 3deae827abdd3de9b7976b423279812d7559e580 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:32 +0000 +Subject: [PATCH 04/47] KEYS: Rename public key parameter name arrays + +Rename the arrays of public key parameters (public key algorithm names, hash +algorithm names and ID type names) so that the array name ends in "_name". + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/public_key.c | 14 +++++++------- + crypto/asymmetric_keys/x509_public_key.c | 8 ++++---- + include/crypto/public_key.h | 6 +++--- + kernel/module_signing.c | 4 ++-- + 4 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index cb2e291..b313df1 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -22,13 +22,13 @@ + + MODULE_LICENSE("GPL"); + +-const char *const pkey_algo[PKEY_ALGO__LAST] = { ++const char *const pkey_algo_name[PKEY_ALGO__LAST] = { + [PKEY_ALGO_DSA] = "DSA", + [PKEY_ALGO_RSA] = "RSA", + }; +-EXPORT_SYMBOL_GPL(pkey_algo); ++EXPORT_SYMBOL_GPL(pkey_algo_name); + +-const char *const pkey_hash_algo[PKEY_HASH__LAST] = { ++const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { + [PKEY_HASH_MD4] = "md4", + [PKEY_HASH_MD5] = "md5", + [PKEY_HASH_SHA1] = "sha1", +@@ -38,13 +38,13 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = { + [PKEY_HASH_SHA512] = "sha512", + [PKEY_HASH_SHA224] = "sha224", + }; +-EXPORT_SYMBOL_GPL(pkey_hash_algo); ++EXPORT_SYMBOL_GPL(pkey_hash_algo_name); + +-const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { ++const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { + [PKEY_ID_PGP] = "PGP", + [PKEY_ID_X509] = "X509", + }; +-EXPORT_SYMBOL_GPL(pkey_id_type); ++EXPORT_SYMBOL_GPL(pkey_id_type_name); + + /* + * Provide a part of a description of the key for /proc/keys. +@@ -56,7 +56,7 @@ static void public_key_describe(const struct key *asymmetric_key, + + if (key) + seq_printf(m, "%s.%s", +- pkey_id_type[key->id_type], key->algo->name); ++ pkey_id_type_name[key->id_type], key->algo->name); + } + + /* +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 06007f0..afbbc36 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -49,7 +49,7 @@ static int x509_check_signature(const struct public_key *pub, + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + +@@ -117,7 +117,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); +- pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, + cert->valid_from.tm_mday, cert->valid_from.tm_hour, +@@ -127,8 +127,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->valid_to.tm_mday, cert->valid_to.tm_hour, + cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", +- pkey_algo[cert->sig_pkey_algo], +- pkey_hash_algo[cert->sig_hash_algo]); ++ pkey_algo_name[cert->sig_pkey_algo], ++ pkey_hash_algo_name[cert->sig_hash_algo]); + + if (!cert->fingerprint || !cert->authority) { + pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index f5b0224..619d570 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -22,7 +22,7 @@ enum pkey_algo { + PKEY_ALGO__LAST + }; + +-extern const char *const pkey_algo[PKEY_ALGO__LAST]; ++extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; + + enum pkey_hash_algo { + PKEY_HASH_MD4, +@@ -36,7 +36,7 @@ enum pkey_hash_algo { + PKEY_HASH__LAST + }; + +-extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; ++extern const char *const pkey_hash_algo_name[PKEY_HASH__LAST]; + + enum pkey_id_type { + PKEY_ID_PGP, /* OpenPGP generated key ID */ +@@ -44,7 +44,7 @@ enum pkey_id_type { + PKEY_ID_TYPE__LAST + }; + +-extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; ++extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; + + /* + * Cryptographic data for the public-key subtype of the asymmetric key type. +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 0034e36..0b6b870 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -55,7 +55,7 @@ static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[hash], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); + +@@ -218,7 +218,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) + return -ENOPKG; + + if (ms.hash >= PKEY_HASH__LAST || +- !pkey_hash_algo[ms.hash]) ++ !pkey_hash_algo_name[ms.hash]) + return -ENOPKG; + + key = request_asymmetric_key(sig, ms.signer_len, +-- +1.8.1.4 + + +From 2acf1a703de1213ad85515a71873f57535dc057d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:33 +0000 +Subject: [PATCH 05/47] KEYS: Move the algorithm pointer array from x509 to + public_key.c + +Move the public-key algorithm pointer array from x509_public_key.c to +public_key.c as it isn't X.509 specific. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/public_key.c | 8 ++++++++ + crypto/asymmetric_keys/x509_public_key.c | 11 +---------- + include/crypto/public_key.h | 1 + + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index b313df1..796ce08 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -28,6 +28,14 @@ const char *const pkey_algo_name[PKEY_ALGO__LAST] = { + }; + EXPORT_SYMBOL_GPL(pkey_algo_name); + ++const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { ++#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ ++ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) ++ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, ++#endif ++}; ++EXPORT_SYMBOL_GPL(pkey_algo); ++ + const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { + [PKEY_HASH_MD4] = "md4", + [PKEY_HASH_MD5] = "md5", +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index afbbc36..fe38628 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -23,15 +23,6 @@ + #include "public_key.h" + #include "x509_parser.h" + +-static const +-struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { +- [PKEY_ALGO_DSA] = NULL, +-#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ +- defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) +- [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, +-#endif +-}; +- + /* + * Check the signature on a certificate using the provided public key + */ +@@ -174,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; ++ cert->pub->algo = pkey_algo[cert->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + + /* Check the signature on the key */ +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 619d570..46bde25 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -23,6 +23,7 @@ enum pkey_algo { + }; + + extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; ++extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST]; + + enum pkey_hash_algo { + PKEY_HASH_MD4, +-- +1.8.1.4 + + +From 3cc2c6f01277dfa00106c3e4f3f3ab8184025b90 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:33 +0000 +Subject: [PATCH 06/47] KEYS: Store public key algo ID in public_key struct + +Store public key algo ID in public_key struct for reference purposes. This +allows it to be removed from the x509_certificate struct and used to find a +default in public_key_verify_signature(). + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509_cert_parser.c | 5 +++-- + crypto/asymmetric_keys/x509_parser.h | 1 - + crypto/asymmetric_keys/x509_public_key.c | 4 ++-- + include/crypto/public_key.h | 1 + + 4 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 7fabc4c..a583930 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -343,8 +343,9 @@ int x509_extract_key_data(void *context, size_t hdrlen, + if (ctx->last_oid != OID_rsaEncryption) + return -ENOPKG; + +- /* There seems to be an extraneous 0 byte on the front of the data */ +- ctx->cert->pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; ++ ++ /* Discard the BIT STRING metadata */ + ctx->key = value + 1; + ctx->key_size = vlen - 1; + return 0; +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index f86dc5f..e583ad0 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -20,7 +20,6 @@ struct x509_certificate { + char *authority; /* Authority key fingerprint as hex */ + struct tm valid_from; + struct tm valid_to; +- enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ + const void *tbs; /* Signed data */ +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index fe38628..fac574c 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -108,7 +108,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); +- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, + cert->valid_from.tm_mday, cert->valid_from.tm_hour, +@@ -165,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- cert->pub->algo = pkey_algo[cert->pkey_algo]; ++ cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + + /* Check the signature on the key */ +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 46bde25..05778df 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -60,6 +60,7 @@ struct public_key { + #define PKEY_CAN_DECRYPT 0x02 + #define PKEY_CAN_SIGN 0x04 + #define PKEY_CAN_VERIFY 0x08 ++ enum pkey_algo pkey_algo : 8; + enum pkey_id_type id_type : 8; + union { + MPI mpi[5]; +-- +1.8.1.4 + + +From 7dcc63793a873198d3b3c4299f896e2896292d84 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:34 +0000 +Subject: [PATCH 07/47] KEYS: Split public_key_verify_signature() and make + available + +Modify public_key_verify_signature() so that it now takes a public_key struct +rather than a key struct and supply a wrapper that takes a key struct. The +wrapper is then used by the asymmetric key subtype and the modified function is +used by X.509 self-signature checking and can be used by PKCS#7 also. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/public_key.c | 40 +++++++++++++++++++++++++------- + crypto/asymmetric_keys/public_key.h | 6 +++++ + crypto/asymmetric_keys/x509_public_key.c | 2 +- + 3 files changed, 39 insertions(+), 9 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index 796ce08..49ac8d8 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -86,21 +86,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy); + /* + * Verify a signature using a public key. + */ +-static int public_key_verify_signature(const struct key *key, +- const struct public_key_signature *sig) ++int public_key_verify_signature(const struct public_key *pk, ++ const struct public_key_signature *sig) + { +- const struct public_key *pk = key->payload.data; ++ const struct public_key_algorithm *algo; ++ ++ BUG_ON(!pk); ++ BUG_ON(!pk->mpi[0]); ++ BUG_ON(!pk->mpi[1]); ++ BUG_ON(!sig); ++ BUG_ON(!sig->digest); ++ BUG_ON(!sig->mpi[0]); ++ ++ algo = pk->algo; ++ if (!algo) { ++ if (pk->pkey_algo >= PKEY_ALGO__LAST) ++ return -ENOPKG; ++ algo = pkey_algo[pk->pkey_algo]; ++ if (!algo) ++ return -ENOPKG; ++ } + +- if (!pk->algo->verify_signature) ++ if (!algo->verify_signature) + return -ENOTSUPP; + +- if (sig->nr_mpi != pk->algo->n_sig_mpi) { ++ if (sig->nr_mpi != algo->n_sig_mpi) { + pr_debug("Signature has %u MPI not %u\n", +- sig->nr_mpi, pk->algo->n_sig_mpi); ++ sig->nr_mpi, algo->n_sig_mpi); + return -EINVAL; + } + +- return pk->algo->verify_signature(pk, sig); ++ return algo->verify_signature(pk, sig); ++} ++EXPORT_SYMBOL_GPL(public_key_verify_signature); ++ ++static int public_key_verify_signature_2(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct public_key *pk = key->payload.data; ++ return public_key_verify_signature(pk, sig); + } + + /* +@@ -111,6 +135,6 @@ struct asymmetric_key_subtype public_key_subtype = { + .name = "public_key", + .describe = public_key_describe, + .destroy = public_key_destroy, +- .verify_signature = public_key_verify_signature, ++ .verify_signature = public_key_verify_signature_2, + }; + EXPORT_SYMBOL_GPL(public_key_subtype); +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +index 5e5e356..5c37a22 100644 +--- a/crypto/asymmetric_keys/public_key.h ++++ b/crypto/asymmetric_keys/public_key.h +@@ -28,3 +28,9 @@ struct public_key_algorithm { + }; + + extern const struct public_key_algorithm RSA_public_key_algorithm; ++ ++/* ++ * public_key.c ++ */ ++extern int public_key_verify_signature(const struct public_key *pk, ++ const struct public_key_signature *sig); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index fac574c..8cb2f70 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -76,7 +76,7 @@ static int x509_check_signature(const struct public_key *pub, + if (ret < 0) + goto error_mpi; + +- ret = pub->algo->verify_signature(pub, sig); ++ ret = public_key_verify_signature(pub, sig); + + pr_debug("Cert Verification: %d\n", ret); + +-- +1.8.1.4 + + +From da18477d1a1987dce0f3c5f78b62e5b223e2bf90 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:35 +0000 +Subject: [PATCH 08/47] KEYS: Store public key algo ID in public_key_signature + struct + +Store public key algorithm ID in public_key_signature struct for reference +purposes. This allows a public_key_signature struct to be embedded in +struct x509_certificate and struct pkcs7_message more easily. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + include/crypto/public_key.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 05778df..b34fda4 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -90,6 +90,7 @@ struct public_key_signature { + u8 *digest; + u8 digest_size; /* Number of bytes in digest */ + u8 nr_mpi; /* Occupancy of mpi[] */ ++ enum pkey_algo pkey_algo : 8; + enum pkey_hash_algo pkey_hash_algo : 8; + union { + MPI mpi[2]; +-- +1.8.1.4 + + +From 29d80acc90a95ef5614cf36d4e30835bcc014cc4 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:35 +0000 +Subject: [PATCH 09/47] X.509: struct x509_certificate needs struct tm + declaring + +struct x509_certificate needs struct tm declaring by #inclusion of linux/time.h +prior to its definition. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509_parser.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index e583ad0..2d01182 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -9,6 +9,7 @@ + * 2 of the Licence, or (at your option) any later version. + */ + ++#include + #include + + struct x509_certificate { +-- +1.8.1.4 + + +From ba3ba9e41abb17a7632075668e4f0a30edb59896 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:35 +0000 +Subject: [PATCH 10/47] X.509: Add bits needed for PKCS#7 + +PKCS#7 validation requires access to the serial number and the raw names in an +X.509 certificate. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509.asn1 | 2 +- + crypto/asymmetric_keys/x509_cert_parser.c | 17 +++++++++++++++++ + crypto/asymmetric_keys/x509_parser.h | 10 ++++++++-- + 3 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 +index bf32b3d..aae0cde 100644 +--- a/crypto/asymmetric_keys/x509.asn1 ++++ b/crypto/asymmetric_keys/x509.asn1 +@@ -6,7 +6,7 @@ Certificate ::= SEQUENCE { + + TBSCertificate ::= SEQUENCE { + version [ 0 ] Version DEFAULT, +- serialNumber CertificateSerialNumber, ++ serialNumber CertificateSerialNumber ({ x509_note_serial }), + signature AlgorithmIdentifier ({ x509_note_pkey_algo }), + issuer Name ({ x509_note_issuer }), + validity Validity, +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index a583930..08bebf1 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -209,6 +209,19 @@ int x509_note_signature(void *context, size_t hdrlen, + } + + /* ++ * Note the certificate serial number ++ */ ++int x509_note_serial(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct x509_parse_context *ctx = context; ++ ctx->cert->raw_serial = value; ++ ctx->cert->raw_serial_size = vlen; ++ return 0; ++} ++ ++/* + * Note some of the name segments from which we'll fabricate a name. + */ + int x509_extract_name_segment(void *context, size_t hdrlen, +@@ -320,6 +333,8 @@ int x509_note_issuer(void *context, size_t hdrlen, + const void *value, size_t vlen) + { + struct x509_parse_context *ctx = context; ++ ctx->cert->raw_issuer = value; ++ ctx->cert->raw_issuer_size = vlen; + return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); + } + +@@ -328,6 +343,8 @@ int x509_note_subject(void *context, size_t hdrlen, + const void *value, size_t vlen) + { + struct x509_parse_context *ctx = context; ++ ctx->cert->raw_subject = value; ++ ctx->cert->raw_subject_size = vlen; + return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); + } + +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 2d01182..a6ce46f 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -24,9 +24,15 @@ struct x509_certificate { + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ + const void *tbs; /* Signed data */ +- size_t tbs_size; /* Size of signed data */ ++ unsigned tbs_size; /* Size of signed data */ ++ unsigned sig_size; /* Size of sigature */ + const void *sig; /* Signature data */ +- size_t sig_size; /* Size of sigature */ ++ const void *raw_serial; /* Raw serial number in ASN.1 */ ++ unsigned raw_serial_size; ++ unsigned raw_issuer_size; ++ const void *raw_issuer; /* Raw issuer name in ASN.1 */ ++ const void *raw_subject; /* Raw subject name in ASN.1 */ ++ unsigned raw_subject_size; + }; + + /* +-- +1.8.1.4 + + +From 4d2f837ab3629d5b4b3bac2bbdbdf2d0060e74a8 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:36 +0000 +Subject: [PATCH 11/47] X.509: Embed public_key_signature struct and create + filler function + +Embed a public_key_signature struct in struct x509_certificate, eliminating +now unnecessary fields, and split x509_check_signature() to create a filler +function for it that attaches a digest of the signed data and an MPI that +represents the signature data. x509_free_certificate() is then modified to +deal with these. + +Whilst we're at it, export both x509_check_signature() and the new +x509_get_sig_params(). + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509_cert_parser.c | 30 +++++------ + crypto/asymmetric_keys/x509_parser.h | 14 ++++-- + crypto/asymmetric_keys/x509_public_key.c | 83 +++++++++++++++++-------------- + 3 files changed, 73 insertions(+), 54 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 08bebf1..931f069 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert) + kfree(cert->subject); + kfree(cert->fingerprint); + kfree(cert->authority); ++ kfree(cert->sig.digest); ++ mpi_free(cert->sig.rsa.s); + kfree(cert); + } + } +@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, + return -ENOPKG; /* Unsupported combination */ + + case OID_md4WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_MD5; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_MD5; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha1WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA1; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha256WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA256; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha384WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA384; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha512WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA512; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha224WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA224; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + } + +@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen, + return -EINVAL; + } + +- ctx->cert->sig = value; +- ctx->cert->sig_size = vlen; ++ ctx->cert->raw_sig = value; ++ ctx->cert->raw_sig_size = vlen; + return 0; + } + +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index a6ce46f..6b1d877 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -21,18 +21,17 @@ struct x509_certificate { + char *authority; /* Authority key fingerprint as hex */ + struct tm valid_from; + struct tm valid_to; +- enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ +- enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ + const void *tbs; /* Signed data */ + unsigned tbs_size; /* Size of signed data */ +- unsigned sig_size; /* Size of sigature */ +- const void *sig; /* Signature data */ ++ unsigned raw_sig_size; /* Size of sigature */ ++ const void *raw_sig; /* Signature data */ + const void *raw_serial; /* Raw serial number in ASN.1 */ + unsigned raw_serial_size; + unsigned raw_issuer_size; + const void *raw_issuer; /* Raw issuer name in ASN.1 */ + const void *raw_subject; /* Raw subject name in ASN.1 */ + unsigned raw_subject_size; ++ struct public_key_signature sig; /* Signature parameters */ + }; + + /* +@@ -40,3 +39,10 @@ struct x509_certificate { + */ + extern void x509_free_certificate(struct x509_certificate *cert); + extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); ++ ++/* ++ * x509_public_key.c ++ */ ++extern int x509_get_sig_params(struct x509_certificate *cert); ++extern int x509_check_signature(const struct public_key *pub, ++ struct x509_certificate *cert); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 8cb2f70..b7c81d8 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -24,72 +24,83 @@ + #include "x509_parser.h" + + /* +- * Check the signature on a certificate using the provided public key ++ * Set up the signature parameters in an X.509 certificate. This involves ++ * digesting the signed data and extracting the signature. + */ +-static int x509_check_signature(const struct public_key *pub, +- const struct x509_certificate *cert) ++int x509_get_sig_params(struct x509_certificate *cert) + { +- struct public_key_signature *sig; + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t digest_size, desc_size; ++ void *digest; + int ret; + + pr_devel("==>%s()\n", __func__); +- ++ ++ if (cert->sig.rsa.s) ++ return 0; ++ ++ cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); ++ if (!cert->sig.rsa.s) ++ return -ENOMEM; ++ cert->sig.nr_mpi = 1; ++ + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + digest_size = crypto_shash_digestsize(tfm); + +- /* We allocate the hash operational data storage on the end of our +- * context data. ++ /* We allocate the hash operational data storage on the end of the ++ * digest storage space. + */ + ret = -ENOMEM; +- sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); +- if (!sig) +- goto error_no_sig; ++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL); ++ if (!digest) ++ goto error; + +- sig->pkey_hash_algo = cert->sig_hash_algo; +- sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; +- sig->digest_size = digest_size; ++ cert->sig.digest = digest; ++ cert->sig.digest_size = digest_size; + +- desc = (void *)sig + sizeof(*sig); +- desc->tfm = tfm; +- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ desc = digest + digest_size; ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error; ++ might_sleep(); ++ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); ++error: ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(x509_get_sig_params); + +- ret = -ENOMEM; +- sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); +- if (!sig->rsa.s) +- goto error; ++/* ++ * Check the signature on a certificate using the provided public key ++ */ ++int x509_check_signature(const struct public_key *pub, ++ struct x509_certificate *cert) ++{ ++ int ret; + +- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); +- if (ret < 0) +- goto error_mpi; ++ pr_devel("==>%s()\n", __func__); + +- ret = public_key_verify_signature(pub, sig); ++ ret = x509_get_sig_params(cert); ++ if (ret < 0) ++ return ret; + ++ ret = public_key_verify_signature(pub, &cert->sig); + pr_debug("Cert Verification: %d\n", ret); +- +-error_mpi: +- mpi_free(sig->rsa.s); +-error: +- kfree(sig); +-error_no_sig: +- crypto_free_shash(tfm); +- +- pr_devel("<==%s() = %d\n", __func__, ret); + return ret; + } ++EXPORT_SYMBOL_GPL(x509_check_signature); + + /* + * Attempt to parse a data blob for a key as an X509 certificate. +@@ -118,8 +129,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->valid_to.tm_mday, cert->valid_to.tm_hour, + cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", +- pkey_algo_name[cert->sig_pkey_algo], +- pkey_hash_algo_name[cert->sig_hash_algo]); ++ pkey_algo_name[cert->sig.pkey_algo], ++ pkey_hash_algo_name[cert->sig.pkey_hash_algo]); + + if (!cert->fingerprint || !cert->authority) { + pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", +-- +1.8.1.4 + + +From 822175026ad1d4640240d1fdd77b1f45ddd9e7a9 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:36 +0000 +Subject: [PATCH 12/47] X.509: Check the algorithm IDs obtained from parsing an + X.509 certificate + +Check that the algorithm IDs obtained from the ASN.1 parse by OID lookup +corresponds to algorithms that are available to us. + +Reported-by: Kees Cook +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index b7c81d8..eb368d4 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -119,6 +119,17 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); ++ ++ if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || ++ cert->sig.pkey_algo >= PKEY_ALGO__LAST || ++ cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || ++ !pkey_algo[cert->pub->pkey_algo] || ++ !pkey_algo[cert->sig.pkey_algo] || ++ !pkey_hash_algo_name[cert->sig.pkey_hash_algo]) { ++ ret = -ENOPKG; ++ goto error_free_cert; ++ } ++ + pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, +-- +1.8.1.4 + + +From 4a1a540f79d36d8b0b8970ea638648cef080057b Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:37 +0000 +Subject: [PATCH 13/47] X.509: Handle certificates that lack an + authorityKeyIdentifier field + +Handle certificates that lack an authorityKeyIdentifier field by assuming +they're self-signed and checking their signatures against themselves. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509_public_key.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index eb368d4..0f55e3b 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -143,8 +143,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pkey_algo_name[cert->sig.pkey_algo], + pkey_hash_algo_name[cert->sig.pkey_hash_algo]); + +- if (!cert->fingerprint || !cert->authority) { +- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", ++ if (!cert->fingerprint) { ++ pr_warn("Cert for '%s' must have a SubjKeyId extension\n", + cert->subject); + ret = -EKEYREJECTED; + goto error_free_cert; +@@ -190,8 +190,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + +- /* Check the signature on the key */ +- if (strcmp(cert->fingerprint, cert->authority) == 0) { ++ /* Check the signature on the key if it appears to be self-signed */ ++ if (!cert->authority || ++ strcmp(cert->fingerprint, cert->authority) == 0) { + ret = x509_check_signature(cert->pub, cert); + if (ret < 0) + goto error_free_cert; +-- +1.8.1.4 + + +From f5e443e719cfb7cae2aea764ad3c9ec9ffba4f60 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:37 +0000 +Subject: [PATCH 14/47] X.509: Export certificate parse and free functions + +Export certificate parse and free functions for use by modules. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +Reviewed-by: Josh Boyer +--- + crypto/asymmetric_keys/x509_cert_parser.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 931f069..9cf0e16 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -11,6 +11,7 @@ + + #define pr_fmt(fmt) "X.509: "fmt + #include ++#include + #include + #include + #include +@@ -52,6 +53,7 @@ void x509_free_certificate(struct x509_certificate *cert) + kfree(cert); + } + } ++EXPORT_SYMBOL_GPL(x509_free_certificate); + + /* + * Parse an X.509 certificate +@@ -97,6 +99,7 @@ error_no_ctx: + error_no_cert: + return ERR_PTR(ret); + } ++EXPORT_SYMBOL_GPL(x509_cert_parse); + + /* + * Note an OID when we find one for later processing when we know how +-- +1.8.1.4 + + +From 792a56d205765cf4ece16868929ad5fbe6b89df4 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:38 +0000 +Subject: [PATCH 15/47] PKCS#7: Implement a parser [RFC 2315] + +Implement a parser for a PKCS#7 signed-data message as described in part of +RFC 2315. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/Kconfig | 9 + + crypto/asymmetric_keys/Makefile | 13 ++ + crypto/asymmetric_keys/pkcs7.asn1 | 127 +++++++++++++ + crypto/asymmetric_keys/pkcs7_parser.c | 326 ++++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/pkcs7_parser.h | 65 +++++++ + include/linux/oid_registry.h | 1 + + 6 files changed, 541 insertions(+) + create mode 100644 crypto/asymmetric_keys/pkcs7.asn1 + create mode 100644 crypto/asymmetric_keys/pkcs7_parser.c + create mode 100644 crypto/asymmetric_keys/pkcs7_parser.h + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 6d2c2ea..413f3f6 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -35,4 +35,13 @@ config X509_CERTIFICATE_PARSER + data and provides the ability to instantiate a crypto key from a + public key packet found inside the certificate. + ++config PKCS7_MESSAGE_PARSER ++ tristate "PKCS#7 message parser" ++ depends on X509_CERTIFICATE_PARSER ++ select ASN1 ++ select OID_REGISTRY ++ help ++ This option provides support for parsing PKCS#7 format messages for ++ signature data and provides the ability to verify the signature. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 0727204..59d8cad 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -25,3 +25,16 @@ $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h + + clean-files += x509-asn1.c x509-asn1.h + clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h ++ ++# ++# PKCS#7 message handling ++# ++obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o ++pkcs7_message-y := \ ++ pkcs7-asn1.o \ ++ pkcs7_parser.o ++ ++$(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h ++$(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h ++ ++clean-files += pkcs7-asn1.c pkcs7-asn1.h +diff --git a/crypto/asymmetric_keys/pkcs7.asn1 b/crypto/asymmetric_keys/pkcs7.asn1 +new file mode 100644 +index 0000000..7bf91ed +--- /dev/null ++++ b/crypto/asymmetric_keys/pkcs7.asn1 +@@ -0,0 +1,127 @@ ++PKCS7ContentInfo ::= SEQUENCE { ++ contentType ContentType, ++ content [0] EXPLICIT SignedData OPTIONAL ++} ++ ++ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID }) ++ ++SignedData ::= SEQUENCE { ++ version INTEGER, ++ digestAlgorithms DigestAlgorithmIdentifiers ({ pkcs7_note_digest_algo }), ++ contentInfo ContentInfo, ++ certificates CHOICE { ++ certSet [0] IMPLICIT ExtendedCertificatesAndCertificates, ++ certSequence [2] IMPLICIT Certificates ++ } OPTIONAL ({ pkcs7_note_certificate_list }), ++ crls CHOICE { ++ crlSet [1] IMPLICIT CertificateRevocationLists, ++ crlSequence [3] IMPLICIT CRLSequence ++ } OPTIONAL, ++ signerInfos SignerInfos ++} ++ ++ContentInfo ::= SEQUENCE { ++ contentType ContentType, ++ content [0] EXPLICIT Data OPTIONAL ++} ++ ++Data ::= ANY ({ pkcs7_note_data }) ++ ++DigestAlgorithmIdentifiers ::= CHOICE { ++ daSet SET OF DigestAlgorithmIdentifier, ++ daSequence SEQUENCE OF DigestAlgorithmIdentifier ++} ++ ++DigestAlgorithmIdentifier ::= SEQUENCE { ++ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }), ++ parameters ANY OPTIONAL ++} ++ ++-- ++-- Certificates and certificate lists ++-- ++ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate ++ ++ExtendedCertificateOrCertificate ::= CHOICE { ++ certificate Certificate, -- X.509 ++ extendedCertificate [0] IMPLICIT ExtendedCertificate -- PKCS#6 ++} ++ ++ExtendedCertificate ::= Certificate -- cheating ++ ++Certificates ::= SEQUENCE OF Certificate ++ ++CertificateRevocationLists ::= SET OF CertificateList ++ ++CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly ++ ++CRLSequence ::= SEQUENCE OF CertificateList ++ ++Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509 ++ ++-- ++-- Signer information ++-- ++SignerInfos ::= CHOICE { ++ siSet SET OF SignerInfo, ++ siSequence SEQUENCE OF SignerInfo ++} ++ ++SignerInfo ::= SEQUENCE { ++ version INTEGER, ++ issuerAndSerialNumber IssuerAndSerialNumber, ++ digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_note_digest_algo }), ++ authenticatedAttributes CHOICE { ++ aaSet [0] IMPLICIT SetOfAuthenticatedAttribute ++ ({ pkcs7_note_set_of_authattrs }), ++ aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute ++ -- Explicit because easier to compute digest on ++ -- sequence of attributes and then reuse encoded ++ -- sequence in aaSequence. ++ } OPTIONAL, ++ digestEncryptionAlgorithm ++ DigestEncryptionAlgorithmIdentifier ({ pkcs7_note_pkey_algo }), ++ encryptedDigest EncryptedDigest, ++ unauthenticatedAttributes CHOICE { ++ uaSet [1] IMPLICIT SET OF UnauthenticatedAttribute, ++ uaSequence [3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute ++ } OPTIONAL ++} ++ ++IssuerAndSerialNumber ::= SEQUENCE { ++ issuer Name ({ pkcs7_note_issuer }), ++ serialNumber CertificateSerialNumber ({ pkcs7_note_serial }) ++} ++ ++CertificateSerialNumber ::= INTEGER ++ ++SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute ++ ++AuthenticatedAttribute ::= SEQUENCE { ++ type OBJECT IDENTIFIER ({ pkcs7_note_OID }), ++ values SET OF ANY ({ pkcs7_note_authenticated_attr }) ++} ++ ++UnauthenticatedAttribute ::= SEQUENCE { ++ type OBJECT IDENTIFIER ({ pkcs7_note_OID }), ++ values SET OF ANY ++} ++ ++DigestEncryptionAlgorithmIdentifier ::= SEQUENCE { ++ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }), ++ parameters ANY OPTIONAL ++} ++ ++EncryptedDigest ::= OCTET STRING ({ pkcs7_note_signature }) ++ ++--- ++--- X.500 Name ++--- ++Name ::= SEQUENCE OF RelativeDistinguishedName ++ ++RelativeDistinguishedName ::= SET OF AttributeValueAssertion ++ ++AttributeValueAssertion ::= SEQUENCE { ++ attributeType OBJECT IDENTIFIER ({ pkcs7_note_OID }), ++ attributeValue ANY ++} +diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c +new file mode 100644 +index 0000000..231aff9 +--- /dev/null ++++ b/crypto/asymmetric_keys/pkcs7_parser.c +@@ -0,0 +1,326 @@ ++/* PKCS#7 parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PKCS7: "fmt ++#include ++#include ++#include ++#include ++#include ++#include "public_key.h" ++#include "pkcs7_parser.h" ++#include "pkcs7-asn1.h" ++ ++struct pkcs7_parse_context { ++ struct pkcs7_message *msg; /* Message being constructed */ ++ struct x509_certificate *certs; /* Certificate cache */ ++ struct x509_certificate **ppcerts; ++ unsigned long data; /* Start of data */ ++ enum OID last_oid; /* Last OID encountered */ ++}; ++ ++/* ++ * Free a PKCS#7 message ++ */ ++void pkcs7_free_message(struct pkcs7_message *pkcs7) ++{ ++ struct x509_certificate *cert; ++ ++ if (pkcs7) { ++ while (pkcs7->certs) { ++ cert = pkcs7->certs; ++ pkcs7->certs = cert->next; ++ x509_free_certificate(cert); ++ } ++ while (pkcs7->crl) { ++ cert = pkcs7->crl; ++ pkcs7->crl = cert->next; ++ x509_free_certificate(cert); ++ } ++ kfree(pkcs7->sig.digest); ++ mpi_free(pkcs7->sig.mpi[0]); ++ kfree(pkcs7); ++ } ++} ++EXPORT_SYMBOL_GPL(pkcs7_free_message); ++ ++/* ++ * Parse a PKCS#7 message ++ */ ++struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) ++{ ++ struct pkcs7_parse_context *ctx; ++ struct pkcs7_message *msg; ++ long ret; ++ ++ ret = -ENOMEM; ++ msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL); ++ if (!msg) ++ goto error_no_sig; ++ ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); ++ if (!ctx) ++ goto error_no_ctx; ++ ++ ctx->msg = msg; ++ ctx->data = (unsigned long)data; ++ ctx->ppcerts = &ctx->certs; ++ ++ /* Attempt to decode the signature */ ++ ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); ++ if (ret < 0) ++ goto error_decode; ++ ++ while (ctx->certs) { ++ struct x509_certificate *cert = ctx->certs; ++ ctx->certs = cert->next; ++ x509_free_certificate(cert); ++ } ++ kfree(ctx); ++ return msg; ++ ++error_decode: ++ kfree(ctx); ++error_no_ctx: ++ pkcs7_free_message(msg); ++error_no_sig: ++ return ERR_PTR(ret); ++} ++EXPORT_SYMBOL_GPL(pkcs7_parse_message); ++ ++/* ++ * Note an OID when we find one for later processing when we know how ++ * to interpret it. ++ */ ++int pkcs7_note_OID(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ ctx->last_oid = look_up_OID(value, vlen); ++ if (ctx->last_oid == OID__NR) { ++ char buffer[50]; ++ sprint_oid(value, vlen, buffer, sizeof(buffer)); ++ printk("PKCS7: Unknown OID: [%lu] %s\n", ++ (unsigned long)value - ctx->data, buffer); ++ } ++ return 0; ++} ++ ++/* ++ * Note the digest algorithm for the signature. ++ */ ++int pkcs7_note_digest_algo(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ switch (ctx->last_oid) { ++ case OID_md4: ++ ctx->msg->sig.pkey_hash_algo = PKEY_HASH_MD4; ++ break; ++ case OID_md5: ++ ctx->msg->sig.pkey_hash_algo = PKEY_HASH_MD5; ++ break; ++ case OID_sha1: ++ ctx->msg->sig.pkey_hash_algo = PKEY_HASH_SHA1; ++ break; ++ case OID_sha256: ++ ctx->msg->sig.pkey_hash_algo = PKEY_HASH_SHA256; ++ break; ++ default: ++ printk("Unsupported digest algo: %u\n", ctx->last_oid); ++ return -ENOPKG; ++ } ++ return 0; ++} ++ ++/* ++ * Note the public key algorithm for the signature. ++ */ ++int pkcs7_note_pkey_algo(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ switch (ctx->last_oid) { ++ case OID_rsaEncryption: ++ ctx->msg->sig.pkey_algo = PKEY_ALGO_RSA; ++ break; ++ default: ++ printk("Unsupported pkey algo: %u\n", ctx->last_oid); ++ return -ENOPKG; ++ } ++ return 0; ++} ++ ++/* ++ * Extract a certificate and store it in the context. ++ */ ++int pkcs7_extract_cert(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ struct x509_certificate *cert; ++ ++ if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) { ++ pr_debug("Cert began with tag %02x at %lu\n", ++ tag, (unsigned long)ctx - ctx->data); ++ return -EBADMSG; ++ } ++ ++ /* We have to correct for the header so that the X.509 parser can start ++ * from the beginning. Note that since X.509 stipulates DER, there ++ * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which ++ * stipulates BER). ++ */ ++ value -= hdrlen; ++ vlen += hdrlen; ++ ++ if (((u8*)value)[1] == 0x80) ++ vlen += 2; /* Indefinite length - there should be an EOC */ ++ ++ cert = x509_cert_parse(value, vlen); ++ if (IS_ERR(cert)) ++ return PTR_ERR(cert); ++ ++ pr_debug("Got cert for %s\n", cert->subject); ++ pr_debug("- fingerprint %s\n", cert->fingerprint); ++ ++ *ctx->ppcerts = cert; ++ ctx->ppcerts = &cert->next; ++ return 0; ++} ++ ++/* ++ * Save the certificate list ++ */ ++int pkcs7_note_certificate_list(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ pr_devel("Got cert list (%02x)\n", tag); ++ ++ *ctx->ppcerts = ctx->msg->certs; ++ ctx->msg->certs = ctx->certs; ++ ctx->certs = NULL; ++ ctx->ppcerts = &ctx->certs; ++ return 0; ++} ++ ++/* ++ * Extract the data from the signature and store that and its content type OID ++ * in the context. ++ */ ++int pkcs7_note_data(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ pr_debug("Got data\n"); ++ ++ ctx->msg->data = value; ++ ctx->msg->data_len = vlen; ++ ctx->msg->data_hdrlen = hdrlen; ++ ctx->msg->data_type = ctx->last_oid; ++ return 0; ++} ++ ++/* ++ * Parse authenticated attributes ++ */ ++int pkcs7_note_authenticated_attr(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); ++ ++ switch (ctx->last_oid) { ++ case OID_messageDigest: ++ if (tag != ASN1_OTS) ++ return -EBADMSG; ++ ctx->msg->msgdigest = value; ++ ctx->msg->msgdigest_len = vlen; ++ return 0; ++ default: ++ return 0; ++ } ++} ++ ++/* ++ * Note the set of auth attributes for digestion purposes [RFC2315 9.3] ++ */ ++int pkcs7_note_set_of_authattrs(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ++ /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ ++ ctx->msg->authattrs = value - (hdrlen - 1); ++ ctx->msg->authattrs_len = vlen + (hdrlen - 1); ++ return 0; ++} ++ ++/* ++ * Note the issuing certificate serial number ++ */ ++int pkcs7_note_serial(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ctx->msg->raw_serial = value; ++ ctx->msg->raw_serial_size = vlen; ++ return 0; ++} ++ ++/* ++ * Note the issuer's name ++ */ ++int pkcs7_note_issuer(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ ctx->msg->raw_issuer = value; ++ ctx->msg->raw_issuer_size = vlen; ++ return 0; ++} ++ ++/* ++ * Note the signature data ++ */ ++int pkcs7_note_signature(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pkcs7_parse_context *ctx = context; ++ MPI mpi; ++ ++ BUG_ON(ctx->msg->sig.pkey_algo != PKEY_ALGO_RSA); ++ ++ mpi = mpi_read_raw_data(value, vlen); ++ if (!mpi) ++ return -ENOMEM; ++ ++ ctx->msg->sig.mpi[0] = mpi; ++ ctx->msg->sig.nr_mpi = 1; ++ return 0; ++} +diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h +new file mode 100644 +index 0000000..5415857 +--- /dev/null ++++ b/crypto/asymmetric_keys/pkcs7_parser.h +@@ -0,0 +1,65 @@ ++/* PKCS#7 crypto data parser internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include "x509_parser.h" ++ ++#define kenter(FMT, ...) \ ++ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) ++#define kleave(FMT, ...) \ ++ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) ++ ++struct pkcs7_message { ++ struct x509_certificate *certs; /* Certificate list */ ++ struct x509_certificate *crl; /* Revocation list */ ++ struct x509_certificate *signer; /* Signing certificate (in ->certs) */ ++ ++ /* Content Data (or NULL) */ ++ enum OID data_type; /* Type of Data */ ++ size_t data_len; /* Length of Data */ ++ size_t data_hdrlen; /* Length of Data ASN.1 header */ ++ const void *data; /* Content Data (or 0) */ ++ ++ /* Message digest - the digest of the Content Data (or NULL) */ ++ const void *msgdigest; ++ unsigned msgdigest_len; ++ ++ /* Authenticated Attribute data (or NULL) */ ++ unsigned authattrs_len; ++ const void *authattrs; ++ ++ /* Issuing cert serial number and issuer's name */ ++ const void *raw_serial; ++ unsigned raw_serial_size; ++ unsigned raw_issuer_size; ++ const void *raw_issuer; ++ ++ /* Message signature. ++ * ++ * This contains the generated digest of _either_ the Content Data or ++ * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of ++ * the attributes contains the digest of the the Content Data within ++ * it. ++ */ ++ struct public_key_signature sig; ++}; ++ ++/* ++ * pkcs7_parser.c ++ */ ++extern struct pkcs7_message *pkcs7_parse_message(const void *data, ++ size_t datalen); ++extern void pkcs7_free_message(struct pkcs7_message *pkcs7); ++ ++/* ++ * pkcs7_verify.c ++ */ ++extern int pkcs7_verify(struct pkcs7_message *pkcs7); +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +index 6926db7..edeff85 100644 +--- a/include/linux/oid_registry.h ++++ b/include/linux/oid_registry.h +@@ -55,6 +55,7 @@ enum OID { + OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ + OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ + OID_sha1, /* 1.3.14.3.2.26 */ ++ OID_sha256, /* 2.16.840.1.101.3.4.2.1 */ + + /* Distinguished Name attribute IDs [RFC 2256] */ + OID_commonName, /* 2.5.4.3 */ +-- +1.8.1.4 + + +From 3b4b82eecde52c1bd75ab11ef7f8a5c13ec73c40 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:38 +0000 +Subject: [PATCH 16/47] PKCS#7: Digest the data in a signed-data message + +Digest the data in a PKCS#7 signed-data message and attach to the +public_key_signature struct contained in the pkcs7_message struct. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/Makefile | 3 +- + crypto/asymmetric_keys/pkcs7_verify.c | 134 ++++++++++++++++++++++++++++++++++ + 2 files changed, 136 insertions(+), 1 deletion(-) + create mode 100644 crypto/asymmetric_keys/pkcs7_verify.c + +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 59d8cad..b6b39e7 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -32,7 +32,8 @@ clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h + obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o + pkcs7_message-y := \ + pkcs7-asn1.o \ +- pkcs7_parser.o ++ pkcs7_parser.o \ ++ pkcs7_verify.o + + $(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h + $(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h +diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c +new file mode 100644 +index 0000000..2f9f26c +--- /dev/null ++++ b/crypto/asymmetric_keys/pkcs7_verify.c +@@ -0,0 +1,134 @@ ++/* Verify the signature on a PKCS#7 message. ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PKCS7: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include "public_key.h" ++#include "pkcs7_parser.h" ++ ++/* ++ * Digest the relevant parts of the PKCS#7 data ++ */ ++static int pkcs7_digest(struct pkcs7_message *pkcs7) ++{ ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ void *digest; ++ int ret; ++ ++ kenter(",%u", pkcs7->sig.pkey_hash_algo); ++ ++ if (pkcs7->sig.pkey_hash_algo >= PKEY_HASH__LAST || ++ !pkey_hash_algo_name[pkcs7->sig.pkey_hash_algo]) ++ return -ENOPKG; ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[pkcs7->sig.pkey_hash_algo], ++ 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ pkcs7->sig.digest_size = digest_size = crypto_shash_digestsize(tfm); ++ ++ ret = -ENOMEM; ++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL); ++ if (!digest) ++ goto error_no_desc; ++ ++ desc = digest + digest_size; ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ /* Digest the message [RFC2315 9.3] */ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest); ++ if (ret < 0) ++ goto error; ++ pr_devel("MsgDigest = [%*ph]\n", 8, digest); ++ ++ /* However, if there are authenticated attributes, there must be a ++ * message digest attribute amongst them which corresponds to the ++ * digest we just calculated. ++ */ ++ if (pkcs7->msgdigest) { ++ u8 tag; ++ ++ if (pkcs7->msgdigest_len != pkcs7->sig.digest_size) { ++ pr_debug("Invalid digest size (%u)\n", ++ pkcs7->msgdigest_len); ++ ret = -EBADMSG; ++ goto error; ++ } ++ ++ if (memcmp(digest, pkcs7->msgdigest, pkcs7->msgdigest_len) != 0) { ++ pr_debug("Message digest doesn't match\n"); ++ ret = -EKEYREJECTED; ++ goto error; ++ } ++ ++ /* We then calculate anew, using the authenticated attributes ++ * as the contents of the digest instead. Note that we need to ++ * convert the attributes from a CONT.0 into a SET before we ++ * hash it. ++ */ ++ memset(digest, 0, pkcs7->sig.digest_size); ++ ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ tag = ASN1_CONS_BIT | ASN1_SET; ++ ret = crypto_shash_update(desc, &tag, 1); ++ if (ret < 0) ++ goto error; ++ ret = crypto_shash_finup(desc, pkcs7->authattrs, ++ pkcs7->authattrs_len, digest); ++ if (ret < 0) ++ goto error; ++ pr_devel("AADigest = [%*ph]\n", 8, digest); ++ } ++ ++ pkcs7->sig.digest = digest; ++ digest = NULL; ++ ++error: ++ kfree(digest); ++error_no_desc: ++ crypto_free_shash(tfm); ++ kleave(" = %d\n", ret); ++ return ret; ++} ++ ++/* ++ * Verify a PKCS#7 message ++ */ ++int pkcs7_verify(struct pkcs7_message *pkcs7) ++{ ++ int ret; ++ ++ /* First of all, digest the data in the PKCS#7 message */ ++ ret = pkcs7_digest(pkcs7); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pkcs7_verify); +-- +1.8.1.4 + + +From e67fed4626a30dd11967abad9187013ff4185991 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:39 +0000 +Subject: [PATCH 17/47] PKCS#7: Find the right key in the PKCS#7 key list and + verify the signature + +Find the appropriate key in the PKCS#7 key list and verify the signature with +it. There may be several keys in there forming a chain. Any link in that +chain or the root of that chain may be in our keyrings. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pkcs7_verify.c | 61 +++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c +index 2f9f26c..3f6f0e2 100644 +--- a/crypto/asymmetric_keys/pkcs7_verify.c ++++ b/crypto/asymmetric_keys/pkcs7_verify.c +@@ -118,6 +118,53 @@ error_no_desc: + } + + /* ++ * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 ++ * uses the issuer's name and the issuing certificate serial number for ++ * matching purposes. These must match the certificate issuer's name (not ++ * subject's name) and the certificate serial number [RFC 2315 6.7]. ++ */ ++static int pkcs7_find_key(struct pkcs7_message *pkcs7) ++{ ++ struct x509_certificate *x509; ++ ++ kenter("%u,%u", pkcs7->raw_serial_size, pkcs7->raw_issuer_size); ++ ++ for (x509 = pkcs7->certs; x509; x509 = x509->next) { ++ pr_devel("- x509 %u,%u\n", ++ x509->raw_serial_size, x509->raw_issuer_size); ++ ++ /* I'm _assuming_ that the generator of the PKCS#7 message will ++ * encode the fields from the X.509 cert in the same way in the ++ * PKCS#7 message - but I can't be 100% sure of that. It's ++ * possible this will need element-by-element comparison. ++ */ ++ if (x509->raw_serial_size != pkcs7->raw_serial_size || ++ memcmp(x509->raw_serial, pkcs7->raw_serial, ++ pkcs7->raw_serial_size) != 0) ++ continue; ++ pr_devel("Found cert serial match\n"); ++ ++ if (x509->raw_issuer_size != pkcs7->raw_issuer_size || ++ memcmp(x509->raw_issuer, pkcs7->raw_issuer, ++ pkcs7->raw_issuer_size) != 0) { ++ pr_warn("X.509 subject and PKCS#7 issuer don't match\n"); ++ continue; ++ } ++ ++ if (x509->pub->pkey_algo != pkcs7->sig.pkey_algo) { ++ pr_warn("X.509 algo and PKCS#7 sig algo don't match\n"); ++ continue; ++ } ++ ++ pkcs7->signer = x509; ++ return 0; ++ } ++ pr_warn("Issuing X.509 cert not found (#%*ph)\n", ++ pkcs7->raw_serial_size, pkcs7->raw_serial); ++ return -ENOKEY; ++} ++ ++/* + * Verify a PKCS#7 message + */ + int pkcs7_verify(struct pkcs7_message *pkcs7) +@@ -129,6 +176,20 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) + if (ret < 0) + return ret; + ++ /* Find the key for the message signature */ ++ ret = pkcs7_find_key(pkcs7); ++ if (ret < 0) ++ return ret; ++ ++ pr_devel("Found X.509 cert\n"); ++ ++ /* Verify the PKCS#7 binary against the key */ ++ ret = public_key_verify_signature(pkcs7->signer->pub, &pkcs7->sig); ++ if (ret < 0) ++ return ret; ++ ++ pr_devel("Verified signature\n"); ++ + return 0; + } + EXPORT_SYMBOL_GPL(pkcs7_verify); +-- +1.8.1.4 + + +From 87ec8d783c887617ee6e85f66a9ce1a03c627e87 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:39 +0000 +Subject: [PATCH 18/47] PKCS#7: Verify internal certificate chain + +Verify certificate chain in the X.509 certificates contained within the PKCS#7 +message as far as possible. If any signature that we should be able to verify +fails, we reject the whole lot. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pkcs7_verify.c | 67 ++++++++++++++++++++++++++++++++++- + crypto/asymmetric_keys/x509_parser.h | 1 + + 2 files changed, 67 insertions(+), 1 deletion(-) + +diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c +index 3f6f0e2..b3774bd 100644 +--- a/crypto/asymmetric_keys/pkcs7_verify.c ++++ b/crypto/asymmetric_keys/pkcs7_verify.c +@@ -165,6 +165,70 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7) + } + + /* ++ * Verify the internal certificate chain as best we can. ++ */ ++static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7) ++{ ++ struct x509_certificate *x509 = pkcs7->signer, *p; ++ int ret; ++ ++ kenter(""); ++ ++ for (;;) { ++ pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint); ++ ret = x509_get_sig_params(x509); ++ if (ret < 0) ++ return ret; ++ ++ if (x509->issuer) ++ pr_debug("- issuer %s\n", x509->issuer); ++ if (x509->authority) ++ pr_debug("- authkeyid %s\n", x509->authority); ++ ++ if (!x509->authority || ++ (x509->subject && ++ strcmp(x509->subject, x509->authority) == 0)) { ++ /* If there's no authority certificate specified, then ++ * the certificate must be self-signed and is the root ++ * of the chain. Likewise if the cert is its own ++ * authority. ++ */ ++ pr_debug("- no auth?\n"); ++ if (x509->raw_subject_size != x509->raw_issuer_size || ++ memcmp(x509->raw_subject, x509->raw_issuer, ++ x509->raw_issuer_size) != 0) ++ return 0; ++ ++ ret = x509_check_signature(x509->pub, x509); ++ if (ret < 0) ++ return ret; ++ x509->signer = x509; ++ pr_debug("- self-signed\n"); ++ return 0; ++ } ++ ++ for (p = pkcs7->certs; p; p = p->next) ++ if (!p->signer && ++ p->raw_subject_size == x509->raw_issuer_size && ++ strcmp(p->fingerprint, x509->authority) == 0 && ++ memcmp(p->raw_subject, x509->raw_issuer, ++ x509->raw_issuer_size) == 0) ++ goto found_issuer; ++ pr_debug("- top\n"); ++ return 0; ++ ++ found_issuer: ++ pr_debug("- issuer %s\n", p->subject); ++ ret = x509_check_signature(p->pub, x509); ++ if (ret < 0) ++ return ret; ++ x509->signer = p; ++ x509 = p; ++ might_sleep(); ++ } ++} ++ ++/* + * Verify a PKCS#7 message + */ + int pkcs7_verify(struct pkcs7_message *pkcs7) +@@ -190,6 +254,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) + + pr_devel("Verified signature\n"); + +- return 0; ++ /* Verify the internal certificate chain */ ++ return pkcs7_verify_sig_chain(pkcs7); + } + EXPORT_SYMBOL_GPL(pkcs7_verify); +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 6b1d877..5e35fba 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -14,6 +14,7 @@ + + struct x509_certificate { + struct x509_certificate *next; ++ const struct x509_certificate *signer; /* Certificate that signed this one */ + struct public_key *pub; /* Public key details */ + char *issuer; /* Name of certificate issuer */ + char *subject; /* Name of certificate subject */ +-- +1.8.1.4 + + +From cc6c40318a05330e4bb201b35378d7c0a0278aaa Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:42 +0000 +Subject: [PATCH 19/47] PKCS#7: Find intersection between PKCS#7 message and + known, trusted keys + +Find the intersection between the X.509 certificate chain contained in a PKCS#7 +message and a set of keys that we already know and trust. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/pkcs7_parser.h | 7 ++ + crypto/asymmetric_keys/pkcs7_trust.c | 149 ++++++++++++++++++++++++++++++++++ + 3 files changed, 157 insertions(+) + create mode 100644 crypto/asymmetric_keys/pkcs7_trust.c + +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index b6b39e7..d63cb43 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -33,6 +33,7 @@ obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o + pkcs7_message-y := \ + pkcs7-asn1.o \ + pkcs7_parser.o \ ++ pkcs7_trust.o \ + pkcs7_verify.o + + $(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h +diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h +index 5415857..ffa72dc 100644 +--- a/crypto/asymmetric_keys/pkcs7_parser.h ++++ b/crypto/asymmetric_keys/pkcs7_parser.h +@@ -60,6 +60,13 @@ extern struct pkcs7_message *pkcs7_parse_message(const void *data, + extern void pkcs7_free_message(struct pkcs7_message *pkcs7); + + /* ++ * pkcs7_trust.c ++ */ ++extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7, ++ struct key *trust_keyring, ++ bool *_trusted); ++ ++/* + * pkcs7_verify.c + */ + extern int pkcs7_verify(struct pkcs7_message *pkcs7); +diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c +new file mode 100644 +index 0000000..cc226f5 +--- /dev/null ++++ b/crypto/asymmetric_keys/pkcs7_trust.c +@@ -0,0 +1,149 @@ ++/* Validate the trust chain of a PKCS#7 message. ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PKCS7: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "public_key.h" ++#include "pkcs7_parser.h" ++ ++/* ++ * Request an asymmetric key. ++ */ ++static struct key *pkcs7_request_asymmetric_key( ++ struct key *keyring, ++ const char *signer, size_t signer_len, ++ const char *authority, size_t auth_len) ++{ ++ key_ref_t key; ++ char *id; ++ ++ kenter(",%zu,,%zu", signer_len, auth_len); ++ ++ /* Construct an identifier. */ ++ id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); ++ if (!id) ++ return ERR_PTR(-ENOMEM); ++ ++ memcpy(id, signer, signer_len); ++ id[signer_len + 0] = ':'; ++ id[signer_len + 1] = ' '; ++ memcpy(id + signer_len + 2, authority, auth_len); ++ id[signer_len + 2 + auth_len] = 0; ++ ++ pr_debug("Look up: \"%s\"\n", id); ++ ++ key = keyring_search(make_key_ref(keyring, 1), ++ &key_type_asymmetric, id); ++ if (IS_ERR(key)) ++ pr_debug("Request for module key '%s' err %ld\n", ++ id, PTR_ERR(key)); ++ kfree(id); ++ ++ if (IS_ERR(key)) { ++ switch (PTR_ERR(key)) { ++ /* Hide some search errors */ ++ case -EACCES: ++ case -ENOTDIR: ++ case -EAGAIN: ++ return ERR_PTR(-ENOKEY); ++ default: ++ return ERR_CAST(key); ++ } ++ } ++ ++ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); ++ return key_ref_to_ptr(key); ++} ++ ++/* ++ * Validate that the certificate chain inside the PKCS#7 message intersects ++ * keys we already know and trust. ++ */ ++int pkcs7_validate_trust(struct pkcs7_message *pkcs7, ++ struct key *trust_keyring, ++ bool *_trusted) ++{ ++ struct public_key_signature *sig = &pkcs7->sig; ++ struct x509_certificate *x509, *last = NULL; ++ struct key *key; ++ bool trusted; ++ int ret; ++ ++ kenter(""); ++ ++ for (x509 = pkcs7->signer; x509; x509 = x509->next) { ++ /* Look to see if this certificate is present in the trusted ++ * keys. ++ */ ++ key = pkcs7_request_asymmetric_key( ++ trust_keyring, ++ x509->subject, strlen(x509->subject), ++ x509->fingerprint, strlen(x509->fingerprint)); ++ if (!IS_ERR(key)) ++ /* One of the X.509 certificates in the PKCS#7 message ++ * is apparently the same as one we already trust. ++ * Verify that the trusted variant can also validate ++ * the signature on the descendent. ++ */ ++ goto matched; ++ if (key == ERR_PTR(-ENOMEM)) ++ return -ENOMEM; ++ ++ /* Self-signed certificates form roots of their own, and if we ++ * don't know them, then we can't accept them. ++ */ ++ if (x509->next == x509) { ++ kleave(" = -EKEYREJECTED [unknown self-signed]"); ++ return -EKEYREJECTED; ++ } ++ ++ might_sleep(); ++ last = x509; ++ sig = &last->sig; ++ } ++ ++ /* No match - see if the root certificate has a signer amongst the ++ * trusted keys. ++ */ ++ if (!last || !last->issuer || !last->authority) { ++ kleave(" = -EKEYREJECTED [no backref]"); ++ return -EKEYREJECTED; ++ } ++ ++ key = pkcs7_request_asymmetric_key( ++ trust_keyring, ++ last->issuer, strlen(last->issuer), ++ last->authority, strlen(last->authority)); ++ if (IS_ERR(key)) ++ return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -EKEYREJECTED; ++ ++matched: ++ ret = verify_signature(key, sig); ++ trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags); ++ key_put(key); ++ if (ret < 0) { ++ if (ret == -ENOMEM) ++ return ret; ++ kleave(" = -EKEYREJECTED [verify %d]", ret); ++ return -EKEYREJECTED; ++ } ++ ++ *_trusted = trusted; ++ kleave(" = 0"); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pkcs7_validate_trust); +-- +1.8.1.4 + + +From f20b0d77771133bd0d7e89932fef494f00687607 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:39 +0000 +Subject: [PATCH 20/47] Provide PE binary definitions + +Provide some PE binary structural and constant definitions as taken from the +pesign package sources. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + include/linux/pe.h | 448 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 448 insertions(+) + create mode 100644 include/linux/pe.h + +diff --git a/include/linux/pe.h b/include/linux/pe.h +new file mode 100644 +index 0000000..9234aef +--- /dev/null ++++ b/include/linux/pe.h +@@ -0,0 +1,448 @@ ++/* ++ * Copyright 2011 Red Hat, Inc. ++ * All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): Peter Jones ++ */ ++#ifndef __LINUX_PE_H ++#define __LINUX_PE_H ++ ++#include ++ ++#define MZ_MAGIC 0x5a4d /* "MZ" */ ++ ++struct mz_hdr { ++ uint16_t magic; /* MZ_MAGIC */ ++ uint16_t lbsize; /* size of last used block */ ++ uint16_t blocks; /* pages in file, 0x3 */ ++ uint16_t relocs; /* relocations */ ++ uint16_t hdrsize; /* header size in "paragraphs" */ ++ uint16_t min_extra_pps; /* .bss */ ++ uint16_t max_extra_pps; /* runtime limit for the arena size */ ++ uint16_t ss; /* relative stack segment */ ++ uint16_t sp; /* initial %sp register */ ++ uint16_t checksum; /* word checksum */ ++ uint16_t ip; /* initial %ip register */ ++ uint16_t cs; /* initial %cs relative to load segment */ ++ uint16_t reloc_table_offset; /* offset of the first relocation */ ++ uint16_t overlay_num; /* overlay number. set to 0. */ ++ uint16_t reserved0[4]; /* reserved */ ++ uint16_t oem_id; /* oem identifier */ ++ uint16_t oem_info; /* oem specific */ ++ uint16_t reserved1[10]; /* reserved */ ++ uint32_t peaddr; /* address of pe header */ ++ char message[64]; /* message to print */ ++}; ++ ++struct mz_reloc { ++ uint16_t offset; ++ uint16_t segment; ++}; ++ ++#define PE_MAGIC 0x00004550 /* "PE\0\0" */ ++#define PE_OPT_MAGIC_PE32 0x010b ++#define PE_OPT_MAGIC_PE32_ROM 0x0107 ++#define PE_OPT_MAGIC_PE32PLUS 0x020b ++ ++/* machine type */ ++#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 ++#define IMAGE_FILE_MACHINE_AM33 0x01d3 ++#define IMAGE_FILE_MACHINE_AMD64 0x8664 ++#define IMAGE_FILE_MACHINE_ARM 0x01c0 ++#define IMAGE_FILE_MACHINE_ARMV7 0x01c4 ++#define IMAGE_FILE_MACHINE_EBC 0x0ebc ++#define IMAGE_FILE_MACHINE_I386 0x014c ++#define IMAGE_FILE_MACHINE_IA64 0x0200 ++#define IMAGE_FILE_MACHINE_M32R 0x9041 ++#define IMAGE_FILE_MACHINE_MIPS16 0x0266 ++#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 ++#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 ++#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 ++#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 ++#define IMAGE_FILE_MACHINE_R4000 0x0166 ++#define IMAGE_FILE_MACHINE_SH3 0x01a2 ++#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 ++#define IMAGE_FILE_MACHINE_SH3E 0x01a4 ++#define IMAGE_FILE_MACHINE_SH4 0x01a6 ++#define IMAGE_FILE_MACHINE_SH5 0x01a8 ++#define IMAGE_FILE_MACHINE_THUMB 0x01c2 ++#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 ++ ++/* flags */ ++#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 ++#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 ++#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 ++#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 ++#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 ++#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 ++#define IMAGE_FILE_16BIT_MACHINE 0x0040 ++#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 ++#define IMAGE_FILE_32BIT_MACHINE 0x0100 ++#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 ++#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 ++#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 ++#define IMAGE_FILE_SYSTEM 0x1000 ++#define IMAGE_FILE_DLL 0x2000 ++#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 ++#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 ++ ++struct pe_hdr { ++ uint32_t magic; /* PE magic */ ++ uint16_t machine; /* machine type */ ++ uint16_t sections; /* number of sections */ ++ uint32_t timestamp; /* time_t */ ++ uint32_t symbol_table; /* symbol table offset */ ++ uint32_t symbols; /* number of symbols */ ++ uint16_t opt_hdr_size; /* size of optional header */ ++ uint16_t flags; /* flags */ ++}; ++ ++#define IMAGE_FILE_OPT_ROM_MAGIC 0x107 ++#define IMAGE_FILE_OPT_PE32_MAGIC 0x10b ++#define IMAGE_FILE_OPT_PE32_PLUS_MAGIC 0x20b ++ ++#define IMAGE_SUBSYSTEM_UNKNOWN 0 ++#define IMAGE_SUBSYSTEM_NATIVE 1 ++#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 ++#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 ++#define IMAGE_SUBSYSTEM_POSIX_CUI 7 ++#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 ++#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 ++#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 ++#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 ++#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 ++#define IMAGE_SUBSYSTEM_XBOX 14 ++ ++#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 ++#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 ++#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 ++#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 ++#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 ++#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 ++#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 ++#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 ++ ++/* the fact that pe32 isn't padded where pe32+ is 64-bit means union won't ++ * work right. vomit. */ ++struct pe32_opt_hdr { ++ /* "standard" header */ ++ uint16_t magic; /* file type */ ++ uint8_t ld_major; /* linker major version */ ++ uint8_t ld_minor; /* linker minor version */ ++ uint32_t text_size; /* size of text section(s) */ ++ uint32_t data_size; /* size of data section(s) */ ++ uint32_t bss_size; /* size of bss section(s) */ ++ uint32_t entry_point; /* file offset of entry point */ ++ uint32_t code_base; /* relative code addr in ram */ ++ uint32_t data_base; /* relative data addr in ram */ ++ /* "windows" header */ ++ uint32_t image_base; /* preferred load address */ ++ uint32_t section_align; /* alignment in bytes */ ++ uint32_t file_align; /* file alignment in bytes */ ++ uint16_t os_major; /* major OS version */ ++ uint16_t os_minor; /* minor OS version */ ++ uint16_t image_major; /* major image version */ ++ uint16_t image_minor; /* minor image version */ ++ uint16_t subsys_major; /* major subsystem version */ ++ uint16_t subsys_minor; /* minor subsystem version */ ++ uint32_t win32_version; /* reserved, must be 0 */ ++ uint32_t image_size; /* image size */ ++ uint32_t header_size; /* header size rounded up to ++ file_align */ ++ uint32_t csum; /* checksum */ ++ uint16_t subsys; /* subsystem */ ++ uint16_t dll_flags; /* more flags! */ ++ uint32_t stack_size_req;/* amt of stack requested */ ++ uint32_t stack_size; /* amt of stack required */ ++ uint32_t heap_size_req; /* amt of heap requested */ ++ uint32_t heap_size; /* amt of heap required */ ++ uint32_t loader_flags; /* reserved, must be 0 */ ++ uint32_t data_dirs; /* number of data dir entries */ ++}; ++ ++struct pe32plus_opt_hdr { ++ uint16_t magic; /* file type */ ++ uint8_t ld_major; /* linker major version */ ++ uint8_t ld_minor; /* linker minor version */ ++ uint32_t text_size; /* size of text section(s) */ ++ uint32_t data_size; /* size of data section(s) */ ++ uint32_t bss_size; /* size of bss section(s) */ ++ uint32_t entry_point; /* file offset of entry point */ ++ uint32_t code_base; /* relative code addr in ram */ ++ /* "windows" header */ ++ uint64_t image_base; /* preferred load address */ ++ uint32_t section_align; /* alignment in bytes */ ++ uint32_t file_align; /* file alignment in bytes */ ++ uint16_t os_major; /* major OS version */ ++ uint16_t os_minor; /* minor OS version */ ++ uint16_t image_major; /* major image version */ ++ uint16_t image_minor; /* minor image version */ ++ uint16_t subsys_major; /* major subsystem version */ ++ uint16_t subsys_minor; /* minor subsystem version */ ++ uint32_t win32_version; /* reserved, must be 0 */ ++ uint32_t image_size; /* image size */ ++ uint32_t header_size; /* header size rounded up to ++ file_align */ ++ uint32_t csum; /* checksum */ ++ uint16_t subsys; /* subsystem */ ++ uint16_t dll_flags; /* more flags! */ ++ uint64_t stack_size_req;/* amt of stack requested */ ++ uint64_t stack_size; /* amt of stack required */ ++ uint64_t heap_size_req; /* amt of heap requested */ ++ uint64_t heap_size; /* amt of heap required */ ++ uint32_t loader_flags; /* reserved, must be 0 */ ++ uint32_t data_dirs; /* number of data dir entries */ ++}; ++ ++struct data_dirent { ++ uint32_t virtual_address; /* relative to load address */ ++ uint32_t size; ++}; ++ ++struct data_directory { ++ struct data_dirent exports; /* .edata */ ++ struct data_dirent imports; /* .idata */ ++ struct data_dirent resources; /* .rsrc */ ++ struct data_dirent exceptions; /* .pdata */ ++ struct data_dirent certs; /* certs */ ++ struct data_dirent base_relocations; /* .reloc */ ++ struct data_dirent debug; /* .debug */ ++ struct data_dirent arch; /* reservered */ ++ struct data_dirent global_ptr; /* global pointer reg. Size=0 */ ++ struct data_dirent tls; /* .tls */ ++ struct data_dirent load_config; /* load configuration structure */ ++ struct data_dirent bound_imports; /* no idea */ ++ struct data_dirent import_addrs; /* import address table */ ++ struct data_dirent delay_imports; /* delay-load import table */ ++ struct data_dirent clr_runtime_hdr; /* .cor (object only) */ ++ struct data_dirent reserved; ++}; ++ ++struct section_header { ++ char name[8]; /* name or "/12\0" string tbl offset */ ++ uint32_t virtual_size; /* size of loaded section in ram */ ++ uint32_t virtual_address; /* relative virtual address */ ++ uint32_t raw_data_size; /* size of the section */ ++ uint32_t data_addr; /* file pointer to first page of sec */ ++ uint32_t relocs; /* file pointer to relocation entries */ ++ uint32_t line_numbers; /* line numbers! */ ++ uint16_t num_relocs; /* number of relocations */ ++ uint16_t num_lin_numbers; /* srsly. */ ++ uint32_t flags; ++}; ++ ++/* they actually defined 0x00000000 as well, but I think we'll skip that one. */ ++#define IMAGE_SCN_RESERVED_0 0x00000001 ++#define IMAGE_SCN_RESERVED_1 0x00000002 ++#define IMAGE_SCN_RESERVED_2 0x00000004 ++#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* don't pad - obsolete */ ++#define IMAGE_SCN_RESERVED_3 0x00000010 ++#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */ ++#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */ ++#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */ ++#define IMAGE_SCN_LNK_OTHER 0x00000100 /* reserved */ ++#define IMAGE_SCN_LNK_INFO 0x00000200 /* .drectve comments */ ++#define IMAGE_SCN_RESERVED_4 0x00000400 ++#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/ ++#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */ ++#define IMAGE_SCN_RESERVED_5 0x00002000 /* spec omits this */ ++#define IMAGE_SCN_RESERVED_6 0x00004000 /* spec omits this */ ++#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data */ ++/* spec lists 0x20000 twice, I suspect they meant 0x10000 for one of them */ ++#define IMAGE_SCN_MEM_PURGEABLE 0x00010000 /* reserved for "future" use */ ++#define IMAGE_SCN_16BIT 0x00020000 /* reserved for "future" use */ ++#define IMAGE_SCN_LOCKED 0x00040000 /* reserved for "future" use */ ++#define IMAGE_SCN_PRELOAD 0x00080000 /* reserved for "future" use */ ++/* and here they just stuck a 1-byte integer in the middle of a bitfield */ ++#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* it does what it says on the box */ ++#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 ++#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 ++#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 ++#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 ++#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 ++#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 ++#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 ++#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 ++#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000 ++#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000 ++#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000 ++#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000 ++#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000 ++#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* extended relocations */ ++#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */ ++#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */ ++#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */ ++#define IMAGE_SCN_MEM_SHARED 0x10000000 /* can be shared */ ++#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* can be executed as code */ ++#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */ ++#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */ ++ ++enum x64_coff_reloc_type { ++ IMAGE_REL_AMD64_ABSOLUTE = 0, ++ IMAGE_REL_AMD64_ADDR64, ++ IMAGE_REL_AMD64_ADDR32, ++ IMAGE_REL_AMD64_ADDR32N, ++ IMAGE_REL_AMD64_REL32, ++ IMAGE_REL_AMD64_REL32_1, ++ IMAGE_REL_AMD64_REL32_2, ++ IMAGE_REL_AMD64_REL32_3, ++ IMAGE_REL_AMD64_REL32_4, ++ IMAGE_REL_AMD64_REL32_5, ++ IMAGE_REL_AMD64_SECTION, ++ IMAGE_REL_AMD64_SECREL, ++ IMAGE_REL_AMD64_SECREL7, ++ IMAGE_REL_AMD64_TOKEN, ++ IMAGE_REL_AMD64_SREL32, ++ IMAGE_REL_AMD64_PAIR, ++ IMAGE_REL_AMD64_SSPAN32, ++}; ++ ++enum arm_coff_reloc_type { ++ IMAGE_REL_ARM_ABSOLUTE, ++ IMAGE_REL_ARM_ADDR32, ++ IMAGE_REL_ARM_ADDR32N, ++ IMAGE_REL_ARM_BRANCH2, ++ IMAGE_REL_ARM_BRANCH1, ++ IMAGE_REL_ARM_SECTION, ++ IMAGE_REL_ARM_SECREL, ++}; ++ ++enum sh_coff_reloc_type { ++ IMAGE_REL_SH3_ABSOLUTE, ++ IMAGE_REL_SH3_DIRECT16, ++ IMAGE_REL_SH3_DIRECT32, ++ IMAGE_REL_SH3_DIRECT8, ++ IMAGE_REL_SH3_DIRECT8_WORD, ++ IMAGE_REL_SH3_DIRECT8_LONG, ++ IMAGE_REL_SH3_DIRECT4, ++ IMAGE_REL_SH3_DIRECT4_WORD, ++ IMAGE_REL_SH3_DIRECT4_LONG, ++ IMAGE_REL_SH3_PCREL8_WORD, ++ IMAGE_REL_SH3_PCREL8_LONG, ++ IMAGE_REL_SH3_PCREL12_WORD, ++ IMAGE_REL_SH3_STARTOF_SECTION, ++ IMAGE_REL_SH3_SIZEOF_SECTION, ++ IMAGE_REL_SH3_SECTION, ++ IMAGE_REL_SH3_SECREL, ++ IMAGE_REL_SH3_DIRECT32_NB, ++ IMAGE_REL_SH3_GPREL4_LONG, ++ IMAGE_REL_SH3_TOKEN, ++ IMAGE_REL_SHM_PCRELPT, ++ IMAGE_REL_SHM_REFLO, ++ IMAGE_REL_SHM_REFHALF, ++ IMAGE_REL_SHM_RELLO, ++ IMAGE_REL_SHM_RELHALF, ++ IMAGE_REL_SHM_PAIR, ++ IMAGE_REL_SHM_NOMODE, ++}; ++ ++enum ppc_coff_reloc_type { ++ IMAGE_REL_PPC_ABSOLUTE, ++ IMAGE_REL_PPC_ADDR64, ++ IMAGE_REL_PPC_ADDR32, ++ IMAGE_REL_PPC_ADDR24, ++ IMAGE_REL_PPC_ADDR16, ++ IMAGE_REL_PPC_ADDR14, ++ IMAGE_REL_PPC_REL24, ++ IMAGE_REL_PPC_REL14, ++ IMAGE_REL_PPC_ADDR32N, ++ IMAGE_REL_PPC_SECREL, ++ IMAGE_REL_PPC_SECTION, ++ IMAGE_REL_PPC_SECREL16, ++ IMAGE_REL_PPC_REFHI, ++ IMAGE_REL_PPC_REFLO, ++ IMAGE_REL_PPC_PAIR, ++ IMAGE_REL_PPC_SECRELLO, ++ IMAGE_REL_PPC_GPREL, ++ IMAGE_REL_PPC_TOKEN, ++}; ++ ++enum x86_coff_reloc_type { ++ IMAGE_REL_I386_ABSOLUTE, ++ IMAGE_REL_I386_DIR16, ++ IMAGE_REL_I386_REL16, ++ IMAGE_REL_I386_DIR32, ++ IMAGE_REL_I386_DIR32NB, ++ IMAGE_REL_I386_SEG12, ++ IMAGE_REL_I386_SECTION, ++ IMAGE_REL_I386_SECREL, ++ IMAGE_REL_I386_TOKEN, ++ IMAGE_REL_I386_SECREL7, ++ IMAGE_REL_I386_REL32, ++}; ++ ++enum ia64_coff_reloc_type { ++ IMAGE_REL_IA64_ABSOLUTE, ++ IMAGE_REL_IA64_IMM14, ++ IMAGE_REL_IA64_IMM22, ++ IMAGE_REL_IA64_IMM64, ++ IMAGE_REL_IA64_DIR32, ++ IMAGE_REL_IA64_DIR64, ++ IMAGE_REL_IA64_PCREL21B, ++ IMAGE_REL_IA64_PCREL21M, ++ IMAGE_REL_IA64_PCREL21F, ++ IMAGE_REL_IA64_GPREL22, ++ IMAGE_REL_IA64_LTOFF22, ++ IMAGE_REL_IA64_SECTION, ++ IMAGE_REL_IA64_SECREL22, ++ IMAGE_REL_IA64_SECREL64I, ++ IMAGE_REL_IA64_SECREL32, ++ IMAGE_REL_IA64_DIR32NB, ++ IMAGE_REL_IA64_SREL14, ++ IMAGE_REL_IA64_SREL22, ++ IMAGE_REL_IA64_SREL32, ++ IMAGE_REL_IA64_UREL32, ++ IMAGE_REL_IA64_PCREL60X, ++ IMAGE_REL_IA64_PCREL60B, ++ IMAGE_REL_IA64_PCREL60F, ++ IMAGE_REL_IA64_PCREL60I, ++ IMAGE_REL_IA64_PCREL60M, ++ IMAGE_REL_IA64_IMMGPREL6, ++ IMAGE_REL_IA64_TOKEN, ++ IMAGE_REL_IA64_GPREL32, ++ IMAGE_REL_IA64_ADDEND, ++}; ++ ++struct coff_reloc { ++ uint32_t virtual_address; ++ uint32_t symbol_table_index; ++ union { ++ enum x64_coff_reloc_type x64_type; ++ enum arm_coff_reloc_type arm_type; ++ enum sh_coff_reloc_type sh_type; ++ enum ppc_coff_reloc_type ppc_type; ++ enum x86_coff_reloc_type x86_type; ++ enum ia64_coff_reloc_type ia64_type; ++ uint16_t data; ++ }; ++}; ++ ++/* ++ * Definitions for the contents of the certs data block ++ */ ++#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 ++#define WIN_CERT_TYPE_EFI_OKCS115 0x0EF0 ++#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 ++ ++#define WIN_CERT_REVISION_1_0 0x0100 ++#define WIN_CERT_REVISION_2_0 0x0200 ++ ++struct win_certificate { ++ uint32_t length; ++ uint16_t revision; ++ uint16_t cert_type; ++}; ++ ++#endif /* __LINUX_PE_H */ +-- +1.8.1.4 + + +From d329754b0c2881b6331aacafab74a26b2d9262b3 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:40 +0000 +Subject: [PATCH 21/47] pefile: Parse a PE binary to find a key and a signature + contained therein + +Parse a PE binary to find a key and a signature contained therein. Later +patches will check the signature and add the key if the signature checks out. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/Kconfig | 10 +- + crypto/asymmetric_keys/Makefile | 8 ++ + crypto/asymmetric_keys/pefile_parser.c | 185 +++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/pefile_parser.h | 31 ++++++ + 4 files changed, 233 insertions(+), 1 deletion(-) + create mode 100644 crypto/asymmetric_keys/pefile_parser.c + create mode 100644 crypto/asymmetric_keys/pefile_parser.h + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 413f3f6..2e7315c 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -31,7 +31,7 @@ config X509_CERTIFICATE_PARSER + select ASN1 + select OID_REGISTRY + help +- This option procides support for parsing X.509 format blobs for key ++ This option provides support for parsing X.509 format blobs for key + data and provides the ability to instantiate a crypto key from a + public key packet found inside the certificate. + +@@ -44,4 +44,12 @@ config PKCS7_MESSAGE_PARSER + This option provides support for parsing PKCS#7 format messages for + signature data and provides the ability to verify the signature. + ++config PE_FILE_PARSER ++ tristate "PE binary-wrapped key parser" ++ depends on X509_CERTIFICATE_PARSER ++ depends on PKCS7_MESSAGE_PARSER ++ help ++ This option provides support for parsing signed PE binaries that ++ contain an X.509 certificate in an internal section. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index d63cb43..2675146 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -40,3 +40,11 @@ $(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h + $(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h + + clean-files += pkcs7-asn1.c pkcs7-asn1.h ++ ++# ++# Signed PE binary-wrapped key handling ++# ++obj-$(CONFIG_PE_FILE_PARSER) += pefile_key_parser.o ++ ++pefile_key_parser-y := \ ++ pefile_parser.o +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +new file mode 100644 +index 0000000..fb80cf0 +--- /dev/null ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -0,0 +1,185 @@ ++/* Parse a signed PE binary that wraps a key. ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "PEFILE: "fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "asymmetric_keys.h" ++#include "public_key.h" ++#include "pefile_parser.h" ++ ++/* ++ * Parse a PE binary. ++ */ ++static int pefile_parse_binary(struct key_preparsed_payload *prep, ++ struct pefile_context *ctx) ++{ ++ const struct mz_hdr *mz = prep->data; ++ const struct pe_hdr *pe; ++ const struct pe32_opt_hdr *pe32; ++ const struct pe32plus_opt_hdr *pe64; ++ const struct data_directory *ddir; ++ const struct data_dirent *dde; ++ const struct section_header *secs, *sec; ++ unsigned loop; ++ size_t cursor, datalen = prep->datalen; ++ ++ kenter(""); ++ ++#define chkaddr(base, x, s) \ ++ do { \ ++ if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \ ++ return -ELIBBAD; \ ++ } while(0) ++ ++ chkaddr(0, 0, sizeof(*mz)); ++ if (mz->magic != MZ_MAGIC) ++ return -ELIBBAD; ++ cursor = sizeof(*mz); ++ ++ chkaddr(cursor, mz->peaddr, sizeof(*pe)); ++ pe = prep->data + mz->peaddr; ++ if (pe->magic != PE_MAGIC) ++ return -ELIBBAD; ++ cursor = mz->peaddr + sizeof(*pe); ++ ++ chkaddr(0, cursor, sizeof(pe32->magic)); ++ pe32 = prep->data + cursor; ++ pe64 = prep->data + cursor; ++ ++ switch (pe32->magic) { ++ case PE_OPT_MAGIC_PE32: ++ chkaddr(0, cursor, sizeof(*pe32)); ++ ctx->image_checksum_offset = ++ (unsigned long)&pe32->csum - (unsigned long)prep->data; ++ ctx->header_size = pe32->header_size; ++ cursor += sizeof(*pe32); ++ ctx->n_data_dirents = pe32->data_dirs; ++ break; ++ ++ case PE_OPT_MAGIC_PE32PLUS: ++ chkaddr(0, cursor, sizeof(*pe64)); ++ ctx->image_checksum_offset = ++ (unsigned long)&pe64->csum - (unsigned long)prep->data; ++ ctx->header_size = pe64->header_size; ++ cursor += sizeof(*pe64); ++ ctx->n_data_dirents = pe64->data_dirs; ++ break; ++ ++ default: ++ pr_devel("Unknown PEOPT magic = %04hx\n", pe32->magic); ++ return -ELIBBAD; ++ } ++ ++ pr_devel("checksum @ %x\n", ctx->image_checksum_offset); ++ pr_devel("header size = %x\n", ctx->header_size); ++ ++ if (cursor >= ctx->header_size || ctx->header_size >= datalen) ++ return -ELIBBAD; ++ ++ if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde) || ++ ctx->n_data_dirents < sizeof(*ddir) / sizeof(*dde)) ++ return -ELIBBAD; ++ ++ ddir = prep->data + cursor; ++ cursor += sizeof(*dde) * ctx->n_data_dirents; ++ ++ ctx->cert_dirent_offset = ++ (unsigned long)&ddir->certs - (unsigned long)prep->data; ++ ctx->certs_size = ddir->certs.size; ++ ++ if (!ddir->certs.virtual_address || !ddir->certs.size) { ++ pr_devel("Unsigned PE binary\n"); ++ return -EKEYREJECTED; ++ } ++ ++ chkaddr(ctx->header_size, ddir->certs.virtual_address, ddir->certs.size); ++ ctx->sig_offset = ddir->certs.virtual_address; ++ ctx->sig_len = ddir->certs.size; ++ pr_devel("cert = %x @%x [%*ph]\n", ++ ctx->sig_len, ctx->sig_offset, ++ ctx->sig_len, prep->data + ctx->sig_offset); ++ ++ /* Parse the section table, checking the parameters and looking for the ++ * section containing the list of keys. ++ */ ++ ctx->n_sections = pe->sections; ++ if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec)) ++ return -ELIBBAD; ++ ctx->secs = secs = prep->data + cursor; ++ cursor += sizeof(*sec) * ctx->n_sections; ++ ++ for (loop = 0; loop < ctx->n_sections; loop++) { ++ sec = &secs[loop]; ++ chkaddr(cursor, sec->data_addr, sec->raw_data_size); ++ if (memcmp(sec->name, ".keylist", 8) == 0) { ++ ctx->keylist_offset = sec->data_addr; ++ ctx->keylist_len = sec->raw_data_size; ++ } ++ } ++ ++ if (ctx->keylist_offset == 0) { ++ pr_devel("No .keylist section in PE binary\n"); ++ return -ENOENT; ++ } ++ ++ pr_devel("keylist = %x @%x [%*ph]\n", ++ ctx->keylist_len, ctx->keylist_offset, ++ ctx->keylist_len, prep->data + ctx->keylist_offset); ++ ++ return 0; ++} ++ ++/* ++ * Parse a PE binary. ++ */ ++static int pefile_key_preparse(struct key_preparsed_payload *prep) ++{ ++ struct pefile_context ctx; ++ int ret; ++ ++ kenter(""); ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ret = pefile_parse_binary(prep, &ctx); ++ if (ret < 0) ++ return ret; ++ ++ return -ENOANO; // Not yet complete ++} ++ ++static struct asymmetric_key_parser pefile_key_parser = { ++ .owner = THIS_MODULE, ++ .name = "pefile", ++ .parse = pefile_key_preparse, ++}; ++ ++/* ++ * Module stuff ++ */ ++static int __init pefile_key_init(void) ++{ ++ return register_asymmetric_key_parser(&pefile_key_parser); ++} ++ ++static void __exit pefile_key_exit(void) ++{ ++ unregister_asymmetric_key_parser(&pefile_key_parser); ++} ++ ++module_init(pefile_key_init); ++module_exit(pefile_key_exit); +diff --git a/crypto/asymmetric_keys/pefile_parser.h b/crypto/asymmetric_keys/pefile_parser.h +new file mode 100644 +index 0000000..82bcaf6 +--- /dev/null ++++ b/crypto/asymmetric_keys/pefile_parser.h +@@ -0,0 +1,31 @@ ++/* PE Binary parser bits ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++#include "pkcs7_parser.h" ++ ++struct pefile_context { ++ unsigned header_size; ++ unsigned image_checksum_offset; ++ unsigned cert_dirent_offset; ++ unsigned n_data_dirents; ++ unsigned n_sections; ++ unsigned certs_size; ++ unsigned sig_offset; ++ unsigned sig_len; ++ unsigned keylist_offset; ++ unsigned keylist_len; ++ const struct section_header *secs; ++ struct pkcs7_message *pkcs7; ++ ++ /* PKCS#7 MS Individual Code Signing content */ ++ const void *digest; /* Digest */ ++ unsigned digest_len; /* Digest length */ ++ enum pkey_hash_algo digest_algo; /* Digest algorithm */ ++}; +-- +1.8.1.4 + + +From 3794d7963e17fc0b0c2f62164306b9a45cb2254e Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:40 +0000 +Subject: [PATCH 22/47] pefile: Strip the wrapper off of the cert data block + +The certificate data block in a PE binary has a wrapper around the PKCS#7 +signature we actually want to get at. Strip this off and check that we've got +something that appears to be a PKCS#7 signature. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pefile_parser.c | 60 ++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index fb80cf0..f2d4df0 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -145,6 +146,61 @@ static int pefile_parse_binary(struct key_preparsed_payload *prep, + } + + /* ++ * Check and strip the PE wrapper from around the signature and check that the ++ * remnant looks something like PKCS#7. ++ */ ++static int pefile_strip_sig_wrapper(struct key_preparsed_payload *prep, ++ struct pefile_context *ctx) ++{ ++ struct win_certificate wrapper; ++ const u8 *pkcs7; ++ ++ if (ctx->sig_len < sizeof(wrapper)) { ++ pr_devel("Signature wrapper too short\n"); ++ return -ELIBBAD; ++ } ++ ++ memcpy(&wrapper, prep->data + ctx->sig_offset, sizeof(wrapper)); ++ pr_devel("sig wrapper = { %x, %x, %x }\n", ++ wrapper.length, wrapper.revision, wrapper.cert_type); ++ if (wrapper.length != ctx->sig_len) { ++ pr_devel("Signature wrapper len wrong\n"); ++ return -ELIBBAD; ++ } ++ if (wrapper.revision != WIN_CERT_REVISION_2_0) { ++ pr_devel("Signature is not revision 2.0\n"); ++ return -ENOTSUPP; ++ } ++ if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) { ++ pr_devel("Signature certificate type is not PKCS\n"); ++ return -ENOTSUPP; ++ } ++ ++ ctx->sig_offset += sizeof(wrapper); ++ ctx->sig_len -= sizeof(wrapper); ++ if (ctx->sig_len == 0) { ++ pr_devel("Signature data missing\n"); ++ return -EKEYREJECTED; ++ } ++ ++ /* What's left should a PKCS#7 cert */ ++ pkcs7 = prep->data + ctx->sig_offset; ++ if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) { ++ if (pkcs7[1] == 0x82 && ++ pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) && ++ pkcs7[3] == ((ctx->sig_len - 4) & 0xff)) ++ return 0; ++ if (pkcs7[1] == 0x80) ++ return 0; ++ if (pkcs7[1] > 0x82) ++ return -EMSGSIZE; ++ } ++ ++ pr_devel("Signature data not PKCS#7\n"); ++ return -ELIBBAD; ++} ++ ++/* + * Parse a PE binary. + */ + static int pefile_key_preparse(struct key_preparsed_payload *prep) +@@ -159,6 +215,10 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + if (ret < 0) + return ret; + ++ ret = pefile_strip_sig_wrapper(prep, &ctx); ++ if (ret < 0) ++ return ret; ++ + return -ENOANO; // Not yet complete + } + +-- +1.8.1.4 + + +From f23895761a15e08959140091dc17004e7e6e2035 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:40 +0000 +Subject: [PATCH 23/47] pefile: Parse the presumed PKCS#7 content of the + certificate blob + +Parse the content of the certificate blob, presuming it to be PKCS#7 format. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pefile_parser.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index f2d4df0..056500f 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -205,6 +205,7 @@ static int pefile_strip_sig_wrapper(struct key_preparsed_payload *prep, + */ + static int pefile_key_preparse(struct key_preparsed_payload *prep) + { ++ struct pkcs7_message *pkcs7; + struct pefile_context ctx; + int ret; + +@@ -219,7 +220,22 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + if (ret < 0) + return ret; + +- return -ENOANO; // Not yet complete ++ pkcs7 = pkcs7_parse_message(prep->data + ctx.sig_offset, ctx.sig_len); ++ if (IS_ERR(pkcs7)) ++ return PTR_ERR(pkcs7); ++ ctx.pkcs7 = pkcs7; ++ ++ if (!ctx.pkcs7->data || !ctx.pkcs7->data_len) { ++ pr_devel("PKCS#7 message does not contain data\n"); ++ ret = -EBADMSG; ++ goto error; ++ } ++ ++ ret = -ENOANO; // Not yet complete ++ ++error: ++ pkcs7_free_message(ctx.pkcs7); ++ return ret; + } + + static struct asymmetric_key_parser pefile_key_parser = { +-- +1.8.1.4 + + +From fcdb91196beb6235eed676c368a662cbdf92b804 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:41 +0000 +Subject: [PATCH 24/47] pefile: Parse the "Microsoft individual code signing" + data blob + +The PKCS#7 certificate should contain a "Microsoft individual code signing" +data blob as its signed content. This blob contains a digest of the signed +content of the PE binary and the OID of the digest algorithm used (typically +SHA256). + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/Makefile | 9 ++- + crypto/asymmetric_keys/mscode.asn1 | 28 +++++++++ + crypto/asymmetric_keys/mscode_parser.c | 110 +++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/pefile_parser.c | 6 ++ + crypto/asymmetric_keys/pefile_parser.h | 5 ++ + include/linux/oid_registry.h | 6 +- + 6 files changed, 162 insertions(+), 2 deletions(-) + create mode 100644 crypto/asymmetric_keys/mscode.asn1 + create mode 100644 crypto/asymmetric_keys/mscode_parser.c + +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 2675146..ddc64bb 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -47,4 +47,11 @@ clean-files += pkcs7-asn1.c pkcs7-asn1.h + obj-$(CONFIG_PE_FILE_PARSER) += pefile_key_parser.o + + pefile_key_parser-y := \ +- pefile_parser.o ++ pefile_parser.o \ ++ mscode_parser.o \ ++ mscode-asn1.o ++ ++$(obj)/mscode_parser.o: $(obj)/mscode-asn1.h $(obj)/mscode-asn1.h ++$(obj)/mscode-asn1.o: $(obj)/mscode-asn1.c $(obj)/mscode-asn1.h ++ ++clean-files += mscode-asn1.c mscode-asn1.h +diff --git a/crypto/asymmetric_keys/mscode.asn1 b/crypto/asymmetric_keys/mscode.asn1 +new file mode 100644 +index 0000000..6d09ba4 +--- /dev/null ++++ b/crypto/asymmetric_keys/mscode.asn1 +@@ -0,0 +1,28 @@ ++--- Microsoft individual code signing data blob parser ++--- ++--- Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++--- Written by David Howells (dhowells@redhat.com) ++--- ++--- This program is free software; you can redistribute it and/or ++--- modify it under the terms of the GNU General Public Licence ++--- as published by the Free Software Foundation; either version ++--- 2 of the Licence, or (at your option) any later version. ++--- ++ ++MSCode ::= SEQUENCE { ++ type SEQUENCE { ++ contentType ContentType, ++ parameters ANY ++ }, ++ content SEQUENCE { ++ digestAlgorithm DigestAlgorithmIdentifier, ++ digest OCTET STRING ({ mscode_note_digest }) ++ } ++} ++ ++ContentType ::= OBJECT IDENTIFIER ({ mscode_note_content_type }) ++ ++DigestAlgorithmIdentifier ::= SEQUENCE { ++ algorithm OBJECT IDENTIFIER ({ mscode_note_digest_algo }), ++ parameters ANY OPTIONAL ++} +diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c +new file mode 100644 +index 0000000..0bd68e0 +--- /dev/null ++++ b/crypto/asymmetric_keys/mscode_parser.c +@@ -0,0 +1,110 @@ ++/* Parse a Microsoft Individual Code Signing blob ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "MSCODE: "fmt ++#include ++#include ++#include ++#include ++#include "pefile_parser.h" ++#include "mscode-asn1.h" ++ ++/* ++ * Parse a Microsoft Individual Code Signing blob ++ */ ++int mscode_parse(struct pefile_context *ctx) ++{ ++ pr_devel("Data: %zu [%*ph]\n", ++ ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen, ++ (unsigned)(ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen), ++ ctx->pkcs7->data - ctx->pkcs7->data_hdrlen); ++ ++ return asn1_ber_decoder(&mscode_decoder, ctx, ++ ctx->pkcs7->data - ctx->pkcs7->data_hdrlen, ++ ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen); ++} ++ ++/* ++ * Check the content type OID ++ */ ++int mscode_note_content_type(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ enum OID oid; ++ ++ oid = look_up_OID(value, vlen); ++ if (oid == OID__NR) { ++ char buffer[50]; ++ sprint_oid(value, vlen, buffer, sizeof(buffer)); ++ printk("MSCODE: Unknown OID: %s\n", buffer); ++ return -EBADMSG; ++ } ++ ++ if (oid != OID_msIndividualSPKeyPurpose) { ++ printk("MSCODE: Unexpected content type OID %u\n", oid); ++ return -EBADMSG; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Note the digest algorithm OID ++ */ ++int mscode_note_digest_algo(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pefile_context *ctx = context; ++ char buffer[50]; ++ enum OID oid; ++ ++ oid = look_up_OID(value, vlen); ++ switch (oid) { ++ case OID_md4: ++ ctx->digest_algo = PKEY_HASH_MD4; ++ break; ++ case OID_md5: ++ ctx->digest_algo = PKEY_HASH_MD5; ++ break; ++ case OID_sha1: ++ ctx->digest_algo = PKEY_HASH_SHA1; ++ break; ++ case OID_sha256: ++ ctx->digest_algo = PKEY_HASH_SHA256; ++ break; ++ ++ case OID__NR: ++ sprint_oid(value, vlen, buffer, sizeof(buffer)); ++ printk("MSCODE: Unknown OID: %s\n", buffer); ++ return -EBADMSG; ++ ++ default: ++ printk("MSCODE: Unsupported content type: %u\n", oid); ++ return -ENOPKG; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Note the digest we're guaranteeing with this certificate ++ */ ++int mscode_note_digest(void *context, size_t hdrlen, ++ unsigned char tag, ++ const void *value, size_t vlen) ++{ ++ struct pefile_context *ctx = context; ++ ctx->digest = value; ++ ctx->digest_len = vlen; ++ return 0; ++} +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index 056500f..f1c8cc1 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -231,6 +231,12 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + goto error; + } + ++ ret = mscode_parse(&ctx); ++ if (ret < 0) ++ goto error; ++ ++ pr_devel("Digest: %u [%*ph]\n", ctx.digest_len, ctx.digest_len, ctx.digest); ++ + ret = -ENOANO; // Not yet complete + + error: +diff --git a/crypto/asymmetric_keys/pefile_parser.h b/crypto/asymmetric_keys/pefile_parser.h +index 82bcaf6..c3462b7 100644 +--- a/crypto/asymmetric_keys/pefile_parser.h ++++ b/crypto/asymmetric_keys/pefile_parser.h +@@ -29,3 +29,8 @@ struct pefile_context { + unsigned digest_len; /* Digest length */ + enum pkey_hash_algo digest_algo; /* Digest algorithm */ + }; ++ ++/* ++ * mscode_parser.c ++ */ ++extern int mscode_parse(struct pefile_context *ctx); +diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h +index edeff85..332dcf5 100644 +--- a/include/linux/oid_registry.h ++++ b/include/linux/oid_registry.h +@@ -52,8 +52,12 @@ enum OID { + OID_md4, /* 1.2.840.113549.2.4 */ + OID_md5, /* 1.2.840.113549.2.5 */ + +- OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ ++ /* Microsoft Authenticode & Software Publishing */ ++ OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ ++ OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ + OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ ++ ++ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ + OID_sha1, /* 1.3.14.3.2.26 */ + OID_sha256, /* 2.16.840.1.101.3.4.2.1 */ + +-- +1.8.1.4 + + +From 63204898d9491f8ba1b90dea8660e8ff778db993 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:41 +0000 +Subject: [PATCH 25/47] pefile: Digest the PE binary and compare to the PKCS#7 + data + +Digest the signed parts of the PE binary, canonicalising the section table +before we need it, and then compare the the resulting digest to the one in the +PKCS#7 signed content. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pefile_parser.c | 198 +++++++++++++++++++++++++++++++++ + 1 file changed, 198 insertions(+) + +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index f1c8cc1..dfdb85e 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -201,6 +201,193 @@ static int pefile_strip_sig_wrapper(struct key_preparsed_payload *prep, + } + + /* ++ * Compare two sections for canonicalisation. ++ */ ++static int pefile_compare_shdrs(const void *a, const void *b) ++{ ++ const struct section_header *shdra = a; ++ const struct section_header *shdrb = b; ++ int rc; ++ ++ if (shdra->data_addr > shdrb->data_addr) ++ return 1; ++ if (shdrb->data_addr > shdra->data_addr) ++ return -1; ++ ++ if (shdra->virtual_address > shdrb->virtual_address) ++ return 1; ++ if (shdrb->virtual_address > shdra->virtual_address) ++ return -1; ++ ++ rc = strcmp(shdra->name, shdrb->name); ++ if (rc != 0) ++ return rc; ++ ++ if (shdra->virtual_size > shdrb->virtual_size) ++ return 1; ++ if (shdrb->virtual_size > shdra->virtual_size) ++ return -1; ++ ++ if (shdra->raw_data_size > shdrb->raw_data_size) ++ return 1; ++ if (shdrb->raw_data_size > shdra->raw_data_size) ++ return -1; ++ ++ return 0; ++} ++ ++/* ++ * Load the contents of the PE binary into the digest, leaving out the image ++ * checksum and the certificate data block. ++ */ ++static int pefile_digest_pe_contents(struct key_preparsed_payload *prep, ++ struct pefile_context *ctx, ++ struct shash_desc *desc) ++{ ++ unsigned *canon, tmp, loop, i, hashed_bytes; ++ int ret; ++ ++ /* Digest the header and data directory, but leave out the image ++ * checksum and the data dirent for the signature. ++ */ ++ ret = crypto_shash_update(desc, prep->data, ctx->image_checksum_offset); ++ if (ret < 0) ++ return ret; ++ ++ tmp = ctx->image_checksum_offset + sizeof(uint32_t); ++ ret = crypto_shash_update(desc, prep->data + tmp, ++ ctx->cert_dirent_offset - tmp); ++ if (ret < 0) ++ return ret; ++ ++ tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent); ++ ret = crypto_shash_update(desc, prep->data + tmp, ++ ctx->header_size - tmp); ++ if (ret < 0) ++ return ret; ++ ++ canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL); ++ if (!canon) ++ return -ENOMEM; ++ ++ /* We have to canonicalise the section table, so we perform an ++ * insertion sort. ++ */ ++ canon[0] = 0; ++ for (loop = 1; loop < ctx->n_sections; loop++) { ++ for (i = 0; i < loop; i++) { ++ if (pefile_compare_shdrs(&ctx->secs[canon[i]], ++ &ctx->secs[loop]) > 0) { ++ memmove(&canon[i + 1], &canon[i], ++ (loop - i) * sizeof(canon[0])); ++ break; ++ } ++ } ++ canon[i] = loop; ++ } ++ ++ hashed_bytes = ctx->header_size; ++ for (loop = 0; loop < ctx->n_sections; loop++) { ++ i = canon[loop]; ++ if (ctx->secs[i].raw_data_size == 0) ++ continue; ++ ret = crypto_shash_update(desc, ++ prep->data + ctx->secs[i].data_addr, ++ ctx->secs[i].raw_data_size); ++ if (ret < 0) { ++ kfree(canon); ++ return ret; ++ } ++ hashed_bytes += ctx->secs[i].raw_data_size; ++ } ++ kfree(canon); ++ ++ if (prep->datalen > hashed_bytes) { ++ tmp = hashed_bytes + ctx->certs_size; ++ ret = crypto_shash_update(desc, ++ prep->data + hashed_bytes, ++ prep->datalen - tmp); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Digest the contents of the PE binary, leaving out the image checksum and the ++ * certificate data block. ++ */ ++static int pefile_digest_pe(struct key_preparsed_payload *prep, ++ struct pefile_context *ctx) ++{ ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ void *digest; ++ int ret; ++ ++ kenter(",%u", ctx->digest_algo); ++ ++ /* Allocate the hashing algorithm we're going to need and find out how ++ * big the hash operational data will be. ++ */ ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[ctx->digest_algo], 0, 0); ++ if (IS_ERR(tfm)) ++ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ ++ if (digest_size != ctx->digest_len) { ++ pr_debug("Digest size mismatch (%zx != %x)\n", ++ digest_size, ctx->digest_len); ++ ret = -EBADMSG; ++ goto error_no_desc; ++ } ++ pr_devel("Digest: desc=%zu size=%zu\n", desc_size, digest_size); ++ ++ ret = -ENOMEM; ++ desc = kzalloc(desc_size + digest_size, GFP_KERNEL); ++ if (!desc) ++ goto error_no_desc; ++ ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error; ++ ++ ret = pefile_digest_pe_contents(prep, ctx, desc); ++ if (ret < 0) ++ goto error; ++ ++ digest = (void *)desc + desc_size; ++ ret = crypto_shash_final(desc, digest); ++ if (ret < 0) ++ goto error; ++ ++ pr_devel("Digest calc = [%*ph]\n", ctx->digest_len, digest); ++ ++ /* Check that the PE file digest matches that in the MSCODE part of the ++ * PKCS#7 certificate. ++ */ ++ if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) { ++ pr_debug("Digest mismatch\n"); ++ ret = -EKEYREJECTED; ++ } else { ++ pr_debug("The digests match!\n"); ++ } ++ ++error: ++ kfree(desc); ++error_no_desc: ++ crypto_free_shash(tfm); ++ kleave(" = %d", ret); ++ return ret; ++} ++ ++/* + * Parse a PE binary. + */ + static int pefile_key_preparse(struct key_preparsed_payload *prep) +@@ -237,6 +424,17 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Digest: %u [%*ph]\n", ctx.digest_len, ctx.digest_len, ctx.digest); + ++ /* Generate the digest and check against the PKCS7 certificate ++ * contents. ++ */ ++ ret = pefile_digest_pe(prep, &ctx); ++ if (ret < 0) ++ goto error; ++ ++ ret = pkcs7_verify(pkcs7); ++ if (ret < 0) ++ goto error; ++ + ret = -ENOANO; // Not yet complete + + error: +-- +1.8.1.4 + + +From 17ed825e5f3f595665abd3fc11a6c180e6762b87 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 Jan 2013 13:58:35 +0000 +Subject: [PATCH 26/47] PEFILE: Validate PKCS#7 trust chain + +Validate the PKCS#7 trust chain against the contents of the system keyring. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 1 + + crypto/asymmetric_keys/pefile_parser.c | 5 +++++ + 2 files changed, 6 insertions(+) + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 2e7315c..2777916 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -48,6 +48,7 @@ config PE_FILE_PARSER + tristate "PE binary-wrapped key parser" + depends on X509_CERTIFICATE_PARSER + depends on PKCS7_MESSAGE_PARSER ++ depends on SYSTEM_TRUSTED_KEYRING + help + This option provides support for parsing signed PE binaries that + contain an X.509 certificate in an internal section. +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index dfdb85e..edad948 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include "asymmetric_keys.h" + #include "public_key.h" +@@ -435,6 +436,10 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + if (ret < 0) + goto error; + ++ ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &prep->trusted); ++ if (ret < 0) ++ goto error; ++ + ret = -ENOANO; // Not yet complete + + error: +-- +1.8.1.4 + + +From ce9ca4236f691264a94bcbe10beda9ec5a035baf Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 15 Jan 2013 15:33:42 +0000 +Subject: [PATCH 27/47] PEFILE: Load the contained key if we consider the + container to be validly signed + +Load the key contained in the PE binary if the signature on the container can +be verified by following the chain of X.509 certificates in the PKCS#7 message +to a key that we already trust. Typically, the trusted key will be acquired +from a source outside of the kernel, such as the UEFI database. + +Signed-off-by: David Howells +Reviewed-by: Kees Cook +--- + crypto/asymmetric_keys/pefile_parser.c | 11 ++++++++++- + crypto/asymmetric_keys/x509_parser.h | 3 +++ + crypto/asymmetric_keys/x509_public_key.c | 3 ++- + 3 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c +index edad948..c3efe39 100644 +--- a/crypto/asymmetric_keys/pefile_parser.c ++++ b/crypto/asymmetric_keys/pefile_parser.c +@@ -395,6 +395,8 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + { + struct pkcs7_message *pkcs7; + struct pefile_context ctx; ++ const void *saved_data; ++ size_t saved_datalen; + int ret; + + kenter(""); +@@ -440,7 +442,14 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) + if (ret < 0) + goto error; + +- ret = -ENOANO; // Not yet complete ++ /* We can now try to load the key */ ++ saved_data = prep->data; ++ saved_datalen = prep->datalen; ++ prep->data += ctx.keylist_offset; ++ prep->datalen = ctx.keylist_len; ++ ret = x509_key_preparse(prep); ++ prep->data = saved_data; ++ prep->datalen = saved_datalen; + + error: + pkcs7_free_message(ctx.pkcs7); +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 5e35fba..65452c4 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -12,6 +12,8 @@ + #include + #include + ++struct key_preparsed_payload; ++ + struct x509_certificate { + struct x509_certificate *next; + const struct x509_certificate *signer; /* Certificate that signed this one */ +@@ -47,3 +49,4 @@ extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen + extern int x509_get_sig_params(struct x509_certificate *cert); + extern int x509_check_signature(const struct public_key *pub, + struct x509_certificate *cert); ++extern int x509_key_preparse(struct key_preparsed_payload *prep); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 0f55e3b..c3e5a6d 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -105,7 +105,7 @@ EXPORT_SYMBOL_GPL(x509_check_signature); + /* + * Attempt to parse a data blob for a key as an X509 certificate. + */ +-static int x509_key_preparse(struct key_preparsed_payload *prep) ++int x509_key_preparse(struct key_preparsed_payload *prep) + { + struct x509_certificate *cert; + struct tm now; +@@ -229,6 +229,7 @@ error_free_cert: + x509_free_certificate(cert); + return ret; + } ++EXPORT_SYMBOL_GPL(x509_key_preparse); + + static struct asymmetric_key_parser x509_key_parser = { + .owner = THIS_MODULE, +-- +1.8.1.4 + + +From 395cc1b55a0645ced39f92b31ba3bcc141e59383 Mon Sep 17 00:00:00 2001 +From: Chun-Yi Lee +Date: Thu, 21 Feb 2013 19:23:49 +0800 +Subject: [PATCH 28/47] MODSIGN: Fix including certificate twice when the + signing_key.x509 already exists + +This issue was found in devel-pekey branch on linux-modsign.git tree. The +x509_certificate_list includes certificate twice when the signing_key.x509 +already exists. +We can reproduce this issue by making kernel twice, the build log of +second time looks like this: + +... + CHK kernel/config_data.h + CERTS kernel/x509_certificate_list + - Including cert /ramdisk/working/joey/linux-modsign/signing_key.x509 + - Including cert signing_key.x509 +... + +Actually the build path was the same with the srctree path when building +kernel. It causes the size of bzImage increased by packaging certificates +twice. + +Cc: Rusty Russell +Cc: Josh Boyer +Cc: Randy Dunlap +Cc: Herbert Xu +Cc: "David S. Miller" +Cc: Michal Marek +Signed-off-by: Chun-Yi Lee +Signed-off-by: David Howells +--- + kernel/Makefile | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index ecff938..52f3426 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -149,7 +149,10 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE + # + ############################################################################### + ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) +-X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) ++X509_CERTIFICATES-y := $(wildcard *.x509) ++ifneq ($(shell pwd), $(srctree)) ++X509_CERTIFICATES-y += $(wildcard $(srctree)/*.x509) ++endif + X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 + X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) + +-- +1.8.1.4 + + +From 0ef575739cff3fda47dd2a9415f066ab44dcc922 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:56 -0400 +Subject: [PATCH 29/47] Secure boot: Add new capability + +Secure boot adds certain policy requirements, including that root must not +be able to do anything that could cause the kernel to execute arbitrary code. +The simplest way to handle this would seem to be to add a new capability +and gate various functionality on that. We'll then strip it from the initial +capability set if required. + +Signed-off-by: Matthew Garrett +--- + include/uapi/linux/capability.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h +index ba478fa..7109e65 100644 +--- a/include/uapi/linux/capability.h ++++ b/include/uapi/linux/capability.h +@@ -343,7 +343,11 @@ struct vfs_cap_data { + + #define CAP_BLOCK_SUSPEND 36 + +-#define CAP_LAST_CAP CAP_BLOCK_SUSPEND ++/* Allow things that trivially permit root to modify the running kernel */ ++ ++#define CAP_COMPROMISE_KERNEL 37 ++ ++#define CAP_LAST_CAP CAP_COMPROMISE_KERNEL + + #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) + +-- +1.8.1.4 + + +From 7312bed4fb9125d4880f11a64521b110079a3c0a Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:05 -0400 +Subject: [PATCH 30/47] SELinux: define mapping for new Secure Boot capability + +Add the name of the new Secure Boot capability. This allows SELinux +policies to properly map CAP_COMPROMISE_KERNEL to the appropriate +capability class. + +Signed-off-by: Josh Boyer +--- + security/selinux/include/classmap.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h +index 14d04e6..ed99a2d 100644 +--- a/security/selinux/include/classmap.h ++++ b/security/selinux/include/classmap.h +@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { + { "memprotect", { "mmap_zero", NULL } }, + { "peer", { "recv", NULL } }, + { "capability2", +- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", +- NULL } }, ++ { "mac_override", "mac_admin", "syslog", "wake_alarm", ++ "block_suspend", "compromise_kernel", NULL } }, + { "kernel_service", { "use_as_override", "create_files_as", NULL } }, + { "tun_socket", + { COMMON_SOCK_PERMS, "attach_queue", NULL } }, +-- +1.8.1.4 + + +From e99e1273b0a50d874d2a53461e95f74460e1b812 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:02 -0400 +Subject: [PATCH 31/47] Secure boot: Add a dummy kernel parameter that will + switch on Secure Boot mode + +This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset +in the init_cred struct, which everything else inherits from. This works on +any machine and can be used to develop even if the box doesn't have UEFI. + +Signed-off-by: Josh Boyer +--- + Documentation/kernel-parameters.txt | 7 +++++++ + kernel/cred.c | 17 +++++++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 8c01a02..ee6c1ca 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -2744,6 +2744,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + Note: increases power consumption, thus should only be + enabled if running jitter sensitive (HPC/RT) workloads. + ++ secureboot_enable= ++ [KNL] Enables an emulated UEFI Secure Boot mode. This ++ locks down various aspects of the kernel guarded by the ++ CAP_COMPROMISE_KERNEL capability. This includes things ++ like /dev/mem, IO port access, and other areas. It can ++ be used on non-UEFI machines for testing purposes. ++ + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be +diff --git a/kernel/cred.c b/kernel/cred.c +index e0573a4..c3f4e3e 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -565,6 +565,23 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++void __init secureboot_enable() ++{ ++ pr_info("Secure boot enabled\n"); ++ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); ++ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++} ++ ++/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ ++static int __init secureboot_enable_opt(char *str) ++{ ++ int sb_enable = !!simple_strtol(str, NULL, 0); ++ if (sb_enable) ++ secureboot_enable(); ++ return 1; ++} ++__setup("secureboot_enable=", secureboot_enable_opt); ++ + /** + * prepare_kernel_cred - Prepare a set of credentials for a kernel service + * @daemon: A userspace daemon to be used as a reference +-- +1.8.1.4 + + +From eeac2b5391d834eefebfae49a100244fdccc82e5 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:03 -0400 +Subject: [PATCH 32/47] efi: Enable secure boot lockdown automatically when + enabled in firmware + +The firmware has a set of flags that indicate whether secure boot is enabled +and enforcing. Use them to indicate whether the kernel should lock itself +down. We also indicate the machine is in secure boot mode by adding the +EFI_SECURE_BOOT bit for use with efi_enabled. + +Signed-off-by: Matthew Garrett +Signed-off-by: Josh Boyer +--- + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ + arch/x86/include/asm/bootparam_utils.h | 8 ++++++-- + arch/x86/include/uapi/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 7 +++++++ + include/linux/cred.h | 2 ++ + include/linux/efi.h | 1 + + 7 files changed, 52 insertions(+), 3 deletions(-) + +diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt +index 199f453..ff651d3 100644 +--- a/Documentation/x86/zero-page.txt ++++ b/Documentation/x86/zero-page.txt +@@ -30,6 +30,8 @@ Offset Proto Name Meaning + 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) + 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer + (below) ++1EB/001 ALL kbd_status Numlock is enabled ++1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns + 1EF/001 ALL sentinel Used to detect broken bootloaders + 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures + 2D0/A00 ALL e820_map E820 memory map table +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 35ee62f..0998ec7 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -906,6 +906,36 @@ fail: + return status; + } + ++static int get_secure_boot(efi_system_table_t *_table) ++{ ++ u8 sb, setup; ++ unsigned long datasize = sizeof(sb); ++ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; ++ efi_status_t status; ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SecureBoot", &var_guid, NULL, &datasize, &sb); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (sb == 0) ++ return 0; ++ ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SetupMode", &var_guid, NULL, &datasize, ++ &setup); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (setup == 1) ++ return 0; ++ ++ return 1; ++} ++ + /* + * Because the x86 boot code expects to be passed a boot_params we + * need to create one ourselves (usually the bootloader would create +@@ -1200,6 +1230,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, + if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + goto fail; + ++ boot_params->secure_boot = get_secure_boot(sys_table); ++ + setup_graphics(boot_params); + + setup_efi_vars(boot_params); +diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h +index 653668d..69a6c08 100644 +--- a/arch/x86/include/asm/bootparam_utils.h ++++ b/arch/x86/include/asm/bootparam_utils.h +@@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params) + memset(&boot_params->olpc_ofw_header, 0, + (char *)&boot_params->efi_info - + (char *)&boot_params->olpc_ofw_header); +- memset(&boot_params->kbd_status, 0, ++ memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status)); ++ /* don't clear boot_params->secure_boot. we set that ourselves ++ * earlier. ++ */ ++ memset(&boot_params->_pad5[0], 0, + (char *)&boot_params->hdr - +- (char *)&boot_params->kbd_status); ++ (char *)&boot_params->_pad5[0]); + memset(&boot_params->_pad7[0], 0, + (char *)&boot_params->edd_mbr_sig_buffer[0] - + (char *)&boot_params->_pad7[0]); +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 0874424..56b7d39 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -132,7 +132,8 @@ struct boot_params { + __u8 eddbuf_entries; /* 0x1e9 */ + __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ + __u8 kbd_status; /* 0x1eb */ +- __u8 _pad5[3]; /* 0x1ec */ ++ __u8 secure_boot; /* 0x1ec */ ++ __u8 _pad5[2]; /* 0x1ed */ + /* + * The sentinel is set to a nonzero value (0xff) in header.S. + * +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 56f7fcf..3af6cf8 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1131,6 +1131,13 @@ void __init setup_arch(char **cmdline_p) + + io_delay_init(); + ++ if (boot_params.secure_boot) { ++#ifdef CONFIG_EFI ++ set_bit(EFI_SECURE_BOOT, &x86_efi_facility); ++#endif ++ secureboot_enable(); ++ } ++ + /* + * Parse the ACPI tables for possible boot-time SMP configuration. + */ +diff --git a/include/linux/cred.h b/include/linux/cred.h +index 04421e8..9e69542 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -156,6 +156,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); + extern int set_create_files_as(struct cred *, struct inode *); + extern void __init cred_init(void); + ++extern void secureboot_enable(void); ++ + /* + * check for validity of credentials + */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 2bc0ad7..10b167a 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *); + #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ + #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ + #define EFI_64BIT 5 /* Is the firmware 64-bit? */ ++#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */ + + #ifdef CONFIG_EFI + # ifdef CONFIG_X86 +-- +1.8.1.4 + + +From a1ac3b80b7a85d4fce665047b9701713fcfc1ea0 Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:30:54 -0400 +Subject: [PATCH 33/47] Add EFI signature data types + +Add the data types that are used for containing hashes, keys and certificates +for cryptographic verification. + +Signed-off-by: David Howells +--- + include/linux/efi.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 10b167a..d3ef7c6 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si + #define EFI_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + ++#define EFI_CERT_SHA256_GUID \ ++ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) ++ ++#define EFI_CERT_X509_GUID \ ++ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +@@ -524,6 +530,20 @@ typedef struct { + + #define EFI_INVALID_TABLE_ADDR (~0UL) + ++typedef struct { ++ efi_guid_t signature_owner; ++ u8 signature_data[]; ++} efi_signature_data_t; ++ ++typedef struct { ++ efi_guid_t signature_type; ++ u32 signature_list_size; ++ u32 signature_header_size; ++ u32 signature_size; ++ u8 signature_header[]; ++ /* efi_signature_data_t signatures[][] */ ++} efi_signature_list_t; ++ + /* + * All runtime access to EFI goes through this structure: + */ +-- +1.8.1.4 + + +From fac308c18ba449322666325f37f6a08ad818cf9f Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:36:28 -0400 +Subject: [PATCH 34/47] Add an EFI signature blob parser and key loader. + +X.509 certificates are loaded into the specified keyring as asymmetric type +keys. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 8 +++ + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/efi_parser.c | 109 ++++++++++++++++++++++++++++++++++++ + include/linux/efi.h | 4 ++ + 4 files changed, 122 insertions(+) + create mode 100644 crypto/asymmetric_keys/efi_parser.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 2777916..429bbb7 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -53,4 +53,12 @@ config PE_FILE_PARSER + This option provides support for parsing signed PE binaries that + contain an X.509 certificate in an internal section. + ++config EFI_SIGNATURE_LIST_PARSER ++ bool "EFI signature list parser" ++ depends on EFI ++ select X509_CERTIFICATE_PARSER ++ help ++ This option provides support for parsing EFI signature lists for ++ X.509 certificates and turning them into keys. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index ddc64bb..360b308 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o + + # + # X.509 Certificate handling +diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c +new file mode 100644 +index 0000000..424896a +--- /dev/null ++++ b/crypto/asymmetric_keys/efi_parser.c +@@ -0,0 +1,109 @@ ++/* EFI signature/key/certificate list parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "EFI: "fmt ++#include ++#include ++#include ++#include ++#include ++ ++static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; ++ ++/** ++ * parse_efi_signature_list - Parse an EFI signature list for certificates ++ * @data: The data blob to parse ++ * @size: The size of the data blob ++ * @keyring: The keyring to add extracted keys to ++ */ ++int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) ++{ ++ unsigned offs = 0; ++ size_t lsize, esize, hsize, elsize; ++ ++ pr_devel("-->%s(,%zu)\n", __func__, size); ++ ++ while (size > 0) { ++ efi_signature_list_t list; ++ const efi_signature_data_t *elem; ++ key_ref_t key; ++ ++ if (size < sizeof(list)) ++ return -EBADMSG; ++ ++ memcpy(&list, data, sizeof(list)); ++ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", ++ offs, ++ list.signature_type.b, list.signature_list_size, ++ list.signature_header_size, list.signature_size); ++ ++ lsize = list.signature_list_size; ++ hsize = list.signature_header_size; ++ esize = list.signature_size; ++ elsize = lsize - sizeof(list) - hsize; ++ ++ if (lsize > size) { ++ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", ++ __func__, offs); ++ return -EBADMSG; ++ } ++ if (lsize < sizeof(list) || ++ lsize - sizeof(list) < hsize || ++ esize < sizeof(*elem) || ++ elsize < esize || ++ elsize % esize != 0) { ++ pr_devel("- bad size combo @%x\n", offs); ++ return -EBADMSG; ++ } ++ ++ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { ++ data += lsize; ++ size -= lsize; ++ offs += lsize; ++ continue; ++ } ++ ++ data += sizeof(list) + hsize; ++ size -= sizeof(list) + hsize; ++ offs += sizeof(list) + hsize; ++ ++ for (; elsize > 0; elsize -= esize) { ++ elem = data; ++ ++ pr_devel("ELEM[%04x]\n", offs); ++ ++ key = key_create_or_update( ++ make_key_ref(keyring, 1), ++ "asymmetric", ++ NULL, ++ &elem->signature_data, ++ esize - sizeof(*elem), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA | ++ KEY_ALLOC_TRUSTED); ++ ++ if (IS_ERR(key)) ++ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("Loaded cert '%s' linked to '%s'\n", ++ key_ref_to_ptr(key)->description, ++ keyring->description); ++ ++ data += esize; ++ size -= esize; ++ offs += esize; ++ } ++ } ++ ++ return 0; ++} +diff --git a/include/linux/efi.h b/include/linux/efi.h +index d3ef7c6..4f0fbb7 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); + extern void efi_reserve_boot_services(void); + extern struct efi_memory_map memmap; + ++struct key; ++extern int __init parse_efi_signature_list(const void *data, size_t size, ++ struct key *keyring); ++ + /** + * efi_range_is_wc - check the WC bit on an address range + * @start: starting kvirt address +-- +1.8.1.4 + + +From 75560e565cb8a4e853a3b6f6c65ed70c1ba29039 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:36:24 -0400 +Subject: [PATCH 35/47] KEYS: Add a system blacklist keyring + +This adds an additional keyring that is used to store certificates that +are blacklisted. This keyring is searched first when loading signed modules +and if the module's certificate is found, it will refuse to load. This is +useful in cases where third party certificates are used for module signing. + +Signed-off-by: Josh Boyer +--- + include/keys/system_keyring.h | 4 ++++ + init/Kconfig | 9 +++++++++ + kernel/module_signing.c | 12 ++++++++++++ + kernel/system_keyring.c | 17 +++++++++++++++++ + 4 files changed, 42 insertions(+) + +diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h +index 8dabc39..e466de1 100644 +--- a/include/keys/system_keyring.h ++++ b/include/keys/system_keyring.h +@@ -18,6 +18,10 @@ + + extern struct key *system_trusted_keyring; + ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++extern struct key *system_blacklist_keyring; ++#endif ++ + #endif + + #endif /* _KEYS_SYSTEM_KEYRING_H */ +diff --git a/init/Kconfig b/init/Kconfig +index b9d8870..4f9771f 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1627,6 +1627,15 @@ config SYSTEM_TRUSTED_KEYRING + + Keys in this keyring are used by module signature checking. + ++config SYSTEM_BLACKLIST_KEYRING ++ bool "Provide system-wide ring of blacklisted keys" ++ depends on KEYS ++ help ++ Provide a system keyring to which blacklisted keys can be added. Keys ++ in the keyring are considered entirely untrusted. Keys in this keyring ++ are used by the module signature checking to reject loading of modules ++ signed with a blacklisted key. ++ + menuconfig MODULES + bool "Enable loadable module support" + help +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 0b6b870..0a29b40 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -158,6 +158,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++ key = keyring_search(make_key_ref(system_blacklist_keyring, 1), ++ &key_type_asymmetric, id); ++ if (!IS_ERR(key)) { ++ /* module is signed with a cert in the blacklist. reject */ ++ pr_err("Module key '%s' is in blacklist\n", id); ++ key_ref_put(key); ++ kfree(id); ++ return ERR_PTR(-EKEYREJECTED); ++ } ++#endif ++ + key = keyring_search(make_key_ref(system_trusted_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +index dae8778..2913c70 100644 +--- a/kernel/system_keyring.c ++++ b/kernel/system_keyring.c +@@ -20,6 +20,9 @@ + + struct key *system_trusted_keyring; + EXPORT_SYMBOL_GPL(system_trusted_keyring); ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++struct key *system_blacklist_keyring; ++#endif + + extern __initdata const u8 system_certificate_list[]; + extern __initdata const u8 system_certificate_list_end[]; +@@ -41,6 +44,20 @@ static __init int system_trusted_keyring_init(void) + panic("Can't allocate system trusted keyring\n"); + + set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); ++ ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++ system_blacklist_keyring = keyring_alloc(".system_blacklist_keyring", ++ KUIDT_INIT(0), KGIDT_INIT(0), ++ current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA, NULL); ++ if (IS_ERR(system_blacklist_keyring)) ++ panic("Can't allocate system blacklist keyring\n"); ++ ++ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_blacklist_keyring->flags); ++#endif ++ + return 0; + } + +-- +1.8.1.4 + + +From e46bf80471882ce1ab0b75dc954b2b59deec6fbb Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:42:16 -0400 +Subject: [PATCH 36/47] MODSIGN: Import certificates from UEFI Secure Boot + +Secure Boot stores a list of allowed certificates in the 'db' variable. +This imports those certificates into the system trusted keyring. This +allows for a third party signing certificate to be used in conjunction +with signed modules. By importing the public certificate into the 'db' +variable, a user can allow a module signed with that certificate to +load. The shim UEFI bootloader has a similar certificate list stored +in the 'MokListRT' variable. We import those as well. + +In the opposite case, Secure Boot maintains a list of disallowed +certificates in the 'dbx' variable. We load those certificates into +the newly introduced system blacklist keyring and forbid any module +signed with those from loading. + +Signed-off-by: Josh Boyer +--- + include/linux/efi.h | 6 ++++ + init/Kconfig | 9 +++++ + kernel/Makefile | 3 ++ + kernel/modsign_uefi.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 110 insertions(+) + create mode 100644 kernel/modsign_uefi.c + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 4f0fbb7..7ac7a17 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si + #define EFI_CERT_X509_GUID \ + EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) + ++#define EFI_IMAGE_SECURITY_DATABASE_GUID \ ++ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) ++ ++#define EFI_SHIM_LOCK_GUID \ ++ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +diff --git a/init/Kconfig b/init/Kconfig +index 4f9771f..da92f1c 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1745,6 +1745,15 @@ config MODULE_SIG_ALL + comment "Do not forget to sign required modules with scripts/sign-file" + depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL + ++config MODULE_SIG_UEFI ++ bool "Allow modules signed with certs stored in UEFI" ++ depends on MODULE_SIG && SYSTEM_BLACKLIST_KEYRING && EFI ++ select EFI_SIGNATURE_LIST_PARSER ++ help ++ This will import certificates stored in UEFI and allow modules ++ signed with those to be loaded. It will also disallow loading ++ of modules stored in the UEFI dbx variable. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/Makefile b/kernel/Makefile +index 52f3426..e2a616f 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SIG) += module_signing.o ++obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o + + $(obj)/configs.o: $(obj)/config_data.h + ++$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar ++ + # config_data.h contains the same information as ikconfig.h but gzipped. + # Info from config_data can be extracted from /proc/config* + targets += config_data.gz +diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c +new file mode 100644 +index 0000000..94b0eb3 +--- /dev/null ++++ b/kernel/modsign_uefi.c +@@ -0,0 +1,92 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) ++{ ++ efi_status_t status; ++ unsigned long lsize = 4; ++ unsigned long tmpdb[4]; ++ void *db = NULL; ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); ++ if (status != EFI_BUFFER_TOO_SMALL) { ++ pr_err("Couldn't get size: 0x%lx\n", status); ++ return NULL; ++ } ++ ++ db = kmalloc(lsize, GFP_KERNEL); ++ if (!db) { ++ pr_err("Couldn't allocate memory for uefi cert list\n"); ++ goto out; ++ } ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, db); ++ if (status != EFI_SUCCESS) { ++ kfree(db); ++ db = NULL; ++ pr_err("Error reading db var: 0x%lx\n", status); ++ } ++out: ++ *size = lsize; ++ return db; ++} ++ ++/* ++ * * Load the certs contained in the UEFI databases ++ * */ ++static int __init load_uefi_certs(void) ++{ ++ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; ++ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; ++ void *db = NULL, *dbx = NULL, *mok = NULL; ++ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; ++ int rc = 0; ++ ++ /* Check if SB is enabled and just return if not */ ++ if (!efi_enabled(EFI_SECURE_BOOT)) ++ return 0; ++ ++ /* Get db, MokListRT, and dbx. They might not exist, so it isn't ++ * an error if we can't get them. ++ */ ++ db = get_cert_list(L"db", &secure_var, &dbsize); ++ if (!db) { ++ pr_err("MODSIGN: Couldn't get UEFI db list\n"); ++ } else { ++ rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring); ++ if (rc) ++ pr_err("Couldn't parse db signatures: %d\n", rc); ++ kfree(db); ++ } ++ ++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); ++ if (!mok) { ++ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); ++ } else { ++ rc = parse_efi_signature_list(mok, moksize, system_trusted_keyring); ++ if (rc) ++ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); ++ kfree(mok); ++ } ++ ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); ++ if (!dbx) { ++ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); ++ } else { ++ rc = parse_efi_signature_list(dbx, dbxsize, ++ system_blacklist_keyring); ++ if (rc) ++ pr_err("Couldn't parse dbx signatures: %d\n", rc); ++ kfree(dbx); ++ } ++ ++ return rc; ++} ++late_initcall(load_uefi_certs); +-- +1.8.1.4 + + +From 8724600edad99706cce510645eff15f28787561a Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:57 -0400 +Subject: [PATCH 37/47] PCI: Lock down BAR access in secure boot environments + +Any hardware that can potentially generate DMA has to be locked down from +userspace in order to avoid it being possible for an attacker to cause +arbitrary kernel behaviour. Default to paranoid - in future we can +potentially relax this for sufficiently IOMMU-isolated devices. + +Signed-off-by: Matthew Garrett +--- + drivers/pci/pci-sysfs.c | 9 +++++++++ + drivers/pci/proc.c | 8 +++++++- + drivers/pci/syscall.c | 2 +- + 3 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 5b4a9d9..db2ff9e 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -622,6 +622,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, + loff_t init_off = off; + u8 *data = (u8*) buf; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (off > dev->cfg_size) + return 0; + if (off + count > dev->cfg_size) { +@@ -928,6 +931,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, + resource_size_t start, end; + int i; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + for (i = 0; i < PCI_ROM_RESOURCE; i++) + if (res == &pdev->resource[i]) + break; +@@ -1035,6 +1041,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) + { ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + return pci_resource_io(filp, kobj, attr, buf, off, count, true); + } + +diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c +index 0812608..544132d 100644 +--- a/drivers/pci/proc.c ++++ b/drivers/pci/proc.c +@@ -136,6 +136,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof + int size = dev->cfg_size; + int cnt; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (pos >= size) + return 0; + if (nbytes >= size) +@@ -215,6 +218,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, + #endif /* HAVE_PCI_MMAP */ + int ret = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + switch (cmd) { + case PCIIOC_CONTROLLER: + ret = pci_domain_nr(dev->bus); +@@ -253,7 +259,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) + struct pci_filp_private *fpriv = file->private_data; + int i, ret; + +- if (!capable(CAP_SYS_RAWIO)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + /* Make sure the caller is mapping a real resource for this device */ +diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c +index e1c1ec5..97e785f 100644 +--- a/drivers/pci/syscall.c ++++ b/drivers/pci/syscall.c +@@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, + u32 dword; + int err = 0; + +- if (!capable(CAP_SYS_ADMIN)) ++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + dev = pci_get_bus_and_slot(bus, dfn); +-- +1.8.1.4 + + +From 2361c561632c00e3974a092454ecc7daafb7cdf6 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:58 -0400 +Subject: [PATCH 38/47] x86: Lock down IO port access in secure boot + environments + +IO port access would permit users to gain access to PCI configuration +registers, which in turn (on a lot of hardware) give access to MMIO register +space. This would potentially permit root to trigger arbitrary DMA, so lock +it down by default. + +Signed-off-by: Matthew Garrett +--- + arch/x86/kernel/ioport.c | 4 ++-- + drivers/char/mem.c | 3 +++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c +index 4ddaf66..f505995 100644 +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -28,7 +28,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) + + if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) + return -EINVAL; +- if (turn_on && !capable(CAP_SYS_RAWIO)) ++ if (turn_on && (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL))) + return -EPERM; + + /* +@@ -103,7 +103,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) + return -EINVAL; + /* Trying to gain more privileges? */ + if (level > old) { +- if (!capable(CAP_SYS_RAWIO)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + } + regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 2c644af..7eee4d8 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, + unsigned long i = *ppos; + const char __user *tmp = buf; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!access_ok(VERIFY_READ, buf, count)) + return -EFAULT; + while (count-- > 0 && i < 65536) { +-- +1.8.1.4 + + +From e97f4dd5b1baaae0854e8a5c87aa4be4d03d1854 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:59 -0400 +Subject: [PATCH 39/47] ACPI: Limit access to custom_method + +It must be impossible for even root to get code executed in kernel context +under a secure boot environment. custom_method effectively allows arbitrary +access to system memory, so it needs to have a capability check here. + +Signed-off-by: Matthew Garrett +--- + drivers/acpi/custom_method.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c +index 12b62f2..edf0710 100644 +--- a/drivers/acpi/custom_method.c ++++ b/drivers/acpi/custom_method.c +@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, + struct acpi_table_header table; + acpi_status status; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!(*ppos)) { + /* parse the table header to get the table length */ + if (count <= sizeof(struct acpi_table_header)) +-- +1.8.1.4 + + +From f0389c3a6d823e2386ab4e21d9e012c4ebd310ac Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:00 -0400 +Subject: [PATCH 40/47] asus-wmi: Restrict debugfs interface + +We have no way of validating what all of the Asus WMI methods do on a +given machine, and there's a risk that some will allow hardware state to +be manipulated in such a way that arbitrary code can be executed in the +kernel. Add a capability check to prevent that. + +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/asus-wmi.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index c11b242..6d5f88f 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -1617,6 +1617,9 @@ static int show_dsts(struct seq_file *m, void *data) + int err; + u32 retval = -1; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); + + if (err < 0) +@@ -1633,6 +1636,9 @@ static int show_devs(struct seq_file *m, void *data) + int err; + u32 retval = -1; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, + &retval); + +@@ -1657,6 +1663,9 @@ static int show_call(struct seq_file *m, void *data) + union acpi_object *obj; + acpi_status status; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, + 1, asus->debug.method_id, + &input, &output); +-- +1.8.1.4 + + +From 2e507337fc23547c7a15e5a102647becf20dba77 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:01 -0400 +Subject: [PATCH 41/47] Restrict /dev/mem and /dev/kmem in secure boot setups + +Allowing users to write to address space makes it possible for the kernel +to be subverted. Restrict this when we need to protect the kernel. + +Signed-off-by: Matthew Garrett +--- + drivers/char/mem.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 7eee4d8..772ee2b 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, + unsigned long copied; + void *ptr; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!valid_phys_addr_range(p, count)) + return -EFAULT; + +@@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, + char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + int err = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (p < (unsigned long) high_memory) { + unsigned long to_write = min_t(unsigned long, count, + (unsigned long)high_memory - p); +-- +1.8.1.4 + + +From ff22d9716846844f8c249dbc965684a8014efed0 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:04 -0400 +Subject: [PATCH 42/47] acpi: Ignore acpi_rsdp kernel parameter in a secure + boot environment + +This option allows userspace to pass the RSDP address to the kernel. This +could potentially be used to circumvent the secure boot trust model. +This is setup through the setup_arch function, which is called before the +security_init function sets up the security_ops, so we cannot use a +capable call here. We ignore the setting if we are booted in Secure Boot +mode. + +Signed-off-by: Josh Boyer +--- + drivers/acpi/osl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index e721863..ed82da7 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -245,7 +245,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); + acpi_physical_address __init acpi_os_get_root_pointer(void) + { + #ifdef CONFIG_KEXEC +- if (acpi_rsdp) ++ if (acpi_rsdp && !efi_enabled(EFI_SECURE_BOOT)) + return acpi_rsdp; + #endif + +-- +1.8.1.4 + + +From b08ac626fbcf917bc219133d49c347d7d58eaae1 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 4 Sep 2012 11:55:13 -0400 +Subject: [PATCH 43/47] kexec: Disable in a secure boot environment + +kexec could be used as a vector for a malicious user to use a signed kernel +to circumvent the secure boot trust model. In the long run we'll want to +support signed kexec payloads, but for the moment we should just disable +loading entirely in that situation. + +Signed-off-by: Matthew Garrett +--- + kernel/kexec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/kexec.c b/kernel/kexec.c +index 59f7b55..8bf1336 100644 +--- a/kernel/kexec.c ++++ b/kernel/kexec.c +@@ -939,7 +939,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, + int result; + + /* We only trust the superuser with rebooting the system. */ +- if (!capable(CAP_SYS_BOOT)) ++ if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + /* +-- +1.8.1.4 + + +From f0d9c2906c1145585882fb7eb167e47e998c2e24 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 5 Oct 2012 10:12:48 -0400 +Subject: [PATCH 44/47] MODSIGN: Always enforce module signing in a Secure Boot + environment + +If a machine is booted into a Secure Boot environment, we need to +protect the trust model. This requires that all modules be signed +with a key that is in the kernel's _modsign keyring. The checks for +this are already done via the 'sig_enforce' module parameter. Make +this visible within the kernel and force it to be true. + +Signed-off-by: Josh Boyer +--- + kernel/cred.c | 8 ++++++++ + kernel/module.c | 4 ++-- + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/kernel/cred.c b/kernel/cred.c +index c3f4e3e..c5554e0 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -565,11 +565,19 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++#ifdef CONFIG_MODULE_SIG ++extern bool sig_enforce; ++#endif ++ + void __init secureboot_enable() + { + pr_info("Secure boot enabled\n"); + cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); + cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++#ifdef CONFIG_MODULE_SIG ++ /* Enable module signature enforcing */ ++ sig_enforce = true; ++#endif + } + + /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ +diff --git a/kernel/module.c b/kernel/module.c +index 0925c9a..af4a476 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ + + #ifdef CONFIG_MODULE_SIG + #ifdef CONFIG_MODULE_SIG_FORCE +-static bool sig_enforce = true; ++bool sig_enforce = true; + #else +-static bool sig_enforce = false; ++bool sig_enforce = false; + + static int param_set_bool_enable_only(const char *val, + const struct kernel_param *kp) +-- +1.8.1.4 + + +From 1c6bfec7db39e46eeb456fb84e3153281690bbe0 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 14:02:09 -0400 +Subject: [PATCH 45/47] hibernate: Disable in a Secure Boot environment + +There is currently no way to verify the resume image when returning +from hibernate. This might compromise the secure boot trust model, +so until we can work with signed hibernate images we disable it in +a Secure Boot environment. + +Signed-off-by: Josh Boyer +--- + kernel/power/hibernate.c | 15 ++++++++++++++- + kernel/power/main.c | 7 ++++++- + kernel/power/user.c | 3 +++ + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index b26f5f1..7f63cb4 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -632,6 +633,10 @@ int hibernate(void) + { + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ return -EPERM; ++ } ++ + lock_system_sleep(); + /* The snapshot device should not be opened while we're running */ + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +@@ -723,7 +728,7 @@ static int software_resume(void) + /* + * If the user said "noresume".. bail out early. + */ +- if (noresume) ++ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) + return 0; + + /* +@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, + int i; + char *start = buf; + ++ if (efi_enabled(EFI_SECURE_BOOT)) { ++ buf += sprintf(buf, "[%s]\n", "disabled"); ++ return buf-start; ++ } ++ + for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { + if (!hibernation_modes[i]) + continue; +@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, + char *p; + int mode = HIBERNATION_INVALID; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + p = memchr(buf, '\n', n); + len = p ? p - buf : n; + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index d77663b..78f8ed5 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + } + #endif + #ifdef CONFIG_HIBERNATION +- s += sprintf(s, "%s\n", "disk"); ++ if (!efi_enabled(EFI_SECURE_BOOT)) { ++ s += sprintf(s, "%s\n", "disk"); ++ } else { ++ s += sprintf(s, "\n"); ++ } + #else + if (s != buf) + /* convert the last space to a newline */ +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 4ed81e7..b11a0f4 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) + struct snapshot_data *data; + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + lock_system_sleep(); + + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +-- +1.8.1.4 + + +From 07cda990d2f18774522889ece30bddf67c703157 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 5 Feb 2013 19:25:05 -0500 +Subject: [PATCH 46/47] efi: Disable secure boot if shim is in insecure mode + +A user can manually tell the shim boot loader to disable validation of +images it loads. When a user does this, it creates a UEFI variable called +MokSBState that does not have the runtime attribute set. Given that the +user explicitly disabled validation, we can honor that and not enable +secure boot mode if that variable is set. + +Signed-off-by: Josh Boyer +--- + arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 0998ec7..4945ee5 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -908,8 +908,9 @@ fail: + + static int get_secure_boot(efi_system_table_t *_table) + { +- u8 sb, setup; ++ u8 sb, setup, moksbstate; + unsigned long datasize = sizeof(sb); ++ u32 attr; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; + efi_status_t status; + +@@ -933,6 +934,23 @@ static int get_secure_boot(efi_system_table_t *_table) + if (setup == 1) + return 0; + ++ /* See if a user has put shim into insecure_mode. If so, and the variable ++ * doesn't have the runtime attribute set, we might as well honor that. ++ */ ++ var_guid = EFI_SHIM_LOCK_GUID; ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"MokSBState", &var_guid, &attr, &datasize, ++ &moksbstate); ++ ++ /* If it fails, we don't care why. Default to secure */ ++ if (status != EFI_SUCCESS) ++ return 1; ++ ++ if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) { ++ if (moksbstate == 1) ++ return 0; ++ } ++ + return 1; + } + +-- +1.8.1.4 + + +From e61066577405c37c2758f9b7fb2694967bdbe921 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 8 Feb 2013 11:12:13 -0800 +Subject: [PATCH 47/47] x86: Lock down MSR writing in secure boot + +Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is +set since it could lead to execution of arbitrary code in kernel mode. + +Signed-off-by: Kees Cook +--- + arch/x86/kernel/msr.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c +index ce13049..fa4dc6c 100644 +--- a/arch/x86/kernel/msr.c ++++ b/arch/x86/kernel/msr.c +@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, + int err = 0; + ssize_t bytes = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + +@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) + err = -EBADF; + break; + } ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ err = -EPERM; ++ break; ++ } + if (copy_from_user(®s, uregs, sizeof regs)) { + err = -EFAULT; + break; +-- +1.8.1.4 + diff --git a/drivers-hwmon-nct6775.patch b/drivers-hwmon-nct6775.patch deleted file mode 100644 index f6ee15c8c..000000000 --- a/drivers-hwmon-nct6775.patch +++ /dev/null @@ -1,6424 +0,0 @@ -Add support for nct6775.c - -This driver is needed on modern Asus motherboards like P8Z77-M PRO, and -other motherboards based on Z77 chipset. - -This patch folds the changes found on those 3.10-rc6 changesets: - -169c05c hwmon: (nct6775) Do not create non-existing attributes -6445e66 hwmon: (nct6775) Fix coding style problems -6d4b362 hwmon: (nct6775) Constify strings -c409fd4 hwmon: (nct6775) Use ARRAY_SIZE for loops where possible -573728c hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776 -2c7fd30 hwmon: (nct6775) Expand scope of supported chips -236d903 hwmon: (nct6775) Drop read/write lock -0fc1f8f hwmon: (nct6775) Only report VID if supported and enabled -8e9285b hwmon: (nct6775) Detect and report additional temperature sources -bbd8dec hwmon: (nct6775) Add support for weighted fan control -cdcaece hwmon: (nct6775) Add support for automatic fan control -77eb5b3 hwmon: (nct6775) Add support for pwm, pwm_mode, and pwm_enable -84d19d9 hwmon: (nct6775) Add power management support -47ece96 hwmon: (nct6775) Add support for fan debounce module parameter -5c25d95 hwmon: (nct6775) Add support for fanX_pulses sysfs attribute -1c65dc3 hwmon: (nct6775) Add support for fan speed attributes -aa136e5 hwmon: (nct6775) Add support for temperature sensors -a6bd587 hwmon: (nct6775) Add case open detection -9de2e2e hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D - -- - -From 9de2e2e84e7d52e4c2a9e1a1e21ab6ac686233c0 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Sun, 20 May 2012 19:29:48 -0700 -Subject: [PATCH] hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D - -This driver will replace the w83627ehf driver for NCT6775F and NCT6776F, -and provides support for NCT6779D. - -This patch provides support for voltage monitor attributes. - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -new file mode 100644 -index 0000000..ccfd5cc ---- /dev/null -+++ b/Documentation/hwmon/nct6775 -@@ -0,0 +1,81 @@ -+Note -+==== -+ -+This driver supersedes the NCT6775F and NCT6776F support in the W83627EHF -+driver. -+ -+Kernel driver NCT6775 -+===================== -+ -+Supported chips: -+ * Nuvoton NCT6775F/W83667HG-I -+ Prefix: 'nct6775' -+ Addresses scanned: ISA address retrieved from Super I/O registers -+ Datasheet: Available from Nuvoton upon request -+ * Nuvoton NCT6776F -+ Prefix: 'nct6776' -+ Addresses scanned: ISA address retrieved from Super I/O registers -+ Datasheet: Available from Nuvoton upon request -+ * Nuvoton NCT6779D -+ Prefix: 'nct6779' -+ Addresses scanned: ISA address retrieved from Super I/O registers -+ Datasheet: Available from Nuvoton upon request -+ -+Authors: -+ Guenter Roeck -+ -+Description -+----------- -+ -+This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D -+super I/O chips. -+ -+The chips support up to 25 temperature monitoring sources. Up to 6 of those are -+direct temperature sensor inputs, the others are special sources such as PECI, -+PCH, and SMBUS. Depending on the chip type, 2 to 6 of the temperature sources -+can be monitored and compared against minimum, maximum, and critical -+temperatures. The driver reports up to 10 of the temperatures to the user. -+There are 4 to 5 fan rotation speed sensors, 8 to 15 analog voltage sensors, -+one VID, alarms with beep warnings (control unimplemented), and some automatic -+fan regulation strategies (plus manual fan control mode). -+ -+The temperature sensor sources on all chips are configurable. The configured -+source for each of the temperature sensors is provided in tempX_label. -+ -+Temperatures are measured in degrees Celsius and measurement resolution is -+either 1 degC or 0.5 degC, depending on the temperature source and -+configuration. An alarm is triggered when the temperature gets higher than -+the high limit; it stays on until the temperature falls below the hysteresis -+value. Alarms are only supported for temp1 to temp6, depending on the chip type. -+ -+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is -+triggered if the rotation speed has dropped below a programmable limit. On -+NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8, -+16, 32, 64 or 128) to give the readings more range or accuracy; the other chips -+do not have a fan speed divider. The driver sets the most suitable fan divisor -+itself; specifically, it doubles the divider value each time a fan speed reading -+returns an invalid value. Some fans might not be present because they share pins -+with other functions. -+ -+Voltage sensors (also known as IN sensors) report their values in millivolts. -+An alarm is triggered if the voltage has crossed a programmable minimum -+or maximum limit. -+ -+The driver supports automatic fan control mode known as Thermal Cruise. -+In this mode, the chip attempts to keep the measured temperature in a -+predefined temperature range. If the temperature goes out of range, fan -+is driven slower/faster to reach the predefined range again. -+ -+The mode works for fan1-fan5. -+ -+Usage Notes -+----------- -+ -+On various ASUS boards with NCT6776F, it appears that CPUTIN is not really -+connected to anything and floats, or that it is connected to some non-standard -+temperature measurement device. As a result, the temperature reported on CPUTIN -+will not reflect a usable value. It often reports unreasonably high -+temperatures, and in some cases the reported temperature declines if the actual -+temperature increases (similar to the raw PECI temperature value - see PECI -+specification for details). CPUTIN should therefore be be ignored on ASUS -+boards. The CPU temperature on ASUS boards is reported from PECI 0. -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 47d2176..a0f1d6a 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -897,6 +897,19 @@ config SENSORS_MCP3021 - This driver can also be built as a module. If so, the module - will be called mcp3021. - -+config SENSORS_NCT6775 -+ tristate "Nuvoton NCT6775F, NCT6776F, NCT6779D" -+ depends on !PPC -+ select HWMON_VID -+ help -+ If you say yes here you get support for the hardware monitoring -+ functionality of the Nuvoton NCT6775F, NCT6776F, and NCT6779D -+ Super-I/O chips. This driver replaces the w83627ehf driver for -+ NCT6775F and NCT6776F. -+ -+ This driver can also be built as a module. If so, the module -+ will be called nct6775. -+ - config SENSORS_NTC_THERMISTOR - tristate "NTC thermistor support" - depends on (!OF && !IIO) || (OF && IIO) -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 5d36a57..8297572 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -105,6 +105,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o - obj-$(CONFIG_SENSORS_MAX6697) += max6697.o - obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o - obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o -+obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o - obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o - obj-$(CONFIG_SENSORS_PC87360) += pc87360.o - obj-$(CONFIG_SENSORS_PC87427) += pc87427.o -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -new file mode 100644 -index 0000000..f75cd82 ---- /dev/null -+++ b/drivers/hwmon/nct6775.c -@@ -0,0 +1,1021 @@ -+/* -+ * nct6775 - Driver for the hardware monitoring functionality of -+ * Nuvoton NCT677x Super-I/O chips -+ * -+ * Copyright (C) 2012 Guenter Roeck -+ * -+ * Derived from w83627ehf driver -+ * Copyright (C) 2005-2012 Jean Delvare -+ * Copyright (C) 2006 Yuan Mu (Winbond), -+ * Rudolf Marek -+ * David Hubbard -+ * Daniel J Blueman -+ * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00) -+ * -+ * Shamelessly ripped from the w83627hf driver -+ * Copyright (C) 2003 Mark Studebaker -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * -+ * Supports the following chips: -+ * -+ * Chip #vin #fan #pwm #temp chip IDs man ID -+ * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3 -+ * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 -+ * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 -+ * -+ * #temp lists the number of monitored temperature sources (first value) plus -+ * the number of directly connectable temperature sensors (second value). -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "lm75.h" -+ -+enum kinds { nct6775, nct6776, nct6779 }; -+ -+/* used to set data->name = nct6775_device_names[data->sio_kind] */ -+static const char * const nct6775_device_names[] = { -+ "nct6775", -+ "nct6776", -+ "nct6779", -+}; -+ -+static unsigned short force_id; -+module_param(force_id, ushort, 0); -+MODULE_PARM_DESC(force_id, "Override the detected device ID"); -+ -+#define DRVNAME "nct6775" -+ -+/* -+ * Super-I/O constants and functions -+ */ -+ -+#define NCT6775_LD_HWM 0x0b -+#define NCT6775_LD_VID 0x0d -+ -+#define SIO_REG_LDSEL 0x07 /* Logical device select */ -+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ -+#define SIO_REG_ENABLE 0x30 /* Logical device enable */ -+#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ -+ -+#define SIO_NCT6775_ID 0xb470 -+#define SIO_NCT6776_ID 0xc330 -+#define SIO_NCT6779_ID 0xc560 -+#define SIO_ID_MASK 0xFFF0 -+ -+static inline void -+superio_outb(int ioreg, int reg, int val) -+{ -+ outb(reg, ioreg); -+ outb(val, ioreg + 1); -+} -+ -+static inline int -+superio_inb(int ioreg, int reg) -+{ -+ outb(reg, ioreg); -+ return inb(ioreg + 1); -+} -+ -+static inline void -+superio_select(int ioreg, int ld) -+{ -+ outb(SIO_REG_LDSEL, ioreg); -+ outb(ld, ioreg + 1); -+} -+ -+static inline int -+superio_enter(int ioreg) -+{ -+ /* -+ * Try to reserve and for exclusive access. -+ */ -+ if (!request_muxed_region(ioreg, 2, DRVNAME)) -+ return -EBUSY; -+ -+ outb(0x87, ioreg); -+ outb(0x87, ioreg); -+ -+ return 0; -+} -+ -+static inline void -+superio_exit(int ioreg) -+{ -+ outb(0xaa, ioreg); -+ outb(0x02, ioreg); -+ outb(0x02, ioreg + 1); -+ release_region(ioreg, 2); -+} -+ -+/* -+ * ISA constants -+ */ -+ -+#define IOREGION_ALIGNMENT (~7) -+#define IOREGION_OFFSET 5 -+#define IOREGION_LENGTH 2 -+#define ADDR_REG_OFFSET 0 -+#define DATA_REG_OFFSET 1 -+ -+#define NCT6775_REG_BANK 0x4E -+#define NCT6775_REG_CONFIG 0x40 -+ -+/* -+ * Not currently used: -+ * REG_MAN_ID has the value 0x5ca3 for all supported chips. -+ * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model. -+ * REG_MAN_ID is at port 0x4f -+ * REG_CHIP_ID is at port 0x58 -+ */ -+ -+#define NUM_REG_ALARM 4 /* Max number of alarm registers */ -+ -+/* Common and NCT6775 specific data */ -+ -+/* Voltage min/max registers for nr=7..14 are in bank 5 */ -+ -+static const u16 NCT6775_REG_IN_MAX[] = { -+ 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a, -+ 0x55c, 0x55e, 0x560, 0x562 }; -+static const u16 NCT6775_REG_IN_MIN[] = { -+ 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b, -+ 0x55d, 0x55f, 0x561, 0x563 }; -+static const u16 NCT6775_REG_IN[] = { -+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552 -+}; -+ -+#define NCT6775_REG_VBAT 0x5D -+ -+static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; -+ -+/* 0..15 voltages, 16..23 fans, 24..31 temperatures */ -+ -+static const s8 NCT6775_ALARM_BITS[] = { -+ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ -+ 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ -+ -1, /* unused */ -+ 6, 7, 11, 10, 23, /* fan1..fan5 */ -+ -1, -1, -1, /* unused */ -+ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ -+ 12, -1 }; /* intrusion0, intrusion1 */ -+ -+/* NCT6776 specific data */ -+ -+static const s8 NCT6776_ALARM_BITS[] = { -+ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ -+ 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ -+ -1, /* unused */ -+ 6, 7, 11, 10, 23, /* fan1..fan5 */ -+ -1, -1, -1, /* unused */ -+ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ -+ 12, 9 }; /* intrusion0, intrusion1 */ -+ -+/* NCT6779 specific data */ -+ -+static const u16 NCT6779_REG_IN[] = { -+ 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, -+ 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e }; -+ -+static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = { -+ 0x459, 0x45A, 0x45B, 0x568 }; -+ -+static const s8 NCT6779_ALARM_BITS[] = { -+ 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ -+ 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */ -+ -1, /* unused */ -+ 6, 7, 11, 10, 23, /* fan1..fan5 */ -+ -1, -1, -1, /* unused */ -+ 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ -+ 12, 9 }; /* intrusion0, intrusion1 */ -+ -+/* -+ * Conversions -+ */ -+ -+/* -+ * Some of the voltage inputs have internal scaling, the tables below -+ * contain 8 (the ADC LSB in mV) * scaling factor * 100 -+ */ -+static const u16 scale_in[15] = { -+ 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800, -+ 800, 800 -+}; -+ -+static inline long in_from_reg(u8 reg, u8 nr) -+{ -+ return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100); -+} -+ -+static inline u8 in_to_reg(u32 val, u8 nr) -+{ -+ return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255); -+} -+ -+/* -+ * Data structures and manipulation thereof -+ */ -+ -+struct nct6775_data { -+ int addr; /* IO base of hw monitor block */ -+ enum kinds kind; -+ const char *name; -+ -+ struct device *hwmon_dev; -+ struct mutex lock; -+ -+ u16 REG_CONFIG; -+ u16 REG_VBAT; -+ -+ const s8 *ALARM_BITS; -+ -+ const u16 *REG_VIN; -+ const u16 *REG_IN_MINMAX[2]; -+ -+ const u16 *REG_ALARM; -+ -+ struct mutex update_lock; -+ bool valid; /* true if following fields are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ -+ /* Register values */ -+ u8 bank; /* current register bank */ -+ u8 in_num; /* number of in inputs we have */ -+ u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ -+ -+ u64 alarms; -+ -+ u8 vid; -+ u8 vrm; -+ -+ u16 have_in; -+}; -+ -+struct nct6775_sio_data { -+ int sioreg; -+ enum kinds kind; -+}; -+ -+static bool is_word_sized(struct nct6775_data *data, u16 reg) -+{ -+ switch (data->kind) { -+ case nct6775: -+ return (((reg & 0xff00) == 0x100 || -+ (reg & 0xff00) == 0x200) && -+ ((reg & 0x00ff) == 0x50 || -+ (reg & 0x00ff) == 0x53 || -+ (reg & 0x00ff) == 0x55)) || -+ (reg & 0xfff0) == 0x630 || -+ reg == 0x640 || reg == 0x642 || -+ reg == 0x662 || -+ ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) || -+ reg == 0x73 || reg == 0x75 || reg == 0x77; -+ case nct6776: -+ return (((reg & 0xff00) == 0x100 || -+ (reg & 0xff00) == 0x200) && -+ ((reg & 0x00ff) == 0x50 || -+ (reg & 0x00ff) == 0x53 || -+ (reg & 0x00ff) == 0x55)) || -+ (reg & 0xfff0) == 0x630 || -+ reg == 0x402 || -+ reg == 0x640 || reg == 0x642 || -+ ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) || -+ reg == 0x73 || reg == 0x75 || reg == 0x77; -+ case nct6779: -+ return reg == 0x150 || reg == 0x153 || reg == 0x155 || -+ ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) || -+ reg == 0x402 || -+ reg == 0x63a || reg == 0x63c || reg == 0x63e || -+ reg == 0x640 || reg == 0x642 || -+ reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 || -+ reg == 0x7b; -+ } -+ return false; -+} -+ -+/* -+ * On older chips, only registers 0x50-0x5f are banked. -+ * On more recent chips, all registers are banked. -+ * Assume that is the case and set the bank number for each access. -+ * Cache the bank number so it only needs to be set if it changes. -+ */ -+static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg) -+{ -+ u8 bank = reg >> 8; -+ if (data->bank != bank) { -+ outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET); -+ outb_p(bank, data->addr + DATA_REG_OFFSET); -+ data->bank = bank; -+ } -+} -+ -+static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) -+{ -+ int res, word_sized = is_word_sized(data, reg); -+ -+ mutex_lock(&data->lock); -+ -+ nct6775_set_bank(data, reg); -+ outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); -+ res = inb_p(data->addr + DATA_REG_OFFSET); -+ if (word_sized) { -+ outb_p((reg & 0xff) + 1, -+ data->addr + ADDR_REG_OFFSET); -+ res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET); -+ } -+ -+ mutex_unlock(&data->lock); -+ return res; -+} -+ -+static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) -+{ -+ int word_sized = is_word_sized(data, reg); -+ -+ mutex_lock(&data->lock); -+ -+ nct6775_set_bank(data, reg); -+ outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); -+ if (word_sized) { -+ outb_p(value >> 8, data->addr + DATA_REG_OFFSET); -+ outb_p((reg & 0xff) + 1, -+ data->addr + ADDR_REG_OFFSET); -+ } -+ outb_p(value & 0xff, data->addr + DATA_REG_OFFSET); -+ -+ mutex_unlock(&data->lock); -+ return 0; -+} -+ -+static struct nct6775_data *nct6775_update_device(struct device *dev) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ int i; -+ -+ mutex_lock(&data->update_lock); -+ -+ if (time_after(jiffies, data->last_updated + HZ + HZ/2) -+ || !data->valid) { -+ /* Measured voltages and limits */ -+ for (i = 0; i < data->in_num; i++) { -+ if (!(data->have_in & (1 << i))) -+ continue; -+ -+ data->in[i][0] = nct6775_read_value(data, -+ data->REG_VIN[i]); -+ data->in[i][1] = nct6775_read_value(data, -+ data->REG_IN_MINMAX[0][i]); -+ data->in[i][2] = nct6775_read_value(data, -+ data->REG_IN_MINMAX[1][i]); -+ } -+ -+ data->alarms = 0; -+ for (i = 0; i < NUM_REG_ALARM; i++) { -+ u8 alarm; -+ if (!data->REG_ALARM[i]) -+ continue; -+ alarm = nct6775_read_value(data, data->REG_ALARM[i]); -+ data->alarms |= ((u64)alarm) << (i << 3); -+ } -+ -+ data->last_updated = jiffies; -+ data->valid = true; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return data; -+} -+ -+/* -+ * Sysfs callback functions -+ */ -+static ssize_t -+show_in_reg(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr)); -+} -+ -+static ssize_t -+store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ unsigned long val; -+ int err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ mutex_lock(&data->update_lock); -+ data->in[nr][index] = in_to_reg(val, nr); -+ nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr], -+ data->in[nr][index]); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_alarm(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = data->ALARM_BITS[sattr->index]; -+ return sprintf(buf, "%u\n", -+ (unsigned int)((data->alarms >> nr) & 0x01)); -+} -+ -+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0); -+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0); -+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0); -+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0); -+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0); -+static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0); -+static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0); -+static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0); -+static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0); -+static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0); -+static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0); -+static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0); -+static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0); -+static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0); -+static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0); -+ -+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); -+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); -+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); -+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); -+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); -+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); -+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); -+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7); -+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8); -+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9); -+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10); -+static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11); -+static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12); -+static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13); -+static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14); -+ -+static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 0, 1); -+static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 1, 1); -+static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 2, 1); -+static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 3, 1); -+static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 4, 1); -+static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 5, 1); -+static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 6, 1); -+static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 7, 1); -+static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 8, 1); -+static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 9, 1); -+static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 10, 1); -+static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 11, 1); -+static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 12, 1); -+static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 13, 1); -+static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 14, 1); -+ -+static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 0, 2); -+static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 1, 2); -+static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 2, 2); -+static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 3, 2); -+static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 4, 2); -+static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 5, 2); -+static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 6, 2); -+static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 7, 2); -+static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 8, 2); -+static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 9, 2); -+static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 10, 2); -+static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 11, 2); -+static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 12, 2); -+static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 13, 2); -+static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg, -+ store_in_reg, 14, 2); -+ -+static struct attribute *nct6775_attributes_in[15][5] = { -+ { -+ &sensor_dev_attr_in0_input.dev_attr.attr, -+ &sensor_dev_attr_in0_min.dev_attr.attr, -+ &sensor_dev_attr_in0_max.dev_attr.attr, -+ &sensor_dev_attr_in0_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in1_input.dev_attr.attr, -+ &sensor_dev_attr_in1_min.dev_attr.attr, -+ &sensor_dev_attr_in1_max.dev_attr.attr, -+ &sensor_dev_attr_in1_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in2_input.dev_attr.attr, -+ &sensor_dev_attr_in2_min.dev_attr.attr, -+ &sensor_dev_attr_in2_max.dev_attr.attr, -+ &sensor_dev_attr_in2_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in3_input.dev_attr.attr, -+ &sensor_dev_attr_in3_min.dev_attr.attr, -+ &sensor_dev_attr_in3_max.dev_attr.attr, -+ &sensor_dev_attr_in3_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in4_input.dev_attr.attr, -+ &sensor_dev_attr_in4_min.dev_attr.attr, -+ &sensor_dev_attr_in4_max.dev_attr.attr, -+ &sensor_dev_attr_in4_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in5_input.dev_attr.attr, -+ &sensor_dev_attr_in5_min.dev_attr.attr, -+ &sensor_dev_attr_in5_max.dev_attr.attr, -+ &sensor_dev_attr_in5_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in6_input.dev_attr.attr, -+ &sensor_dev_attr_in6_min.dev_attr.attr, -+ &sensor_dev_attr_in6_max.dev_attr.attr, -+ &sensor_dev_attr_in6_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in7_input.dev_attr.attr, -+ &sensor_dev_attr_in7_min.dev_attr.attr, -+ &sensor_dev_attr_in7_max.dev_attr.attr, -+ &sensor_dev_attr_in7_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in8_input.dev_attr.attr, -+ &sensor_dev_attr_in8_min.dev_attr.attr, -+ &sensor_dev_attr_in8_max.dev_attr.attr, -+ &sensor_dev_attr_in8_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in9_input.dev_attr.attr, -+ &sensor_dev_attr_in9_min.dev_attr.attr, -+ &sensor_dev_attr_in9_max.dev_attr.attr, -+ &sensor_dev_attr_in9_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in10_input.dev_attr.attr, -+ &sensor_dev_attr_in10_min.dev_attr.attr, -+ &sensor_dev_attr_in10_max.dev_attr.attr, -+ &sensor_dev_attr_in10_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in11_input.dev_attr.attr, -+ &sensor_dev_attr_in11_min.dev_attr.attr, -+ &sensor_dev_attr_in11_max.dev_attr.attr, -+ &sensor_dev_attr_in11_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in12_input.dev_attr.attr, -+ &sensor_dev_attr_in12_min.dev_attr.attr, -+ &sensor_dev_attr_in12_max.dev_attr.attr, -+ &sensor_dev_attr_in12_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in13_input.dev_attr.attr, -+ &sensor_dev_attr_in13_min.dev_attr.attr, -+ &sensor_dev_attr_in13_max.dev_attr.attr, -+ &sensor_dev_attr_in13_alarm.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_in14_input.dev_attr.attr, -+ &sensor_dev_attr_in14_min.dev_attr.attr, -+ &sensor_dev_attr_in14_max.dev_attr.attr, -+ &sensor_dev_attr_in14_alarm.dev_attr.attr, -+ NULL -+ }, -+}; -+ -+static const struct attribute_group nct6775_group_in[15] = { -+ { .attrs = nct6775_attributes_in[0] }, -+ { .attrs = nct6775_attributes_in[1] }, -+ { .attrs = nct6775_attributes_in[2] }, -+ { .attrs = nct6775_attributes_in[3] }, -+ { .attrs = nct6775_attributes_in[4] }, -+ { .attrs = nct6775_attributes_in[5] }, -+ { .attrs = nct6775_attributes_in[6] }, -+ { .attrs = nct6775_attributes_in[7] }, -+ { .attrs = nct6775_attributes_in[8] }, -+ { .attrs = nct6775_attributes_in[9] }, -+ { .attrs = nct6775_attributes_in[10] }, -+ { .attrs = nct6775_attributes_in[11] }, -+ { .attrs = nct6775_attributes_in[12] }, -+ { .attrs = nct6775_attributes_in[13] }, -+ { .attrs = nct6775_attributes_in[14] }, -+}; -+ -+static ssize_t -+show_name(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%s\n", data->name); -+} -+ -+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -+ -+static ssize_t -+show_vid(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -+} -+ -+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); -+ -+/* -+ * Driver and device management -+ */ -+ -+static void nct6775_device_remove_files(struct device *dev) -+{ -+ /* -+ * some entries in the following arrays may not have been used in -+ * device_create_file(), but device_remove_file() will ignore them -+ */ -+ int i; -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ -+ for (i = 0; i < data->in_num; i++) -+ sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); -+ -+ device_remove_file(dev, &dev_attr_name); -+ device_remove_file(dev, &dev_attr_cpu0_vid); -+} -+ -+/* Get the monitoring functions started */ -+static inline void nct6775_init_device(struct nct6775_data *data) -+{ -+ u8 tmp; -+ -+ /* Start monitoring if needed */ -+ if (data->REG_CONFIG) { -+ tmp = nct6775_read_value(data, data->REG_CONFIG); -+ if (!(tmp & 0x01)) -+ nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01); -+ } -+ -+ /* Enable VBAT monitoring if needed */ -+ tmp = nct6775_read_value(data, data->REG_VBAT); -+ if (!(tmp & 0x01)) -+ nct6775_write_value(data, data->REG_VBAT, tmp | 0x01); -+} -+ -+static int nct6775_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct nct6775_sio_data *sio_data = dev->platform_data; -+ struct nct6775_data *data; -+ struct resource *res; -+ int i, err = 0; -+ -+ res = platform_get_resource(pdev, IORESOURCE_IO, 0); -+ if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, -+ DRVNAME)) -+ return -EBUSY; -+ -+ data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data), -+ GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ -+ data->kind = sio_data->kind; -+ data->addr = res->start; -+ mutex_init(&data->lock); -+ mutex_init(&data->update_lock); -+ data->name = nct6775_device_names[data->kind]; -+ data->bank = 0xff; /* Force initial bank selection */ -+ platform_set_drvdata(pdev, data); -+ -+ switch (data->kind) { -+ case nct6775: -+ data->in_num = 9; -+ -+ data->ALARM_BITS = NCT6775_ALARM_BITS; -+ -+ data->REG_CONFIG = NCT6775_REG_CONFIG; -+ data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_VIN = NCT6775_REG_IN; -+ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; -+ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_ALARM = NCT6775_REG_ALARM; -+ break; -+ case nct6776: -+ data->in_num = 9; -+ -+ data->ALARM_BITS = NCT6776_ALARM_BITS; -+ -+ data->REG_CONFIG = NCT6775_REG_CONFIG; -+ data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_VIN = NCT6775_REG_IN; -+ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; -+ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_ALARM = NCT6775_REG_ALARM; -+ break; -+ case nct6779: -+ data->in_num = 15; -+ -+ data->ALARM_BITS = NCT6779_ALARM_BITS; -+ -+ data->REG_CONFIG = NCT6775_REG_CONFIG; -+ data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_VIN = NCT6779_REG_IN; -+ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; -+ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_ALARM = NCT6779_REG_ALARM; -+ break; -+ default: -+ return -ENODEV; -+ } -+ data->have_in = (1 << data->in_num) - 1; -+ -+ /* Initialize the chip */ -+ nct6775_init_device(data); -+ -+ data->vrm = vid_which_vrm(); -+ err = superio_enter(sio_data->sioreg); -+ if (err) -+ return err; -+ -+ /* -+ * Read VID value -+ * We can get the VID input values directly at logical device D 0xe3. -+ */ -+ superio_select(sio_data->sioreg, NCT6775_LD_VID); -+ data->vid = superio_inb(sio_data->sioreg, 0xe3); -+ superio_exit(sio_data->sioreg); -+ -+ err = device_create_file(dev, &dev_attr_cpu0_vid); -+ if (err) -+ return err; -+ -+ for (i = 0; i < data->in_num; i++) { -+ if (!(data->have_in & (1 << i))) -+ continue; -+ err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]); -+ if (err) -+ goto exit_remove; -+ } -+ -+ err = device_create_file(dev, &dev_attr_name); -+ if (err) -+ goto exit_remove; -+ -+ data->hwmon_dev = hwmon_device_register(dev); -+ if (IS_ERR(data->hwmon_dev)) { -+ err = PTR_ERR(data->hwmon_dev); -+ goto exit_remove; -+ } -+ -+ return 0; -+ -+exit_remove: -+ nct6775_device_remove_files(dev); -+ return err; -+} -+ -+static int nct6775_remove(struct platform_device *pdev) -+{ -+ struct nct6775_data *data = platform_get_drvdata(pdev); -+ -+ hwmon_device_unregister(data->hwmon_dev); -+ nct6775_device_remove_files(&pdev->dev); -+ -+ return 0; -+} -+ -+static struct platform_driver nct6775_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = DRVNAME, -+ }, -+ .probe = nct6775_probe, -+ .remove = nct6775_remove, -+}; -+ -+/* nct6775_find() looks for a '627 in the Super-I/O config space */ -+static int __init nct6775_find(int sioaddr, unsigned short *addr, -+ struct nct6775_sio_data *sio_data) -+{ -+ static const char sio_name_NCT6775[] __initconst = "NCT6775F"; -+ static const char sio_name_NCT6776[] __initconst = "NCT6776F"; -+ static const char sio_name_NCT6779[] __initconst = "NCT6779D"; -+ -+ u16 val; -+ const char *sio_name; -+ int err; -+ -+ err = superio_enter(sioaddr); -+ if (err) -+ return err; -+ -+ if (force_id) -+ val = force_id; -+ else -+ val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) -+ | superio_inb(sioaddr, SIO_REG_DEVID + 1); -+ switch (val & SIO_ID_MASK) { -+ case SIO_NCT6775_ID: -+ sio_data->kind = nct6775; -+ sio_name = sio_name_NCT6775; -+ break; -+ case SIO_NCT6776_ID: -+ sio_data->kind = nct6776; -+ sio_name = sio_name_NCT6776; -+ break; -+ case SIO_NCT6779_ID: -+ sio_data->kind = nct6779; -+ sio_name = sio_name_NCT6779; -+ break; -+ default: -+ if (val != 0xffff) -+ pr_debug("unsupported chip ID: 0x%04x\n", val); -+ superio_exit(sioaddr); -+ return -ENODEV; -+ } -+ -+ /* We have a known chip, find the HWM I/O address */ -+ superio_select(sioaddr, NCT6775_LD_HWM); -+ val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) -+ | superio_inb(sioaddr, SIO_REG_ADDR + 1); -+ *addr = val & IOREGION_ALIGNMENT; -+ if (*addr == 0) { -+ pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); -+ superio_exit(sioaddr); -+ return -ENODEV; -+ } -+ -+ /* Activate logical device if needed */ -+ val = superio_inb(sioaddr, SIO_REG_ENABLE); -+ if (!(val & 0x01)) { -+ pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); -+ superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); -+ } -+ -+ superio_exit(sioaddr); -+ pr_info("Found %s chip at %#x\n", sio_name, *addr); -+ sio_data->sioreg = sioaddr; -+ -+ return 0; -+} -+ -+/* -+ * when Super-I/O functions move to a separate file, the Super-I/O -+ * bus will manage the lifetime of the device and this module will only keep -+ * track of the nct6775 driver. But since we platform_device_alloc(), we -+ * must keep track of the device -+ */ -+static struct platform_device *pdev; -+ -+static int __init sensors_nct6775_init(void) -+{ -+ int err; -+ unsigned short address; -+ struct resource res; -+ struct nct6775_sio_data sio_data; -+ -+ /* -+ * initialize sio_data->kind and sio_data->sioreg. -+ * -+ * when Super-I/O functions move to a separate file, the Super-I/O -+ * driver will probe 0x2e and 0x4e and auto-detect the presence of a -+ * nct6775 hardware monitor, and call probe() -+ */ -+ if (nct6775_find(0x2e, &address, &sio_data) && -+ nct6775_find(0x4e, &address, &sio_data)) -+ return -ENODEV; -+ -+ err = platform_driver_register(&nct6775_driver); -+ if (err) -+ goto exit; -+ -+ pdev = platform_device_alloc(DRVNAME, address); -+ if (!pdev) { -+ err = -ENOMEM; -+ pr_err("Device allocation failed\n"); -+ goto exit_unregister; -+ } -+ -+ err = platform_device_add_data(pdev, &sio_data, -+ sizeof(struct nct6775_sio_data)); -+ if (err) { -+ pr_err("Platform data allocation failed\n"); -+ goto exit_device_put; -+ } -+ -+ memset(&res, 0, sizeof(res)); -+ res.name = DRVNAME; -+ res.start = address + IOREGION_OFFSET; -+ res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; -+ res.flags = IORESOURCE_IO; -+ -+ err = acpi_check_resource_conflict(&res); -+ if (err) -+ goto exit_device_put; -+ -+ err = platform_device_add_resources(pdev, &res, 1); -+ if (err) { -+ pr_err("Device resource addition failed (%d)\n", err); -+ goto exit_device_put; -+ } -+ -+ /* platform_device_add calls probe() */ -+ err = platform_device_add(pdev); -+ if (err) { -+ pr_err("Device addition failed (%d)\n", err); -+ goto exit_device_put; -+ } -+ -+ return 0; -+ -+exit_device_put: -+ platform_device_put(pdev); -+exit_unregister: -+ platform_driver_unregister(&nct6775_driver); -+exit: -+ return err; -+} -+ -+static void __exit sensors_nct6775_exit(void) -+{ -+ platform_device_unregister(pdev); -+ platform_driver_unregister(&nct6775_driver); -+} -+ -+MODULE_AUTHOR("Guenter Roeck "); -+MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(sensors_nct6775_init); -+module_exit(sensors_nct6775_exit); - -From a6bd587842772cd3e63a689c7ff4d64cf25284a3 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 03:13:34 -0800 -Subject: [PATCH] hwmon: (nct6775) Add case open detection - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index f75cd82..435691f 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -76,6 +76,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); - * Super-I/O constants and functions - */ - -+#define NCT6775_LD_ACPI 0x0a - #define NCT6775_LD_HWM 0x0b - #define NCT6775_LD_VID 0x0d - -@@ -186,6 +187,11 @@ static const s8 NCT6775_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, -1 }; /* intrusion0, intrusion1 */ - -+#define INTRUSION_ALARM_BASE 30 -+ -+static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; -+static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; -+ - /* NCT6776 specific data */ - - static const s8 NCT6776_ALARM_BITS[] = { -@@ -694,6 +700,56 @@ show_vid(struct device *dev, struct device_attribute *attr, char *buf) - - static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -+/* Case open detection */ -+ -+static ssize_t -+clear_caseopen(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct nct6775_sio_data *sio_data = dev->platform_data; -+ int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE; -+ unsigned long val; -+ u8 reg; -+ int ret; -+ -+ if (kstrtoul(buf, 10, &val) || val != 0) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ -+ /* -+ * Use CR registers to clear caseopen status. -+ * The CR registers are the same for all chips, and not all chips -+ * support clearing the caseopen status through "regular" registers. -+ */ -+ ret = superio_enter(sio_data->sioreg); -+ if (ret) { -+ count = ret; -+ goto error; -+ } -+ -+ superio_select(sio_data->sioreg, NCT6775_LD_ACPI); -+ reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]); -+ reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr]; -+ superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); -+ reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr]; -+ superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); -+ superio_exit(sio_data->sioreg); -+ -+ data->valid = false; /* Force cache refresh */ -+error: -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static struct sensor_device_attribute sda_caseopen[] = { -+ SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm, -+ clear_caseopen, INTRUSION_ALARM_BASE), -+ SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm, -+ clear_caseopen, INTRUSION_ALARM_BASE + 1), -+}; -+ - /* - * Driver and device management - */ -@@ -710,6 +766,9 @@ static void nct6775_device_remove_files(struct device *dev) - for (i = 0; i < data->in_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); - -+ device_remove_file(dev, &sda_caseopen[0].dev_attr); -+ device_remove_file(dev, &sda_caseopen[1].dev_attr); -+ - device_remove_file(dev, &dev_attr_name); - device_remove_file(dev, &dev_attr_cpu0_vid); - } -@@ -828,6 +887,14 @@ static int nct6775_probe(struct platform_device *pdev) - goto exit_remove; - } - -+ for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { -+ if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0) -+ continue; -+ err = device_create_file(dev, &sda_caseopen[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ - err = device_create_file(dev, &dev_attr_name); - if (err) - goto exit_remove; - -From aa136e5dad9fbec9e98867278555a81f2d75ea10 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 03:26:05 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for temperature sensors - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 435691f..fd0dd15 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -57,6 +57,8 @@ - #include - #include "lm75.h" - -+#define USE_ALTERNATE -+ - enum kinds { nct6775, nct6776, nct6779 }; - - /* used to set data->name = nct6775_device_names[data->sio_kind] */ -@@ -156,6 +158,9 @@ superio_exit(int ioreg) - * REG_CHIP_ID is at port 0x58 - */ - -+#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ -+#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */ -+ - #define NUM_REG_ALARM 4 /* Max number of alarm registers */ - - /* Common and NCT6775 specific data */ -@@ -173,6 +178,7 @@ static const u16 NCT6775_REG_IN[] = { - }; - - #define NCT6775_REG_VBAT 0x5D -+#define NCT6775_REG_DIODE 0x5E - - static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; - -@@ -187,11 +193,58 @@ static const s8 NCT6775_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, -1 }; /* intrusion0, intrusion1 */ - -+#define TEMP_ALARM_BASE 24 - #define INTRUSION_ALARM_BASE 30 - - static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; - static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; - -+static const u16 NCT6775_REG_TEMP[] = { -+ 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; -+ -+static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { -+ 0, 0x152, 0x252, 0x628, 0x629, 0x62A }; -+static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = { -+ 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D }; -+static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = { -+ 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C }; -+ -+static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { -+ 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; -+ -+static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; -+ -+static const char *const nct6775_temp_label[] = { -+ "", -+ "SYSTIN", -+ "CPUTIN", -+ "AUXTIN", -+ "AMD SB-TSI", -+ "PECI Agent 0", -+ "PECI Agent 1", -+ "PECI Agent 2", -+ "PECI Agent 3", -+ "PECI Agent 4", -+ "PECI Agent 5", -+ "PECI Agent 6", -+ "PECI Agent 7", -+ "PCH_CHIP_CPU_MAX_TEMP", -+ "PCH_CHIP_TEMP", -+ "PCH_CPU_TEMP", -+ "PCH_MCH_TEMP", -+ "PCH_DIM0_TEMP", -+ "PCH_DIM1_TEMP", -+ "PCH_DIM2_TEMP", -+ "PCH_DIM3_TEMP" -+}; -+ -+static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1] -+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 }; -+ -+static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1] -+ = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06, -+ 0xa07 }; -+ - /* NCT6776 specific data */ - - static const s8 NCT6776_ALARM_BITS[] = { -@@ -203,6 +256,41 @@ static const s8 NCT6776_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { -+ 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; -+ -+static const char *const nct6776_temp_label[] = { -+ "", -+ "SYSTIN", -+ "CPUTIN", -+ "AUXTIN", -+ "SMBUSMASTER 0", -+ "SMBUSMASTER 1", -+ "SMBUSMASTER 2", -+ "SMBUSMASTER 3", -+ "SMBUSMASTER 4", -+ "SMBUSMASTER 5", -+ "SMBUSMASTER 6", -+ "SMBUSMASTER 7", -+ "PECI Agent 0", -+ "PECI Agent 1", -+ "PCH_CHIP_CPU_MAX_TEMP", -+ "PCH_CHIP_TEMP", -+ "PCH_CPU_TEMP", -+ "PCH_MCH_TEMP", -+ "PCH_DIM0_TEMP", -+ "PCH_DIM1_TEMP", -+ "PCH_DIM2_TEMP", -+ "PCH_DIM3_TEMP", -+ "BYTE_TEMP" -+}; -+ -+static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] -+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 }; -+ -+static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] -+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; -+ - /* NCT6779 specific data */ - - static const u16 NCT6779_REG_IN[] = { -@@ -221,6 +309,56 @@ static const s8 NCT6779_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; -+static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { -+ 0x18, 0x152 }; -+static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = { -+ 0x3a, 0x153 }; -+static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = { -+ 0x39, 0x155 }; -+ -+static const u16 NCT6779_REG_TEMP_OFFSET[] = { -+ 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c }; -+ -+static const char *const nct6779_temp_label[] = { -+ "", -+ "SYSTIN", -+ "CPUTIN", -+ "AUXTIN0", -+ "AUXTIN1", -+ "AUXTIN2", -+ "AUXTIN3", -+ "", -+ "SMBUSMASTER 0", -+ "SMBUSMASTER 1", -+ "SMBUSMASTER 2", -+ "SMBUSMASTER 3", -+ "SMBUSMASTER 4", -+ "SMBUSMASTER 5", -+ "SMBUSMASTER 6", -+ "SMBUSMASTER 7", -+ "PECI Agent 0", -+ "PECI Agent 1", -+ "PCH_CHIP_CPU_MAX_TEMP", -+ "PCH_CHIP_TEMP", -+ "PCH_CPU_TEMP", -+ "PCH_MCH_TEMP", -+ "PCH_DIM0_TEMP", -+ "PCH_DIM1_TEMP", -+ "PCH_DIM2_TEMP", -+ "PCH_DIM3_TEMP", -+ "BYTE_TEMP" -+}; -+ -+static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] -+ = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407, -+ 0x408, 0 }; -+ -+static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] -+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; -+ - /* - * Conversions - */ -@@ -256,14 +394,27 @@ struct nct6775_data { - struct device *hwmon_dev; - struct mutex lock; - -+ u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, -+ * 3=temp_crit -+ */ -+ u8 temp_src[NUM_TEMP]; -+ u16 reg_temp_config[NUM_TEMP]; -+ const char * const *temp_label; -+ int temp_label_num; -+ - u16 REG_CONFIG; - u16 REG_VBAT; -+ u16 REG_DIODE; - - const s8 *ALARM_BITS; - - const u16 *REG_VIN; - const u16 *REG_IN_MINMAX[2]; - -+ const u16 *REG_TEMP_SOURCE; /* temp register sources */ -+ -+ const u16 *REG_TEMP_OFFSET; -+ - const u16 *REG_ALARM; - - struct mutex update_lock; -@@ -275,11 +426,18 @@ struct nct6775_data { - u8 in_num; /* number of in inputs we have */ - u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ - -+ u8 temp_fixed_num; /* 3 or 6 */ -+ u8 temp_type[NUM_TEMP_FIXED]; -+ s8 temp_offset[NUM_TEMP_FIXED]; -+ s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, -+ * 3=temp_crit */ - u64 alarms; - - u8 vid; - u8 vrm; - -+ u16 have_temp; -+ u16 have_temp_fixed; - u16 have_in; - }; - -@@ -379,10 +537,29 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) - return 0; - } - -+/* We left-align 8-bit temperature values to make the code simpler */ -+static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg) -+{ -+ u16 res; -+ -+ res = nct6775_read_value(data, reg); -+ if (!is_word_sized(data, reg)) -+ res <<= 8; -+ -+ return res; -+} -+ -+static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value) -+{ -+ if (!is_word_sized(data, reg)) -+ value >>= 8; -+ return nct6775_write_value(data, reg, value); -+} -+ - static struct nct6775_data *nct6775_update_device(struct device *dev) - { - struct nct6775_data *data = dev_get_drvdata(dev); -- int i; -+ int i, j; - - mutex_lock(&data->update_lock); - -@@ -401,6 +578,22 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - data->REG_IN_MINMAX[1][i]); - } - -+ /* Measured temperatures and limits */ -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ for (j = 0; j < 4; j++) { -+ if (data->reg_temp[j][i]) -+ data->temp[j][i] -+ = nct6775_read_temp(data, -+ data->reg_temp[j][i]); -+ } -+ if (!(data->have_temp_fixed & (1 << i))) -+ continue; -+ data->temp_offset[i] -+ = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]); -+ } -+ - data->alarms = 0; - for (i = 0; i < NUM_REG_ALARM; i++) { - u8 alarm; -@@ -682,6 +875,275 @@ static const struct attribute_group nct6775_group_in[15] = { - }; - - static ssize_t -+show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]); -+} -+ -+static ssize_t -+show_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ -+ return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr])); -+} -+ -+static ssize_t -+store_temp(struct device *dev, struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ int err; -+ long val; -+ -+ err = kstrtol(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ mutex_lock(&data->update_lock); -+ data->temp[index][nr] = LM75_TEMP_TO_REG(val); -+ nct6775_write_temp(data, data->reg_temp[index][nr], -+ data->temp[index][nr]); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ -+ return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000); -+} -+ -+static ssize_t -+store_temp_offset(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ long val; -+ int err; -+ -+ err = kstrtol(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127); -+ -+ mutex_lock(&data->update_lock); -+ data->temp_offset[nr] = val; -+ nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val); -+ mutex_unlock(&data->update_lock); -+ -+ return count; -+} -+ -+static ssize_t -+show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ return sprintf(buf, "%d\n", (int)data->temp_type[nr]); -+} -+ -+static ssize_t -+store_temp_type(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ u8 vbat, diode, bit; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ if (val != 1 && val != 3 && val != 4) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ -+ data->temp_type[nr] = val; -+ vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr); -+ diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr); -+ bit = 0x02 << nr; -+ switch (val) { -+ case 1: /* CPU diode (diode, current mode) */ -+ vbat |= bit; -+ diode |= bit; -+ break; -+ case 3: /* diode, voltage mode */ -+ vbat |= bit; -+ break; -+ case 4: /* thermistor */ -+ break; -+ } -+ nct6775_write_value(data, data->REG_VBAT, vbat); -+ nct6775_write_value(data, data->REG_DIODE, diode); -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static struct sensor_device_attribute_2 sda_temp_input[] = { -+ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), -+ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0), -+ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0), -+ SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0), -+ SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0), -+ SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0), -+ SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0), -+ SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0), -+ SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0), -+ SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0), -+}; -+ -+static struct sensor_device_attribute sda_temp_label[] = { -+ SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0), -+ SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1), -+ SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2), -+ SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3), -+ SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4), -+ SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5), -+ SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6), -+ SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7), -+ SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8), -+ SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9), -+}; -+ -+static struct sensor_device_attribute_2 sda_temp_max[] = { -+ SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 0, 1), -+ SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 1, 1), -+ SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 2, 1), -+ SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 3, 1), -+ SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 4, 1), -+ SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 5, 1), -+ SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 6, 1), -+ SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 7, 1), -+ SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 8, 1), -+ SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 9, 1), -+}; -+ -+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { -+ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 0, 2), -+ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 1, 2), -+ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 2, 2), -+ SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 3, 2), -+ SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 4, 2), -+ SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 5, 2), -+ SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 6, 2), -+ SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 7, 2), -+ SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 8, 2), -+ SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 9, 2), -+}; -+ -+static struct sensor_device_attribute_2 sda_temp_crit[] = { -+ SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 0, 3), -+ SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 1, 3), -+ SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 2, 3), -+ SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 3, 3), -+ SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 4, 3), -+ SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 5, 3), -+ SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 6, 3), -+ SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 7, 3), -+ SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 8, 3), -+ SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp, -+ 9, 3), -+}; -+ -+static struct sensor_device_attribute sda_temp_offset[] = { -+ SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 0), -+ SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 1), -+ SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 2), -+ SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 3), -+ SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 4), -+ SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset, -+ store_temp_offset, 5), -+}; -+ -+static struct sensor_device_attribute sda_temp_type[] = { -+ SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 0), -+ SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 1), -+ SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 2), -+ SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 3), -+ SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 4), -+ SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type, -+ store_temp_type, 5), -+}; -+ -+static struct sensor_device_attribute sda_temp_alarm[] = { -+ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE), -+ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE + 1), -+ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE + 2), -+ SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE + 3), -+ SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE + 4), -+ SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, -+ TEMP_ALARM_BASE + 5), -+}; -+ -+#define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm) -+ -+static ssize_t - show_name(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = dev_get_drvdata(dev); -@@ -766,6 +1228,23 @@ static void nct6775_device_remove_files(struct device *dev) - for (i = 0; i < data->in_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); - -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ device_remove_file(dev, &sda_temp_input[i].dev_attr); -+ device_remove_file(dev, &sda_temp_label[i].dev_attr); -+ device_remove_file(dev, &sda_temp_max[i].dev_attr); -+ device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); -+ device_remove_file(dev, &sda_temp_crit[i].dev_attr); -+ if (!(data->have_temp_fixed & (1 << i))) -+ continue; -+ device_remove_file(dev, &sda_temp_type[i].dev_attr); -+ device_remove_file(dev, &sda_temp_offset[i].dev_attr); -+ if (i >= NUM_TEMP_ALARM) -+ continue; -+ device_remove_file(dev, &sda_temp_alarm[i].dev_attr); -+ } -+ - device_remove_file(dev, &sda_caseopen[0].dev_attr); - device_remove_file(dev, &sda_caseopen[1].dev_attr); - -@@ -776,7 +1255,8 @@ static void nct6775_device_remove_files(struct device *dev) - /* Get the monitoring functions started */ - static inline void nct6775_init_device(struct nct6775_data *data) - { -- u8 tmp; -+ int i; -+ u8 tmp, diode; - - /* Start monitoring if needed */ - if (data->REG_CONFIG) { -@@ -785,10 +1265,33 @@ static inline void nct6775_init_device(struct nct6775_data *data) - nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01); - } - -+ /* Enable temperature sensors if needed */ -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ if (!data->reg_temp_config[i]) -+ continue; -+ tmp = nct6775_read_value(data, data->reg_temp_config[i]); -+ if (tmp & 0x01) -+ nct6775_write_value(data, data->reg_temp_config[i], -+ tmp & 0xfe); -+ } -+ - /* Enable VBAT monitoring if needed */ - tmp = nct6775_read_value(data, data->REG_VBAT); - if (!(tmp & 0x01)) - nct6775_write_value(data, data->REG_VBAT, tmp | 0x01); -+ -+ diode = nct6775_read_value(data, data->REG_DIODE); -+ -+ for (i = 0; i < data->temp_fixed_num; i++) { -+ if (!(data->have_temp_fixed & (1 << i))) -+ continue; -+ if ((tmp & (0x02 << i))) /* diode */ -+ data->temp_type[i] = 3 - ((diode >> i) & 0x02); -+ else /* thermistor */ -+ data->temp_type[i] = 4; -+ } - } - - static int nct6775_probe(struct platform_device *pdev) -@@ -797,7 +1300,11 @@ static int nct6775_probe(struct platform_device *pdev) - struct nct6775_sio_data *sio_data = dev->platform_data; - struct nct6775_data *data; - struct resource *res; -- int i, err = 0; -+ int i, s, err = 0; -+ int src, mask, available; -+ const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config; -+ const u16 *reg_temp_alternate, *reg_temp_crit; -+ int num_reg_temp; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, -@@ -820,44 +1327,233 @@ static int nct6775_probe(struct platform_device *pdev) - switch (data->kind) { - case nct6775: - data->in_num = 9; -+ data->temp_fixed_num = 3; - - data->ALARM_BITS = NCT6775_ALARM_BITS; - -+ data->temp_label = nct6775_temp_label; -+ data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); -+ - data->REG_CONFIG = NCT6775_REG_CONFIG; - data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_DIODE = NCT6775_REG_DIODE; - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; -+ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -+ -+ reg_temp = NCT6775_REG_TEMP; -+ num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); -+ reg_temp_over = NCT6775_REG_TEMP_OVER; -+ reg_temp_hyst = NCT6775_REG_TEMP_HYST; -+ reg_temp_config = NCT6775_REG_TEMP_CONFIG; -+ reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE; -+ reg_temp_crit = NCT6775_REG_TEMP_CRIT; -+ - break; - case nct6776: - data->in_num = 9; -+ data->temp_fixed_num = 3; - - data->ALARM_BITS = NCT6776_ALARM_BITS; - -+ data->temp_label = nct6776_temp_label; -+ data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); -+ - data->REG_CONFIG = NCT6775_REG_CONFIG; - data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_DIODE = NCT6775_REG_DIODE; - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; -+ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -+ -+ reg_temp = NCT6775_REG_TEMP; -+ num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); -+ reg_temp_over = NCT6775_REG_TEMP_OVER; -+ reg_temp_hyst = NCT6775_REG_TEMP_HYST; -+ reg_temp_config = NCT6776_REG_TEMP_CONFIG; -+ reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE; -+ reg_temp_crit = NCT6776_REG_TEMP_CRIT; -+ - break; - case nct6779: - data->in_num = 15; -+ data->temp_fixed_num = 6; - - data->ALARM_BITS = NCT6779_ALARM_BITS; - -+ data->temp_label = nct6779_temp_label; -+ data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); -+ - data->REG_CONFIG = NCT6775_REG_CONFIG; - data->REG_VBAT = NCT6775_REG_VBAT; -+ data->REG_DIODE = NCT6775_REG_DIODE; - data->REG_VIN = NCT6779_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; -+ data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6779_REG_ALARM; -+ -+ reg_temp = NCT6779_REG_TEMP; -+ num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP); -+ reg_temp_over = NCT6779_REG_TEMP_OVER; -+ reg_temp_hyst = NCT6779_REG_TEMP_HYST; -+ reg_temp_config = NCT6779_REG_TEMP_CONFIG; -+ reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE; -+ reg_temp_crit = NCT6779_REG_TEMP_CRIT; -+ - break; - default: - return -ENODEV; - } - data->have_in = (1 << data->in_num) - 1; -+ data->have_temp = 0; -+ -+ /* -+ * On some boards, not all available temperature sources are monitored, -+ * even though some of the monitoring registers are unused. -+ * Get list of unused monitoring registers, then detect if any fan -+ * controls are configured to use unmonitored temperature sources. -+ * If so, assign the unmonitored temperature sources to available -+ * monitoring registers. -+ */ -+ mask = 0; -+ available = 0; -+ for (i = 0; i < num_reg_temp; i++) { -+ if (reg_temp[i] == 0) -+ continue; -+ -+ src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; -+ if (!src || (mask & (1 << src))) -+ available |= 1 << i; -+ -+ mask |= 1 << src; -+ } -+ -+ mask = 0; -+ s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */ -+ for (i = 0; i < num_reg_temp; i++) { -+ if (reg_temp[i] == 0) -+ continue; -+ -+ src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; -+ if (!src || (mask & (1 << src))) -+ continue; -+ -+ if (src >= data->temp_label_num || -+ !strlen(data->temp_label[src])) { -+ dev_info(dev, -+ "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n", -+ src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]); -+ continue; -+ } -+ -+ mask |= 1 << src; -+ -+ /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */ -+ if (src <= data->temp_fixed_num) { -+ data->have_temp |= 1 << (src - 1); -+ data->have_temp_fixed |= 1 << (src - 1); -+ data->reg_temp[0][src - 1] = reg_temp[i]; -+ data->reg_temp[1][src - 1] = reg_temp_over[i]; -+ data->reg_temp[2][src - 1] = reg_temp_hyst[i]; -+ data->reg_temp_config[src - 1] = reg_temp_config[i]; -+ data->temp_src[src - 1] = src; -+ continue; -+ } -+ -+ if (s >= NUM_TEMP) -+ continue; -+ -+ /* Use dynamic index for other sources */ -+ data->have_temp |= 1 << s; -+ data->reg_temp[0][s] = reg_temp[i]; -+ data->reg_temp[1][s] = reg_temp_over[i]; -+ data->reg_temp[2][s] = reg_temp_hyst[i]; -+ data->reg_temp_config[s] = reg_temp_config[i]; -+ if (reg_temp_crit[src - 1]) -+ data->reg_temp[3][s] = reg_temp_crit[src - 1]; -+ -+ data->temp_src[s] = src; -+ s++; -+ } -+ -+#ifdef USE_ALTERNATE -+ /* -+ * Go through the list of alternate temp registers and enable -+ * if possible. -+ * The temperature is already monitored if the respective bit in -+ * is set. -+ */ -+ for (i = 0; i < data->temp_label_num - 1; i++) { -+ if (!reg_temp_alternate[i]) -+ continue; -+ if (mask & (1 << (i + 1))) -+ continue; -+ if (i < data->temp_fixed_num) { -+ if (data->have_temp & (1 << i)) -+ continue; -+ data->have_temp |= 1 << i; -+ data->have_temp_fixed |= 1 << i; -+ data->reg_temp[0][i] = reg_temp_alternate[i]; -+ data->reg_temp[1][i] = reg_temp_over[i]; -+ data->reg_temp[2][i] = reg_temp_hyst[i]; -+ data->temp_src[i] = i + 1; -+ continue; -+ } -+ -+ if (s >= NUM_TEMP) /* Abort if no more space */ -+ break; -+ -+ data->have_temp |= 1 << s; -+ data->reg_temp[0][s] = reg_temp_alternate[i]; -+ data->temp_src[s] = i + 1; -+ s++; -+ } -+#endif /* USE_ALTERNATE */ -+ -+ switch (data->kind) { -+ case nct6775: -+ break; -+ case nct6776: -+ /* -+ * On NCT6776, AUXTIN and VIN3 pins are shared. -+ * Only way to detect it is to check if AUXTIN is used -+ * as a temperature source, and if that source is -+ * enabled. -+ * -+ * If that is the case, disable in6, which reports VIN3. -+ * Otherwise disable temp3. -+ */ -+ if (data->have_temp & (1 << 2)) { -+ u8 reg = nct6775_read_value(data, -+ data->reg_temp_config[2]); -+ if (reg & 0x01) -+ data->have_temp &= ~(1 << 2); -+ else -+ data->have_in &= ~(1 << 6); -+ } -+ break; -+ case nct6779: -+ /* -+ * Shared pins: -+ * VIN4 / AUXTIN0 -+ * VIN5 / AUXTIN1 -+ * VIN6 / AUXTIN2 -+ * VIN7 / AUXTIN3 -+ * -+ * There does not seem to be a clean way to detect if VINx or -+ * AUXTINx is active, so for keep both sensor types enabled -+ * for now. -+ */ -+ break; -+ } - - /* Initialize the chip */ - nct6775_init_device(data); -@@ -887,6 +1583,52 @@ static int nct6775_probe(struct platform_device *pdev) - goto exit_remove; - } - -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ err = device_create_file(dev, &sda_temp_input[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ if (data->temp_label) { -+ err = device_create_file(dev, -+ &sda_temp_label[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (data->reg_temp[1][i]) { -+ err = device_create_file(dev, -+ &sda_temp_max[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (data->reg_temp[2][i]) { -+ err = device_create_file(dev, -+ &sda_temp_max_hyst[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (data->reg_temp[3][i]) { -+ err = device_create_file(dev, -+ &sda_temp_crit[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (!(data->have_temp_fixed & (1 << i))) -+ continue; -+ err = device_create_file(dev, &sda_temp_type[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ err = device_create_file(dev, &sda_temp_offset[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ if (i >= NUM_TEMP_ALARM || -+ data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0) -+ continue; -+ err = device_create_file(dev, &sda_temp_alarm[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ - for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { - if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0) - continue; - -From 1c65dc365ed38d6839fcc231ea38a6163fb9d343 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 07:56:24 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for fan speed attributes - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -index ccfd5cc..dcd56a3 100644 ---- a/Documentation/hwmon/nct6775 -+++ b/Documentation/hwmon/nct6775 -@@ -53,8 +53,9 @@ triggered if the rotation speed has dropped below a programmable limit. On - NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8, - 16, 32, 64 or 128) to give the readings more range or accuracy; the other chips - do not have a fan speed divider. The driver sets the most suitable fan divisor --itself; specifically, it doubles the divider value each time a fan speed reading --returns an invalid value. Some fans might not be present because they share pins -+itself; specifically, it increases the divider value each time a fan speed -+reading returns an invalid value, and it reduces it if the fan speed reading -+is lower than optimal. Some fans might not be present because they share pins - with other functions. - - Voltage sensors (also known as IN sensors) report their values in millivolts. -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index fd0dd15..bafcae5 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -180,6 +180,9 @@ static const u16 NCT6775_REG_IN[] = { - #define NCT6775_REG_VBAT 0x5D - #define NCT6775_REG_DIODE 0x5E - -+#define NCT6775_REG_FANDIV1 0x506 -+#define NCT6775_REG_FANDIV2 0x507 -+ - static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; - - /* 0..15 voltages, 16..23 fans, 24..31 temperatures */ -@@ -193,12 +196,16 @@ static const s8 NCT6775_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, -1 }; /* intrusion0, intrusion1 */ - -+#define FAN_ALARM_BASE 16 - #define TEMP_ALARM_BASE 24 - #define INTRUSION_ALARM_BASE 30 - - static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; - static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; - -+static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; -+static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; -+ - static const u16 NCT6775_REG_TEMP[] = { - 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; - -@@ -256,6 +263,8 @@ static const s8 NCT6776_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; -+ - static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; - -@@ -309,6 +318,8 @@ static const s8 NCT6779_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; -+ - static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; - static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { - 0x18, 0x152 }; -@@ -363,6 +374,44 @@ static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] - * Conversions - */ - -+static unsigned int fan_from_reg8(u16 reg, unsigned int divreg) -+{ -+ if (reg == 0 || reg == 255) -+ return 0; -+ return 1350000U / (reg << divreg); -+} -+ -+static unsigned int fan_from_reg13(u16 reg, unsigned int divreg) -+{ -+ if ((reg & 0xff1f) == 0xff1f) -+ return 0; -+ -+ reg = (reg & 0x1f) | ((reg & 0xff00) >> 3); -+ -+ if (reg == 0) -+ return 0; -+ -+ return 1350000U / reg; -+} -+ -+static unsigned int fan_from_reg16(u16 reg, unsigned int divreg) -+{ -+ if (reg == 0 || reg == 0xffff) -+ return 0; -+ -+ /* -+ * Even though the registers are 16 bit wide, the fan divisor -+ * still applies. -+ */ -+ return 1350000U / (reg << divreg); -+} -+ -+static inline unsigned int -+div_from_reg(u8 reg) -+{ -+ return 1 << reg; -+} -+ - /* - * Some of the voltage inputs have internal scaling, the tables below - * contain 8 (the ADC LSB in mV) * scaling factor * 100 -@@ -411,12 +460,17 @@ struct nct6775_data { - const u16 *REG_VIN; - const u16 *REG_IN_MINMAX[2]; - -- const u16 *REG_TEMP_SOURCE; /* temp register sources */ -+ const u16 *REG_FAN; -+ const u16 *REG_FAN_MIN; - -+ const u16 *REG_TEMP_SOURCE; /* temp register sources */ - const u16 *REG_TEMP_OFFSET; - - const u16 *REG_ALARM; - -+ unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg); -+ unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg); -+ - struct mutex update_lock; - bool valid; /* true if following fields are valid */ - unsigned long last_updated; /* In jiffies */ -@@ -425,6 +479,12 @@ struct nct6775_data { - u8 bank; /* current register bank */ - u8 in_num; /* number of in inputs we have */ - u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ -+ unsigned int rpm[5]; -+ u16 fan_min[5]; -+ u8 fan_div[5]; -+ u8 has_fan; /* some fan inputs can be disabled */ -+ u8 has_fan_min; /* some fans don't have min register */ -+ bool has_fan_div; - - u8 temp_fixed_num; /* 3 or 6 */ - u8 temp_type[NUM_TEMP_FIXED]; -@@ -556,6 +616,153 @@ static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value) - return nct6775_write_value(data, reg, value); - } - -+/* This function assumes that the caller holds data->update_lock */ -+static void nct6775_write_fan_div(struct nct6775_data *data, int nr) -+{ -+ u8 reg; -+ -+ switch (nr) { -+ case 0: -+ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70) -+ | (data->fan_div[0] & 0x7); -+ nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); -+ break; -+ case 1: -+ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7) -+ | ((data->fan_div[1] << 4) & 0x70); -+ nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); -+ break; -+ case 2: -+ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70) -+ | (data->fan_div[2] & 0x7); -+ nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); -+ break; -+ case 3: -+ reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7) -+ | ((data->fan_div[3] << 4) & 0x70); -+ nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); -+ break; -+ } -+} -+ -+static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr) -+{ -+ if (data->kind == nct6775) -+ nct6775_write_fan_div(data, nr); -+} -+ -+static void nct6775_update_fan_div(struct nct6775_data *data) -+{ -+ u8 i; -+ -+ i = nct6775_read_value(data, NCT6775_REG_FANDIV1); -+ data->fan_div[0] = i & 0x7; -+ data->fan_div[1] = (i & 0x70) >> 4; -+ i = nct6775_read_value(data, NCT6775_REG_FANDIV2); -+ data->fan_div[2] = i & 0x7; -+ if (data->has_fan & (1<<3)) -+ data->fan_div[3] = (i & 0x70) >> 4; -+} -+ -+static void nct6775_update_fan_div_common(struct nct6775_data *data) -+{ -+ if (data->kind == nct6775) -+ nct6775_update_fan_div(data); -+} -+ -+static void nct6775_init_fan_div(struct nct6775_data *data) -+{ -+ int i; -+ -+ nct6775_update_fan_div_common(data); -+ /* -+ * For all fans, start with highest divider value if the divider -+ * register is not initialized. This ensures that we get a -+ * reading from the fan count register, even if it is not optimal. -+ * We'll compute a better divider later on. -+ */ -+ for (i = 0; i < 3; i++) { -+ if (!(data->has_fan & (1 << i))) -+ continue; -+ if (data->fan_div[i] == 0) { -+ data->fan_div[i] = 7; -+ nct6775_write_fan_div_common(data, i); -+ } -+ } -+} -+ -+static void nct6775_init_fan_common(struct device *dev, -+ struct nct6775_data *data) -+{ -+ int i; -+ u8 reg; -+ -+ if (data->has_fan_div) -+ nct6775_init_fan_div(data); -+ -+ /* -+ * If fan_min is not set (0), set it to 0xff to disable it. This -+ * prevents the unnecessary warning when fanX_min is reported as 0. -+ */ -+ for (i = 0; i < 5; i++) { -+ if (data->has_fan_min & (1 << i)) { -+ reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); -+ if (!reg) -+ nct6775_write_value(data, data->REG_FAN_MIN[i], -+ data->has_fan_div ? 0xff -+ : 0xff1f); -+ } -+ } -+} -+ -+static void nct6775_select_fan_div(struct device *dev, -+ struct nct6775_data *data, int nr, u16 reg) -+{ -+ u8 fan_div = data->fan_div[nr]; -+ u16 fan_min; -+ -+ if (!data->has_fan_div) -+ return; -+ -+ /* -+ * If we failed to measure the fan speed, or the reported value is not -+ * in the optimal range, and the clock divider can be modified, -+ * let's try that for next time. -+ */ -+ if (reg == 0x00 && fan_div < 0x07) -+ fan_div++; -+ else if (reg != 0x00 && reg < 0x30 && fan_div > 0) -+ fan_div--; -+ -+ if (fan_div != data->fan_div[nr]) { -+ dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n", -+ nr + 1, div_from_reg(data->fan_div[nr]), -+ div_from_reg(fan_div)); -+ -+ /* Preserve min limit if possible */ -+ if (data->has_fan_min & (1 << nr)) { -+ fan_min = data->fan_min[nr]; -+ if (fan_div > data->fan_div[nr]) { -+ if (fan_min != 255 && fan_min > 1) -+ fan_min >>= 1; -+ } else { -+ if (fan_min != 255) { -+ fan_min <<= 1; -+ if (fan_min > 254) -+ fan_min = 254; -+ } -+ } -+ if (fan_min != data->fan_min[nr]) { -+ data->fan_min[nr] = fan_min; -+ nct6775_write_value(data, data->REG_FAN_MIN[nr], -+ fan_min); -+ } -+ } -+ data->fan_div[nr] = fan_div; -+ nct6775_write_fan_div_common(data, nr); -+ } -+} -+ - static struct nct6775_data *nct6775_update_device(struct device *dev) - { - struct nct6775_data *data = dev_get_drvdata(dev); -@@ -565,6 +772,9 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - - if (time_after(jiffies, data->last_updated + HZ + HZ/2) - || !data->valid) { -+ /* Fan clock dividers */ -+ nct6775_update_fan_div_common(data); -+ - /* Measured voltages and limits */ - for (i = 0; i < data->in_num; i++) { - if (!(data->have_in & (1 << i))) -@@ -578,6 +788,24 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - data->REG_IN_MINMAX[1][i]); - } - -+ /* Measured fan speeds and limits */ -+ for (i = 0; i < 5; i++) { -+ u16 reg; -+ -+ if (!(data->has_fan & (1 << i))) -+ continue; -+ -+ reg = nct6775_read_value(data, data->REG_FAN[i]); -+ data->rpm[i] = data->fan_from_reg(reg, -+ data->fan_div[i]); -+ -+ if (data->has_fan_min & (1 << i)) -+ data->fan_min[i] = nct6775_read_value(data, -+ data->REG_FAN_MIN[i]); -+ -+ nct6775_select_fan_div(dev, data, i, reg); -+ } -+ - /* Measured temperatures and limits */ - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) -@@ -875,6 +1103,166 @@ static const struct attribute_group nct6775_group_in[15] = { - }; - - static ssize_t -+show_fan(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ return sprintf(buf, "%d\n", data->rpm[nr]); -+} -+ -+static ssize_t -+show_fan_min(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ return sprintf(buf, "%d\n", -+ data->fan_from_reg_min(data->fan_min[nr], -+ data->fan_div[nr])); -+} -+ -+static ssize_t -+show_fan_div(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); -+} -+ -+static ssize_t -+store_fan_min(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ unsigned int reg; -+ u8 new_div; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ mutex_lock(&data->update_lock); -+ if (!data->has_fan_div) { -+ /* NCT6776F or NCT6779D; we know this is a 13 bit register */ -+ if (!val) { -+ val = 0xff1f; -+ } else { -+ if (val > 1350000U) -+ val = 135000U; -+ val = 1350000U / val; -+ val = (val & 0x1f) | ((val << 3) & 0xff00); -+ } -+ data->fan_min[nr] = val; -+ goto write_min; /* Leave fan divider alone */ -+ } -+ if (!val) { -+ /* No min limit, alarm disabled */ -+ data->fan_min[nr] = 255; -+ new_div = data->fan_div[nr]; /* No change */ -+ dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1); -+ goto write_div; -+ } -+ reg = 1350000U / val; -+ if (reg >= 128 * 255) { -+ /* -+ * Speed below this value cannot possibly be represented, -+ * even with the highest divider (128) -+ */ -+ data->fan_min[nr] = 254; -+ new_div = 7; /* 128 == (1 << 7) */ -+ dev_warn(dev, -+ "fan%u low limit %lu below minimum %u, set to minimum\n", -+ nr + 1, val, data->fan_from_reg_min(254, 7)); -+ } else if (!reg) { -+ /* -+ * Speed above this value cannot possibly be represented, -+ * even with the lowest divider (1) -+ */ -+ data->fan_min[nr] = 1; -+ new_div = 0; /* 1 == (1 << 0) */ -+ dev_warn(dev, -+ "fan%u low limit %lu above maximum %u, set to maximum\n", -+ nr + 1, val, data->fan_from_reg_min(1, 0)); -+ } else { -+ /* -+ * Automatically pick the best divider, i.e. the one such -+ * that the min limit will correspond to a register value -+ * in the 96..192 range -+ */ -+ new_div = 0; -+ while (reg > 192 && new_div < 7) { -+ reg >>= 1; -+ new_div++; -+ } -+ data->fan_min[nr] = reg; -+ } -+ -+write_div: -+ /* -+ * Write both the fan clock divider (if it changed) and the new -+ * fan min (unconditionally) -+ */ -+ if (new_div != data->fan_div[nr]) { -+ dev_dbg(dev, "fan%u clock divider changed from %u to %u\n", -+ nr + 1, div_from_reg(data->fan_div[nr]), -+ div_from_reg(new_div)); -+ data->fan_div[nr] = new_div; -+ nct6775_write_fan_div_common(data, nr); -+ /* Give the chip time to sample a new speed value */ -+ data->last_updated = jiffies; -+ } -+ -+write_min: -+ nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]); -+ mutex_unlock(&data->update_lock); -+ -+ return count; -+} -+ -+static struct sensor_device_attribute sda_fan_input[] = { -+ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), -+ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), -+ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), -+ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), -+ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), -+}; -+ -+static struct sensor_device_attribute sda_fan_alarm[] = { -+ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE), -+ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1), -+ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2), -+ SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3), -+ SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4), -+}; -+ -+static struct sensor_device_attribute sda_fan_min[] = { -+ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 0), -+ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 1), -+ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 2), -+ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 3), -+ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 4), -+}; -+ -+static struct sensor_device_attribute sda_fan_div[] = { -+ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), -+ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), -+ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), -+ SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), -+ SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), -+}; -+ -+static ssize_t - show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = nct6775_update_device(dev); -@@ -1228,6 +1616,12 @@ static void nct6775_device_remove_files(struct device *dev) - for (i = 0; i < data->in_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); - -+ for (i = 0; i < 5; i++) { -+ device_remove_file(dev, &sda_fan_input[i].dev_attr); -+ device_remove_file(dev, &sda_fan_alarm[i].dev_attr); -+ device_remove_file(dev, &sda_fan_div[i].dev_attr); -+ device_remove_file(dev, &sda_fan_min[i].dev_attr); -+ } - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) - continue; -@@ -1294,6 +1688,75 @@ static inline void nct6775_init_device(struct nct6775_data *data) - } - } - -+static int -+nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, -+ struct nct6775_data *data) -+{ -+ int regval; -+ bool fan3pin, fan3min, fan4pin, fan4min, fan5pin; -+ int ret; -+ -+ ret = superio_enter(sio_data->sioreg); -+ if (ret) -+ return ret; -+ -+ /* fan4 and fan5 share some pins with the GPIO and serial flash */ -+ if (data->kind == nct6775) { -+ regval = superio_inb(sio_data->sioreg, 0x2c); -+ -+ fan3pin = regval & (1 << 6); -+ fan3min = fan3pin; -+ -+ /* On NCT6775, fan4 shares pins with the fdc interface */ -+ fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); -+ fan4min = 0; -+ fan5pin = 0; -+ } else if (data->kind == nct6776) { -+ bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; -+ -+ superio_select(sio_data->sioreg, NCT6775_LD_HWM); -+ regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE); -+ -+ if (regval & 0x80) -+ fan3pin = gpok; -+ else -+ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); -+ -+ if (regval & 0x40) -+ fan4pin = gpok; -+ else -+ fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01; -+ -+ if (regval & 0x20) -+ fan5pin = gpok; -+ else -+ fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02; -+ -+ fan4min = fan4pin; -+ fan3min = fan3pin; -+ } else { /* NCT6779D */ -+ regval = superio_inb(sio_data->sioreg, 0x1c); -+ -+ fan3pin = !(regval & (1 << 5)); -+ fan4pin = !(regval & (1 << 6)); -+ fan5pin = !(regval & (1 << 7)); -+ -+ fan3min = fan3pin; -+ fan4min = fan4pin; -+ } -+ -+ superio_exit(sio_data->sioreg); -+ -+ data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */ -+ data->has_fan |= fan3pin << 2; -+ data->has_fan_min |= fan3min << 2; -+ -+ data->has_fan |= (fan4pin << 3) | (fan5pin << 4); -+ data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); -+ -+ return 0; -+} -+ - static int nct6775_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -1327,10 +1790,14 @@ static int nct6775_probe(struct platform_device *pdev) - switch (data->kind) { - case nct6775: - data->in_num = 9; -+ data->has_fan_div = true; - data->temp_fixed_num = 3; - - data->ALARM_BITS = NCT6775_ALARM_BITS; - -+ data->fan_from_reg = fan_from_reg16; -+ data->fan_from_reg_min = fan_from_reg8; -+ - data->temp_label = nct6775_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); - -@@ -1340,6 +1807,8 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_FAN = NCT6775_REG_FAN; -+ data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1355,10 +1824,14 @@ static int nct6775_probe(struct platform_device *pdev) - break; - case nct6776: - data->in_num = 9; -+ data->has_fan_div = false; - data->temp_fixed_num = 3; - - data->ALARM_BITS = NCT6776_ALARM_BITS; - -+ data->fan_from_reg = fan_from_reg13; -+ data->fan_from_reg_min = fan_from_reg13; -+ - data->temp_label = nct6776_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); - -@@ -1368,6 +1841,8 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_FAN = NCT6775_REG_FAN; -+ data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1383,10 +1858,14 @@ static int nct6775_probe(struct platform_device *pdev) - break; - case nct6779: - data->in_num = 15; -+ data->has_fan_div = false; - data->temp_fixed_num = 6; - - data->ALARM_BITS = NCT6779_ALARM_BITS; - -+ data->fan_from_reg = fan_from_reg13; -+ data->fan_from_reg_min = fan_from_reg13; -+ - data->temp_label = nct6779_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); - -@@ -1396,6 +1875,8 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6779_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_FAN = NCT6779_REG_FAN; -+ data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6779_REG_ALARM; -@@ -1575,6 +2056,13 @@ static int nct6775_probe(struct platform_device *pdev) - if (err) - return err; - -+ err = nct6775_check_fan_inputs(sio_data, data); -+ if (err) -+ goto exit_remove; -+ -+ /* Read fan clock dividers immediately */ -+ nct6775_init_fan_common(dev, data); -+ - for (i = 0; i < data->in_num; i++) { - if (!(data->have_in & (1 << i))) - continue; -@@ -1583,6 +2071,32 @@ static int nct6775_probe(struct platform_device *pdev) - goto exit_remove; - } - -+ for (i = 0; i < 5; i++) { -+ if (data->has_fan & (1 << i)) { -+ err = device_create_file(dev, -+ &sda_fan_input[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ err = device_create_file(dev, -+ &sda_fan_alarm[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ if (data->kind != nct6776 && -+ data->kind != nct6779) { -+ err = device_create_file(dev, -+ &sda_fan_div[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (data->has_fan_min & (1 << i)) { -+ err = device_create_file(dev, -+ &sda_fan_min[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ } -+ } -+ - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) - continue; - -From 5c25d954d37b7c18606d7ef99122424552b86ef2 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 11 Dec 2012 07:29:06 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for fanX_pulses sysfs attribute - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index bafcae5..fea6ed7 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -205,6 +205,7 @@ static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; - - static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; - static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; -+static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; - - static const u16 NCT6775_REG_TEMP[] = { - 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; -@@ -264,6 +265,7 @@ static const s8 NCT6776_ALARM_BITS[] = { - 12, 9 }; /* intrusion0, intrusion1 */ - - static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; -+static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; - - static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; -@@ -319,6 +321,8 @@ static const s8 NCT6779_ALARM_BITS[] = { - 12, 9 }; /* intrusion0, intrusion1 */ - - static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; -+static const u16 NCT6779_REG_FAN_PULSES[] = { -+ 0x644, 0x645, 0x646, 0x647, 0x648 }; - - static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; - static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { -@@ -462,6 +466,7 @@ struct nct6775_data { - - const u16 *REG_FAN; - const u16 *REG_FAN_MIN; -+ const u16 *REG_FAN_PULSES; - - const u16 *REG_TEMP_SOURCE; /* temp register sources */ - const u16 *REG_TEMP_OFFSET; -@@ -481,6 +486,7 @@ struct nct6775_data { - u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ - unsigned int rpm[5]; - u16 fan_min[5]; -+ u8 fan_pulses[5]; - u8 fan_div[5]; - u8 has_fan; /* some fan inputs can be disabled */ - u8 has_fan_min; /* some fans don't have min register */ -@@ -802,6 +808,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - if (data->has_fan_min & (1 << i)) - data->fan_min[i] = nct6775_read_value(data, - data->REG_FAN_MIN[i]); -+ data->fan_pulses[i] = -+ nct6775_read_value(data, data->REG_FAN_PULSES[i]); - - nct6775_select_fan_div(dev, data, i, reg); - } -@@ -1225,6 +1233,41 @@ write_min: - return count; - } - -+static ssize_t -+show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int p = data->fan_pulses[sattr->index]; -+ -+ return sprintf(buf, "%d\n", p ? : 4); -+} -+ -+static ssize_t -+store_fan_pulses(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ if (val > 4) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ data->fan_pulses[nr] = val & 3; -+ nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3); -+ mutex_unlock(&data->update_lock); -+ -+ return count; -+} -+ - static struct sensor_device_attribute sda_fan_input[] = { - SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), - SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), -@@ -1254,6 +1297,19 @@ static struct sensor_device_attribute sda_fan_min[] = { - store_fan_min, 4), - }; - -+static struct sensor_device_attribute sda_fan_pulses[] = { -+ SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, -+ store_fan_pulses, 0), -+ SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, -+ store_fan_pulses, 1), -+ SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, -+ store_fan_pulses, 2), -+ SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, -+ store_fan_pulses, 3), -+ SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses, -+ store_fan_pulses, 4), -+}; -+ - static struct sensor_device_attribute sda_fan_div[] = { - SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), - SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), -@@ -1621,6 +1677,7 @@ static void nct6775_device_remove_files(struct device *dev) - device_remove_file(dev, &sda_fan_alarm[i].dev_attr); - device_remove_file(dev, &sda_fan_div[i].dev_attr); - device_remove_file(dev, &sda_fan_min[i].dev_attr); -+ device_remove_file(dev, &sda_fan_pulses[i].dev_attr); - } - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) -@@ -1809,6 +1866,7 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; -+ data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1843,6 +1901,7 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; -+ data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1877,6 +1936,7 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6779_REG_FAN; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; -+ data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; - data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6779_REG_ALARM; -@@ -2094,6 +2154,10 @@ static int nct6775_probe(struct platform_device *pdev) - if (err) - goto exit_remove; - } -+ err = device_create_file(dev, -+ &sda_fan_pulses[i].dev_attr); -+ if (err) -+ goto exit_remove; - } - } - - -From 47ece9645f288d46420d64dab90a182bde87bbbb Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 07:59:32 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for fan debounce module - parameter - -If set, fan debounce is enabled when loading the driver. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index fea6ed7..ffb56bb 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -72,6 +72,10 @@ static unsigned short force_id; - module_param(force_id, ushort, 0); - MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -+static unsigned short fan_debounce; -+module_param(fan_debounce, ushort, 0); -+MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); -+ - #define DRVNAME "nct6775" - - /* -@@ -183,6 +187,8 @@ static const u16 NCT6775_REG_IN[] = { - #define NCT6775_REG_FANDIV1 0x506 - #define NCT6775_REG_FANDIV2 0x507 - -+#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0 -+ - static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; - - /* 0..15 voltages, 16..23 fans, 24..31 temperatures */ -@@ -2110,6 +2116,28 @@ static int nct6775_probe(struct platform_device *pdev) - */ - superio_select(sio_data->sioreg, NCT6775_LD_VID); - data->vid = superio_inb(sio_data->sioreg, 0xe3); -+ -+ if (fan_debounce) { -+ u8 tmp; -+ -+ superio_select(sio_data->sioreg, NCT6775_LD_HWM); -+ tmp = superio_inb(sio_data->sioreg, -+ NCT6775_REG_CR_FAN_DEBOUNCE); -+ switch (data->kind) { -+ case nct6775: -+ tmp |= 0x1e; -+ break; -+ case nct6776: -+ case nct6779: -+ tmp |= 0x3e; -+ break; -+ } -+ superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE, -+ tmp); -+ dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n", -+ data->name); -+ } -+ - superio_exit(sio_data->sioreg); - - err = device_create_file(dev, &dev_attr_cpu0_vid); - -From 84d19d92f78e10f8bdc1b3e1b5ddcaf5895edaf7 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 08:01:39 -0800 -Subject: [PATCH] hwmon: (nct6775) Add power management support - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index ffb56bb..56d7652 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -511,6 +511,12 @@ struct nct6775_data { - u16 have_temp; - u16 have_temp_fixed; - u16 have_in; -+#ifdef CONFIG_PM -+ /* Remember extra register values over suspend/resume */ -+ u8 vbat; -+ u8 fandiv1; -+ u8 fandiv2; -+#endif - }; - - struct nct6775_sio_data { -@@ -2270,10 +2276,90 @@ static int nct6775_remove(struct platform_device *pdev) - return 0; - } - -+#ifdef CONFIG_PM -+static int nct6775_suspend(struct device *dev) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct nct6775_sio_data *sio_data = dev->platform_data; -+ -+ mutex_lock(&data->update_lock); -+ data->vbat = nct6775_read_value(data, data->REG_VBAT); -+ if (sio_data->kind == nct6775) { -+ data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1); -+ data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2); -+ } -+ mutex_unlock(&data->update_lock); -+ -+ return 0; -+} -+ -+static int nct6775_resume(struct device *dev) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct nct6775_sio_data *sio_data = dev->platform_data; -+ int i, j; -+ -+ mutex_lock(&data->update_lock); -+ data->bank = 0xff; /* Force initial bank selection */ -+ -+ /* Restore limits */ -+ for (i = 0; i < data->in_num; i++) { -+ if (!(data->have_in & (1 << i))) -+ continue; -+ -+ nct6775_write_value(data, data->REG_IN_MINMAX[0][i], -+ data->in[i][1]); -+ nct6775_write_value(data, data->REG_IN_MINMAX[1][i], -+ data->in[i][2]); -+ } -+ -+ for (i = 0; i < 5; i++) { -+ if (!(data->has_fan_min & (1 << i))) -+ continue; -+ -+ nct6775_write_value(data, data->REG_FAN_MIN[i], -+ data->fan_min[i]); -+ } -+ -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ -+ for (j = 1; j < 4; j++) -+ if (data->reg_temp[j][i]) -+ nct6775_write_temp(data, data->reg_temp[j][i], -+ data->temp[j][i]); -+ } -+ -+ /* Restore other settings */ -+ nct6775_write_value(data, data->REG_VBAT, data->vbat); -+ if (sio_data->kind == nct6775) { -+ nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1); -+ nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); -+ } -+ -+ /* Force re-reading all values */ -+ data->valid = false; -+ mutex_unlock(&data->update_lock); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops nct6775_dev_pm_ops = { -+ .suspend = nct6775_suspend, -+ .resume = nct6775_resume, -+}; -+ -+#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops) -+#else -+#define NCT6775_DEV_PM_OPS NULL -+#endif /* CONFIG_PM */ -+ - static struct platform_driver nct6775_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, -+ .pm = NCT6775_DEV_PM_OPS, - }, - .probe = nct6775_probe, - .remove = nct6775_remove, - -From 77eb5b3703d995e6c72ef4a1e5411821f81df7e4 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 08:30:54 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for pwm, pwm_mode, and - pwm_enable - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -index dcd56a3..7c9f1d3 100644 ---- a/Documentation/hwmon/nct6775 -+++ b/Documentation/hwmon/nct6775 -@@ -69,6 +69,24 @@ is driven slower/faster to reach the predefined range again. - - The mode works for fan1-fan5. - -+sysfs attributes -+---------------- -+ -+pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range: -+ 0 (lowest speed) to 255 (full) -+ -+pwm[1-5]_enable - this file controls mode of fan/temperature control: -+ * 0 Fan control disabled (fans set to maximum speed) -+ * 1 Manual mode, write to pwm[0-5] any value 0-255 -+ * 2 "Thermal Cruise" mode -+ * 3 "Fan Speed Cruise" mode -+ * 4 "Smart Fan III" mode (NCT6775F only) -+ * 5 "Smart Fan IV" mode -+ -+pwm[1-5]_mode - controls if output is PWM or DC level -+ * 0 DC output -+ * 1 PWM output -+ - Usage Notes - ----------- - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 56d7652..ad4ecc0 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -96,6 +96,8 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); - #define SIO_NCT6779_ID 0xc560 - #define SIO_ID_MASK 0xFFF0 - -+enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; -+ - static inline void - superio_outb(int ioreg, int reg, int val) - { -@@ -209,6 +211,15 @@ static const s8 NCT6775_ALARM_BITS[] = { - static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; - static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; - -+/* DC or PWM output fan configuration */ -+static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 }; -+static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 }; -+ -+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; -+ -+static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; -+static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; -+ - static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; - static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; - static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; -@@ -270,6 +281,9 @@ static const s8 NCT6776_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; -+static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; -+ - static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; - static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; - -@@ -380,6 +394,20 @@ static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] - static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] - = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; - -+static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) -+{ -+ if (mode == 0 && pwm == 255) -+ return off; -+ return mode + 1; -+} -+ -+static int pwm_enable_to_reg(enum pwm_enable mode) -+{ -+ if (mode == off) -+ return 0; -+ return mode - 1; -+} -+ - /* - * Conversions - */ -@@ -471,9 +499,16 @@ struct nct6775_data { - const u16 *REG_IN_MINMAX[2]; - - const u16 *REG_FAN; -+ const u16 *REG_FAN_MODE; - const u16 *REG_FAN_MIN; - const u16 *REG_FAN_PULSES; - -+ const u8 *REG_PWM_MODE; -+ const u8 *PWM_MODE_MASK; -+ -+ const u16 *REG_PWM[1]; /* [0]=pwm */ -+ const u16 *REG_PWM_READ; -+ - const u16 *REG_TEMP_SOURCE; /* temp register sources */ - const u16 *REG_TEMP_OFFSET; - -@@ -494,6 +529,7 @@ struct nct6775_data { - u16 fan_min[5]; - u8 fan_pulses[5]; - u8 fan_div[5]; -+ u8 has_pwm; - u8 has_fan; /* some fan inputs can be disabled */ - u8 has_fan_min; /* some fans don't have min register */ - bool has_fan_div; -@@ -505,6 +541,18 @@ struct nct6775_data { - * 3=temp_crit */ - u64 alarms; - -+ u8 pwm_num; /* number of pwm */ -+ u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */ -+ enum pwm_enable pwm_enable[5]; -+ /* 0->off -+ * 1->manual -+ * 2->thermal cruise mode (also called SmartFan I) -+ * 3->fan speed cruise mode -+ * 4->SmartFan III -+ * 5->enhanced variable thermal cruise (SmartFan IV) -+ */ -+ u8 pwm[1][5]; /* [0]=pwm */ -+ - u8 vid; - u8 vrm; - -@@ -781,6 +829,36 @@ static void nct6775_select_fan_div(struct device *dev, - } - } - -+static void nct6775_update_pwm(struct device *dev) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ int i, j; -+ int fanmodecfg; -+ bool duty_is_dc; -+ -+ for (i = 0; i < data->pwm_num; i++) { -+ if (!(data->has_pwm & (1 << i))) -+ continue; -+ -+ duty_is_dc = data->REG_PWM_MODE[i] && -+ (nct6775_read_value(data, data->REG_PWM_MODE[i]) -+ & data->PWM_MODE_MASK[i]); -+ data->pwm_mode[i] = duty_is_dc; -+ -+ fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]); -+ for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) { -+ if (data->REG_PWM[j] && data->REG_PWM[j][i]) { -+ data->pwm[j][i] -+ = nct6775_read_value(data, -+ data->REG_PWM[j][i]); -+ } -+ } -+ -+ data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i], -+ (fanmodecfg >> 4) & 7); -+ } -+} -+ - static struct nct6775_data *nct6775_update_device(struct device *dev) - { - struct nct6775_data *data = dev_get_drvdata(dev); -@@ -826,6 +904,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - nct6775_select_fan_div(dev, data, i, reg); - } - -+ nct6775_update_pwm(dev); -+ - /* Measured temperatures and limits */ - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) -@@ -1600,6 +1680,170 @@ static struct sensor_device_attribute sda_temp_alarm[] = { - #define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm) - - static ssize_t -+show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ -+ return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]); -+} -+ -+static ssize_t -+store_pwm_mode(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ u8 reg; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ if (val > 1) -+ return -EINVAL; -+ -+ /* Setting DC mode is not supported for all chips/channels */ -+ if (data->REG_PWM_MODE[nr] == 0) { -+ if (val) -+ return -EINVAL; -+ return count; -+ } -+ -+ mutex_lock(&data->update_lock); -+ data->pwm_mode[nr] = val; -+ reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]); -+ reg &= ~data->PWM_MODE_MASK[nr]; -+ if (val) -+ reg |= data->PWM_MODE_MASK[nr]; -+ nct6775_write_value(data, data->REG_PWM_MODE[nr], reg); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_pwm(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ int pwm; -+ -+ /* -+ * For automatic fan control modes, show current pwm readings. -+ * Otherwise, show the configured value. -+ */ -+ if (index == 0 && data->pwm_enable[nr] > manual) -+ pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]); -+ else -+ pwm = data->pwm[index][nr]; -+ -+ return sprintf(buf, "%d\n", pwm); -+} -+ -+static ssize_t -+store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ val = clamp_val(val, 0, 255); -+ -+ mutex_lock(&data->update_lock); -+ data->pwm[index][nr] = val; -+ nct6775_write_value(data, data->REG_PWM[index][nr], val); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ -+ return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]); -+} -+ -+static ssize_t -+store_pwm_enable(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ u16 reg; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ if (val > sf4) -+ return -EINVAL; -+ -+ if (val == sf3 && data->kind != nct6775) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ data->pwm_enable[nr] = val; -+ if (val == off) { -+ /* -+ * turn off pwm control: select manual mode, set pwm to maximum -+ */ -+ data->pwm[0][nr] = 255; -+ nct6775_write_value(data, data->REG_PWM[0][nr], 255); -+ } -+ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); -+ reg &= 0x0f; -+ reg |= pwm_enable_to_reg(val) << 4; -+ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0); -+static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0); -+static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0); -+static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0); -+static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0); -+ -+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, -+ store_pwm_mode, 0); -+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, -+ store_pwm_mode, 1); -+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode, -+ store_pwm_mode, 2); -+static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode, -+ store_pwm_mode, 3); -+static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode, -+ store_pwm_mode, 4); -+ -+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, -+ store_pwm_enable, 0); -+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, -+ store_pwm_enable, 1); -+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable, -+ store_pwm_enable, 2); -+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, -+ store_pwm_enable, 3); -+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable, -+ store_pwm_enable, 4); -+ -+static ssize_t - show_name(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = dev_get_drvdata(dev); -@@ -1609,6 +1853,47 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf) - - static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -+static struct attribute *nct6775_attributes_pwm[5][4] = { -+ { -+ &sensor_dev_attr_pwm1.dev_attr.attr, -+ &sensor_dev_attr_pwm1_mode.dev_attr.attr, -+ &sensor_dev_attr_pwm1_enable.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_pwm2.dev_attr.attr, -+ &sensor_dev_attr_pwm2_mode.dev_attr.attr, -+ &sensor_dev_attr_pwm2_enable.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_pwm3.dev_attr.attr, -+ &sensor_dev_attr_pwm3_mode.dev_attr.attr, -+ &sensor_dev_attr_pwm3_enable.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_pwm4.dev_attr.attr, -+ &sensor_dev_attr_pwm4_mode.dev_attr.attr, -+ &sensor_dev_attr_pwm4_enable.dev_attr.attr, -+ NULL -+ }, -+ { -+ &sensor_dev_attr_pwm5.dev_attr.attr, -+ &sensor_dev_attr_pwm5_mode.dev_attr.attr, -+ &sensor_dev_attr_pwm5_enable.dev_attr.attr, -+ NULL -+ }, -+}; -+ -+static const struct attribute_group nct6775_group_pwm[5] = { -+ { .attrs = nct6775_attributes_pwm[0] }, -+ { .attrs = nct6775_attributes_pwm[1] }, -+ { .attrs = nct6775_attributes_pwm[2] }, -+ { .attrs = nct6775_attributes_pwm[3] }, -+ { .attrs = nct6775_attributes_pwm[4] }, -+}; -+ - static ssize_t - show_vid(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -1681,6 +1966,9 @@ static void nct6775_device_remove_files(struct device *dev) - int i; - struct nct6775_data *data = dev_get_drvdata(dev); - -+ for (i = 0; i < data->pwm_num; i++) -+ sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]); -+ - for (i = 0; i < data->in_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); - -@@ -1763,6 +2051,7 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - { - int regval; - bool fan3pin, fan3min, fan4pin, fan4min, fan5pin; -+ bool pwm3pin, pwm4pin, pwm5pin; - int ret; - - ret = superio_enter(sio_data->sioreg); -@@ -1775,11 +2064,14 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - - fan3pin = regval & (1 << 6); - fan3min = fan3pin; -+ pwm3pin = regval & (1 << 7); - - /* On NCT6775, fan4 shares pins with the fdc interface */ - fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); - fan4min = 0; - fan5pin = 0; -+ pwm4pin = 0; -+ pwm5pin = 0; - } else if (data->kind == nct6776) { - bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; - -@@ -1803,6 +2095,9 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - - fan4min = fan4pin; - fan3min = fan3pin; -+ pwm3pin = fan3pin; -+ pwm4pin = 0; -+ pwm5pin = 0; - } else { /* NCT6779D */ - regval = superio_inb(sio_data->sioreg, 0x1c); - -@@ -1810,6 +2105,10 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - fan4pin = !(regval & (1 << 6)); - fan5pin = !(regval & (1 << 7)); - -+ pwm3pin = !(regval & (1 << 0)); -+ pwm4pin = !(regval & (1 << 1)); -+ pwm5pin = !(regval & (1 << 2)); -+ - fan3min = fan3pin; - fan4min = fan4pin; - } -@@ -1823,6 +2122,8 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - data->has_fan |= (fan4pin << 3) | (fan5pin << 4); - data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); - -+ data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4); -+ - return 0; - } - -@@ -1859,6 +2160,7 @@ static int nct6775_probe(struct platform_device *pdev) - switch (data->kind) { - case nct6775: - data->in_num = 9; -+ data->pwm_num = 3; - data->has_fan_div = true; - data->temp_fixed_num = 3; - -@@ -1877,8 +2179,13 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6775_REG_FAN; -+ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; -+ data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM_READ = NCT6775_REG_PWM_READ; -+ data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; -+ data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1894,6 +2201,7 @@ static int nct6775_probe(struct platform_device *pdev) - break; - case nct6776: - data->in_num = 9; -+ data->pwm_num = 3; - data->has_fan_div = false; - data->temp_fixed_num = 3; - -@@ -1912,8 +2220,13 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6775_REG_FAN; -+ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; -+ data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM_READ = NCT6775_REG_PWM_READ; -+ data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; -+ data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6775_REG_ALARM; -@@ -1929,6 +2242,7 @@ static int nct6775_probe(struct platform_device *pdev) - break; - case nct6779: - data->in_num = 15; -+ data->pwm_num = 5; - data->has_fan_div = false; - data->temp_fixed_num = 6; - -@@ -1947,8 +2261,13 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; - data->REG_FAN = NCT6779_REG_FAN; -+ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; -+ data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM_READ = NCT6775_REG_PWM_READ; -+ data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; -+ data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; - data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_ALARM = NCT6779_REG_ALARM; -@@ -2157,6 +2476,16 @@ static int nct6775_probe(struct platform_device *pdev) - /* Read fan clock dividers immediately */ - nct6775_init_fan_common(dev, data); - -+ /* Register sysfs hooks */ -+ for (i = 0; i < data->pwm_num; i++) { -+ if (!(data->has_pwm & (1 << i))) -+ continue; -+ -+ err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]); -+ if (err) -+ goto exit_remove; -+ } -+ - for (i = 0; i < data->in_num; i++) { - if (!(data->have_in & (1 << i))) - continue; - -From cdcaeceb74ff3686eb25de6812870fbc765c3c39 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 09:04:52 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for automatic fan control - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -index 7c9f1d3..b4fe6bc 100644 ---- a/Documentation/hwmon/nct6775 -+++ b/Documentation/hwmon/nct6775 -@@ -87,6 +87,75 @@ pwm[1-5]_mode - controls if output is PWM or DC level - * 0 DC output - * 1 PWM output - -+Common fan control attributes -+----------------------------- -+ -+pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. -+ For example, select '1' for temp1_input. -+ -+Thermal Cruise mode (2) -+----------------------- -+ -+If the temperature is in the range defined by: -+ -+pwm[1-5]_target_temp Target temperature, unit millidegree Celsius -+ (range 0 - 127000) -+pwm[1-5]_temp_tolerance -+ Target temperature tolerance, unit millidegree Celsius -+ -+there are no changes to fan speed. Once the temperature leaves the interval, fan -+speed increases (if temperature is higher that desired) or decreases (if -+temperature is lower than desired), using the following limits and time -+intervals. -+ -+pwm[1-5]_start fan pwm start value (range 1 - 255), to start fan -+ when the temperature is above defined range. -+pwm[1-5]_floor lowest fan pwm (range 0 - 255) if temperature is below -+ the defined range. If set to 0, the fan is expected to -+ stop if the temperature is below the defined range. -+pwm[1-5]_step_up_time milliseconds before fan speed is increased -+pwm[1-5]_step_down_time milliseconds before fan speed is decreased -+pwm[1-5]_stop_time how many milliseconds must elapse to switch -+ corresponding fan off (when the temperature was below -+ defined range). -+ -+Speed Cruise mode (3) -+--------------------- -+ -+This modes tries to keep the fan speed constant. -+ -+fan[1-5]_target Target fan speed -+fan[1-5]_tolerance -+ Target speed tolerance -+ -+ -+Untested; use at your own risk. -+ -+Smart Fan IV mode (5) -+--------------------- -+ -+This mode offers multiple slopes to control the fan speed. The slopes can be -+controlled by setting the pwm and temperature attributes. When the temperature -+rises, the chip will calculate the DC/PWM output based on the current slope. -+There are up to seven data points depending on the chip type. Subsequent data -+points should be set to higher temperatures and higher pwm values to achieve -+higher fan speeds with increasing temperature. The last data point reflects -+critical temperature mode, in which the fans should run at full speed. -+ -+pwm[1-5]_auto_point[1-7]_pwm -+ pwm value to be set if temperature reaches matching -+ temperature range. -+pwm[1-5]_auto_point[1-7]_temp -+ Temperature over which the matching pwm is enabled. -+pwm[1-5]_temp_tolerance -+ Temperature tolerance, unit millidegree Celsius -+pwm[1-5]_crit_temp_tolerance -+ Temperature tolerance for critical temperature, -+ unit millidegree Celsius -+ -+pwm[1-5]_step_up_time milliseconds before fan speed is increased -+pwm[1-5]_step_down_time milliseconds before fan speed is decreased -+ - Usage Notes - ----------- - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index ad4ecc0..47b1d89 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -215,8 +215,23 @@ static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; - static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 }; - static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 }; - --static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; -+/* Advanced Fan control, some values are common for all fans */ - -+static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 }; -+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; -+static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = { -+ 0x103, 0x203, 0x303, 0x803, 0x903 }; -+static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = { -+ 0x104, 0x204, 0x304, 0x804, 0x904 }; -+static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { -+ 0x105, 0x205, 0x305, 0x805, 0x905 }; -+static const u16 NCT6775_REG_FAN_START_OUTPUT[] -+ = { 0x106, 0x206, 0x306, 0x806, 0x906 }; -+static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a }; -+static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b }; -+ -+static const u16 NCT6775_REG_FAN_STOP_TIME[] = { -+ 0x107, 0x207, 0x307, 0x807, 0x907 }; - static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; - static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; - -@@ -237,8 +252,26 @@ static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; - -+static const u16 NCT6775_REG_TEMP_SEL[] = { -+ 0x100, 0x200, 0x300, 0x800, 0x900 }; -+ - static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; - -+static const u16 NCT6775_REG_AUTO_TEMP[] = { -+ 0x121, 0x221, 0x321, 0x821, 0x921 }; -+static const u16 NCT6775_REG_AUTO_PWM[] = { -+ 0x127, 0x227, 0x327, 0x827, 0x927 }; -+ -+#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p)) -+#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p)) -+ -+static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 }; -+ -+static const u16 NCT6775_REG_CRITICAL_TEMP[] = { -+ 0x135, 0x235, 0x335, 0x835, 0x935 }; -+static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = { -+ 0x138, 0x238, 0x338, 0x838, 0x938 }; -+ - static const char *const nct6775_temp_label[] = { - "", - "SYSTIN", -@@ -281,6 +314,9 @@ static const s8 NCT6776_ALARM_BITS[] = { - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -+static const u16 NCT6776_REG_TOLERANCE_H[] = { -+ 0x10c, 0x20c, 0x30c, 0x80c, 0x90c }; -+ - static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; - static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; - -@@ -344,6 +380,11 @@ static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; - static const u16 NCT6779_REG_FAN_PULSES[] = { - 0x644, 0x645, 0x646, 0x647, 0x648 }; - -+static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { -+ 0x136, 0x236, 0x336, 0x836, 0x936 }; -+static const u16 NCT6779_REG_CRITICAL_PWM[] = { -+ 0x137, 0x237, 0x337, 0x837, 0x937 }; -+ - static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; - static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { - 0x18, 0x152 }; -@@ -412,6 +453,18 @@ static int pwm_enable_to_reg(enum pwm_enable mode) - * Conversions - */ - -+/* 1 is DC mode, output in ms */ -+static unsigned int step_time_from_reg(u8 reg, u8 mode) -+{ -+ return mode ? 400 * reg : 100 * reg; -+} -+ -+static u8 step_time_to_reg(unsigned int msec, u8 mode) -+{ -+ return clamp_val((mode ? (msec + 200) / 400 : -+ (msec + 50) / 100), 1, 255); -+} -+ - static unsigned int fan_from_reg8(u16 reg, unsigned int divreg) - { - if (reg == 0 || reg == 255) -@@ -444,6 +497,14 @@ static unsigned int fan_from_reg16(u16 reg, unsigned int divreg) - return 1350000U / (reg << divreg); - } - -+static u16 fan_to_reg(u32 fan, unsigned int divreg) -+{ -+ if (!fan) -+ return 0; -+ -+ return (1350000U / fan) >> divreg; -+} -+ - static inline unsigned int - div_from_reg(u8 reg) - { -@@ -498,18 +559,31 @@ struct nct6775_data { - const u16 *REG_VIN; - const u16 *REG_IN_MINMAX[2]; - -+ const u16 *REG_TARGET; - const u16 *REG_FAN; - const u16 *REG_FAN_MODE; - const u16 *REG_FAN_MIN; - const u16 *REG_FAN_PULSES; -+ const u16 *REG_FAN_TIME[3]; -+ -+ const u16 *REG_TOLERANCE_H; - - const u8 *REG_PWM_MODE; - const u8 *PWM_MODE_MASK; - -- const u16 *REG_PWM[1]; /* [0]=pwm */ -+ const u16 *REG_PWM[5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -+ * [3]=pwm_max, [4]=pwm_step -+ */ - const u16 *REG_PWM_READ; - -+ const u16 *REG_AUTO_TEMP; -+ const u16 *REG_AUTO_PWM; -+ -+ const u16 *REG_CRITICAL_TEMP; -+ const u16 *REG_CRITICAL_TEMP_TOLERANCE; -+ - const u16 *REG_TEMP_SOURCE; /* temp register sources */ -+ const u16 *REG_TEMP_SEL; - const u16 *REG_TEMP_OFFSET; - - const u16 *REG_ALARM; -@@ -551,7 +625,26 @@ struct nct6775_data { - * 4->SmartFan III - * 5->enhanced variable thermal cruise (SmartFan IV) - */ -- u8 pwm[1][5]; /* [0]=pwm */ -+ u8 pwm[5][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -+ * [3]=pwm_max, [4]=pwm_step -+ */ -+ -+ u8 target_temp[5]; -+ u8 target_temp_mask; -+ u32 target_speed[5]; -+ u32 target_speed_tolerance[5]; -+ u8 speed_tolerance_limit; -+ -+ u8 temp_tolerance[2][5]; -+ u8 tolerance_mask; -+ -+ u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */ -+ -+ /* Automatic fan speed control registers */ -+ int auto_pwm_num; -+ u8 auto_pwm[5][7]; -+ u8 auto_temp[5][7]; -+ u8 pwm_temp_sel[5]; - - u8 vid; - u8 vrm; -@@ -833,7 +926,7 @@ static void nct6775_update_pwm(struct device *dev) - { - struct nct6775_data *data = dev_get_drvdata(dev); - int i, j; -- int fanmodecfg; -+ int fanmodecfg, reg; - bool duty_is_dc; - - for (i = 0; i < data->pwm_num; i++) { -@@ -856,6 +949,96 @@ static void nct6775_update_pwm(struct device *dev) - - data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i], - (fanmodecfg >> 4) & 7); -+ -+ if (!data->temp_tolerance[0][i] || -+ data->pwm_enable[i] != speed_cruise) -+ data->temp_tolerance[0][i] = fanmodecfg & 0x0f; -+ if (!data->target_speed_tolerance[i] || -+ data->pwm_enable[i] == speed_cruise) { -+ u8 t = fanmodecfg & 0x0f; -+ if (data->REG_TOLERANCE_H) { -+ t |= (nct6775_read_value(data, -+ data->REG_TOLERANCE_H[i]) & 0x70) >> 1; -+ } -+ data->target_speed_tolerance[i] = t; -+ } -+ -+ data->temp_tolerance[1][i] = -+ nct6775_read_value(data, -+ data->REG_CRITICAL_TEMP_TOLERANCE[i]); -+ -+ reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]); -+ data->pwm_temp_sel[i] = reg & 0x1f; -+ /* If fan can stop, report floor as 0 */ -+ if (reg & 0x80) -+ data->pwm[2][i] = 0; -+ } -+} -+ -+static void nct6775_update_pwm_limits(struct device *dev) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ int i, j; -+ u8 reg; -+ u16 reg_t; -+ -+ for (i = 0; i < data->pwm_num; i++) { -+ if (!(data->has_pwm & (1 << i))) -+ continue; -+ -+ for (j = 0; j < 3; j++) { -+ data->fan_time[j][i] = -+ nct6775_read_value(data, data->REG_FAN_TIME[j][i]); -+ } -+ -+ reg_t = nct6775_read_value(data, data->REG_TARGET[i]); -+ /* Update only in matching mode or if never updated */ -+ if (!data->target_temp[i] || -+ data->pwm_enable[i] == thermal_cruise) -+ data->target_temp[i] = reg_t & data->target_temp_mask; -+ if (!data->target_speed[i] || -+ data->pwm_enable[i] == speed_cruise) { -+ if (data->REG_TOLERANCE_H) { -+ reg_t |= (nct6775_read_value(data, -+ data->REG_TOLERANCE_H[i]) & 0x0f) << 8; -+ } -+ data->target_speed[i] = reg_t; -+ } -+ -+ for (j = 0; j < data->auto_pwm_num; j++) { -+ data->auto_pwm[i][j] = -+ nct6775_read_value(data, -+ NCT6775_AUTO_PWM(data, i, j)); -+ data->auto_temp[i][j] = -+ nct6775_read_value(data, -+ NCT6775_AUTO_TEMP(data, i, j)); -+ } -+ -+ /* critical auto_pwm temperature data */ -+ data->auto_temp[i][data->auto_pwm_num] = -+ nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]); -+ -+ switch (data->kind) { -+ case nct6775: -+ reg = nct6775_read_value(data, -+ NCT6775_REG_CRITICAL_ENAB[i]); -+ data->auto_pwm[i][data->auto_pwm_num] = -+ (reg & 0x02) ? 0xff : 0x00; -+ break; -+ case nct6776: -+ data->auto_pwm[i][data->auto_pwm_num] = 0xff; -+ break; -+ case nct6779: -+ reg = nct6775_read_value(data, -+ NCT6779_REG_CRITICAL_PWM_ENABLE[i]); -+ if (reg & 1) -+ data->auto_pwm[i][data->auto_pwm_num] = -+ nct6775_read_value(data, -+ NCT6779_REG_CRITICAL_PWM[i]); -+ else -+ data->auto_pwm[i][data->auto_pwm_num] = 0xff; -+ break; -+ } - } - } - -@@ -905,6 +1088,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - } - - nct6775_update_pwm(dev); -+ nct6775_update_pwm_limits(dev); - - /* Measured temperatures and limits */ - for (i = 0; i < NUM_TEMP; i++) { -@@ -1754,20 +1938,91 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, - int nr = sattr->nr; - int index = sattr->index; - unsigned long val; -+ int minval[5] = { 0, 1, 1, data->pwm[2][nr], 0 }; -+ int maxval[5] -+ = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255 }; - int err; -+ u8 reg; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; -- val = clamp_val(val, 0, 255); -+ val = clamp_val(val, minval[index], maxval[index]); - - mutex_lock(&data->update_lock); - data->pwm[index][nr] = val; - nct6775_write_value(data, data->REG_PWM[index][nr], val); -+ if (index == 2) { /* floor: disable if val == 0 */ -+ reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); -+ reg &= 0x7f; -+ if (val) -+ reg |= 0x80; -+ nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); -+ } - mutex_unlock(&data->update_lock); - return count; - } - -+/* Returns 0 if OK, -EINVAL otherwise */ -+static int check_trip_points(struct nct6775_data *data, int nr) -+{ -+ int i; -+ -+ for (i = 0; i < data->auto_pwm_num - 1; i++) { -+ if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) -+ return -EINVAL; -+ } -+ for (i = 0; i < data->auto_pwm_num - 1; i++) { -+ if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) -+ return -EINVAL; -+ } -+ /* validate critical temperature and pwm if enabled (pwm > 0) */ -+ if (data->auto_pwm[nr][data->auto_pwm_num]) { -+ if (data->auto_temp[nr][data->auto_pwm_num - 1] > -+ data->auto_temp[nr][data->auto_pwm_num] || -+ data->auto_pwm[nr][data->auto_pwm_num - 1] > -+ data->auto_pwm[nr][data->auto_pwm_num]) -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static void pwm_update_registers(struct nct6775_data *data, int nr) -+{ -+ u8 reg; -+ -+ switch (data->pwm_enable[nr]) { -+ case off: -+ case manual: -+ break; -+ case speed_cruise: -+ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); -+ reg = (reg & ~data->tolerance_mask) | -+ (data->target_speed_tolerance[nr] & data->tolerance_mask); -+ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); -+ nct6775_write_value(data, data->REG_TARGET[nr], -+ data->target_speed[nr] & 0xff); -+ if (data->REG_TOLERANCE_H) { -+ reg = (data->target_speed[nr] >> 8) & 0x0f; -+ reg |= (data->target_speed_tolerance[nr] & 0x38) << 1; -+ nct6775_write_value(data, -+ data->REG_TOLERANCE_H[nr], -+ reg); -+ } -+ break; -+ case thermal_cruise: -+ nct6775_write_value(data, data->REG_TARGET[nr], -+ data->target_temp[nr]); -+ /* intentional */ -+ default: -+ reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); -+ reg = (reg & ~data->tolerance_mask) | -+ data->temp_tolerance[0][nr]; -+ nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); -+ break; -+ } -+} -+ - static ssize_t - show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -1798,6 +2053,12 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, - if (val == sf3 && data->kind != nct6775) - return -EINVAL; - -+ if (val == sf4 && check_trip_points(data, nr)) { -+ dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n"); -+ dev_err(dev, "Adjust trip points and try again\n"); -+ return -EINVAL; -+ } -+ - mutex_lock(&data->update_lock); - data->pwm_enable[nr] = val; - if (val == off) { -@@ -1807,6 +2068,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, - data->pwm[0][nr] = 255; - nct6775_write_value(data, data->REG_PWM[0][nr], 255); - } -+ pwm_update_registers(data, nr); - reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); - reg &= 0x0f; - reg |= pwm_enable_to_reg(val) << 4; -@@ -1815,6 +2077,235 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, - return count; - } - -+static ssize_t -+show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int i, src, sel = 0; -+ -+ src = data->pwm_temp_sel[sattr->index]; -+ -+ for (i = 0; i < NUM_TEMP; i++) { -+ if (!(data->have_temp & (1 << i))) -+ continue; -+ if (src == data->temp_src[i]) { -+ sel = i + 1; -+ break; -+ } -+ } -+ -+ return sprintf(buf, "%d\n", sel); -+} -+ -+static ssize_t -+store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err, reg, src; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ if (val == 0 || val > NUM_TEMP) -+ return -EINVAL; -+ if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1]) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ src = data->temp_src[val - 1]; -+ data->pwm_temp_sel[nr] = src; -+ reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); -+ reg &= 0xe0; -+ reg |= src; -+ nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); -+ mutex_unlock(&data->update_lock); -+ -+ return count; -+} -+ -+static ssize_t -+show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ -+ return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000); -+} -+ -+static ssize_t -+store_target_temp(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, -+ data->target_temp_mask); -+ -+ mutex_lock(&data->update_lock); -+ data->target_temp[nr] = val; -+ pwm_update_registers(data, nr); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_target_speed(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ -+ return sprintf(buf, "%d\n", -+ fan_from_reg16(data->target_speed[nr], -+ data->fan_div[nr])); -+} -+ -+static ssize_t -+store_target_speed(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ u16 speed; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ val = clamp_val(val, 0, 1350000U); -+ speed = fan_to_reg(val, data->fan_div[nr]); -+ -+ mutex_lock(&data->update_lock); -+ data->target_speed[nr] = speed; -+ pwm_update_registers(data, nr); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_temp_tolerance(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ -+ return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000); -+} -+ -+static ssize_t -+store_temp_tolerance(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ /* Limit tolerance as needed */ -+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask); -+ -+ mutex_lock(&data->update_lock); -+ data->temp_tolerance[index][nr] = val; -+ if (index) -+ pwm_update_registers(data, nr); -+ else -+ nct6775_write_value(data, -+ data->REG_CRITICAL_TEMP_TOLERANCE[nr], -+ val); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+/* -+ * Fan speed tolerance is a tricky beast, since the associated register is -+ * a tick counter, but the value is reported and configured as rpm. -+ * Compute resulting low and high rpm values and report the difference. -+ */ -+static ssize_t -+show_speed_tolerance(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ int low = data->target_speed[nr] - data->target_speed_tolerance[nr]; -+ int high = data->target_speed[nr] + data->target_speed_tolerance[nr]; -+ int tolerance; -+ -+ if (low <= 0) -+ low = 1; -+ if (high > 0xffff) -+ high = 0xffff; -+ if (high < low) -+ high = low; -+ -+ tolerance = (fan_from_reg16(low, data->fan_div[nr]) -+ - fan_from_reg16(high, data->fan_div[nr])) / 2; -+ -+ return sprintf(buf, "%d\n", tolerance); -+} -+ -+static ssize_t -+store_speed_tolerance(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err; -+ int low, high; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ high = fan_from_reg16(data->target_speed[nr], -+ data->fan_div[nr]) + val; -+ low = fan_from_reg16(data->target_speed[nr], -+ data->fan_div[nr]) - val; -+ if (low <= 0) -+ low = 1; -+ if (high < low) -+ high = low; -+ -+ val = (fan_to_reg(low, data->fan_div[nr]) - -+ fan_to_reg(high, data->fan_div[nr])) / 2; -+ -+ /* Limit tolerance as needed */ -+ val = clamp_val(val, 0, data->speed_tolerance_limit); -+ -+ mutex_lock(&data->update_lock); -+ data->target_speed_tolerance[nr] = val; -+ pwm_update_registers(data, nr); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ - static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0); - static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0); - static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0); -@@ -1843,6 +2334,88 @@ static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 4); - -+static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_temp_sel, store_pwm_temp_sel, 0); -+static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_temp_sel, store_pwm_temp_sel, 1); -+static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_temp_sel, store_pwm_temp_sel, 2); -+static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_temp_sel, store_pwm_temp_sel, 3); -+static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_temp_sel, store_pwm_temp_sel, 4); -+ -+static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp, -+ store_target_temp, 0); -+static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp, -+ store_target_temp, 1); -+static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp, -+ store_target_temp, 2); -+static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp, -+ store_target_temp, 3); -+static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp, -+ store_target_temp, 4); -+ -+static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed, -+ store_target_speed, 0); -+static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed, -+ store_target_speed, 1); -+static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed, -+ store_target_speed, 2); -+static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed, -+ store_target_speed, 3); -+static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed, -+ store_target_speed, 4); -+ -+static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO, -+ show_speed_tolerance, store_speed_tolerance, 0); -+static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO, -+ show_speed_tolerance, store_speed_tolerance, 1); -+static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO, -+ show_speed_tolerance, store_speed_tolerance, 2); -+static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO, -+ show_speed_tolerance, store_speed_tolerance, 3); -+static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO, -+ show_speed_tolerance, store_speed_tolerance, 4); -+ -+/* Smart Fan registers */ -+ -+static ssize_t -+show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ -+ return sprintf(buf, "%d\n", -+ step_time_from_reg(data->fan_time[index][nr], -+ data->pwm_mode[nr])); -+} -+ -+static ssize_t -+store_fan_time(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ val = step_time_to_reg(val, data->pwm_mode[nr]); -+ mutex_lock(&data->update_lock); -+ data->fan_time[index][nr] = val; -+ nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ - static ssize_t - show_name(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -1853,35 +2426,190 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf) - - static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - --static struct attribute *nct6775_attributes_pwm[5][4] = { -+static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 0, 0); -+static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 1, 0); -+static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 2, 0); -+static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 3, 0); -+static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 4, 0); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 0, 1); -+static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 1, 1); -+static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 2, 1); -+static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 3, 1); -+static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time, -+ store_fan_time, 4, 1); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO, -+ show_fan_time, store_fan_time, 0, 2); -+static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO, -+ show_fan_time, store_fan_time, 1, 2); -+static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO, -+ show_fan_time, store_fan_time, 2, 2); -+static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO, -+ show_fan_time, store_fan_time, 3, 2); -+static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO, -+ show_fan_time, store_fan_time, 4, 2); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 0, 1); -+static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 1, 1); -+static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 2, 1); -+static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 3, 1); -+static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 4, 1); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 0, 2); -+static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 1, 2); -+static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 2, 2); -+static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 3, 2); -+static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm, -+ store_pwm, 4, 2); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 0, 0); -+static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 1, 0); -+static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 2, 0); -+static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 3, 0); -+static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 4, 0); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 0, 1); -+static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 1, 1); -+static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 2, 1); -+static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 3, 1); -+static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO, -+ show_temp_tolerance, store_temp_tolerance, 4, 1); -+ -+/* pwm_max is not supported on all chips */ -+static struct sensor_device_attribute_2 sda_pwm_max[] = { -+ SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, -+ 0, 3), -+ SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, -+ 1, 3), -+ SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, -+ 2, 3), -+ SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, -+ 3, 3), -+ SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm, -+ 4, 3), -+}; -+ -+/* pwm_step is not supported on all chips */ -+static struct sensor_device_attribute_2 sda_pwm_step[] = { -+ SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4), -+ SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4), -+ SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4), -+ SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4), -+ SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), -+}; -+ -+static struct attribute *nct6775_attributes_pwm[5][15] = { - { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm1_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm1_target_temp.dev_attr.attr, -+ &sensor_dev_attr_fan1_target.dev_attr.attr, -+ &sensor_dev_attr_fan1_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm1_stop_time.dev_attr.attr, -+ &sensor_dev_attr_pwm1_step_up_time.dev_attr.attr, -+ &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, -+ &sensor_dev_attr_pwm1_start.dev_attr.attr, -+ &sensor_dev_attr_pwm1_floor.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_mode.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm2_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm2_target_temp.dev_attr.attr, -+ &sensor_dev_attr_fan2_target.dev_attr.attr, -+ &sensor_dev_attr_fan2_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm2_stop_time.dev_attr.attr, -+ &sensor_dev_attr_pwm2_step_up_time.dev_attr.attr, -+ &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, -+ &sensor_dev_attr_pwm2_start.dev_attr.attr, -+ &sensor_dev_attr_pwm2_floor.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_mode.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm3_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm3_target_temp.dev_attr.attr, -+ &sensor_dev_attr_fan3_target.dev_attr.attr, -+ &sensor_dev_attr_fan3_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm3_stop_time.dev_attr.attr, -+ &sensor_dev_attr_pwm3_step_up_time.dev_attr.attr, -+ &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, -+ &sensor_dev_attr_pwm3_start.dev_attr.attr, -+ &sensor_dev_attr_pwm3_floor.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_pwm4.dev_attr.attr, - &sensor_dev_attr_pwm4_mode.dev_attr.attr, - &sensor_dev_attr_pwm4_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm4_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm4_target_temp.dev_attr.attr, -+ &sensor_dev_attr_fan4_target.dev_attr.attr, -+ &sensor_dev_attr_fan4_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm4_stop_time.dev_attr.attr, -+ &sensor_dev_attr_pwm4_step_up_time.dev_attr.attr, -+ &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, -+ &sensor_dev_attr_pwm4_start.dev_attr.attr, -+ &sensor_dev_attr_pwm4_floor.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_pwm5.dev_attr.attr, - &sensor_dev_attr_pwm5_mode.dev_attr.attr, - &sensor_dev_attr_pwm5_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm5_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm5_target_temp.dev_attr.attr, -+ &sensor_dev_attr_fan5_target.dev_attr.attr, -+ &sensor_dev_attr_fan5_tolerance.dev_attr.attr, -+ &sensor_dev_attr_pwm5_stop_time.dev_attr.attr, -+ &sensor_dev_attr_pwm5_step_up_time.dev_attr.attr, -+ &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, -+ &sensor_dev_attr_pwm5_start.dev_attr.attr, -+ &sensor_dev_attr_pwm5_floor.dev_attr.attr, - NULL - }, - }; -@@ -1895,6 +2623,277 @@ static const struct attribute_group nct6775_group_pwm[5] = { - }; - - static ssize_t -+show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ -+ return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]); -+} -+ -+static ssize_t -+store_auto_pwm(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int point = sattr->index; -+ unsigned long val; -+ int err; -+ u8 reg; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ if (val > 255) -+ return -EINVAL; -+ -+ if (point == data->auto_pwm_num) { -+ if (data->kind != nct6775 && !val) -+ return -EINVAL; -+ if (data->kind != nct6779 && val) -+ val = 0xff; -+ } -+ -+ mutex_lock(&data->update_lock); -+ data->auto_pwm[nr][point] = val; -+ if (point < data->auto_pwm_num) { -+ nct6775_write_value(data, -+ NCT6775_AUTO_PWM(data, nr, point), -+ data->auto_pwm[nr][point]); -+ } else { -+ switch (data->kind) { -+ case nct6775: -+ /* disable if needed (pwm == 0) */ -+ reg = nct6775_read_value(data, -+ NCT6775_REG_CRITICAL_ENAB[nr]); -+ if (val) -+ reg |= 0x02; -+ else -+ reg &= ~0x02; -+ nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr], -+ reg); -+ break; -+ case nct6776: -+ break; /* always enabled, nothing to do */ -+ case nct6779: -+ nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr], -+ val); -+ reg = nct6775_read_value(data, -+ NCT6779_REG_CRITICAL_PWM_ENABLE[nr]); -+ if (val == 255) -+ reg &= ~0x01; -+ else -+ reg |= 0x01; -+ nct6775_write_value(data, -+ NCT6779_REG_CRITICAL_PWM_ENABLE[nr], -+ reg); -+ break; -+ } -+ } -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t -+show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int point = sattr->index; -+ -+ /* -+ * We don't know for sure if the temperature is signed or unsigned. -+ * Assume it is unsigned. -+ */ -+ return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000); -+} -+ -+static ssize_t -+store_auto_temp(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int point = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err) -+ return err; -+ if (val > 255000) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000); -+ if (point < data->auto_pwm_num) { -+ nct6775_write_value(data, -+ NCT6775_AUTO_TEMP(data, nr, point), -+ data->auto_temp[nr][point]); -+ } else { -+ nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr], -+ data->auto_temp[nr][point]); -+ } -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+/* -+ * The number of auto-point trip points is chip dependent. -+ * Need to check support while generating/removing attribute files. -+ */ -+static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = { -+ SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 0), -+ SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 0), -+ SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 1), -+ SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 1), -+ SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 2), -+ SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 2), -+ SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 3), -+ SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 3), -+ SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 4), -+ SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 4), -+ SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 5), -+ SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 5), -+ SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 0, 6), -+ SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 0, 6), -+ -+ SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 0), -+ SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 0), -+ SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 1), -+ SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 1), -+ SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 2), -+ SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 2), -+ SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 3), -+ SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 3), -+ SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 4), -+ SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 4), -+ SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 5), -+ SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 5), -+ SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 1, 6), -+ SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 1, 6), -+ -+ SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 0), -+ SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 0), -+ SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 1), -+ SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 1), -+ SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 2), -+ SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 2), -+ SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 3), -+ SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 3), -+ SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 4), -+ SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 4), -+ SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 5), -+ SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 5), -+ SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 2, 6), -+ SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 2, 6), -+ -+ SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 0), -+ SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 0), -+ SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 1), -+ SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 1), -+ SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 2), -+ SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 2), -+ SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 3), -+ SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 3), -+ SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 4), -+ SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 4), -+ SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 5), -+ SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 5), -+ SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 3, 6), -+ SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 3, 6), -+ -+ SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 0), -+ SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 0), -+ SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 1), -+ SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 1), -+ SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 2), -+ SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 2), -+ SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 3), -+ SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 3), -+ SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 4), -+ SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 4), -+ SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 5), -+ SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 5), -+ SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO, -+ show_auto_pwm, store_auto_pwm, 4, 6), -+ SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO, -+ show_auto_temp, store_auto_temp, 4, 6), -+}; -+ -+static ssize_t - show_vid(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = dev_get_drvdata(dev); -@@ -1969,6 +2968,15 @@ static void nct6775_device_remove_files(struct device *dev) - for (i = 0; i < data->pwm_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]); - -+ for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++) -+ device_remove_file(dev, &sda_pwm_max[i].dev_attr); -+ -+ for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) -+ device_remove_file(dev, &sda_pwm_step[i].dev_attr); -+ -+ for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) -+ device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); -+ - for (i = 0; i < data->in_num; i++) - sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); - -@@ -2161,6 +3169,7 @@ static int nct6775_probe(struct platform_device *pdev) - case nct6775: - data->in_num = 9; - data->pwm_num = 3; -+ data->auto_pwm_num = 6; - data->has_fan_div = true; - data->temp_fixed_num = 3; - -@@ -2168,6 +3177,9 @@ static int nct6775_probe(struct platform_device *pdev) - - data->fan_from_reg = fan_from_reg16; - data->fan_from_reg_min = fan_from_reg8; -+ data->target_temp_mask = 0x7f; -+ data->tolerance_mask = 0x0f; -+ data->speed_tolerance_limit = 15; - - data->temp_label = nct6775_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6775_temp_label); -@@ -2178,16 +3190,30 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TARGET = NCT6775_REG_TARGET; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; -+ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; -+ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; -+ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; - data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; -+ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; -+ data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; -+ data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; -+ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; -+ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; -+ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; -+ data->REG_CRITICAL_TEMP_TOLERANCE -+ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; -+ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; - data->REG_ALARM = NCT6775_REG_ALARM; - - reg_temp = NCT6775_REG_TEMP; -@@ -2202,6 +3228,7 @@ static int nct6775_probe(struct platform_device *pdev) - case nct6776: - data->in_num = 9; - data->pwm_num = 3; -+ data->auto_pwm_num = 4; - data->has_fan_div = false; - data->temp_fixed_num = 3; - -@@ -2209,6 +3236,9 @@ static int nct6775_probe(struct platform_device *pdev) - - data->fan_from_reg = fan_from_reg13; - data->fan_from_reg_min = fan_from_reg13; -+ data->target_temp_mask = 0xff; -+ data->tolerance_mask = 0x07; -+ data->speed_tolerance_limit = 63; - - data->temp_label = nct6776_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); -@@ -2219,16 +3249,29 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6775_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TARGET = NCT6775_REG_TARGET; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; -+ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; -+ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; -+ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; -+ data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; - data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; -+ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; -+ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; -+ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; -+ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; -+ data->REG_CRITICAL_TEMP_TOLERANCE -+ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; -+ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; - data->REG_ALARM = NCT6775_REG_ALARM; - - reg_temp = NCT6775_REG_TEMP; -@@ -2243,6 +3286,7 @@ static int nct6775_probe(struct platform_device *pdev) - case nct6779: - data->in_num = 15; - data->pwm_num = 5; -+ data->auto_pwm_num = 4; - data->has_fan_div = false; - data->temp_fixed_num = 6; - -@@ -2250,6 +3294,9 @@ static int nct6775_probe(struct platform_device *pdev) - - data->fan_from_reg = fan_from_reg13; - data->fan_from_reg_min = fan_from_reg13; -+ data->target_temp_mask = 0xff; -+ data->tolerance_mask = 0x07; -+ data->speed_tolerance_limit = 63; - - data->temp_label = nct6779_temp_label; - data->temp_label_num = ARRAY_SIZE(nct6779_temp_label); -@@ -2260,16 +3307,29 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_VIN = NCT6779_REG_IN; - data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; - data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; -+ data->REG_TARGET = NCT6775_REG_TARGET; - data->REG_FAN = NCT6779_REG_FAN; - data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; -+ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; -+ data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; -+ data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; -+ data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; - data->REG_PWM[0] = NCT6775_REG_PWM; -+ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; -+ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; -+ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; -+ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; -+ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; -+ data->REG_CRITICAL_TEMP_TOLERANCE -+ = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; - data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; -+ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; - data->REG_ALARM = NCT6779_REG_ALARM; - - reg_temp = NCT6779_REG_TEMP; -@@ -2484,6 +3544,31 @@ static int nct6775_probe(struct platform_device *pdev) - err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]); - if (err) - goto exit_remove; -+ -+ if (data->REG_PWM[3]) { -+ err = device_create_file(dev, -+ &sda_pwm_max[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ if (data->REG_PWM[4]) { -+ err = device_create_file(dev, -+ &sda_pwm_step[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } -+ } -+ for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { -+ struct sensor_device_attribute_2 *attr = -+ &sda_auto_pwm_arrays[i]; -+ -+ if (!(data->has_pwm & (1 << attr->nr))) -+ continue; -+ if (attr->index > data->auto_pwm_num) -+ continue; -+ err = device_create_file(dev, &attr->dev_attr); -+ if (err) -+ goto exit_remove; - } - - for (i = 0; i < data->in_num; i++) { -@@ -2518,7 +3603,7 @@ static int nct6775_probe(struct platform_device *pdev) - goto exit_remove; - } - err = device_create_file(dev, -- &sda_fan_pulses[i].dev_attr); -+ &sda_fan_pulses[i].dev_attr); - if (err) - goto exit_remove; - } - -From bbd8decd4123648ddeba2be485bc7e1a3117bfe4 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 09:08:29 -0800 -Subject: [PATCH] hwmon: (nct6775) Add support for weighted fan control - -The NCT677X series support weighted fan control. In this mode, a secondary -temperature source is used in addition to the primary temperature source to -control fan speed. Add support for this feature. - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -index b4fe6bc..3f5587e 100644 ---- a/Documentation/hwmon/nct6775 -+++ b/Documentation/hwmon/nct6775 -@@ -92,6 +92,25 @@ Common fan control attributes - - pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index. - For example, select '1' for temp1_input. -+pwm[1-5]_weight_temp_sel -+ Secondary temperature source. Value is temperature -+ sensor index. For example, select '1' for temp1_input. -+ Set to 0 to disable secondary temperature control. -+ -+If secondary temperature functionality is enabled, it is controlled with the -+following attributes. -+ -+pwm[1-5]_weight_duty_step -+ Duty step size. -+pwm[1-5]_weight_temp_step -+ Temperature step size. With each step over -+ temp_step_base, the value of weight_duty_step is added -+ to the current pwm value. -+pwm[1-5]_weight_temp_step_base -+ Temperature at which secondary temperature control kicks -+ in. -+pwm[1-5]_weight_temp_step_tol -+ Temperature step tolerance. - - Thermal Cruise mode (2) - ----------------------- -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 47b1d89..f80ff82 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -255,6 +255,17 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - static const u16 NCT6775_REG_TEMP_SEL[] = { - 0x100, 0x200, 0x300, 0x800, 0x900 }; - -+static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { -+ 0x139, 0x239, 0x339, 0x839, 0x939 }; -+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { -+ 0x13a, 0x23a, 0x33a, 0x83a, 0x93a }; -+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { -+ 0x13b, 0x23b, 0x33b, 0x83b, 0x93b }; -+static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { -+ 0x13c, 0x23c, 0x33c, 0x83c, 0x93c }; -+static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { -+ 0x13d, 0x23d, 0x33d, 0x83d, 0x93d }; -+ - static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; - - static const u16 NCT6775_REG_AUTO_TEMP[] = { -@@ -323,6 +334,9 @@ static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; - static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; - static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; - -+static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { -+ 0x13e, 0x23e, 0x33e, 0x83e, 0x93e }; -+ - static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { - 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; - -@@ -571,8 +585,9 @@ struct nct6775_data { - const u8 *REG_PWM_MODE; - const u8 *PWM_MODE_MASK; - -- const u16 *REG_PWM[5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -- * [3]=pwm_max, [4]=pwm_step -+ const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -+ * [3]=pwm_max, [4]=pwm_step, -+ * [5]=weight_duty_step, [6]=weight_duty_base - */ - const u16 *REG_PWM_READ; - -@@ -584,6 +599,9 @@ struct nct6775_data { - - const u16 *REG_TEMP_SOURCE; /* temp register sources */ - const u16 *REG_TEMP_SEL; -+ const u16 *REG_WEIGHT_TEMP_SEL; -+ const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */ -+ - const u16 *REG_TEMP_OFFSET; - - const u16 *REG_ALARM; -@@ -625,8 +643,9 @@ struct nct6775_data { - * 4->SmartFan III - * 5->enhanced variable thermal cruise (SmartFan IV) - */ -- u8 pwm[5][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -- * [3]=pwm_max, [4]=pwm_step -+ u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, -+ * [3]=pwm_max, [4]=pwm_step, -+ * [5]=weight_duty_step, [6]=weight_duty_base - */ - - u8 target_temp[5]; -@@ -645,6 +664,10 @@ struct nct6775_data { - u8 auto_pwm[5][7]; - u8 auto_temp[5][7]; - u8 pwm_temp_sel[5]; -+ u8 pwm_weight_temp_sel[5]; -+ u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol, -+ * 2->temp_base -+ */ - - u8 vid; - u8 vrm; -@@ -972,6 +995,19 @@ static void nct6775_update_pwm(struct device *dev) - /* If fan can stop, report floor as 0 */ - if (reg & 0x80) - data->pwm[2][i] = 0; -+ -+ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]); -+ data->pwm_weight_temp_sel[i] = reg & 0x1f; -+ /* If weight is disabled, report weight source as 0 */ -+ if (j == 1 && !(reg & 0x80)) -+ data->pwm_weight_temp_sel[i] = 0; -+ -+ /* Weight temp data */ -+ for (j = 0; j < 3; j++) { -+ data->weight_temp[j][i] -+ = nct6775_read_value(data, -+ data->REG_WEIGHT_TEMP[j][i]); -+ } - } - } - -@@ -1938,9 +1974,9 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, - int nr = sattr->nr; - int index = sattr->index; - unsigned long val; -- int minval[5] = { 0, 1, 1, data->pwm[2][nr], 0 }; -- int maxval[5] -- = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255 }; -+ int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 }; -+ int maxval[7] -+ = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 }; - int err; - u8 reg; - -@@ -2078,13 +2114,9 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, - } - - static ssize_t --show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) -+show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src) - { -- struct nct6775_data *data = nct6775_update_device(dev); -- struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -- int i, src, sel = 0; -- -- src = data->pwm_temp_sel[sattr->index]; -+ int i, sel = 0; - - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) -@@ -2099,6 +2131,16 @@ show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) - } - - static ssize_t -+show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int index = sattr->index; -+ -+ return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]); -+} -+ -+static ssize_t - store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) - { -@@ -2129,6 +2171,56 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, - } - - static ssize_t -+show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int index = sattr->index; -+ -+ return show_pwm_temp_sel_common(data, buf, -+ data->pwm_weight_temp_sel[index]); -+} -+ -+static ssize_t -+store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); -+ int nr = sattr->index; -+ unsigned long val; -+ int err, reg, src; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ if (val > NUM_TEMP) -+ return -EINVAL; -+ if (val && (!(data->have_temp & (1 << (val - 1))) || -+ !data->temp_src[val - 1])) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ if (val) { -+ src = data->temp_src[val - 1]; -+ data->pwm_weight_temp_sel[nr] = src; -+ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); -+ reg &= 0xe0; -+ reg |= (src | 0x80); -+ nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); -+ } else { -+ data->pwm_weight_temp_sel[nr] = 0; -+ reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); -+ reg &= 0x7f; -+ nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); -+ } -+ mutex_unlock(&data->update_lock); -+ -+ return count; -+} -+ -+static ssize_t - show_target_temp(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = nct6775_update_device(dev); -@@ -2381,6 +2473,115 @@ static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO, - /* Smart Fan registers */ - - static ssize_t -+show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct nct6775_data *data = nct6775_update_device(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ -+ return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000); -+} -+ -+static ssize_t -+store_weight_temp(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct nct6775_data *data = dev_get_drvdata(dev); -+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); -+ int nr = sattr->nr; -+ int index = sattr->index; -+ unsigned long val; -+ int err; -+ -+ err = kstrtoul(buf, 10, &val); -+ if (err < 0) -+ return err; -+ -+ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255); -+ -+ mutex_lock(&data->update_lock); -+ data->weight_temp[index][nr] = val; -+ nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, -+ 0); -+static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, -+ 1); -+static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, -+ 2); -+static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, -+ 3); -+static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO, -+ show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, -+ 4); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 0, 0); -+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 1, 0); -+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 2, 0); -+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 3, 0); -+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 4, 0); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 0, 1); -+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 1, 1); -+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 2, 1); -+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 3, 1); -+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 4, 1); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 0, 2); -+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 1, 2); -+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 2, 2); -+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 3, 2); -+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO, -+ show_weight_temp, store_weight_temp, 4, 2); -+ -+static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 0, 5); -+static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 1, 5); -+static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 2, 5); -+static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 3, 5); -+static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 4, 5); -+ -+/* duty_base is not supported on all chips */ -+static struct sensor_device_attribute_2 sda_weight_duty_base[] = { -+ SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 0, 6), -+ SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 1, 6), -+ SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 2, 6), -+ SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 3, 6), -+ SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO, -+ show_pwm, store_pwm, 4, 6), -+}; -+ -+static ssize_t - show_fan_time(struct device *dev, struct device_attribute *attr, char *buf) - { - struct nct6775_data *data = nct6775_update_device(dev); -@@ -2526,7 +2727,7 @@ static struct sensor_device_attribute_2 sda_pwm_step[] = { - SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4), - }; - --static struct attribute *nct6775_attributes_pwm[5][15] = { -+static struct attribute *nct6775_attributes_pwm[5][20] = { - { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, -@@ -2542,6 +2743,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { - &sensor_dev_attr_pwm1_step_down_time.dev_attr.attr, - &sensor_dev_attr_pwm1_start.dev_attr.attr, - &sensor_dev_attr_pwm1_floor.dev_attr.attr, -+ &sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr, -+ &sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr, -+ &sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr, -+ &sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr, - NULL - }, - { -@@ -2559,6 +2765,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { - &sensor_dev_attr_pwm2_step_down_time.dev_attr.attr, - &sensor_dev_attr_pwm2_start.dev_attr.attr, - &sensor_dev_attr_pwm2_floor.dev_attr.attr, -+ &sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr, -+ &sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr, -+ &sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr, -+ &sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr, - NULL - }, - { -@@ -2576,6 +2787,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { - &sensor_dev_attr_pwm3_step_down_time.dev_attr.attr, - &sensor_dev_attr_pwm3_start.dev_attr.attr, - &sensor_dev_attr_pwm3_floor.dev_attr.attr, -+ &sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr, -+ &sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr, -+ &sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr, -+ &sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr, - NULL - }, - { -@@ -2593,6 +2809,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { - &sensor_dev_attr_pwm4_step_down_time.dev_attr.attr, - &sensor_dev_attr_pwm4_start.dev_attr.attr, - &sensor_dev_attr_pwm4_floor.dev_attr.attr, -+ &sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr, -+ &sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr, -+ &sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr, -+ &sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr, - NULL - }, - { -@@ -2610,6 +2831,11 @@ static struct attribute *nct6775_attributes_pwm[5][15] = { - &sensor_dev_attr_pwm5_step_down_time.dev_attr.attr, - &sensor_dev_attr_pwm5_start.dev_attr.attr, - &sensor_dev_attr_pwm5_floor.dev_attr.attr, -+ &sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr, -+ &sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr, -+ &sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr, -+ &sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr, -+ &sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr, - NULL - }, - }; -@@ -2974,6 +3200,9 @@ static void nct6775_device_remove_files(struct device *dev) - for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++) - device_remove_file(dev, &sda_pwm_step[i].dev_attr); - -+ for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++) -+ device_remove_file(dev, &sda_weight_duty_base[i].dev_attr); -+ - for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) - device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr); - -@@ -3203,6 +3432,7 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; - data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT; - data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT; -+ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6775_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK; -@@ -3214,6 +3444,10 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; -+ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; -+ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; -+ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; -+ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; - data->REG_ALARM = NCT6775_REG_ALARM; - - reg_temp = NCT6775_REG_TEMP; -@@ -3261,6 +3495,8 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_PWM[0] = NCT6775_REG_PWM; - data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; - data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; -+ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; -+ data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; -@@ -3272,6 +3508,10 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; -+ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; -+ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; -+ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; -+ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; - data->REG_ALARM = NCT6775_REG_ALARM; - - reg_temp = NCT6775_REG_TEMP; -@@ -3319,6 +3559,8 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_PWM[0] = NCT6775_REG_PWM; - data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; - data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; -+ data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP; -+ data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE; - data->REG_PWM_READ = NCT6775_REG_PWM_READ; - data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; - data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; -@@ -3330,6 +3572,10 @@ static int nct6775_probe(struct platform_device *pdev) - data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; - data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; - data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; -+ data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL; -+ data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP; -+ data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL; -+ data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE; - data->REG_ALARM = NCT6779_REG_ALARM; - - reg_temp = NCT6779_REG_TEMP; -@@ -3557,6 +3803,12 @@ static int nct6775_probe(struct platform_device *pdev) - if (err) - goto exit_remove; - } -+ if (data->REG_PWM[6]) { -+ err = device_create_file(dev, -+ &sda_weight_duty_base[i].dev_attr); -+ if (err) -+ goto exit_remove; -+ } - } - for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) { - struct sensor_device_attribute_2 *attr = - -From 8e9285b0bb2ab48924032147baa29699c0bbee7c Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 4 Dec 2012 08:03:37 -0800 -Subject: [PATCH] hwmon: (nct6775) Detect and report additional temperature - sources - -Scan all temperature sources used for fan control and report if additional -monitoring registers are available. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index f80ff82..6d58597 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -3364,6 +3364,32 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, - return 0; - } - -+static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, -+ int *available, int *mask) -+{ -+ int i; -+ u8 src; -+ -+ for (i = 0; i < data->pwm_num && *available; i++) { -+ int index; -+ -+ if (!regp[i]) -+ continue; -+ src = nct6775_read_value(data, regp[i]); -+ src &= 0x1f; -+ if (!src || (*mask & (1 << src))) -+ continue; -+ if (src >= data->temp_label_num || -+ !strlen(data->temp_label[src])) -+ continue; -+ -+ index = __ffs(*available); -+ nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src); -+ *available &= ~(1 << index); -+ *mask |= 1 << src; -+ } -+} -+ - static int nct6775_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -3614,6 +3640,13 @@ static int nct6775_probe(struct platform_device *pdev) - mask |= 1 << src; - } - -+ /* -+ * Now find unmonitored temperature registers and enable monitoring -+ * if additional monitoring registers are available. -+ */ -+ add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask); -+ add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask); -+ - mask = 0; - s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */ - for (i = 0; i < num_reg_temp; i++) { - -From 0fc1f8fc614ca0fef78011b34ef8da638eb9acea Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 26 Feb 2013 09:43:50 -0800 -Subject: [PATCH] hwmon: (nct6775) Only report VID if supported and enabled - -VID is not always enabled (NCT6775, NCT6776) or supported (NCT6779). - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 6d58597..752fbd7 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -3401,6 +3401,8 @@ static int nct6775_probe(struct platform_device *pdev) - const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config; - const u16 *reg_temp_alternate, *reg_temp_crit; - int num_reg_temp; -+ bool have_vid = false; -+ u8 cr2a; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, -@@ -3769,17 +3771,31 @@ static int nct6775_probe(struct platform_device *pdev) - /* Initialize the chip */ - nct6775_init_device(data); - -- data->vrm = vid_which_vrm(); - err = superio_enter(sio_data->sioreg); - if (err) - return err; - -+ cr2a = superio_inb(sio_data->sioreg, 0x2a); -+ switch (data->kind) { -+ case nct6775: -+ have_vid = (cr2a & 0x40); -+ break; -+ case nct6776: -+ have_vid = (cr2a & 0x60) == 0x40; -+ break; -+ case nct6779: -+ break; -+ } -+ - /* - * Read VID value - * We can get the VID input values directly at logical device D 0xe3. - */ -- superio_select(sio_data->sioreg, NCT6775_LD_VID); -- data->vid = superio_inb(sio_data->sioreg, 0xe3); -+ if (have_vid) { -+ superio_select(sio_data->sioreg, NCT6775_LD_VID); -+ data->vid = superio_inb(sio_data->sioreg, 0xe3); -+ data->vrm = vid_which_vrm(); -+ } - - if (fan_debounce) { - u8 tmp; -@@ -3804,9 +3820,11 @@ static int nct6775_probe(struct platform_device *pdev) - - superio_exit(sio_data->sioreg); - -- err = device_create_file(dev, &dev_attr_cpu0_vid); -- if (err) -- return err; -+ if (have_vid) { -+ err = device_create_file(dev, &dev_attr_cpu0_vid); -+ if (err) -+ return err; -+ } - - err = nct6775_check_fan_inputs(sio_data, data); - if (err) - -From 236d9039480059f97dc9d3cd75e3651582b62997 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Fri, 8 Mar 2013 07:42:00 -0800 -Subject: [PATCH] hwmon: (nct6775) Drop read/write lock - -The read/write lock is acquired for each read/write operation from/to the chip. -This occurs either during initialization, when it is not needed, or during -updates, when the update_lock is held as well, and it is not needed either. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 752fbd7..2269bb2 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -554,7 +554,6 @@ struct nct6775_data { - const char *name; - - struct device *hwmon_dev; -- struct mutex lock; - - u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, - * 3=temp_crit -@@ -745,8 +744,6 @@ static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) - { - int res, word_sized = is_word_sized(data, reg); - -- mutex_lock(&data->lock); -- - nct6775_set_bank(data, reg); - outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); - res = inb_p(data->addr + DATA_REG_OFFSET); -@@ -755,8 +752,6 @@ static u16 nct6775_read_value(struct nct6775_data *data, u16 reg) - data->addr + ADDR_REG_OFFSET); - res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET); - } -- -- mutex_unlock(&data->lock); - return res; - } - -@@ -764,8 +759,6 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) - { - int word_sized = is_word_sized(data, reg); - -- mutex_lock(&data->lock); -- - nct6775_set_bank(data, reg); - outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); - if (word_sized) { -@@ -774,8 +767,6 @@ static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value) - data->addr + ADDR_REG_OFFSET); - } - outb_p(value & 0xff, data->addr + DATA_REG_OFFSET); -- -- mutex_unlock(&data->lock); - return 0; - } - -@@ -3416,7 +3407,6 @@ static int nct6775_probe(struct platform_device *pdev) - - data->kind = sio_data->kind; - data->addr = res->start; -- mutex_init(&data->lock); - mutex_init(&data->update_lock); - data->name = nct6775_device_names[data->kind]; - data->bank = 0xff; /* Force initial bank selection */ - -From 2c7fd30da21bf6bda12d7a0f678e4fd8ed362c96 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 2 Apr 2013 08:53:19 -0700 -Subject: [PATCH] hwmon: (nct6775) Expand scope of supported chips - -NCT6775, NCT6776, and NCT6779 have a number of variants with the same -chip ID but different chip labels. Add text "or compatible" to the -message displayed when the driver is loaded and rephrase the Kconfig -entry to reflect that it also supports compatible chips. - -Signed-off-by: Guenter Roeck - -diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775 -index 3f5587e..4e9ef60 100644 ---- a/Documentation/hwmon/nct6775 -+++ b/Documentation/hwmon/nct6775 -@@ -8,15 +8,15 @@ Kernel driver NCT6775 - ===================== - - Supported chips: -- * Nuvoton NCT6775F/W83667HG-I -+ * Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I - Prefix: 'nct6775' - Addresses scanned: ISA address retrieved from Super I/O registers - Datasheet: Available from Nuvoton upon request -- * Nuvoton NCT6776F -+ * Nuvoton NCT5577D/NCT6776D/NCT6776F - Prefix: 'nct6776' - Addresses scanned: ISA address retrieved from Super I/O registers - Datasheet: Available from Nuvoton upon request -- * Nuvoton NCT6779D -+ * Nuvoton NCT5532D/NCT6779D - Prefix: 'nct6779' - Addresses scanned: ISA address retrieved from Super I/O registers - Datasheet: Available from Nuvoton upon request -@@ -28,7 +28,7 @@ Description - ----------- - - This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D --super I/O chips. -+and compatible super I/O chips. - - The chips support up to 25 temperature monitoring sources. Up to 6 of those are - direct temperature sensor inputs, the others are special sources such as PECI, -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 4986961..26ebff0 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -908,14 +908,14 @@ config SENSORS_MCP3021 - will be called mcp3021. - - config SENSORS_NCT6775 -- tristate "Nuvoton NCT6775F, NCT6776F, NCT6779D" -+ tristate "Nuvoton NCT6775F and compatibles" - depends on !PPC - select HWMON_VID - help - If you say yes here you get support for the hardware monitoring -- functionality of the Nuvoton NCT6775F, NCT6776F, and NCT6779D -- Super-I/O chips. This driver replaces the w83627ehf driver for -- NCT6775F and NCT6776F. -+ functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D -+ and compatible Super-I/O chips. This driver replaces the -+ w83627ehf driver for NCT6775F and NCT6776F. - - This driver can also be built as a module. If so, the module - will be called nct6775. -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 2269bb2..d05a700 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -4072,16 +4072,17 @@ static struct platform_driver nct6775_driver = { - .remove = nct6775_remove, - }; - -+static const char *nct6775_sio_names[] __initconst = { -+ "NCT6775F", -+ "NCT6776D/F", -+ "NCT6779D", -+}; -+ - /* nct6775_find() looks for a '627 in the Super-I/O config space */ - static int __init nct6775_find(int sioaddr, unsigned short *addr, - struct nct6775_sio_data *sio_data) - { -- static const char sio_name_NCT6775[] __initconst = "NCT6775F"; -- static const char sio_name_NCT6776[] __initconst = "NCT6776F"; -- static const char sio_name_NCT6779[] __initconst = "NCT6779D"; -- - u16 val; -- const char *sio_name; - int err; - - err = superio_enter(sioaddr); -@@ -4096,15 +4097,12 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr, - switch (val & SIO_ID_MASK) { - case SIO_NCT6775_ID: - sio_data->kind = nct6775; -- sio_name = sio_name_NCT6775; - break; - case SIO_NCT6776_ID: - sio_data->kind = nct6776; -- sio_name = sio_name_NCT6776; - break; - case SIO_NCT6779_ID: - sio_data->kind = nct6779; -- sio_name = sio_name_NCT6779; - break; - default: - if (val != 0xffff) -@@ -4132,7 +4130,8 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr, - } - - superio_exit(sioaddr); -- pr_info("Found %s chip at %#x\n", sio_name, *addr); -+ pr_info("Found %s or compatible chip at %#x\n", -+ nct6775_sio_names[sio_data->kind], *addr); - sio_data->sioreg = sioaddr; - - return 0; - -From 573728c647fb991ec7be6408a4975413d2ace6c3 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Fri, 5 Apr 2013 23:15:53 -0700 -Subject: [PATCH] hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776 - -Per datasheet, VIN3 and AUXTIN share the same external pin. However, there -is no clean way to detect this condition. Furthermore, both are reported -by the BIOS on Supermicro C7H61. It may thus be possible that chip revisions -exist where both attributes are supported at the same time. -Better play safe and report both. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index d05a700..8d0e4c4 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -3721,43 +3721,6 @@ static int nct6775_probe(struct platform_device *pdev) - } - #endif /* USE_ALTERNATE */ - -- switch (data->kind) { -- case nct6775: -- break; -- case nct6776: -- /* -- * On NCT6776, AUXTIN and VIN3 pins are shared. -- * Only way to detect it is to check if AUXTIN is used -- * as a temperature source, and if that source is -- * enabled. -- * -- * If that is the case, disable in6, which reports VIN3. -- * Otherwise disable temp3. -- */ -- if (data->have_temp & (1 << 2)) { -- u8 reg = nct6775_read_value(data, -- data->reg_temp_config[2]); -- if (reg & 0x01) -- data->have_temp &= ~(1 << 2); -- else -- data->have_in &= ~(1 << 6); -- } -- break; -- case nct6779: -- /* -- * Shared pins: -- * VIN4 / AUXTIN0 -- * VIN5 / AUXTIN1 -- * VIN6 / AUXTIN2 -- * VIN7 / AUXTIN3 -- * -- * There does not seem to be a clean way to detect if VINx or -- * AUXTINx is active, so for keep both sensor types enabled -- * for now. -- */ -- break; -- } -- - /* Initialize the chip */ - nct6775_init_device(data); - - -From c409fd43bdea705799d21531600b8f305b120009 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Tue, 9 Apr 2013 05:04:00 -0700 -Subject: [PATCH] hwmon: (nct6775) Use ARRAY_SIZE for loops where possible - -This ensures that the loop iterations are correct even if/when -the number of elements in an array changes. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 8d0e4c4..04ccfff 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -854,7 +854,7 @@ static void nct6775_init_fan_div(struct nct6775_data *data) - * reading from the fan count register, even if it is not optimal. - * We'll compute a better divider later on. - */ -- for (i = 0; i < 3; i++) { -+ for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) { - if (!(data->has_fan & (1 << i))) - continue; - if (data->fan_div[i] == 0) { -@@ -877,7 +877,7 @@ static void nct6775_init_fan_common(struct device *dev, - * If fan_min is not set (0), set it to 0xff to disable it. This - * prevents the unnecessary warning when fanX_min is reported as 0. - */ -- for (i = 0; i < 5; i++) { -+ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { - if (data->has_fan_min & (1 << i)) { - reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); - if (!reg) -@@ -994,7 +994,7 @@ static void nct6775_update_pwm(struct device *dev) - data->pwm_weight_temp_sel[i] = 0; - - /* Weight temp data */ -- for (j = 0; j < 3; j++) { -+ for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) { - data->weight_temp[j][i] - = nct6775_read_value(data, - data->REG_WEIGHT_TEMP[j][i]); -@@ -1013,7 +1013,7 @@ static void nct6775_update_pwm_limits(struct device *dev) - if (!(data->has_pwm & (1 << i))) - continue; - -- for (j = 0; j < 3; j++) { -+ for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) { - data->fan_time[j][i] = - nct6775_read_value(data, data->REG_FAN_TIME[j][i]); - } -@@ -1095,7 +1095,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - } - - /* Measured fan speeds and limits */ -- for (i = 0; i < 5; i++) { -+ for (i = 0; i < ARRAY_SIZE(data->rpm); i++) { - u16 reg; - - if (!(data->has_fan & (1 << i))) -@@ -1121,7 +1121,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - for (i = 0; i < NUM_TEMP; i++) { - if (!(data->have_temp & (1 << i))) - continue; -- for (j = 0; j < 4; j++) { -+ for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) { - if (data->reg_temp[j][i]) - data->temp[j][i] - = nct6775_read_temp(data, -@@ -3983,7 +3983,7 @@ static int nct6775_resume(struct device *dev) - data->in[i][2]); - } - -- for (i = 0; i < 5; i++) { -+ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { - if (!(data->has_fan_min & (1 << i))) - continue; - -@@ -3995,7 +3995,7 @@ static int nct6775_resume(struct device *dev) - if (!(data->have_temp & (1 << i))) - continue; - -- for (j = 1; j < 4; j++) -+ for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++) - if (data->reg_temp[j][i]) - nct6775_write_temp(data, data->reg_temp[j][i], - data->temp[j][i]); - -From 6d4b3621bb613da51ae7474c50f5cb37465b6f37 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Sun, 21 Apr 2013 09:08:11 -0700 -Subject: [PATCH] hwmon: (nct6775) Constify strings - -nct6775_sio_names should be a constant pointer to an array of -constant strings. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 04ccfff..14da90e 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -4035,7 +4035,7 @@ static struct platform_driver nct6775_driver = { - .remove = nct6775_remove, - }; - --static const char *nct6775_sio_names[] __initconst = { -+static const char * const nct6775_sio_names[] __initconst = { - "NCT6775F", - "NCT6776D/F", - "NCT6779D", - -From 6445e6600fa632448cac64e71119310378464ad9 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Sun, 21 Apr 2013 09:13:28 -0700 -Subject: [PATCH] hwmon: (nct6775) Fix coding style problems - -Add space around binary operators (CodingStyle, chapter 3.1). - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index 14da90e..f43f5e5 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -833,7 +833,7 @@ static void nct6775_update_fan_div(struct nct6775_data *data) - data->fan_div[1] = (i & 0x70) >> 4; - i = nct6775_read_value(data, NCT6775_REG_FANDIV2); - data->fan_div[2] = i & 0x7; -- if (data->has_fan & (1<<3)) -+ if (data->has_fan & (1 << 3)) - data->fan_div[3] = (i & 0x70) >> 4; - } - -@@ -1076,7 +1076,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) - - mutex_lock(&data->update_lock); - -- if (time_after(jiffies, data->last_updated + HZ + HZ/2) -+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - /* Fan clock dividers */ - nct6775_update_fan_div_common(data); -@@ -1177,7 +1177,7 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, - return err; - mutex_lock(&data->update_lock); - data->in[nr][index] = in_to_reg(val, nr); -- nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr], -+ nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], - data->in[nr][index]); - mutex_unlock(&data->update_lock); - return count; - -From 169c05cd54473ba4cc37bf4d22e7631395d14f68 Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Thu, 9 May 2013 10:40:01 -0700 -Subject: [PATCH] hwmon: (nct6775) Do not create non-existing attributes - -Overtemperature and hysteresis registers only exist for primary -temperature registers, not for alternates, so do not assign -those registers when initializing alternates. - -Signed-off-by: Guenter Roeck - -diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c -index f43f5e5..04638ae 100644 ---- a/drivers/hwmon/nct6775.c -+++ b/drivers/hwmon/nct6775.c -@@ -3705,8 +3705,10 @@ static int nct6775_probe(struct platform_device *pdev) - data->have_temp |= 1 << i; - data->have_temp_fixed |= 1 << i; - data->reg_temp[0][i] = reg_temp_alternate[i]; -- data->reg_temp[1][i] = reg_temp_over[i]; -- data->reg_temp[2][i] = reg_temp_hyst[i]; -+ if (i < num_reg_temp) { -+ data->reg_temp[1][i] = reg_temp_over[i]; -+ data->reg_temp[2][i] = reg_temp_hyst[i]; -+ } - data->temp_src[i] = i + 1; - continue; - } diff --git a/drm-i915-correctly-restore-fences-with-objects-attac.patch b/drm-i915-correctly-restore-fences-with-objects-attac.patch new file mode 100644 index 000000000..69bb93fa5 --- /dev/null +++ b/drm-i915-correctly-restore-fences-with-objects-attac.patch @@ -0,0 +1,113 @@ +From 94a335dba34ff47cad3d6d0c29b452d43a1be3c8 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Wed, 17 Jul 2013 14:51:28 +0200 +Subject: [PATCH] drm/i915: correctly restore fences with objects attached +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To avoid stalls we delay tiling changes and especially hold of +committing the new fence state for as long as possible. +Synchronization points are in the execbuf code and in our gtt fault +handler. + +Unfortunately we've missed that tricky detail when adding proper fence +restore code in + +commit 19b2dbde5732170a03bd82cc8bd442cf88d856f7 +Author: Chris Wilson +Date: Wed Jun 12 10:15:12 2013 +0100 + + drm/i915: Restore fences after resume and GPU resets + +The result was that we've restored fences for objects with no tiling, +since the object<->fence link still existed after resume. Now that +wouldn't have been too bad since any subsequent access would have +fixed things up, but if we've changed from tiled to untiled real havoc +happened: + +The tiling stride is stored -1 in the fence register, so a stride of 0 +resulted in all 1s in the top 32bits, and so a completely bogus fence +spanning everything from the start of the object to the top of the +GTT. The tell-tale in the register dumps looks like: + + FENCE START 2: 0x0214d001 + FENCE END 2: 0xfffff3ff + +Bit 11 isn't set since the hw doesn't store it, even when writing all +1s (at least on my snb here). + +To prevent such a gaffle in the future add a sanity check for fences +with an untiled object attached in i915_gem_write_fence. + +v2: Fix the WARN, spotted by Chris. + +v3: Trying to reuse get_fences looked ugly and obfuscated the code. +Instead reuse update_fence and to make it really dtrt also move the +fence dirty state clearing into update_fence. + +Cc: Chris Wilson +Cc: Stéphane Marchesin +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60530 +Cc: stable@vger.kernel.org (for 3.10 only) +Reviewed-by: Chris Wilson +Tested-by: Matthew Garrett +Tested-by: Björn Bidar +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 97afd26..d9e2208 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2258,7 +2258,17 @@ void i915_gem_restore_fences(struct drm_device *dev) + + for (i = 0; i < dev_priv->num_fence_regs; i++) { + struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; +- i915_gem_write_fence(dev, i, reg->obj); ++ ++ /* ++ * Commit delayed tiling changes if we have an object still ++ * attached to the fence, otherwise just clear the fence. ++ */ ++ if (reg->obj) { ++ i915_gem_object_update_fence(reg->obj, reg, ++ reg->obj->tiling_mode); ++ } else { ++ i915_gem_write_fence(dev, i, NULL); ++ } + } + } + +@@ -2795,6 +2805,10 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg, + if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj)) + mb(); + ++ WARN(obj && (!obj->stride || !obj->tiling_mode), ++ "bogus fence setup with stride: 0x%x, tiling mode: %i\n", ++ obj->stride, obj->tiling_mode); ++ + switch (INTEL_INFO(dev)->gen) { + case 7: + case 6: +@@ -2836,6 +2850,7 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, + fence->obj = NULL; + list_del_init(&fence->lru_list); + } ++ obj->fence_dirty = false; + } + + static int +@@ -2965,7 +2980,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj) + return 0; + + i915_gem_object_update_fence(obj, reg, enable); +- obj->fence_dirty = false; + + return 0; + } +-- +1.8.3.1 + diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch index 0f28ed240..fb2e58ee9 100644 --- a/drm-i915-dp-stfu.patch +++ b/drm-i915-dp-stfu.patch @@ -1,17 +1,17 @@ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 296cfc2..516e1e2 100644 +index fb2fbc1..0aaf67d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -350,7 +350,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) - if (!is_edp(intel_dp)) - return; +@@ -283,7 +283,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; + if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) { - WARN(1, "eDP powered off while attempting aux channel communication.\n"); + DRM_ERROR("eDP powered off while attempting aux channel communication.\n"); DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", - I915_READ(PCH_PP_STATUS), - I915_READ(PCH_PP_CONTROL)); -@@ -447,7 +447,7 @@ intel_dp_aux_ch(struct intel_dp *intel_d + I915_READ(pp_stat_reg), + I915_READ(pp_ctrl_reg)); +@@ -376,7 +376,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, } if (try == 3) { @@ -20,7 +20,7 @@ index 296cfc2..516e1e2 100644 I915_READ(ch_ctl)); ret = -EBUSY; goto out; -@@ -1024,8 +1024,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) +@@ -995,8 +995,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) return; DRM_DEBUG_KMS("Turn eDP VDD on\n"); @@ -31,7 +31,7 @@ index 296cfc2..516e1e2 100644 intel_dp->want_panel_vdd = true; -@@ -1090,7 +1090,8 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) +@@ -1070,7 +1070,8 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) return; DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); @@ -41,7 +41,7 @@ index 296cfc2..516e1e2 100644 intel_dp->want_panel_vdd = false; -@@ -1160,7 +1161,8 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) +@@ -1144,7 +1145,8 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power off\n"); @@ -49,5 +49,5 @@ index 296cfc2..516e1e2 100644 + if (!intel_dp->want_panel_vdd) + DRM_ERROR("Need VDD to turn off panel\n"); - pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); + pp = ironlake_get_pp_control(intel_dp); + /* We need to switch off panel power _and_ force vdd, for otherwise some diff --git a/i7300_edac_single_mode_fixup.patch b/i7300_edac_single_mode_fixup.patch deleted file mode 100644 index ed08ab961..000000000 --- a/i7300_edac_single_mode_fixup.patch +++ /dev/null @@ -1,108 +0,0 @@ -commit 8ed5b5d41168a98cffa63e2f6c51c3243e159706 -Author: Mauro Carvalho Chehab -Date: Wed Mar 13 22:56:33 2013 -0300 - - i7300_edac: Fix memory detection in single mode - - When the machine is on single mode, only branch 0 channel 0 - is valid. However, the code is not honouring it: - - [ 1952.639341] EDAC DEBUG: i7300_get_mc_regs: Memory controller operating on single mode - ... - [ 1952.639351] EDAC DEBUG: i7300_init_csrows: AMB-present CH0 = 0x1: - [ 1952.639353] EDAC DEBUG: i7300_init_csrows: AMB-present CH1 = 0x0: - [ 1952.639355] EDAC DEBUG: i7300_init_csrows: AMB-present CH2 = 0x0: - [ 1952.639358] EDAC DEBUG: i7300_init_csrows: AMB-present CH3 = 0x0: - ... - [ 1952.639360] EDAC DEBUG: decode_mtr: MTR0 CH0: DIMMs are Present (mtr) - [ 1952.639362] EDAC DEBUG: decode_mtr: WIDTH: x8 - [ 1952.639363] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled - [ 1952.639364] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s) - [ 1952.639366] EDAC DEBUG: decode_mtr: NUMRANK: single - [ 1952.639367] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows - [ 1952.639368] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns - [ 1952.639370] EDAC DEBUG: decode_mtr: SIZE: 512 MB - [ 1952.639371] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code - [ 1952.639373] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode - [ 1952.639374] EDAC DEBUG: decode_mtr: MTR0 CH1: DIMMs are Present (mtr) - [ 1952.639376] EDAC DEBUG: decode_mtr: WIDTH: x8 - [ 1952.639377] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled - [ 1952.639379] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s) - [ 1952.639380] EDAC DEBUG: decode_mtr: NUMRANK: single - [ 1952.639381] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows - [ 1952.639383] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns - [ 1952.639384] EDAC DEBUG: decode_mtr: SIZE: 512 MB - [ 1952.639385] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code - [ 1952.639387] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode - ... - [ 1952.639449] EDAC DEBUG: print_dimm_size: channel 0 | channel 1 | channel 2 | channel 3 | - [ 1952.639451] EDAC DEBUG: print_dimm_size: ------------------------------------------------------------- - [ 1952.639453] EDAC DEBUG: print_dimm_size: csrow/SLOT 0 512 MB | 512 MB | 0 MB | 0 MB | - [ 1952.639456] EDAC DEBUG: print_dimm_size: csrow/SLOT 1 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639458] EDAC DEBUG: print_dimm_size: csrow/SLOT 2 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639460] EDAC DEBUG: print_dimm_size: csrow/SLOT 3 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639462] EDAC DEBUG: print_dimm_size: csrow/SLOT 4 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639464] EDAC DEBUG: print_dimm_size: csrow/SLOT 5 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639466] EDAC DEBUG: print_dimm_size: csrow/SLOT 6 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639468] EDAC DEBUG: print_dimm_size: csrow/SLOT 7 0 MB | 0 MB | 0 MB | 0 MB | - [ 1952.639470] EDAC DEBUG: print_dimm_size: ------------------------------------------------------------- - - Instead of detecting a single memory at channel 0, it is showing - twice the memory. - - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c -index 087c27b..9004c64 100644 ---- a/drivers/edac/i7300_edac.c -+++ b/drivers/edac/i7300_edac.c -@@ -750,15 +750,23 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) - struct i7300_dimm_info *dinfo; - int rc = -ENODEV; - int mtr; -- int ch, branch, slot, channel; -+ int ch, branch, slot, channel, max_channel, max_branch; - struct dimm_info *dimm; - - pvt = mci->pvt_info; - - edac_dbg(2, "Memory Technology Registers:\n"); - -+ if (IS_SINGLE_MODE(pvt->mc_settings_a)) { -+ max_branch = 1; -+ max_channel = 1; -+ } else { -+ max_branch = MAX_BRANCHES; -+ max_channel = MAX_CH_PER_BRANCH; -+ } -+ - /* Get the AMB present registers for the four channels */ -- for (branch = 0; branch < MAX_BRANCHES; branch++) { -+ for (branch = 0; branch < max_branch; branch++) { - /* Read and dump branch 0's MTRs */ - channel = to_channel(0, branch); - pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], -@@ -767,6 +775,9 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) - edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", - channel, pvt->ambpresent[channel]); - -+ if (max_channel == 1) -+ continue; -+ - channel = to_channel(1, branch); - pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], - AMBPRESENT_1, -@@ -778,11 +789,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) - /* Get the set of MTR[0-7] regs by each branch */ - for (slot = 0; slot < MAX_SLOTS; slot++) { - int where = mtr_regs[slot]; -- for (branch = 0; branch < MAX_BRANCHES; branch++) { -+ for (branch = 0; branch < max_branch; branch++) { - pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], - where, - &pvt->mtr[slot][branch]); -- for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) { -+ for (ch = 0; ch < max_channel; ch++) { - int channel = to_channel(ch, branch); - - dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, diff --git a/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch b/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch deleted file mode 100644 index 8f37348e9..000000000 --- a/ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 0e3f585c132e7716b8b96c20c59b15a24ec2790e Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Mon, 1 Jul 2013 20:21:30 +0200 -Subject: [PATCH 11/40] ipv6: call udp_push_pending_frames when uncorking a - socket with AF_INET pending data - -[ Upstream commit 8822b64a0fa64a5dd1dfcf837c5b0be83f8c05d1 ] - -We accidentally call down to ip6_push_pending_frames when uncorking -pending AF_INET data on a ipv6 socket. This results in the following -splat (from Dave Jones): - -skbuff: skb_under_panic: text:ffffffff816765f6 len:48 put:40 head:ffff88013deb6df0 data:ffff88013deb6dec tail:0x2c end:0xc0 dev: -------------[ cut here ]------------ -kernel BUG at net/core/skbuff.c:126! -invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC -Modules linked in: dccp_ipv4 dccp 8021q garp bridge stp dlci mpoa snd_seq_dummy sctp fuse hidp tun bnep nfnetlink scsi_transport_iscsi rfcomm can_raw can_bcm af_802154 appletalk caif_socket can caif ipt_ULOG x25 rose af_key pppoe pppox ipx phonet irda llc2 ppp_generic slhc p8023 psnap p8022 llc crc_ccitt atm bluetooth -+netrom ax25 nfc rfkill rds af_rxrpc coretemp hwmon kvm_intel kvm crc32c_intel snd_hda_codec_realtek ghash_clmulni_intel microcode pcspkr snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep usb_debug snd_seq snd_seq_device snd_pcm e1000e snd_page_alloc snd_timer ptp snd pps_core soundcore xfs libcrc32c -CPU: 2 PID: 8095 Comm: trinity-child2 Not tainted 3.10.0-rc7+ #37 -task: ffff8801f52c2520 ti: ffff8801e6430000 task.ti: ffff8801e6430000 -RIP: 0010:[] [] skb_panic+0x63/0x65 -RSP: 0018:ffff8801e6431de8 EFLAGS: 00010282 -RAX: 0000000000000086 RBX: ffff8802353d3cc0 RCX: 0000000000000006 -RDX: 0000000000003b90 RSI: ffff8801f52c2ca0 RDI: ffff8801f52c2520 -RBP: ffff8801e6431e08 R08: 0000000000000000 R09: 0000000000000000 -R10: 0000000000000001 R11: 0000000000000001 R12: ffff88022ea0c800 -R13: ffff88022ea0cdf8 R14: ffff8802353ecb40 R15: ffffffff81cc7800 -FS: 00007f5720a10740(0000) GS:ffff880244c00000(0000) knlGS:0000000000000000 -CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -CR2: 0000000005862000 CR3: 000000022843c000 CR4: 00000000001407e0 -DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000600 -Stack: - ffff88013deb6dec 000000000000002c 00000000000000c0 ffffffff81a3f6e4 - ffff8801e6431e18 ffffffff8159a9aa ffff8801e6431e90 ffffffff816765f6 - ffffffff810b756b 0000000700000002 ffff8801e6431e40 0000fea9292aa8c0 -Call Trace: - [] skb_push+0x3a/0x40 - [] ip6_push_pending_frames+0x1f6/0x4d0 - [] ? mark_held_locks+0xbb/0x140 - [] udp_v6_push_pending_frames+0x2b9/0x3d0 - [] ? udplite_getfrag+0x20/0x20 - [] udp_lib_setsockopt+0x1aa/0x1f0 - [] ? fget_light+0x387/0x4f0 - [] udpv6_setsockopt+0x34/0x40 - [] sock_common_setsockopt+0x14/0x20 - [] SyS_setsockopt+0x71/0xd0 - [] tracesys+0xdd/0xe2 -Code: 00 00 48 89 44 24 10 8b 87 d8 00 00 00 48 89 44 24 08 48 8b 87 e8 00 00 00 48 c7 c7 c0 04 aa 81 48 89 04 24 31 c0 e8 e1 7e ff ff <0f> 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 -RIP [] skb_panic+0x63/0x65 - RSP - -This patch adds a check if the pending data is of address family AF_INET -and directly calls udp_push_ending_frames from udp_v6_push_pending_frames -if that is the case. - -This bug was found by Dave Jones with trinity. - -(Also move the initialization of fl6 below the AF_INET check, even if -not strictly necessary.) - -Cc: Dave Jones -Cc: YOSHIFUJI Hideaki -Signed-off-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - include/net/udp.h | 1 + - net/ipv4/udp.c | 3 ++- - net/ipv6/udp.c | 7 ++++++- - 3 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/include/net/udp.h b/include/net/udp.h -index 065f379..ad99eed 100644 ---- a/include/net/udp.h -+++ b/include/net/udp.h -@@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum, - extern void udp_err(struct sk_buff *, u32); - extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, - struct msghdr *msg, size_t len); -+extern int udp_push_pending_frames(struct sock *sk); - extern void udp_flush_pending_frames(struct sock *sk); - extern int udp_rcv(struct sk_buff *skb); - extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 0bf5d39..93b731d 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -799,7 +799,7 @@ send: - /* - * Push out all pending data as one UDP datagram. Socket is locked. - */ --static int udp_push_pending_frames(struct sock *sk) -+int udp_push_pending_frames(struct sock *sk) - { - struct udp_sock *up = udp_sk(sk); - struct inet_sock *inet = inet_sk(sk); -@@ -818,6 +818,7 @@ out: - up->pending = 0; - return err; - } -+EXPORT_SYMBOL(udp_push_pending_frames); - - int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 42923b1..e7b28f9 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -955,11 +955,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) - struct udphdr *uh; - struct udp_sock *up = udp_sk(sk); - struct inet_sock *inet = inet_sk(sk); -- struct flowi6 *fl6 = &inet->cork.fl.u.ip6; -+ struct flowi6 *fl6; - int err = 0; - int is_udplite = IS_UDPLITE(sk); - __wsum csum = 0; - -+ if (up->pending == AF_INET) -+ return udp_push_pending_frames(sk); -+ -+ fl6 = &inet->cork.fl.u.ip6; -+ - /* Grab the skbuff where UDP header space exists. */ - if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) - goto out; --- -1.7.11.7 diff --git a/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch b/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch deleted file mode 100644 index 97c3b1981..000000000 --- a/ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 1fcbda94eb3ababc95eff46548962ceb14de638e Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Tue, 2 Jul 2013 08:04:05 +0200 -Subject: [PATCH 12/40] ipv6: ip6_append_data_mtu did not care about pmtudisc - and frag_size - -[ Upstream commit 75a493e60ac4bbe2e977e7129d6d8cbb0dd236be ] - -If the socket had an IPV6_MTU value set, ip6_append_data_mtu lost track -of this when appending the second frame on a corked socket. This results -in the following splat: - -[37598.993962] ------------[ cut here ]------------ -[37598.994008] kernel BUG at net/core/skbuff.c:2064! -[37598.994008] invalid opcode: 0000 [#1] SMP -[37598.994008] Modules linked in: tcp_lp uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core videodev media vfat fat usb_storage fuse ebtable_nat xt_CHECKSUM bridge stp llc ipt_MASQUERADE nf_conntrack_netbios_ns nf_conntrack_broadcast ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat -+nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp libiscsi -+scsi_transport_iscsi rfcomm bnep iTCO_wdt iTCO_vendor_support snd_hda_codec_conexant arc4 iwldvm mac80211 snd_hda_intel acpi_cpufreq mperf coretemp snd_hda_codec microcode cdc_wdm cdc_acm -[37598.994008] snd_hwdep cdc_ether snd_seq snd_seq_device usbnet mii joydev btusb snd_pcm bluetooth i2c_i801 e1000e lpc_ich mfd_core ptp iwlwifi pps_core snd_page_alloc mei cfg80211 snd_timer thinkpad_acpi snd tpm_tis soundcore rfkill tpm tpm_bios vhost_net tun macvtap macvlan kvm_intel kvm uinput binfmt_misc -+dm_crypt i915 i2c_algo_bit drm_kms_helper drm i2c_core wmi video -[37598.994008] CPU 0 -[37598.994008] Pid: 27320, comm: t2 Not tainted 3.9.6-200.fc18.x86_64 #1 LENOVO 27744PG/27744PG -[37598.994008] RIP: 0010:[] [] skb_copy_and_csum_bits+0x325/0x330 -[37598.994008] RSP: 0018:ffff88003670da18 EFLAGS: 00010202 -[37598.994008] RAX: ffff88018105c018 RBX: 0000000000000004 RCX: 00000000000006c0 -[37598.994008] RDX: ffff88018105a6c0 RSI: ffff88018105a000 RDI: ffff8801e1b0aa00 -[37598.994008] RBP: ffff88003670da78 R08: 0000000000000000 R09: ffff88018105c040 -[37598.994008] R10: ffff8801e1b0aa00 R11: 0000000000000000 R12: 000000000000fff8 -[37598.994008] R13: 00000000000004fc R14: 00000000ffff0504 R15: 0000000000000000 -[37598.994008] FS: 00007f28eea59740(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000 -[37598.994008] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b -[37598.994008] CR2: 0000003d935789e0 CR3: 00000000365cb000 CR4: 00000000000407f0 -[37598.994008] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -[37598.994008] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 -[37598.994008] Process t2 (pid: 27320, threadinfo ffff88003670c000, task ffff88022c162ee0) -[37598.994008] Stack: -[37598.994008] ffff88022e098a00 ffff88020f973fc0 0000000000000008 00000000000004c8 -[37598.994008] ffff88020f973fc0 00000000000004c4 ffff88003670da78 ffff8801e1b0a200 -[37598.994008] 0000000000000018 00000000000004c8 ffff88020f973fc0 00000000000004c4 -[37598.994008] Call Trace: -[37598.994008] [] ip6_append_data+0xccf/0xfe0 -[37598.994008] [] ? ip_copy_metadata+0x1a0/0x1a0 -[37598.994008] [] ? _raw_spin_lock_bh+0x16/0x40 -[37598.994008] [] udpv6_sendmsg+0x1ed/0xc10 -[37598.994008] [] ? sock_has_perm+0x75/0x90 -[37598.994008] [] inet_sendmsg+0x63/0xb0 -[37598.994008] [] ? selinux_socket_sendmsg+0x23/0x30 -[37598.994008] [] sock_sendmsg+0xb0/0xe0 -[37598.994008] [] ? __switch_to+0x181/0x4a0 -[37598.994008] [] sys_sendto+0x12d/0x180 -[37598.994008] [] ? __audit_syscall_entry+0x94/0xf0 -[37598.994008] [] ? syscall_trace_enter+0x231/0x240 -[37598.994008] [] tracesys+0xdd/0xe2 -[37598.994008] Code: fe 07 00 00 48 c7 c7 04 28 a6 81 89 45 a0 4c 89 4d b8 44 89 5d a8 e8 1b ac b1 ff 44 8b 5d a8 4c 8b 4d b8 8b 45 a0 e9 cf fe ff ff <0f> 0b 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 48 -[37598.994008] RIP [] skb_copy_and_csum_bits+0x325/0x330 -[37598.994008] RSP -[37599.007323] ---[ end trace d69f6a17f8ac8eee ]--- - -While there, also check if path mtu discovery is activated for this -socket. The logic was adapted from ip6_append_data when first writing -on the corked socket. - -This bug was introduced with commit -0c1833797a5a6ec23ea9261d979aa18078720b74 ("ipv6: fix incorrect ipsec -fragment"). - -v2: -a) Replace IPV6_PMTU_DISC_DO with IPV6_PMTUDISC_PROBE. -b) Don't pass ipv6_pinfo to ip6_append_data_mtu (suggestion by Gao - feng, thanks!). -c) Change mtu to unsigned int, else we get a warning about - non-matching types because of the min()-macro type-check. - -Acked-by: Gao feng -Cc: YOSHIFUJI Hideaki -Signed-off-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_output.c | 16 ++++++++++------ - 1 file changed, 10 insertions(+), 6 deletions(-) - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index d5d20cd..6e3ddf8 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1098,11 +1098,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, - return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; - } - --static void ip6_append_data_mtu(int *mtu, -+static void ip6_append_data_mtu(unsigned int *mtu, - int *maxfraglen, - unsigned int fragheaderlen, - struct sk_buff *skb, -- struct rt6_info *rt) -+ struct rt6_info *rt, -+ bool pmtuprobe) - { - if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { - if (skb == NULL) { -@@ -1114,7 +1115,9 @@ static void ip6_append_data_mtu(int *mtu, - * this fragment is not first, the headers - * space is regarded as data space. - */ -- *mtu = dst_mtu(rt->dst.path); -+ *mtu = min(*mtu, pmtuprobe ? -+ rt->dst.dev->mtu : -+ dst_mtu(rt->dst.path)); - } - *maxfraglen = ((*mtu - fragheaderlen) & ~7) - + fragheaderlen - sizeof(struct frag_hdr); -@@ -1131,11 +1134,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, - struct ipv6_pinfo *np = inet6_sk(sk); - struct inet_cork *cork; - struct sk_buff *skb, *skb_prev = NULL; -- unsigned int maxfraglen, fragheaderlen; -+ unsigned int maxfraglen, fragheaderlen, mtu; - int exthdrlen; - int dst_exthdrlen; - int hh_len; -- int mtu; - int copy; - int err; - int offset = 0; -@@ -1292,7 +1294,9 @@ alloc_new_skb: - /* update mtu and maxfraglen if necessary */ - if (skb == NULL || skb_prev == NULL) - ip6_append_data_mtu(&mtu, &maxfraglen, -- fragheaderlen, skb, rt); -+ fragheaderlen, skb, rt, -+ np->pmtudisc == -+ IPV6_PMTUDISC_PROBE); - - skb_prev = skb; - --- -1.7.11.7 diff --git a/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch b/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch deleted file mode 100644 index 8f6c41d28..000000000 --- a/ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch +++ /dev/null @@ -1,52 +0,0 @@ -From a963a37d384d71ad43b3e9e79d68d42fbe0901f3 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 26 Jun 2013 04:15:07 -0700 -Subject: [PATCH] ipv6: ip6_sk_dst_check() must not assume ipv6 dst - -It's possible to use AF_INET6 sockets and to connect to an IPv4 -destination. After this, socket dst cache is a pointer to a rtable, -not rt6_info. - -ip6_sk_dst_check() should check the socket dst cache is IPv6, or else -various corruptions/crashes can happen. - -Dave Jones can reproduce immediate crash with -trinity -q -l off -n -c sendmsg -c connect - -With help from Hannes Frederic Sowa - -Reported-by: Dave Jones -Reported-by: Hannes Frederic Sowa -Signed-off-by: Eric Dumazet -Acked-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_output.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 95703ba..d5d20cd 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -821,11 +821,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, - const struct flowi6 *fl6) - { - struct ipv6_pinfo *np = inet6_sk(sk); -- struct rt6_info *rt = (struct rt6_info *)dst; -+ struct rt6_info *rt; - - if (!dst) - goto out; - -+ if (dst->ops->family != AF_INET6) { -+ dst_release(dst); -+ return NULL; -+ } -+ -+ rt = (struct rt6_info *)dst; - /* Yes, checking route validity in not connected - * case is not very simple. Take into account, - * that we do not support routing by source, TOS, --- -1.8.2.1 - diff --git a/iwlwifi-add-new-pci-id-for-6x35-series.patch b/iwlwifi-add-new-pci-id-for-6x35-series.patch deleted file mode 100644 index ba616400f..000000000 --- a/iwlwifi-add-new-pci-id-for-6x35-series.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 20ecf9fd3bebc4147e2996c08a75d6f0229b90df Mon Sep 17 00:00:00 2001 -From: Shuduo Sang -Date: Sat, 30 Mar 2013 06:26:37 +0000 -Subject: iwlwifi: add new pci id for 6x35 series - -some new thinkpad laptops use intel chip with new pci id need be added -lspci -vnn output: - Network controller [0280]: Intel Corporation Centrino Advanced-N 6235 - [8086:088f] (rev 24) - Subsystem: Intel Corporation Device [8086:5260] - -Signed-off-by: Shuduo Sang -Reviewed-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg ---- -diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c -index 46ca91f..0016bb2 100644 ---- a/drivers/net/wireless/iwlwifi/pcie/drv.c -+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c -@@ -241,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { - {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, - {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, - {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, -+ {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)}, - - /* 105 Series */ - {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, --- -cgit v0.9.2 diff --git a/iwlwifi-pcie-fix-race-in-queue-unmapping.patch b/iwlwifi-pcie-fix-race-in-queue-unmapping.patch deleted file mode 100644 index ad9194af3..000000000 --- a/iwlwifi-pcie-fix-race-in-queue-unmapping.patch +++ /dev/null @@ -1,56 +0,0 @@ -From: Emmanuel Grumbach - -When a queue is disabled, it frees all its entries. Later, -the op_mode might still get notifications from the firmware -that triggers to free entries in the tx queue. The transport -should be prepared for these races and know to ignore -reclaim calls on queues that have been disabled and whose -entries have been freed. - -Cc: stable@vger.kernel.org -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/iwlwifi/pcie/tx.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c -index cb5c679..faaf77c 100644 ---- a/drivers/net/wireless/iwlwifi/pcie/tx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c -@@ -578,9 +578,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) - - spin_lock_bh(&txq->lock); - while (q->write_ptr != q->read_ptr) { -+ IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", -+ txq_id, q->read_ptr); - iwl_pcie_txq_free_tfd(trans, txq); - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); - } -+ txq->active = false; - spin_unlock_bh(&txq->lock); - } - -@@ -929,6 +932,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - - spin_lock_bh(&txq->lock); - -+ if (!txq->active) { -+ IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n", -+ txq_id, ssn); -+ goto out; -+ } -+ - if (txq->q.read_ptr == tfd_num) - goto out; - -@@ -1105,6 +1114,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, - (fifo << SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << SCD_QUEUE_STTS_REG_POS_WSL) | - SCD_QUEUE_STTS_REG_MSK); -+ trans_pcie->txq[txq_id].active = true; - IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", - txq_id, fifo, ssn & 0xff); - } --- -1.7.11.7 diff --git a/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch b/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch deleted file mode 100644 index 661fc5035..000000000 --- a/iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Emmanuel Grumbach - -When the queue is unmapped while it was so loaded that -mac80211's was stopped, we need to wake the queue after -having freed all the packets in the queue. -Not doing so can result in weird stuff like: - -* run lots of traffic (mac80211's queue gets stopped) -* RFKILL -* de-assert RFKILL -* no traffic - -Cc: stable@vger.kernel.org -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/iwlwifi/pcie/tx.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c -index faaf77c..4e7b8d4 100644 ---- a/drivers/net/wireless/iwlwifi/pcie/tx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c -@@ -585,6 +585,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) - } - txq->active = false; - spin_unlock_bh(&txq->lock); -+ -+ /* just in case - this queue may have been stopped */ -+ iwl_wake_queue(trans, txq); - } - - /* --- -1.7.11.7 diff --git a/kernel.spec b/kernel.spec index 517280272..9098ef4e9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,19 +62,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 201 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 9 +%define base_sublevel 10 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -649,9 +649,6 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch -Patch200: debug-bad-pte-dmi.patch -Patch201: debug-bad-pte-modules.patch - Patch390: defaults-acpi-video.patch Patch391: acpi-video-dos.patch Patch394: acpi-debug-infinite-loop.patch @@ -670,7 +667,7 @@ Patch530: silence-fbcon-logo.patch Patch800: crash-driver.patch # secure boot -Patch1000: secure-boot-20130506.patch +Patch1000: devel-pekey-secure-boot-20130502.patch # virt + ksm patches @@ -718,11 +715,9 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch Patch21000: arm-export-read_current_timer.patch # ARM omap -Patch21003: arm-omap-ehci-fix.patch # ARM tegra Patch21005: arm-tegra-usb-no-reset-linux33.patch -Patch21006: arm-tegra-fixclk.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -738,15 +733,6 @@ Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch -#rhbz 916544 -Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch - -#rhbz 859282 -Patch24113: VMX-x86-handle-host-TSC-calibration-failure.patch - -#rhbz 921500 -Patch25001: i7300_edac_single_mode_fixup.patch - #rhbz 927469 Patch25007: fix-child-thread-introspection.patch @@ -765,12 +751,6 @@ Patch25033: fanotify-info-leak-in-copy_event_to_user.patch #rhbz 969644 Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch -#rhbz 975995 -Patch25047: drivers-hwmon-nct6775.patch - -Patch25050: iwlwifi-pcie-fix-race-in-queue-unmapping.patch -Patch25051: iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch - #rhbz 903741 Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch @@ -788,38 +768,21 @@ Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch Patch25056: iwl3945-better-skb-management-in-rx-path.patch Patch25057: iwl4965-better-skb-management-in-rx-path.patch -#CVE-2013-2234 rhbz 980995 981007 -Patch25058: af_key-fix-info-leaks-in-notify-messages.patch - -#CVE-2013-2232 rhbz 981552 981564 -Patch25060: ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch - -#rhbz 976789 980643 -Patch25062: vhost-net-fix-use-after-free-in-vhost_net_flush.patch - #rhbz 959721 Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch -#rhbz 986538 -Patch25065: iwlwifi-add-new-pci-id-for-6x35-series.patch - -#CVE-2013-4163 rhbz 987633 987639 -Patch25067: ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch - -#CVE-2013-4162 rhbz 987627 987656 -Patch25068: ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch - -Patch26000: cve-2013-4125.patch - #rhbz 979581 Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch +#rhbz 989093 +Patch25071: drm-i915-correctly-restore-fences-with-objects-attac.patch + #rhbz 977053 Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch @@ -1373,10 +1336,6 @@ ApplyPatch taint-vbox.patch ApplyPatch vmbugon-warnon.patch -ApplyPatch debug-bad-pte-dmi.patch -ApplyPatch debug-bad-pte-modules.patch - - # Architecture patches # x86(-64) @@ -1384,9 +1343,7 @@ ApplyPatch debug-bad-pte-modules.patch # ARM # ApplyPatch arm-export-read_current_timer.patch -ApplyPatch arm-omap-ehci-fix.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch -ApplyPatch arm-tegra-fixclk.patch # # bugfixes to drivers and filesystems @@ -1451,7 +1408,7 @@ ApplyPatch silence-fbcon-logo.patch ApplyPatch crash-driver.patch # secure boot -ApplyPatch secure-boot-20130506.patch +ApplyPatch devel-pekey-secure-boot-20130502.patch # Assorted Virt Fixes @@ -1504,15 +1461,6 @@ ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch -#rhbz 916544 -ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch - -#rhbz 921500 -ApplyPatch i7300_edac_single_mode_fixup.patch - -#rhbz 859282 -ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch - #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch @@ -1531,12 +1479,6 @@ ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch #rhbz 969644 ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch -#rhbz 975995 -ApplyPatch drivers-hwmon-nct6775.patch - -ApplyPatch iwlwifi-pcie-fix-race-in-queue-unmapping.patch -ApplyPatch iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch - #rhbz 903741 ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch @@ -1554,38 +1496,21 @@ ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch ApplyPatch iwl3945-better-skb-management-in-rx-path.patch ApplyPatch iwl4965-better-skb-management-in-rx-path.patch -#CVE-2013-2234 rhbz 980995 981007 -ApplyPatch af_key-fix-info-leaks-in-notify-messages.patch - -#CVE-2013-2232 rhbz 981552 981564 -ApplyPatch ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch - -#rhbz 976789 980643 -ApplyPatch vhost-net-fix-use-after-free-in-vhost_net_flush.patch - #rhbz 959721 ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch #rhbz 885407 ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch -ApplyPatch cve-2013-4125.patch - -#rhbz 986538 -ApplyPatch iwlwifi-add-new-pci-id-for-6x35-series.patch - -#CVE-2013-4163 rhbz 987633 987639 -ApplyPatch ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch - -#CVE-2013-4162 rhbz 987627 987656 -ApplyPatch ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch - #rhbz 979581 ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch +#rhbz 989093 +ApplyPatch drm-i915-correctly-restore-fences-with-objects-attac.patch + #rhbz 977053 ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch @@ -2439,6 +2364,26 @@ fi # ||----w | # || || %changelog +* Thu Aug 01 2013 Justin M. Forbes +- Rebase to 3.10.4 + dropped: + debug-bad-pte-dmi.patch + debug-bad-pte-modules.patch + VMX-x86-handle-host-TSC-calibration-failure.patch + ipv6-ip6_sk_dst_check-must-not-assume-ipv6-dst.patch + af_key-fix-info-leaks-in-notify-messages.patch + arm-tegra-fixclk.patch + vhost-net-fix-use-after-free-in-vhost_net_flush.patch + 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch + i7300_edac_single_mode_fixup.patch + drivers-hwmon-nct6775.patch + iwlwifi-pcie-fix-race-in-queue-unmapping.patch + iwlwifi-pcie-wake-the-queue-if-stopped-when-being-unmapped.patch + cve-2013-4125.patch + iwlwifi-add-new-pci-id-for-6x35-series.patch + ipv6-ip6_append_data_mtu-did-not-care-about-pmtudisc-and_frag_size.patch + ipv6-call-udp_push_pending_frames-when-uncorking-a-socket-with-AF_INET-pending-data.patch + * Thu Aug 01 2013 Josh Boyer - Fix mac80211 connection issues (rhbz 981445) - Fix firmware issues with iwl4965 and rfkill (rhbz 977053) diff --git a/secure-boot-20130506.patch b/secure-boot-20130506.patch deleted file mode 100644 index f2267f23a..000000000 --- a/secure-boot-20130506.patch +++ /dev/null @@ -1,1474 +0,0 @@ -From 5b93084a9e220fb63d549c0acba389dc39c12ea5 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/19] Secure boot: Add new capability - -Secure boot adds certain policy requirements, including that root must not -be able to do anything that could cause the kernel to execute arbitrary code. -The simplest way to handle this would seem to be to add a new capability -and gate various functionality on that. We'll then strip it from the initial -capability set if required. - -Signed-off-by: Matthew Garrett ---- - include/uapi/linux/capability.h | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h -index ba478fa..7109e65 100644 ---- a/include/uapi/linux/capability.h -+++ b/include/uapi/linux/capability.h -@@ -343,7 +343,11 @@ struct vfs_cap_data { - - #define CAP_BLOCK_SUSPEND 36 - --#define CAP_LAST_CAP CAP_BLOCK_SUSPEND -+/* Allow things that trivially permit root to modify the running kernel */ -+ -+#define CAP_COMPROMISE_KERNEL 37 -+ -+#define CAP_LAST_CAP CAP_COMPROMISE_KERNEL - - #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) - --- -1.8.1.4 - - -From 01cd96f927fd11fd43ba4631bd7a314e09ca9939 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability - -Add the name of the new Secure Boot capability. This allows SELinux -policies to properly map CAP_COMPROMISE_KERNEL to the appropriate -capability class. - -Signed-off-by: Josh Boyer ---- - security/selinux/include/classmap.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index 14d04e6..ed99a2d 100644 ---- a/security/selinux/include/classmap.h -+++ b/security/selinux/include/classmap.h -@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { - { "memprotect", { "mmap_zero", NULL } }, - { "peer", { "recv", NULL } }, - { "capability2", -- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", -- NULL } }, -+ { "mac_override", "mac_admin", "syslog", "wake_alarm", -+ "block_suspend", "compromise_kernel", NULL } }, - { "kernel_service", { "use_as_override", "create_files_as", NULL } }, - { "tun_socket", - { COMMON_SOCK_PERMS, "attach_queue", NULL } }, --- -1.8.1.4 - - -From aabe98772f0b63652df87a2dd566ad2e66fbe14f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will - switch on Secure Boot mode - -This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset -in the init_cred struct, which everything else inherits from. This works on -any machine and can be used to develop even if the box doesn't have UEFI. - -Signed-off-by: Josh Boyer ---- - Documentation/kernel-parameters.txt | 7 +++++++ - kernel/cred.c | 17 +++++++++++++++++ - 2 files changed, 24 insertions(+) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 8ccbf27..5bd14a4 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -2706,6 +2706,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - Note: increases power consumption, thus should only be - enabled if running jitter sensitive (HPC/RT) workloads. - -+ secureboot_enable= -+ [KNL] Enables an emulated UEFI Secure Boot mode. This -+ locks down various aspects of the kernel guarded by the -+ CAP_COMPROMISE_KERNEL capability. This includes things -+ like /dev/mem, IO port access, and other areas. It can -+ be used on non-UEFI machines for testing purposes. -+ - security= [SECURITY] Choose a security module to enable at boot. - If this boot parameter is not specified, only the first - security module asking for security registration will be -diff --git a/kernel/cred.c b/kernel/cred.c -index e0573a4..c3f4e3e 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -565,6 +565,23 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+void __init secureboot_enable() -+{ -+ pr_info("Secure boot enabled\n"); -+ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); -+ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+} -+ -+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -+static int __init secureboot_enable_opt(char *str) -+{ -+ int sb_enable = !!simple_strtol(str, NULL, 0); -+ if (sb_enable) -+ secureboot_enable(); -+ return 1; -+} -+__setup("secureboot_enable=", secureboot_enable_opt); -+ - /** - * prepare_kernel_cred - Prepare a set of credentials for a kernel service - * @daemon: A userspace daemon to be used as a reference --- -1.8.1.4 - - -From 76de11cca755aca928ed2f6b6c99ffc3328cde13 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when - enabled in firmware - -The firmware has a set of flags that indicate whether secure boot is enabled -and enforcing. Use them to indicate whether the kernel should lock itself -down. We also indicate the machine is in secure boot mode by adding the -EFI_SECURE_BOOT bit for use with efi_enabled. - -Signed-off-by: Matthew Garrett -Signed-off-by: Josh Boyer ---- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ - arch/x86/include/asm/bootparam_utils.h | 8 ++++++-- - arch/x86/include/uapi/asm/bootparam.h | 3 ++- - arch/x86/kernel/setup.c | 7 +++++++ - include/linux/cred.h | 2 ++ - include/linux/efi.h | 1 + - 7 files changed, 52 insertions(+), 3 deletions(-) - -diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt -index 199f453..ff651d3 100644 ---- a/Documentation/x86/zero-page.txt -+++ b/Documentation/x86/zero-page.txt -@@ -30,6 +30,8 @@ Offset Proto Name Meaning - 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) - 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer - (below) -+1EB/001 ALL kbd_status Numlock is enabled -+1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns - 1EF/001 ALL sentinel Used to detect broken bootloaders - 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures - 2D0/A00 ALL e820_map E820 memory map table -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 35ee62f..0998ec7 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -906,6 +906,36 @@ fail: - return status; - } - -+static int get_secure_boot(efi_system_table_t *_table) -+{ -+ u8 sb, setup; -+ unsigned long datasize = sizeof(sb); -+ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; -+ efi_status_t status; -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SecureBoot", &var_guid, NULL, &datasize, &sb); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (sb == 0) -+ return 0; -+ -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SetupMode", &var_guid, NULL, &datasize, -+ &setup); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (setup == 1) -+ return 0; -+ -+ return 1; -+} -+ - /* - * Because the x86 boot code expects to be passed a boot_params we - * need to create one ourselves (usually the bootloader would create -@@ -1200,6 +1230,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, - if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) - goto fail; - -+ boot_params->secure_boot = get_secure_boot(sys_table); -+ - setup_graphics(boot_params); - - setup_efi_vars(boot_params); -diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h -index 653668d..7856ca7 100644 ---- a/arch/x86/include/asm/bootparam_utils.h -+++ b/arch/x86/include/asm/bootparam_utils.h -@@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params) - memset(&boot_params->olpc_ofw_header, 0, - (char *)&boot_params->efi_info - - (char *)&boot_params->olpc_ofw_header); -- memset(&boot_params->kbd_status, 0, -+ memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status)); -+ /* don't clear boot_params->secure_boot. we set that ourselves -+ * earlier. -+ */ -+ memset(&boot_params->_pad5[0], 0, - (char *)&boot_params->hdr - -- (char *)&boot_params->kbd_status); -+ (char *)&boot_params->_pad5[0]); - memset(&boot_params->_pad7[0], 0, - (char *)&boot_params->edd_mbr_sig_buffer[0] - - (char *)&boot_params->_pad7[0]); -diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h -index 0874424..56b7d39 100644 ---- a/arch/x86/include/uapi/asm/bootparam.h -+++ b/arch/x86/include/uapi/asm/bootparam.h -@@ -132,7 +132,8 @@ struct boot_params { - __u8 eddbuf_entries; /* 0x1e9 */ - __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ - __u8 kbd_status; /* 0x1eb */ -- __u8 _pad5[3]; /* 0x1ec */ -+ __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad5[2]; /* 0x1ed */ - /* - * The sentinel is set to a nonzero value (0xff) in header.S. - * -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index fae9134..b7465a5 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -1133,6 +1133,13 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -+ if (boot_params.secure_boot) { -+#ifdef CONFIG_EFI -+ set_bit(EFI_SECURE_BOOT, &x86_efi_facility); -+#endif -+ secureboot_enable(); -+ } -+ - /* - * Parse the ACPI tables for possible boot-time SMP configuration. - */ -diff --git a/include/linux/cred.h b/include/linux/cred.h -index 04421e8..9e69542 100644 ---- a/include/linux/cred.h -+++ b/include/linux/cred.h -@@ -156,6 +156,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); - extern int set_create_files_as(struct cred *, struct inode *); - extern void __init cred_init(void); - -+extern void secureboot_enable(void); -+ - /* - * check for validity of credentials - */ -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 3d7df3d..178b32c 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *); - #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ - #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ - #define EFI_64BIT 5 /* Is the firmware 64-bit? */ -+#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */ - - #ifdef CONFIG_EFI - # ifdef CONFIG_X86 --- -1.8.1.4 - - -From cd3b94aed727f9f77901e319058f2bc7257e64c8 Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 05/19] Add EFI signature data types - -Add the data types that are used for containing hashes, keys and certificates -for cryptographic verification. - -Signed-off-by: David Howells ---- - include/linux/efi.h | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 178b32c..77373a7 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si - #define EFI_FILE_SYSTEM_GUID \ - EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -+#define EFI_CERT_SHA256_GUID \ -+ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) -+ -+#define EFI_CERT_X509_GUID \ -+ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -@@ -524,6 +530,20 @@ typedef struct { - - #define EFI_INVALID_TABLE_ADDR (~0UL) - -+typedef struct { -+ efi_guid_t signature_owner; -+ u8 signature_data[]; -+} efi_signature_data_t; -+ -+typedef struct { -+ efi_guid_t signature_type; -+ u32 signature_list_size; -+ u32 signature_header_size; -+ u32 signature_size; -+ u8 signature_header[]; -+ /* efi_signature_data_t signatures[][] */ -+} efi_signature_list_t; -+ - /* - * All runtime access to EFI goes through this structure: - */ --- -1.8.1.4 - - -From 62e8fff1a3d879c9377f3e8b9bb3aac2bc115b5f Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader. - -X.509 certificates are loaded into the specified keyring as asymmetric type -keys. - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Kconfig | 8 +++ - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++ - include/linux/efi.h | 4 ++ - 4 files changed, 121 insertions(+) - create mode 100644 crypto/asymmetric_keys/efi_parser.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 6d2c2ea..ace9c30 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER - data and provides the ability to instantiate a crypto key from a - public key packet found inside the certificate. - -+config EFI_SIGNATURE_LIST_PARSER -+ bool "EFI signature list parser" -+ depends on EFI -+ select X509_CERTIFICATE_PARSER -+ help -+ This option provides support for parsing EFI signature lists for -+ X.509 certificates and turning them into keys. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 0727204..cd8388e 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o - - # - # X.509 Certificate handling -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c -new file mode 100644 -index 0000000..636feb1 ---- /dev/null -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -0,0 +1,108 @@ -+/* EFI signature/key/certificate list parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "EFI: "fmt -+#include -+#include -+#include -+#include -+#include -+ -+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; -+ -+/** -+ * parse_efi_signature_list - Parse an EFI signature list for certificates -+ * @data: The data blob to parse -+ * @size: The size of the data blob -+ * @keyring: The keyring to add extracted keys to -+ */ -+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) -+{ -+ unsigned offs = 0; -+ size_t lsize, esize, hsize, elsize; -+ -+ pr_devel("-->%s(,%zu)\n", __func__, size); -+ -+ while (size > 0) { -+ efi_signature_list_t list; -+ const efi_signature_data_t *elem; -+ key_ref_t key; -+ -+ if (size < sizeof(list)) -+ return -EBADMSG; -+ -+ memcpy(&list, data, sizeof(list)); -+ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", -+ offs, -+ list.signature_type.b, list.signature_list_size, -+ list.signature_header_size, list.signature_size); -+ -+ lsize = list.signature_list_size; -+ hsize = list.signature_header_size; -+ esize = list.signature_size; -+ elsize = lsize - sizeof(list) - hsize; -+ -+ if (lsize > size) { -+ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", -+ __func__, offs); -+ return -EBADMSG; -+ } -+ if (lsize < sizeof(list) || -+ lsize - sizeof(list) < hsize || -+ esize < sizeof(*elem) || -+ elsize < esize || -+ elsize % esize != 0) { -+ pr_devel("- bad size combo @%x\n", offs); -+ return -EBADMSG; -+ } -+ -+ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { -+ data += lsize; -+ size -= lsize; -+ offs += lsize; -+ continue; -+ } -+ -+ data += sizeof(list) + hsize; -+ size -= sizeof(list) + hsize; -+ offs += sizeof(list) + hsize; -+ -+ for (; elsize > 0; elsize -= esize) { -+ elem = data; -+ -+ pr_devel("ELEM[%04x]\n", offs); -+ -+ key = key_create_or_update( -+ make_key_ref(keyring, 1), -+ "asymmetric", -+ NULL, -+ &elem->signature_data, -+ esize - sizeof(*elem), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ -+ if (IS_ERR(key)) -+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("Loaded cert '%s' linked to '%s'\n", -+ key_ref_to_ptr(key)->description, -+ keyring->description); -+ -+ data += esize; -+ size -= esize; -+ offs += esize; -+ } -+ } -+ -+ return 0; -+} -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 77373a7..9dab408 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); - extern void efi_reserve_boot_services(void); - extern struct efi_memory_map memmap; - -+struct key; -+extern int __init parse_efi_signature_list(const void *data, size_t size, -+ struct key *keyring); -+ - /** - * efi_range_is_wc - check the WC bit on an address range - * @start: starting kvirt address --- -1.8.1.4 - - -From 7a798ef2fea17b56c4769c9c942d678dd8341fd3 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring - -This adds an additional keyring that is used to store certificates that -are blacklisted. This keyring is searched first when loading signed modules -and if the module's certificate is found, it will refuse to load. This is -useful in cases where third party certificates are used for module signing. - -Signed-off-by: Josh Boyer ---- - init/Kconfig | 8 ++++++++ - kernel/modsign_pubkey.c | 14 ++++++++++++++ - kernel/module-internal.h | 3 +++ - kernel/module_signing.c | 12 ++++++++++++ - 4 files changed, 37 insertions(+) - -diff --git a/init/Kconfig b/init/Kconfig -index 5341d72..9fa68df 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1679,6 +1679,14 @@ config MODULE_SIG_ALL - comment "Do not forget to sign required modules with scripts/sign-file" - depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL - -+config MODULE_SIG_BLACKLIST -+ bool "Support for blacklisting module signature certificates" -+ depends on MODULE_SIG -+ help -+ This adds support for keeping a blacklist of certificates that -+ should not pass module signature verification. If a module is -+ signed with something in this keyring, the load will be rejected. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 2b6e699..4cd408d 100644 ---- a/kernel/modsign_pubkey.c -+++ b/kernel/modsign_pubkey.c -@@ -17,6 +17,9 @@ - #include "module-internal.h" - - struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+struct key *modsign_blacklist; -+#endif - - extern __initdata const u8 modsign_certificate_list[]; - extern __initdata const u8 modsign_certificate_list_end[]; -@@ -43,6 +46,17 @@ static __init int module_verify_init(void) - if (IS_ERR(modsign_keyring)) - panic("Can't allocate module signing keyring\n"); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ modsign_blacklist = keyring_alloc(".modsign_blacklist", -+ KUIDT_INIT(0), KGIDT_INIT(0), -+ current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA, NULL); -+ if (IS_ERR(modsign_blacklist)) -+ panic("Can't allocate module signing blacklist keyring\n"); -+#endif -+ - return 0; - } - -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 24f9247..51a8380 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -10,5 +10,8 @@ - */ - - extern struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+extern struct key *modsign_blacklist; -+#endif - - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index f2970bd..5423195 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - - pr_debug("Look up: \"%s\"\n", id); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ key = keyring_search(make_key_ref(modsign_blacklist, 1), -+ &key_type_asymmetric, id); -+ if (!IS_ERR(key)) { -+ /* module is signed with a cert in the blacklist. reject */ -+ pr_err("Module key '%s' is in blacklist\n", id); -+ key_ref_put(key); -+ kfree(id); -+ return ERR_PTR(-EKEYREJECTED); -+ } -+#endif -+ - key = keyring_search(make_key_ref(modsign_keyring, 1), - &key_type_asymmetric, id); - if (IS_ERR(key)) --- -1.8.1.4 - - -From a245b231b8d61f9c12c389043c77c390d0f3c23d Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot - -Secure Boot stores a list of allowed certificates in the 'db' variable. -This imports those certificates into the module signing keyring. This -allows for a third party signing certificate to be used in conjunction -with signed modules. By importing the public certificate into the 'db' -variable, a user can allow a module signed with that certificate to -load. The shim UEFI bootloader has a similar certificate list stored -in the 'MokListRT' variable. We import those as well. - -In the opposite case, Secure Boot maintains a list of disallowed -certificates in the 'dbx' variable. We load those certificates into -the newly introduced module blacklist keyring and forbid any module -signed with those from loading. - -Signed-off-by: Josh Boyer ---- - include/linux/efi.h | 6 ++++ - init/Kconfig | 9 ++++++ - kernel/Makefile | 3 ++ - kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 108 insertions(+) - create mode 100644 kernel/modsign_uefi.c - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 9dab408..b1a1809 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si - #define EFI_CERT_X509_GUID \ - EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) - -+#define EFI_IMAGE_SECURITY_DATABASE_GUID \ -+ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) -+ -+#define EFI_SHIM_LOCK_GUID \ -+ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -diff --git a/init/Kconfig b/init/Kconfig -index 9fa68df..606295c 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1687,6 +1687,15 @@ config MODULE_SIG_BLACKLIST - should not pass module signature verification. If a module is - signed with something in this keyring, the load will be rejected. - -+config MODULE_SIG_UEFI -+ bool "Allow modules signed with certs stored in UEFI" -+ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI -+ select EFI_SIGNATURE_LIST_PARSER -+ help -+ This will import certificates stored in UEFI and allow modules -+ signed with those to be loaded. It will also disallow loading -+ of modules stored in the UEFI dbx variable. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/Makefile b/kernel/Makefile -index bbde5f1..d102fb2 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -53,6 +53,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o -+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -112,6 +113,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o - - $(obj)/configs.o: $(obj)/config_data.h - -+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar -+ - # config_data.h contains the same information as ikconfig.h but gzipped. - # Info from config_data can be extracted from /proc/config* - targets += config_data.gz -diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c -new file mode 100644 -index 0000000..b9237d7 ---- /dev/null -+++ b/kernel/modsign_uefi.c -@@ -0,0 +1,90 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "module-internal.h" -+ -+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) -+{ -+ efi_status_t status; -+ unsigned long lsize = 4; -+ unsigned long tmpdb[4]; -+ void *db = NULL; -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); -+ if (status != EFI_BUFFER_TOO_SMALL) { -+ pr_err("Couldn't get size: 0x%lx\n", status); -+ return NULL; -+ } -+ -+ db = kmalloc(lsize, GFP_KERNEL); -+ if (!db) { -+ pr_err("Couldn't allocate memory for uefi cert list\n"); -+ goto out; -+ } -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, db); -+ if (status != EFI_SUCCESS) { -+ kfree(db); -+ db = NULL; -+ pr_err("Error reading db var: 0x%lx\n", status); -+ } -+out: -+ *size = lsize; -+ return db; -+} -+ -+/* -+ * * Load the certs contained in the UEFI databases -+ * */ -+static int __init load_uefi_certs(void) -+{ -+ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; -+ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; -+ void *db = NULL, *dbx = NULL, *mok = NULL; -+ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; -+ int rc = 0; -+ -+ /* Check if SB is enabled and just return if not */ -+ if (!efi_enabled(EFI_SECURE_BOOT)) -+ return 0; -+ -+ /* Get db, MokListRT, and dbx. They might not exist, so it isn't -+ * an error if we can't get them. -+ */ -+ db = get_cert_list(L"db", &secure_var, &dbsize); -+ if (!db) { -+ pr_err("MODSIGN: Couldn't get UEFI db list\n"); -+ } else { -+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse db signatures: %d\n", rc); -+ kfree(db); -+ } -+ -+ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); -+ if (!mok) { -+ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); -+ } else { -+ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); -+ kfree(mok); -+ } -+ -+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); -+ if (!dbx) { -+ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); -+ } else { -+ rc = parse_efi_signature_list(dbx, dbxsize, -+ modsign_blacklist); -+ if (rc) -+ pr_err("Couldn't parse dbx signatures: %d\n", rc); -+ kfree(dbx); -+ } -+ -+ return rc; -+} -+late_initcall(load_uefi_certs); --- -1.8.1.4 - - -From 39e04e6106f21d0440c099fd6911863a0023f52a Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments - -Any hardware that can potentially generate DMA has to be locked down from -userspace in order to avoid it being possible for an attacker to cause -arbitrary kernel behaviour. Default to paranoid - in future we can -potentially relax this for sufficiently IOMMU-isolated devices. - -Signed-off-by: Matthew Garrett - -jwb: Temporarily work around https://bugzilla.redhat.com/show_bug.cgi?id=908888 ---- - drivers/pci/pci-sysfs.c | 16 ++++++++++++++++ - drivers/pci/proc.c | 8 +++++++- - drivers/pci/syscall.c | 2 +- - 3 files changed, 24 insertions(+), 2 deletions(-) - -diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index 9c6e9bb..09c311e 100644 ---- a/drivers/pci/pci-sysfs.c -+++ b/drivers/pci/pci-sysfs.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include "pci.h" - - static int sysfs_initialized; /* = 0 */ -@@ -622,6 +623,11 @@ pci_write_config(struct file* filp, struct kobject *kobj, - loff_t init_off = off; - u8 *data = (u8*) buf; - -+ /* Work around rhbz 908888 for now -+ if (!capable(CAP_COMPROMISE_KERNEL))*/ -+ if (efi_enabled(EFI_SECURE_BOOT)) -+ return -EPERM; -+ - if (off > dev->cfg_size) - return 0; - if (off + count > dev->cfg_size) { -@@ -928,6 +934,11 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, - resource_size_t start, end; - int i; - -+ /* Work around rhbz 908888 for now -+ if (!capable(CAP_COMPROMISE_KERNEL)) */ -+ if (efi_enabled(EFI_SECURE_BOOT)) -+ return -EPERM; -+ - for (i = 0; i < PCI_ROM_RESOURCE; i++) - if (res == &pdev->resource[i]) - break; -@@ -1035,6 +1046,11 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) - { -+ /* Work around rhbz 908888 for now -+ if (!capable(CAP_COMPROMISE_KERNEL)) */ -+ if (efi_enabled(EFI_SECURE_BOOT)) -+ return -EPERM; -+ - return pci_resource_io(filp, kobj, attr, buf, off, count, true); - } - -diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index 0b00947..7639f68 100644 ---- a/drivers/pci/proc.c -+++ b/drivers/pci/proc.c -@@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof - int size = dp->size; - int cnt; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (pos >= size) - return 0; - if (nbytes >= size) -@@ -219,6 +222,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, - #endif /* HAVE_PCI_MMAP */ - int ret = 0; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - switch (cmd) { - case PCIIOC_CONTROLLER: - ret = pci_domain_nr(dev->bus); -@@ -259,7 +265,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) - struct pci_filp_private *fpriv = file->private_data; - int i, ret; - -- if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - /* Make sure the caller is mapping a real resource for this device */ -diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c -index e1c1ec5..97e785f 100644 ---- a/drivers/pci/syscall.c -+++ b/drivers/pci/syscall.c -@@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, - u32 dword; - int err = 0; - -- if (!capable(CAP_SYS_ADMIN)) -+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - dev = pci_get_bus_and_slot(bus, dfn); --- -1.8.1.4 - - -From 45e3db2ab117829efd167f96487ea7d6f9e1ea6d Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot - environments - -IO port access would permit users to gain access to PCI configuration -registers, which in turn (on a lot of hardware) give access to MMIO register -space. This would potentially permit root to trigger arbitrary DMA, so lock -it down by default. - -Signed-off-by: Matthew Garrett ---- - arch/x86/kernel/ioport.c | 4 ++-- - drivers/char/mem.c | 3 +++ - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c -index 4ddaf66..f505995 100644 ---- a/arch/x86/kernel/ioport.c -+++ b/arch/x86/kernel/ioport.c -@@ -28,7 +28,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) - - if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) - return -EINVAL; -- if (turn_on && !capable(CAP_SYS_RAWIO)) -+ if (turn_on && (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL))) - return -EPERM; - - /* -@@ -103,7 +103,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) - return -EINVAL; - /* Trying to gain more privileges? */ - if (level > old) { -- if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - } - regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 2c644af..7eee4d8 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, - unsigned long i = *ppos; - const char __user *tmp = buf; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - while (count-- > 0 && i < 65536) { --- -1.8.1.4 - - -From 62cc8b181cd49e047f4999a3e4f65a4f222fb2c9 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 11/19] ACPI: Limit access to custom_method - -It must be impossible for even root to get code executed in kernel context -under a secure boot environment. custom_method effectively allows arbitrary -access to system memory, so it needs to have a capability check here. - -Signed-off-by: Matthew Garrett ---- - drivers/acpi/custom_method.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index 12b62f2..edf0710 100644 ---- a/drivers/acpi/custom_method.c -+++ b/drivers/acpi/custom_method.c -@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, - struct acpi_table_header table; - acpi_status status; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!(*ppos)) { - /* parse the table header to get the table length */ - if (count <= sizeof(struct acpi_table_header)) --- -1.8.1.4 - - -From b11830a03ddfa478ad5a73a88067a2a7d55dce5b Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface - -We have no way of validating what all of the Asus WMI methods do on a -given machine, and there's a risk that some will allow hardware state to -be manipulated in such a way that arbitrary code can be executed in the -kernel. Add a capability check to prevent that. - -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/asus-wmi.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c11b242..6d5f88f 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -1617,6 +1617,9 @@ static int show_dsts(struct seq_file *m, void *data) - int err; - u32 retval = -1; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); - - if (err < 0) -@@ -1633,6 +1636,9 @@ static int show_devs(struct seq_file *m, void *data) - int err; - u32 retval = -1; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, - &retval); - -@@ -1657,6 +1663,9 @@ static int show_call(struct seq_file *m, void *data) - union acpi_object *obj; - acpi_status status; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, - 1, asus->debug.method_id, - &input, &output); --- -1.8.1.4 - - -From 0d64b3972b75e420cddde5ba5c85f98046774450 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups - -Allowing users to write to address space makes it possible for the kernel -to be subverted. Restrict this when we need to protect the kernel. - -Signed-off-by: Matthew Garrett ---- - drivers/char/mem.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 7eee4d8..772ee2b 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, - unsigned long copied; - void *ptr; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!valid_phys_addr_range(p, count)) - return -EFAULT; - -@@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, - char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ - int err = 0; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (p < (unsigned long) high_memory) { - unsigned long to_write = min_t(unsigned long, count, - (unsigned long)high_memory - p); --- -1.8.1.4 - - -From 9f39d364fb1b8270a85ad9541710d4a7dd3bc0b5 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure - boot environment - -This option allows userspace to pass the RSDP address to the kernel. This -could potentially be used to circumvent the secure boot trust model. -This is setup through the setup_arch function, which is called before the -security_init function sets up the security_ops, so we cannot use a -capable call here. We ignore the setting if we are booted in Secure Boot -mode. - -Signed-off-by: Josh Boyer ---- - drivers/acpi/osl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 586e7e9..8950454 100644 ---- a/drivers/acpi/osl.c -+++ b/drivers/acpi/osl.c -@@ -245,7 +245,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); - acpi_physical_address __init acpi_os_get_root_pointer(void) - { - #ifdef CONFIG_KEXEC -- if (acpi_rsdp) -+ if (acpi_rsdp && !efi_enabled(EFI_SECURE_BOOT)) - return acpi_rsdp; - #endif - --- -1.8.1.4 - - -From c06f86d634932ceb788e9d883346e2d5e4117f52 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 15/19] kexec: Disable in a secure boot environment - -kexec could be used as a vector for a malicious user to use a signed kernel -to circumvent the secure boot trust model. In the long run we'll want to -support signed kexec payloads, but for the moment we should just disable -loading entirely in that situation. - -Signed-off-by: Matthew Garrett ---- - kernel/kexec.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kernel/kexec.c b/kernel/kexec.c -index ffd4e11..e276744 100644 ---- a/kernel/kexec.c -+++ b/kernel/kexec.c -@@ -946,7 +946,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, - int result; - - /* We only trust the superuser with rebooting the system. */ -- if (!capable(CAP_SYS_BOOT)) -+ if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - /* --- -1.8.1.4 - - -From 3555227817a9adbed51995104f4aeae4c6c36be9 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot - environment - -If a machine is booted into a Secure Boot environment, we need to -protect the trust model. This requires that all modules be signed -with a key that is in the kernel's _modsign keyring. The checks for -this are already done via the 'sig_enforce' module parameter. Make -this visible within the kernel and force it to be true. - -Signed-off-by: Josh Boyer ---- - kernel/cred.c | 8 ++++++++ - kernel/module.c | 4 ++-- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/kernel/cred.c b/kernel/cred.c -index c3f4e3e..c5554e0 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -565,11 +565,19 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+#ifdef CONFIG_MODULE_SIG -+extern bool sig_enforce; -+#endif -+ - void __init secureboot_enable() - { - pr_info("Secure boot enabled\n"); - cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); - cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+#ifdef CONFIG_MODULE_SIG -+ /* Enable module signature enforcing */ -+ sig_enforce = true; -+#endif - } - - /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -diff --git a/kernel/module.c b/kernel/module.c -index 0925c9a..af4a476 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - - #ifdef CONFIG_MODULE_SIG - #ifdef CONFIG_MODULE_SIG_FORCE --static bool sig_enforce = true; -+bool sig_enforce = true; - #else --static bool sig_enforce = false; -+bool sig_enforce = false; - - static int param_set_bool_enable_only(const char *val, - const struct kernel_param *kp) --- -1.8.1.4 - - -From 844991aad05c36af54bf4540a71e2f5430da444f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment - -There is currently no way to verify the resume image when returning -from hibernate. This might compromise the secure boot trust model, -so until we can work with signed hibernate images we disable it in -a Secure Boot environment. - -Signed-off-by: Josh Boyer ---- - kernel/power/hibernate.c | 15 ++++++++++++++- - kernel/power/main.c | 7 ++++++- - kernel/power/user.c | 3 +++ - 3 files changed, 23 insertions(+), 2 deletions(-) - -diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index b26f5f1..7f63cb4 100644 ---- a/kernel/power/hibernate.c -+++ b/kernel/power/hibernate.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include "power.h" - -@@ -632,6 +633,10 @@ int hibernate(void) - { - int error; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) { -+ return -EPERM; -+ } -+ - lock_system_sleep(); - /* The snapshot device should not be opened while we're running */ - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -@@ -723,7 +728,7 @@ static int software_resume(void) - /* - * If the user said "noresume".. bail out early. - */ -- if (noresume) -+ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) - return 0; - - /* -@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, - int i; - char *start = buf; - -+ if (efi_enabled(EFI_SECURE_BOOT)) { -+ buf += sprintf(buf, "[%s]\n", "disabled"); -+ return buf-start; -+ } -+ - for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { - if (!hibernation_modes[i]) - continue; -@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, - char *p; - int mode = HIBERNATION_INVALID; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - p = memchr(buf, '\n', n); - len = p ? p - buf : n; - -diff --git a/kernel/power/main.c b/kernel/power/main.c -index d77663b..78f8ed5 100644 ---- a/kernel/power/main.c -+++ b/kernel/power/main.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #include "power.h" - -@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, - } - #endif - #ifdef CONFIG_HIBERNATION -- s += sprintf(s, "%s\n", "disk"); -+ if (!efi_enabled(EFI_SECURE_BOOT)) { -+ s += sprintf(s, "%s\n", "disk"); -+ } else { -+ s += sprintf(s, "\n"); -+ } - #else - if (s != buf) - /* convert the last space to a newline */ -diff --git a/kernel/power/user.c b/kernel/power/user.c -index 4ed81e7..b11a0f4 100644 ---- a/kernel/power/user.c -+++ b/kernel/power/user.c -@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) - struct snapshot_data *data; - int error; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - lock_system_sleep(); - - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { --- -1.8.1.4 - - -From 6f6d20668d3294e6a29d01a13a7415a542cb6413 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 5 Feb 2013 19:25:05 -0500 -Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode - -A user can manually tell the shim boot loader to disable validation of -images it loads. When a user does this, it creates a UEFI variable called -MokSBState that does not have the runtime attribute set. Given that the -user explicitly disabled validation, we can honor that and not enable -secure boot mode if that variable is set. - -Signed-off-by: Josh Boyer ---- - arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 0998ec7..4945ee5 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -908,8 +908,9 @@ fail: - - static int get_secure_boot(efi_system_table_t *_table) - { -- u8 sb, setup; -+ u8 sb, setup, moksbstate; - unsigned long datasize = sizeof(sb); -+ u32 attr; - efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; - efi_status_t status; - -@@ -933,6 +934,23 @@ static int get_secure_boot(efi_system_table_t *_table) - if (setup == 1) - return 0; - -+ /* See if a user has put shim into insecure_mode. If so, and the variable -+ * doesn't have the runtime attribute set, we might as well honor that. -+ */ -+ var_guid = EFI_SHIM_LOCK_GUID; -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"MokSBState", &var_guid, &attr, &datasize, -+ &moksbstate); -+ -+ /* If it fails, we don't care why. Default to secure */ -+ if (status != EFI_SUCCESS) -+ return 1; -+ -+ if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) { -+ if (moksbstate == 1) -+ return 0; -+ } -+ - return 1; - } - --- -1.8.1.4 - - -From 53afc5a04d5b0fbdad1e4a34fbbecfdb5ff2f6dd Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Fri, 8 Feb 2013 11:12:13 -0800 -Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot - -Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is -set since it could lead to execution of arbitrary code in kernel mode. - -Signed-off-by: Kees Cook ---- - arch/x86/kernel/msr.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c -index ce13049..fa4dc6c 100644 ---- a/arch/x86/kernel/msr.c -+++ b/arch/x86/kernel/msr.c -@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, - int err = 0; - ssize_t bytes = 0; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (count % 8) - return -EINVAL; /* Invalid chunk size */ - -@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) - err = -EBADF; - break; - } -+ if (!capable(CAP_COMPROMISE_KERNEL)) { -+ err = -EPERM; -+ break; -+ } - if (copy_from_user(®s, uregs, sizeof regs)) { - err = -EFAULT; - break; --- -1.8.1.4 - diff --git a/sources b/sources index 5947c8bcb..a87e5a10a 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz -552146435b7ecc414bf8e3cd8bb6ac4a patch-3.9.11.xz +4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz +2e46ab138670b3171b52b849568cb42f patch-3.10.4.xz diff --git a/vhost-net-fix-use-after-free-in-vhost_net_flush.patch b/vhost-net-fix-use-after-free-in-vhost_net_flush.patch deleted file mode 100644 index f9a6a7b9f..000000000 --- a/vhost-net-fix-use-after-free-in-vhost_net_flush.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0c9d7f6ea817d5328a09a78e901b16e1836ca4d7 Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Tue, 25 Jun 2013 17:29:46 +0300 -Subject: [PATCH] vhost-net: fix use-after-free in vhost_net_flush - -vhost_net_ubuf_put_and_wait has a confusing name: -it will actually also free it's argument. -Thus since commit 1280c27f8e29acf4af2da914e80ec27c3dbd5c01 - "vhost-net: flush outstanding DMAs on memory change" -vhost_net_flush tries to use the argument after passing it -to vhost_net_ubuf_put_and_wait, this results -in use after free. -To fix, don't free the argument in vhost_net_ubuf_put_and_wait, -add an new API for callers that want to free ubufs. - -Acked-by: Asias He -Acked-by: Jason Wang -Signed-off-by: Michael S. Tsirkin ---- - drivers/vhost/net.c | 4 ++-- - drivers/vhost/vhost.c | 5 +++++ - drivers/vhost/vhost.h | 1 + - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c -index dfff647..d8d4f57 100644 ---- a/drivers/vhost/net.c -+++ b/drivers/vhost/net.c -@@ -857,7 +857,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) - mutex_unlock(&vq->mutex); - - if (oldubufs) { -- vhost_ubuf_put_and_wait(oldubufs); -+ vhost_ubuf_put_wait_and_free(oldubufs); - mutex_lock(&vq->mutex); - vhost_zerocopy_signal_used(n, vq); - mutex_unlock(&vq->mutex); -@@ -875,7 +875,7 @@ err_used: - rcu_assign_pointer(vq->private_data, oldsock); - vhost_net_enable_vq(n, vq); - if (ubufs) -- vhost_ubuf_put_and_wait(ubufs); -+ vhost_ubuf_put_wait_and_free(ubufs); - err_ubufs: - fput(sock->file); - err_vq: -diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c -index 9759249..ff53c9e 100644 ---- a/drivers/vhost/vhost.c -+++ b/drivers/vhost/vhost.c -@@ -1581,5 +1581,10 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) - { - kref_put(&ubufs->kref, vhost_zerocopy_done_signal); - wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); -+} -+ -+void vhost_ubuf_put_wait_and_free(struct vhost_ubuf_ref *ubufs) -+{ -+ vhost_ubuf_put_and_wait(ubufs); - kfree(ubufs); - } -diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h -index 17261e2..dd63b35 100644 ---- a/drivers/vhost/vhost.h -+++ b/drivers/vhost/vhost.h -@@ -63,6 +63,7 @@ struct vhost_ubuf_ref { - struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy); - void vhost_ubuf_put(struct vhost_ubuf_ref *); - void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *); -+void vhost_ubuf_put_wait_and_free(struct vhost_ubuf_ref *); - - struct ubuf_info; - --- -1.8.2.1 - From 07ec8863b586f50149a48c3a536215a9ced6e956 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 1 Aug 2013 12:39:35 -0500 Subject: [PATCH 387/492] Update s390x config --- config-s390x | 36 +++++++++++++++++++++++++++++++----- kernel.spec | 3 +++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/config-s390x b/config-s390x index 9ab57f8aa..ec4fd04e5 100644 --- a/config-s390x +++ b/config-s390x @@ -38,6 +38,7 @@ CONFIG_CMM=m CONFIG_CMM_PROC=y # CONFIG_NETIUCV is not set CONFIG_SMSGIUCV=m +CONFIG_CRASH_DUMP=y # # SCSI low-level drivers @@ -250,21 +251,35 @@ CONFIG_SCM_BLOCK=m CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_S390_PTDUMP is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set -CONFIG_PCI_NR_FUNCTIONS=64 -CONFIG_HOTPLUG_PCI=m -# CONFIG_HOTPLUG_PCI_CPCI is not set -# CONFIG_HOTPLUG_PCI_SHPC is not set -CONFIG_HOTPLUG_PCI_S390=m +# CONFIG_PCI is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_SGI_IOC4 is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_HID is not set + +# CONFIG_INPUT is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# CONFIG_ACCESSIBILITY is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_STAGING is not set +# CONFIG_MEMSTICK is not set # CONFIG_MEDIA_SUPPORT is not set # CONFIG_USB_SUPPORT is not set # CONFIG_DRM is not set # CONFIG_SOUND is not set # CONFIG_DW_DMAC is not set +# CONFIG_I2C is not set # CONFIG_I2C_SMBUS is not set # CONFIG_I2C_STUB is not set # CONFIG_I2C_HELPER_AUTO is not set @@ -272,3 +287,14 @@ CONFIG_HOTPLUG_PCI_S390=m # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_PHYLIB is not set +# CONFIG_ATM_DRIVERS is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_SH_ETH is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_IEEE802154_DRIVERS is not set + +# CONFIG_FMC is not set diff --git a/kernel.spec b/kernel.spec index 9098ef4e9..8c535e22e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2364,6 +2364,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 01 2013 Justin M. Forbes +- Update s390x config + * Thu Aug 01 2013 Justin M. Forbes - Rebase to 3.10.4 dropped: From 39186108a02d57b0d3c1329a7673baa29816884f Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 1 Aug 2013 20:50:20 +0100 Subject: [PATCH 388/492] rebase ARM config --- Makefile.config | 20 +- arm-lpae-ax88796.patch | 21 ++ arm-omap-load-tfp410.patch | 14 + config-arm-generic | 542 +++---------------------------------- config-arm-kirkwood | 527 +++++++++++++++++++++++++++++++++++- config-armv7 | 188 +++++++++++-- config-armv7-generic | 94 +++---- config-armv7-tegra | 108 -------- kernel.spec | 41 +-- 9 files changed, 823 insertions(+), 732 deletions(-) create mode 100644 arm-lpae-ax88796.patch create mode 100644 arm-omap-load-tfp410.patch delete mode 100644 config-armv7-tegra diff --git a/Makefile.config b/Makefile.config index 790ed2444..f8c0cc991 100644 --- a/Makefile.config +++ b/Makefile.config @@ -11,7 +11,6 @@ CONFIGFILES = \ $(CFG)-s390x.config \ $(CFG)-armv5tel-kirkwood.config \ $(CFG)-armv7l.config $(CFG)-armv7hl.config \ - $(CFG)-armv7l-tegra.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-ppc64.config $(CFG)-ppc64p7.config $(CFG)-ppc64-debug.config @@ -33,19 +32,16 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic -temp-armv7-generic: config-armv7-generic temp-generic +temp-arm-generic: config-arm-generic temp-generic + perl merge.pl $^ > $@ + +temp-armv7-generic: config-armv7-generic temp-arm-generic perl merge.pl $^ > $@ temp-armv7: config-armv7 temp-armv7-generic - perl merge.pl $^ > $@ - -temp-armv7-tegra: config-armv7-tegra temp-armv7-generic - perl merge.pl $^ > $@ - -temp-arm-generic: config-arm-generic temp-generic perl merge.pl $^ > $@ -temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic +temp-armv5tel-kirkwood: config-arm-kirkwood temp-generic perl merge.pl $^ > $@ temp-x86-32: config-x86-32-generic config-x86-generic @@ -117,15 +113,9 @@ kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood kernel-$(VERSION)-armv7l.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7-tegra - perl merge.pl $^ arm > $@ - kernel-$(VERSION)-armv7hl.config: /dev/null temp-armv7 perl merge.pl $^ arm > $@ -kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7-tegra - perl merge.pl $^ arm > $@ - kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/arm-lpae-ax88796.patch b/arm-lpae-ax88796.patch new file mode 100644 index 000000000..b1bdc760c --- /dev/null +++ b/arm-lpae-ax88796.patch @@ -0,0 +1,21 @@ +X-Git-Url: http://git.linaro.org/gitweb?p=people%2Fahs3%2Farndale-acpi.git;a=blobdiff_plain;f=drivers%2Fnet%2Fethernet%2F8390%2Fax88796.c;fp=drivers%2Fnet%2Fethernet%2F8390%2Fax88796.c;h=763e575c82bc5d24e1927ad685dfbdd7a0eaa19e;hp=70dba5d01ad3cc8178318f9976a5922894a86859;hb=fe8e7c500d3d25234759351096d457b6e557ebd9;hpb=af28003b46fa7b2c5d7b52e0d4bc8f725a6305f1 + +diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c +index 70dba5d..763e575 100644 +--- a/drivers/net/ethernet/8390/ax88796.c ++++ b/drivers/net/ethernet/8390/ax88796.c +@@ -828,7 +828,14 @@ static int ax_probe(struct platform_device *pdev) + struct ei_device *ei_local; + struct ax_device *ax; + struct resource *irq, *mem, *mem2; ++#ifndef CONFIG_ARM_LPAE ++ /* LPAE breaks this code as __aeabi_uldivmod for 64-bit ++ * is not supported in lib1funcs.s yet ++ */ + unsigned long mem_size, mem2_size = 0; ++#else ++ u32 mem_size, mem2_size = 0; ++#endif + int ret = 0; + + dev = ax__alloc_ei_netdev(sizeof(struct ax_device)); diff --git a/arm-omap-load-tfp410.patch b/arm-omap-load-tfp410.patch new file mode 100644 index 000000000..0f2ba5457 --- /dev/null +++ b/arm-omap-load-tfp410.patch @@ -0,0 +1,14 @@ +diff -urNp linux-3.9.4-300.fc19.armv7hl_orig/drivers/video/omap2/dss/core.c linux-3.9.4-300.fc19.armv7hl/drivers/video/omap2/dss/core.c +--- linux-3.9.4-300.fc19.armv7hl_orig/drivers/video/omap2/dss/core.c 2013-04-28 20:36:01.000000000 -0400 ++++ linux-3.9.4-300.fc19.armv7hl/drivers/video/omap2/dss/core.c 2013-05-31 12:24:07.711334359 -0400 +@@ -596,6 +596,9 @@ static int __init omap_dss_init(void) + { + int r; + ++ /* hack to load panel-tfp410 driver */ ++ request_module("panel-tfp410"); ++ + r = omap_dss_bus_register(); + if (r) + return r; +Binary files linux-3.9.4-300.fc19.armv7hl_orig/drivers/video/omap2/dss/.Makefile.swp and linux-3.9.4-300.fc19.armv7hl/drivers/video/omap2/dss/.Makefile.swp differ diff --git a/config-arm-generic b/config-arm-generic index 7951f541f..efce65434 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -1,507 +1,43 @@ -# Generic ARM config. This is common config options that should be -# enabled on all ARM kernels and hence should be added here -# -# FIXME - we need to add debug/nodebug generic build options -# CONFIG_DEBUG_PER_CPU_MAPS is not set - -# Generic ARM processor options -CONFIG_ARM=y - -CONFIG_ARM_THUMB=y -CONFIG_AEABI=y -CONFIG_VFP=y -CONFIG_ARM_UNWIND=y -# CONFIG_ARCH_MULTI_V7 is not set -# CONFIG_OABI_COMPAT is not set - -CONFIG_SMP=y -CONFIG_NR_CPUS=4 -CONFIG_SMP_ON_UP=y - -CONFIG_ARM_ARCH_TIMER=y - -CONFIG_CMDLINE="" - -# CONFIG_ARM_LPAE is not set -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y -CONFIG_HIGHPTE=y -CONFIG_HW_PERF_EVENTS=y -CONFIG_UACCESS_WITH_MEMCPY=y -# CONFIG_GENERIC_CPUFREQ_CPU0 is not set - -# Generic ARM Errata -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_751472=y -CONFIG_ARM_ERRATA_742230=y -CONFIG_ARM_ERRATA_742231=y -CONFIG_ARM_ERRATA_754327=y -CONFIG_ARM_ERRATA_764369=y -CONFIG_ARM_ERRATA_775420=y -CONFIG_PL310_ERRATA_753970=y - -# Generic ARM config options -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_LOCAL_TIMERS=y - -CONFIG_ATAGS=y -CONFIG_ATAGS_PROC=y - -CONFIG_PL330_DMA=y -CONFIG_AMBA_PL08X=y -CONFIG_PL330_DMA=y -# CONFIG_XIP_KERNEL is not set -# CONFIG_PID_IN_CONTEXTIDR is not set - -# Generic options we want for ARM that aren't defualt -CONFIG_EARLY_PRINTK=y - -CONFIG_HIGHMEM=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y - -CONFIG_RCU_FANOUT=32 - -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set -# CONFIG_CPU_IDLE_GOV_LADDER is not set -CONFIG_CPU_IDLE_GOV_MENU=y - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - -CONFIG_PM=y -CONFIG_PM_STD_PARTITION="" -CONFIG_SUSPEND=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_CPU_TOPOLOGY=y - -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - -# CONFIG_XEN is not set - -CONFIG_PINCTRL=y -CONFIG_PINCONF=y - -CONFIG_COMMON_CLK=y - -CONFIG_THERMAL=y - -CONFIG_ETHERNET=y - -CONFIG_PERF_EVENTS=y -CONFIG_PERF_COUNTERS=y - -CONFIG_CC_STACKPROTECTOR=y - -CONFIG_SECCOMP=y -CONFIG_STRICT_DEVMEM=y - -CONFIG_SPARSE_IRQ=y - -# Generic HW for all ARM platforms -CONFIG_LEDS_GPIO=m - -CONFIG_LBDAF=y - -CONFIG_GPIOLIB=y -CONFIG_RFKILL_GPIO=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -CONFIG_GPIO_GENERIC_PLATFORM=m -CONFIG_PINCTRL_SINGLE=m -CONFIG_POWER_RESET_GPIO=y - -CONFIG_USB_ULPI=y - -CONFIG_SND_ARM=y -CONFIG_SND_ARMAACI=m -CONFIG_SND_SOC=m -CONFIG_SND_DESIGNWARE_I2S=m -CONFIG_SND_SIMPLE_CARD=m -# CONFIG_SND_SOC_CACHE_LZO is not set -CONFIG_SND_SOC_ALL_CODECS=m -CONFIG_SND_SPI=y - -CONFIG_AX88796=m -CONFIG_AX88796_93CX6=y -CONFIG_SMC91X=m -CONFIG_DM9000=m -CONFIG_DM9000_DEBUGLEVEL=4 -# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set -CONFIG_SMC911X=m -CONFIG_SMSC911X=m - -CONFIG_SERIO_AMBAKMI=m -CONFIG_I2C_NOMADIK=m -CONFIG_ARM_SP805_WATCHDOG=m -CONFIG_FB_ARMCLCD=m -CONFIG_FB_SSD1307=m -CONFIG_MPCORE_WATCHDOG=m -CONFIG_BACKLIGHT_PWM=m - -CONFIG_MMC_ARMMMCI=m -CONFIG_MMC_SDHCI_PLTFM=m -CONFIG_MMC_SDHCI_OF=m -CONFIG_MMC_SPI=m -CONFIG_MMC_DW=m -CONFIG_MMC_DW_PLTFM=m -CONFIG_MMC_DW_PCI=m -# CONFIG_MMC_DW_EXYNOS is not set -# CONFIG_MMC_DW_IDMAC is not set -CONFIG_MMC_SDHCI_PXAV3=m -CONFIG_MMC_SDHCI_PXAV2=m - -# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set - -CONFIG_SPI=y -# Generic GPIO options -CONFIG_GENERIC_GPIO=y - -CONFIG_MTD=m -CONFIG_MTD_TESTS=m -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_OF_PARTS=y -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLKDEVS=m -CONFIG_MTD_BLOCK=m -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_MTD_AR7_PARTS is not set -CONFIG_MTD_CFI=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_CFI_UTIL=y -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOC2001PLUS=m -# CONFIG_MTD_DOCPROBE_ADVANCED is not set -CONFIG_MTD_ALAUDA=m -# CONFIG_MTD_ONENAND is not set -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_IMPA7=m -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_PHYSMAP=m -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_M25P80=m -CONFIG_M25PXX_USE_FAST_READ=y -CONFIG_MTD_NAND=m -CONFIG_MTD_NAND_ECC=m -CONFIG_MTD_NAND_IDS=m -# CONFIG_MTD_NAND_CAFE is not set -# CONFIG_MTD_NAND_ECC_SMC is not set -# CONFIG_MTD_NAND_DENALI is not set -# CONFIG_MTD_NAND_DOCG4 is not set -CONFIG_MTD_NAND_GPIO=m -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_NAND_NANDSIM is not set -CONFIG_MTD_NAND_ORION=m -# CONFIG_MTD_NAND_RICOH is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_OTP is not set -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_PLATRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_SLRAM is not set -CONFIG_MTD_DATAFLASH=m -CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y -CONFIG_MTD_DATAFLASH_OTP=y -CONFIG_MTD_SST25L=m -CONFIG_MTD_UBI=m -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_UBI_BEB_RESERVE=1 -# CONFIG_MTD_UBI_GLUEBI is not set -# CONFIG_MTD_UBI_DEBUG is not set -CONFIG_MG_DISK=m -CONFIG_MG_DISK_RES=0 - -# CONFIG_SM_FTL is not set - -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -# CONFIG_JFFS2_SUMMARY is not set -# CONFIG_JFFS2_FS_XATTR is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -# CONFIG_JFFS2_LZO is not set -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set - -CONFIG_UBIFS_FS=m -CONFIG_UBIFS_FS_XATTR=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -CONFIG_UBIFS_FS_LZO=y -CONFIG_UBIFS_FS_ZLIB=y -# CONFIG_UBIFS_FS_DEBUG is not set - -# HW crypto and rng -CONFIG_CRYPTO_SHA1_ARM=m -CONFIG_CRYPTO_AES_ARM=m -CONFIG_HW_RANDOM_ATMEL=m -CONFIG_HW_RANDOM_EXYNOS=m - -# Device tree -CONFIG_DTC=y -CONFIG_OF=y -CONFIG_USE_OF=y -CONFIG_OF_DEVICE=y -CONFIG_OF_IRQ=y -CONFIG_OF_GPIO=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set - -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_OF_GPIO=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y -CONFIG_I2C_MUX_PINCTRL=m -CONFIG_OF_MDIO=m -CONFIG_MDIO_BUS_MUX_GPIO=m -CONFIG_MDIO_BUS_MUX_MMIOREG=m - -CONFIG_BPF_JIT=y - -CONFIG_RCU_FANOUT_LEAF=16 -CONFIG_EDAC=y -CONFIG_EDAC_MM_EDAC=m -CONFIG_EDAC_LEGACY_SYSFS=y - -CONFIG_RTC_DRV_88PM80X=m -CONFIG_RTC_DRV_DS1305=m -CONFIG_RTC_DRV_DS1390=m -CONFIG_RTC_DRV_DS3234=m -CONFIG_RTC_DRV_M41T93=m -CONFIG_RTC_DRV_M41T94=m -CONFIG_RTC_DRV_MAX6902=m -CONFIG_RTC_DRV_MC13XXX=m -CONFIG_RTC_DRV_PCF2123=m -CONFIG_RTC_DRV_PL030=m -CONFIG_RTC_DRV_PL031=m -CONFIG_RTC_DRV_R9701=m -CONFIG_RTC_DRV_RS5C348=m -CONFIG_RTC_DRV_SNVS=m - -CONFIG_RFKILL_REGULATOR=m -CONFIG_INPUT_88PM80X_ONKEY=y -CONFIG_INPUT_GP2A=m -CONFIG_INPUT_GPIO_TILT_POLLED=m -CONFIG_INPUT_PWM_BEEPER=m -CONFIG_INPUT_ARIZONA_HAPTICS=m -CONFIG_INPUT_MC13783_PWRBUTTON=m - -CONFIG_SERIAL_AMBA_PL010=m -CONFIG_SERIAL_AMBA_PL011=m -CONFIG_SERIAL_MAX3100=m -CONFIG_SERIAL_MAX310X=y -CONFIG_SERIAL_IFX6X60=m - -CONFIG_GPIO_74X164=m -CONFIG_GPIO_ADNP=m -CONFIG_GPIO_ARIZONA=m -CONFIG_GPIO_MAX7301=m -CONFIG_GPIO_MC33880=m -CONFIG_GPIO_MCP23S08=m -CONFIG_GPIO_PL061=y - -CONFIG_SPI_ALTERA=m -CONFIG_SPI_BITBANG=m -CONFIG_SPI_BUTTERFLY=m -CONFIG_SPI_DW_MMIO=m -CONFIG_SPI_GPIO=m -CONFIG_SPI_LM70_LLP=m -CONFIG_SPI_OC_TINY=m -CONFIG_SPI_PL022=m -CONFIG_SPI_SC18IS602=m -CONFIG_SPI_XCOMM=m -CONFIG_SPI_XILINX=m -CONFIG_SPI_DESIGNWARE=m -CONFIG_SPI_SPIDEV=m -CONFIG_SPI_TLE62X0=m -CONFIG_BMP085_SPI=m -CONFIG_BMP085_SPI=m -CONFIG_EEPROM_AT25=m -CONFIG_EEPROM_93XX46=m -CONFIG_KS8851=m -CONFIG_MICREL_KS8995MA=m -CONFIG_LIBERTAS_SPI=m -CONFIG_P54_SPI=m -CONFIG_P54_SPI_DEFAULT_EEPROM=y - -CONFIG_MFD_CORE=m -CONFIG_MFD_88PM800=m -CONFIG_MFD_88PM805=m -CONFIG_MFD_ARIZONA_SPI=m -CONFIG_MFD_MC13XXX_SPI=m -CONFIG_MFD_SYSCON=y -# CONFIG_MFD_WM5102 is not set -# CONFIG_MFD_WM5110 is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_MFD_AS3711 is not set -# CONFIG_MFD_SMSC is not set -# CONFIG_MFD_DA9055 is not set -# CONFIG_MFD_MAX8907 is not set - -CONFIG_REGULATOR_VIRTUAL_CONSUMER=m -CONFIG_REGULATOR_USERSPACE_CONSUMER=m -# CONFIG_REGULATOR_DUMMY is not set -CONFIG_REGULATOR_GPIO=m -CONFIG_REGULATOR_AD5398=m -CONFIG_REGULATOR_ANATOP=m -CONFIG_REGULATOR_ARIZONA=m -CONFIG_REGULATOR_FAN53555=m -CONFIG_REGULATOR_ISL6271A=m -CONFIG_REGULATOR_LP3972=m -CONFIG_REGULATOR_MAX1586=m -CONFIG_REGULATOR_MAX8649=m -CONFIG_REGULATOR_MAX8660=m -CONFIG_REGULATOR_MAX8952=m -CONFIG_REGULATOR_MAX8973=m -CONFIG_REGULATOR_MC13783=m -CONFIG_REGULATOR_MC13892=m -CONFIG_REGULATOR_LP3971=m -CONFIG_REGULATOR_TPS51632=m -CONFIG_REGULATOR_TPS62360=m -CONFIG_REGULATOR_TPS65023=m -CONFIG_REGULATOR_TPS6524X=m -CONFIG_REGULATOR_TPS6507X=m -CONFIG_CHARGER_MANAGER=y -CONFIG_EXTCON_GPIO=m - -CONFIG_SENSORS_AD7314=m -CONFIG_SENSORS_ADCXX=m -CONFIG_SENSORS_LM70=m -CONFIG_SENSORS_MAX1111=m -CONFIG_SENSORS_MC13783_ADC=m -CONFIG_SENSORS_ADS7871=m -CONFIG_SENSORS_LIS3_SPI=m - -CONFIG_IEEE802154_AT86RF230=m -CONFIG_IEEE802154_MRF24J40=m - -# CONFIG_ARM_VIRT_EXT is not set -# CONFIG_PINCTRL_EXYNOS4 is not set -# CONFIG_PINCTRL_EXYNOS5440 is not set - -# CONFIG_AUTO_ZRELADDR is not set +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_DT_BL_CPUFREQ is not set +CONFIG_ARM_GIC=y # CONFIG_ASYMMETRIC_KEY_TYPE is not set - -# CONFIG_VFIO is not set - -# CONFIG_XIP_KERNEL is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_APM_EMULATION is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# CONFIG_SERIAL_8250_EM is not set -# CONFIG_GPIO_EM is not set -# CONFIG_HVC_DCC is not set -# CONFIG_LEDS_RENESAS_TPU is not set -CONFIG_LEDS_DAC124S085=m -CONFIG_LEDS_MC13783=m - -# CONFIG_VIRTIO_CONSOLE is not set - -# Possibly part of Snowball -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set - -# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_BACKLIGHT_PWM=m # CONFIG_COMMON_CLK_DEBUG is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_ARM_KPROBES_TEST is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_COMMON_CLK=y +CONFIG_DMA_OF=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_ETHERNET=y +CONFIG_FB_SSD1307=m +CONFIG_GENERIC_GPIO=y +CONFIG_GPIOLIB=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HW_PERF_EVENTS=y +# CONFIG_I2C_NOMADIK is not set +CONFIG_INPUT_PWM_BEEPER=m +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_LEDS_RENESAS_TPU is not set +CONFIG_MMC_ARMMMCI=y +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +CONFIG_MMC=y +CONFIG_NFS_FS=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NO_HZ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF=y +CONFIG_PERF_EVENTS=y +# CONFIG_PID_IN_CONTEXTIDR is not set +CONFIG_PWM=y +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011=y -# CONFIG_DEBUG_PINCTRL is not set - -# HW Disabled because it causes issues on ARM platforms - -# disable TPM on arm at least on the trimslices it causes havoc -# CONFIG_TCG_TPM is not set - -# CONFIG_IMA is not set - -# ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! -# CONFIG_CRYSTALHD is not set - -# these modules all fail with missing __bad_udelay -# http://www.spinics.net/lists/arm/msg15615.html provides some background -# CONFIG_SUNGEM is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_RADEON is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_ATM_HE is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SFC is not set - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set - -CONFIG_TOUCHSCREEN_ADS7846=m -CONFIG_TOUCHSCREEN_AD7877=m -CONFIG_TOUCHSCREEN_TSC2005=m -CONFIG_TOUCHSCREEN_MC13783=m - -# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] -# CONFIG_TOUCHSCREEN_EETI is not set -# CONFIG_TOUCHSCREEN_EGALAX is not set -# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set - -# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set -# CONFIG_PANEL_ACX565AKM is not set -# CONFIG_PANEL_N8X0 is not set - -# CONFIG_LCD_L4F00242T03 is not set -# CONFIG_LCD_LMS283GF05 is not set -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_ILI9320 is not set -# CONFIG_LCD_TDO24M is not set -# CONFIG_LCD_VGG2432A4 is not set -# CONFIG_LCD_S6E63M0 is not set -# CONFIG_LCD_LD9040 is not set -# CONFIG_LCD_AMS369FG06 is not set - -# CONFIG_FB_MX3 is not set -# CONFIG_MX3_IPU is not set -# CONFIG_MX3_IPU_IRQS is not set - -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_CS89x0 is not set -# CONFIG_DVB_USB_PCTV452E is not set -# CONFIG_PINCTRL_EXYNOS is not set - -# CONFIG_EZX_PCAP is not set - -# CONFIG_EXTCON_ARIZONA is not set +# CONFIG_CRYPTO_TEST is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index b622c8051..ac240358f 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -1,8 +1,515 @@ -CONFIG_ARCH_KIRKWOOD=y -CONFIG_ARCH_KIRKWOOD_DT=y +# Generic ARM config. This is common config options that should be +# enabled on all ARM kernels and hence should be added here +# +# FIXME - we need to add debug/nodebug generic build options +# CONFIG_DEBUG_PER_CPU_MAPS is not set + +# Generic ARM processor options +CONFIG_ARM=y + +CONFIG_ARM_THUMB=y +CONFIG_AEABI=y +CONFIG_ARM_UNWIND=y +# CONFIG_ARCH_MULTI_V7 is not set +# CONFIG_OABI_COMPAT is not set # CONFIG_SMP is not set # CONFIG_VFP is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_SMP_ON_UP=y + +CONFIG_ARM_ARCH_TIMER=y + +CONFIG_CMDLINE="" + +# CONFIG_ARM_LPAE is not set +# CONFIG_FPE_NWFPE is not set +CONFIG_FPE_FASTFPE=y +CONFIG_HIGHPTE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_UACCESS_WITH_MEMCPY=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set + +# Generic ARM Errata +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_751472=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_ARM_ERRATA_742231=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_PL310_ERRATA_753970=y + +# Generic ARM config options +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_LOCAL_TIMERS=y + +CONFIG_ATAGS=y +CONFIG_ATAGS_PROC=y + +CONFIG_PL330_DMA=y +CONFIG_AMBA_PL08X=y +CONFIG_PL330_DMA=y +# CONFIG_XIP_KERNEL is not set +# CONFIG_PID_IN_CONTEXTIDR is not set + +# Generic options we want for ARM that aren't defualt +CONFIG_EARLY_PRINTK=y + +CONFIG_HIGHMEM=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y + +CONFIG_RCU_FANOUT=32 + +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +# CONFIG_CPU_IDLE_GOV_LADDER is not set +CONFIG_CPU_IDLE_GOV_MENU=y + +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +CONFIG_PM=y +CONFIG_PM_STD_PARTITION="" +CONFIG_SUSPEND=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_CPU_TOPOLOGY=y + +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + +# CONFIG_XEN is not set + +CONFIG_PINCTRL=y +CONFIG_PINCONF=y + +CONFIG_COMMON_CLK=y + +CONFIG_THERMAL=y + +CONFIG_ETHERNET=y + +CONFIG_PERF_EVENTS=y +CONFIG_PERF_COUNTERS=y + +CONFIG_CC_STACKPROTECTOR=y + +CONFIG_SECCOMP=y +CONFIG_STRICT_DEVMEM=y + +CONFIG_SPARSE_IRQ=y + +# Generic HW for all ARM platforms +CONFIG_LEDS_GPIO=m + +CONFIG_LBDAF=y + +CONFIG_GPIOLIB=y +CONFIG_RFKILL_GPIO=m +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_PINCTRL_SINGLE=m +CONFIG_POWER_RESET_GPIO=y + +CONFIG_USB_ULPI=y + +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=m +CONFIG_SND_SOC=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_SIMPLE_CARD=m +# CONFIG_SND_SOC_CACHE_LZO is not set +CONFIG_SND_SOC_ALL_CODECS=m +CONFIG_SND_SPI=y + +CONFIG_AX88796=m +CONFIG_AX88796_93CX6=y +CONFIG_SMC91X=m +CONFIG_DM9000=m +CONFIG_DM9000_DEBUGLEVEL=4 +# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set +CONFIG_SMC911X=m +CONFIG_SMSC911X=m + +CONFIG_SERIO_AMBAKMI=m +CONFIG_I2C_NOMADIK=m +CONFIG_ARM_SP805_WATCHDOG=m +CONFIG_FB_ARMCLCD=m +CONFIG_FB_SSD1307=m +CONFIG_MPCORE_WATCHDOG=m +CONFIG_BACKLIGHT_PWM=m + +CONFIG_MMC_ARMMMCI=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SPI=m +CONFIG_MMC_DW=m +CONFIG_MMC_DW_PLTFM=m +CONFIG_MMC_DW_PCI=m +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_IDMAC is not set +CONFIG_MMC_SDHCI_PXAV3=m +CONFIG_MMC_SDHCI_PXAV2=m + +# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set + +CONFIG_SPI=y +# Generic GPIO options +CONFIG_GENERIC_GPIO=y + +CONFIG_MTD=m +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_CFI=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_ALAUDA=m +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_IMPA7=m +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_PHYSMAP=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_ECC=m +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_DOCG4 is not set +CONFIG_MTD_NAND_GPIO=m +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_ORION=m +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y +CONFIG_MTD_DATAFLASH_OTP=y +CONFIG_MTD_SST25L=m +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_MG_DISK=m +CONFIG_MG_DISK_RES=0 + +# CONFIG_SM_FTL is not set + +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set + +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set + +# HW crypto and rng +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m +CONFIG_HW_RANDOM_ATMEL=m +CONFIG_HW_RANDOM_EXYNOS=m + +# Device tree +CONFIG_DTC=y +CONFIG_OF=y +CONFIG_USE_OF=y +CONFIG_OF_DEVICE=y +CONFIG_OF_IRQ=y +CONFIG_OF_GPIO=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set + +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_OF_GPIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_OF_MDIO=m +CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_MDIO_BUS_MUX_MMIOREG=m + +CONFIG_BPF_JIT=y + +CONFIG_RCU_FANOUT_LEAF=16 +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_LEGACY_SYSFS=y + +CONFIG_RTC_DRV_88PM80X=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_MC13XXX=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_PL030=m +CONFIG_RTC_DRV_PL031=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_SNVS=m + +CONFIG_RFKILL_REGULATOR=m +CONFIG_INPUT_88PM80X_ONKEY=y +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_ARIZONA_HAPTICS=m +CONFIG_INPUT_MC13783_PWRBUTTON=m + +CONFIG_SERIAL_AMBA_PL010=m +CONFIG_SERIAL_AMBA_PL011=m +CONFIG_SERIAL_MAX3100=m +CONFIG_SERIAL_MAX310X=y +CONFIG_SERIAL_IFX6X60=m + +CONFIG_GPIO_74X164=m +CONFIG_GPIO_ADNP=m +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_PL061=y + +CONFIG_SPI_ALTERA=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_OC_TINY=m +CONFIG_SPI_PL022=m +CONFIG_SPI_SC18IS602=m +CONFIG_SPI_XCOMM=m +CONFIG_SPI_XILINX=m +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m +CONFIG_BMP085_SPI=m +CONFIG_BMP085_SPI=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93XX46=m +CONFIG_KS8851=m +CONFIG_MICREL_KS8995MA=m +CONFIG_LIBERTAS_SPI=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y + +CONFIG_MFD_CORE=m +CONFIG_MFD_88PM800=m +CONFIG_MFD_88PM805=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_MC13XXX_SPI=m +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_WM5102 is not set +# CONFIG_MFD_WM5110 is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_MAX8907 is not set + +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_GPIO=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_ARIZONA=m +CONFIG_REGULATOR_FAN53555=m +CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_LP3972=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8973=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_MC13892=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_TPS51632=m +CONFIG_REGULATOR_TPS62360=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6524X=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_CHARGER_MANAGER=y +CONFIG_EXTCON_GPIO=m + +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MC13783_ADC=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_LIS3_SPI=m + +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m + +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_PINCTRL_EXYNOS4 is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set + +# CONFIG_AUTO_ZRELADDR is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + +# CONFIG_VFIO is not set + +# CONFIG_XIP_KERNEL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_GPIO_EM is not set +# CONFIG_HVC_DCC is not set +# CONFIG_LEDS_RENESAS_TPU is not set +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_MC13783=m + +# CONFIG_VIRTIO_CONSOLE is not set + +# Possibly part of Snowball +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set + +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_COMMON_CLK_DEBUG is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set + +# CONFIG_DEBUG_PINCTRL is not set + +# HW Disabled because it causes issues on ARM platforms + +# disable TPM on arm at least on the trimslices it causes havoc +# CONFIG_TCG_TPM is not set + +# CONFIG_IMA is not set + +# ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! +# CONFIG_CRYSTALHD is not set + +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SFC is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set + +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_MC13783=m + +# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set + +# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_PANEL_ACX565AKM is not set +# CONFIG_PANEL_N8X0 is not set + +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set + +# CONFIG_FB_MX3 is not set +# CONFIG_MX3_IPU is not set +# CONFIG_MX3_IPU_IRQS is not set + +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_CS89x0 is not set +# CONFIG_DVB_USB_PCTV452E is not set +# CONFIG_PINCTRL_EXYNOS is not set + +# CONFIG_EZX_PCAP is not set + +# CONFIG_EXTCON_ARIZONA is not set +CONFIG_ARCH_KIRKWOOD=y +CONFIG_ARCH_KIRKWOOD_DT=y + +CONFIG_MACH_CLOUDBOX_DT=y CONFIG_MACH_D2NET_V2=y CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_DOCKSTAR=y @@ -37,6 +544,7 @@ CONFIG_MACH_OPENRD_CLIENT=y CONFIG_MACH_OPENRD_ULTIMATE=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y +CONFIG_MACH_READYNAS_DT=y CONFIG_MACH_SHEEVAPLUG=y CONFIG_MACH_TOPKICK_DT=y CONFIG_MACH_TS219=y @@ -75,6 +583,21 @@ CONFIG_OF_DISPLAY_TIMING=y CONFIG_OF_VIDEOMODE=y CONFIG_SND_ATMEL_SOC=m +CONFIG_TI_DAC7512=m +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SPI_FSL_SPI is not set +CONFIG_SPI_ORION=m +CONFIG_SPI_PXA2XX=m +CONFIG_SPI_TOPCLIFF_PCH=m +# CONFIG_SPI_DW_PCI is not set +CONFIG_GPIO_RCAR=m +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_USB_EHCI_HCD_ORION=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_COMMON_CLK_SI5351=m + # CONFIG_CPU_FEROCEON_OLD_ID is not set # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set diff --git a/config-armv7 b/config-armv7 index db8a2b69d..1bbb3d524 100644 --- a/config-armv7 +++ b/config-armv7 @@ -1,22 +1,20 @@ # ARM unified arch kernel -CONFIG_CPU_V7=y -# CONFIG_ARCH_MULTI_V4 is not set -# CONFIG_ARCH_MULTI_V4T is not set -# CONFIG_ARCH_MULTI_V6 is not set -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -# This is V6 so we'll eventually support it in v5 unified kernels + # CONFIG_ARCH_BCM is not set CONFIG_ARCH_HIGHBANK=y CONFIG_ARCH_MVEBU=y -# CONFIG_ARCH_MXC is not set +CONFIG_ARCH_MXC=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_ARCH_PICOXCELL=y +# CONFIG_ARCH_SIRF is not set CONFIG_ARCH_SOCFPGA=y +# CONFIG_PLAT_SPEAR is not set CONFIG_ARCH_SUNXI=y +CONFIG_ARCH_TEGRA=y +# CONFIG_ARCH_U8500 is not set CONFIG_ARCH_VEXPRESS_CA9X4=y -CONFIG_ARCH_VEXPRESS_DT=y -CONFIG_ARCH_VIRT=y +CONFIG_ARCH_VEXPRESS=y +# CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_WM8850 is not set CONFIG_ARCH_ZYNQ=y @@ -26,6 +24,9 @@ CONFIG_ARCH_ZYNQ=y # CONFIG_VIRTIO_CONSOLE is not set # CONFIG_ARM_VIRT_EXT is not set +# Generic +CONFIG_REMOTEPROC=m + # highbank # 2013/04/19 - stability issues # CONFIG_CPU_IDLE_CALXEDA is not set @@ -71,13 +72,15 @@ CONFIG_MVEBU_CLK_GATING=y CONFIG_MMC_MVSDIO=m CONFIG_SPI_ORION=m CONFIG_USB_MV_UDC=m +CONFIG_MVEBU_MBUS=y +CONFIG_ARMADA_THERMAL=m # omap CONFIG_ARCH_OMAP2PLUS_TYPICAL=y # CONFIG_ARCH_OMAP2 is not set CONFIG_ARCH_OMAP3=y CONFIG_ARCH_OMAP4=y -# CONFIG_SOC_OMAP5 is not set +CONFIG_SOC_OMAP5=y # CONFIG_SOC_OMAP2420 is not set # CONFIG_SOC_OMAP2430 is not set CONFIG_SOC_OMAP3430=y @@ -111,6 +114,7 @@ CONFIG_MACH_TI8148EVM=y CONFIG_MACH_OMAP_4430SDP=y CONFIG_MACH_OMAP4_PANDA=y +CONFIG_SOC_HAS_REALTIME_COUNTER=y CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX=y CONFIG_OMAP_MUX_WARNINGS=y @@ -206,7 +210,7 @@ CONFIG_MTD_NAND_OMAP2=y CONFIG_MTD_NAND_OMAP_PREFETCH=y CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y CONFIG_SPI_DAVINCI=m -CONFIG_SPI_OMAP24XX=y +CONFIG_SPI_OMAP24XX=m CONFIG_MFD_TI_SSP=m CONFIG_SPI_TI_SSP=m @@ -238,7 +242,7 @@ CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m CONFIG_HW_RANDOM_OMAP=m -# CONFIG_DRM_TILCDC is not set +CONFIG_DRM_TILCDC=m CONFIG_DRM_OMAP=m CONFIG_DRM_OMAP_NUM_CRTCS=2 CONFIG_OMAP2_VRAM=y @@ -318,7 +322,7 @@ CONFIG_SND_SOC_TWL4030=m CONFIG_SND_SOC_TWL6040=m CONFIG_RADIO_WL128X=m -# CONFIG_OMAP_REMOTEPROC is not set +CONFIG_OMAP_REMOTEPROC=m # CONFIG_TIDSPBRIDGE is not set # CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 @@ -373,13 +377,48 @@ CONFIG_PINCTRL_SUNXI=y # CONFIG_RTC_DRV_SUN4I=y # imx -# CONFIG_BACKLIGHT_PWM is not set -# CONFIG_DRM_IMX is not set -# CONFIG_DRM_IMX_FB_HELPER=m -# CONFIG_DRM_IMX_PARALLEL_DISPLAY=m -# CONFIG_DRM_IMX_IPUV3_CORE=m -# CONFIG_DRM_IMX_IPUV3=m -# CONFIG_VIDEO_CODA is not set +CONFIG_MXC_IRQ_PRIOR=y +# CONFIG_MXC_DEBUG_BOARD is not set +CONFIG_MACH_IMX51_DT=y +# CONFIG_MACH_MX51_BABBAGE is not set +# CONFIG_MACH_EUKREA_CPUIMX51SD is not set +CONFIG_SOC_IMX53=y +CONFIG_SOC_IMX6Q=y +CONFIG_PATA_IMX=m +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=m +CONFIG_KEYBOARD_IMX=m +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_I2C_IMX=m +CONFIG_SPI_IMX=m +CONFIG_W1_MASTER_MXC=m +CONFIG_IMX2_WDT=m +# CONFIG_FB_MX3 is not set +CONFIG_SND_IMX_SOC=m +CONFIG_SND_SOC_IMX_SGTL5000=m +CONFIG_USB_EHCI_MXC=m +CONFIG_USB_IMX21_HCD=m +CONFIG_USB_MXS_PHY=m +CONFIG_MMC_SDHCI_ESDHC_IMX=m +CONFIG_MMC_MXC=m +CONFIG_SPI_MXS=m +CONFIG_RTC_DRV_IMXDI=m +CONFIG_RTC_DRV_MXC=m +# CONFIG_MX3_IPU is not set +# CONFIG_MX3_IPU_IRQS is not set +CONFIG_IMX_SDMA=m +CONFIG_IMX_DMA=m +# CONFIG_MXS_DMA is not set +CONFIG_PWM_IMX=m +CONFIG_BACKLIGHT_PWM=m +CONFIG_DRM_IMX=m +CONFIG_DRM_IMX_FB_HELPER=m +CONFIG_DRM_IMX_PARALLEL_DISPLAY=m +CONFIG_DRM_IMX_IPUV3_CORE=m +CONFIG_DRM_IMX_IPUV3=m +CONFIG_DRM_IMX_TVE=m +CONFIG_VIDEO_CODA=m CONFIG_INPUT_PWM_BEEPER=m CONFIG_INPUT_88PM80X_ONKEY=m @@ -394,8 +433,106 @@ CONFIG_CRYPTO_DEV_PICOXCELL=m CONFIG_HW_RANDOM_PICOXCELL=m # ST Ericsson -# CONFIG_I2C_NOMADIK is not set -# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_MACH_HREFV60=y +CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_UX500_DT=y + +CONFIG_ABX500_CORE=y +CONFIG_UX500_DEBUG_UART=2 +CONFIG_AB8500_CORE=y +CONFIG_STE_DMA40=y +CONFIG_HSEM_U8500=m +CONFIG_PINCTRL_ABX500=y +CONFIG_PINCTRL_AB8500=y +CONFIG_I2C_NOMADIK=m +CONFIG_KEYBOARD_NOMADIK=m +CONFIG_DB8500_CPUFREQ_COOLING=m +CONFIG_DB8500_THERMAL=y +CONFIG_UX500_WATCHDOG=m +CONFIG_INPUT_AB8500_PONKEY=m +CONFIG_REGULATOR_AB8500=y +CONFIG_AB8500_USB=m +CONFIG_RTC_DRV_AB8500=m +CONFIG_PWM_AB8500=m +CONFIG_SND_SOC_UX500=m +CONFIG_SND_SOC_UX500_PLAT_DMA=m +CONFIG_SND_SOC_UX500_MACH_MOP500=m +CONFIG_CLKSRC_DBX500_PRCMU=y +CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK=y +CONFIG_CRYPTO_DEV_UX500=m +CONFIG_CRYPTO_DEV_UX500_CRYP=m +CONFIG_CRYPTO_DEV_UX500_HASH=m +CONFIG_SENSORS_LIS3_I2C=m +CONFIG_AB8500_BM=y +CONFIG_AB8500_GPADC=y +CONFIG_SENSORS_AB8500=m +CONFIG_STE_MODEM_RPROC=m + +# tegra +CONFIG_ARCH_TEGRA_2x_SOC=y +CONFIG_ARCH_TEGRA_3x_SOC=y +# CONFIG_ARCH_TEGRA_114_SOC is not set + +CONFIG_SERIAL_TEGRA=y + +CONFIG_TEGRA_PCI=y +CONFIG_TEGRA_IOMMU_GART=y +CONFIG_TEGRA_IOMMU_SMMU=y +CONFIG_MMC_SDHCI_TEGRA=m + +CONFIG_I2C_TEGRA=m + +CONFIG_TEGRA_SYSTEM_DMA=y +CONFIG_TEGRA_EMC_SCALING_ENABLE=y +CONFIG_TEGRA_AHB=y +CONFIG_TEGRA20_APB_DMA=y +# CONFIG_SPI_TEGRA114 is not set +CONFIG_SPI_TEGRA20_SFLASH=m +CONFIG_SPI_TEGRA20_SLINK=m + +CONFIG_KEYBOARD_TEGRA=m +CONFIG_PINCTRL_TEGRA=y +CONFIG_PINCTRL_TEGRA20=y +CONFIG_PINCTRL_TEGRA30=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_RTC_DRV_TEGRA=y + +CONFIG_SND_SOC_TEGRA=m +CONFIG_SND_SOC_TEGRA_ALC5632=m +CONFIG_SND_SOC_TEGRA_WM8753=m +CONFIG_SND_SOC_TEGRA_WM8903=m +CONFIG_SND_SOC_TEGRA_WM9712=m +CONFIG_SND_SOC_TEGRA_TRIMSLICE=m +CONFIG_SND_SOC_TEGRA30_AHUB=m +CONFIG_SND_SOC_TEGRA30_I2S=m +CONFIG_SND_SOC_TEGRA20_AC97=m + +# AC100 (PAZ00) +CONFIG_MFD_NVEC=y +CONFIG_MFD_TPS80031=y +CONFIG_KEYBOARD_NVEC=y +CONFIG_SERIO_NVEC_PS2=y +CONFIG_NVEC_POWER=y +CONFIG_POWER_SUPPLY=y +CONFIG_NVEC_LEDS=y +CONFIG_NVEC_PAZ00=y +CONFIG_MFD_TPS6586X=y +CONFIG_GPIO_TPS6586X=y +CONFIG_REGULATOR_TPS6586X=m +CONFIG_RTC_DRV_TPS6586X=m + +CONFIG_PWM_TEGRA=m + +CONFIG_TEGRA_HOST1X=m +CONFIG_TEGRA_HOST1X_FIREWALL=y + +CONFIG_DRM_TEGRA=y +# CONFIG_DRM_TEGRA_STAGING is not set +# CONFIG_DRM_TEGRA_DEBUG is not set + +CONFIG_CRYPTO_DEV_TEGRA_AES=m + +CONFIG_LEDS_RENESAS_TPU=y # ZYNQ CONFIG_LATTICE_ECP3_CONFIG=m @@ -419,8 +556,6 @@ CONFIG_REGULATOR_FAN53555=m # CONFIG_REGULATOR_DUMMY is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set -CONFIG_RFKILL_REGULATOR=m -CONFIG_REGULATOR_GPIO=m CONFIG_REGULATOR_AD5398=m CONFIG_REGULATOR_ISL6271A=m CONFIG_REGULATOR_MAX1586=m @@ -499,3 +634,6 @@ CONFIG_REGULATOR_LP8755=m # CONFIG_POWER_RESET_QNAP is not set # CONFIG_POWER_RESET_RESTART is not set # CONFIG_OMAP2_DSS_DEBUG is not set +# CONFIG_DRM_TEGRA_DEBUG is not set +# CONFIG_CRYPTO_DEV_UX500_DEBUG is not set +# CONFIG_AB8500_DEBUG is not set diff --git a/config-armv7-generic b/config-armv7-generic index c005a4efc..897a7e3ee 100644 --- a/config-armv7-generic +++ b/config-armv7-generic @@ -2,6 +2,11 @@ # Generic ARM config options CONFIG_ARM=y +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y + CONFIG_CMDLINE="" CONFIG_HAVE_ARM_ARCH_TIMER=y CONFIG_HAVE_ARM_TWD=y @@ -9,10 +14,10 @@ CONFIG_AEABI=y CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_NEON=y + CONFIG_ARM_UNWIND=y CONFIG_ARM_THUMB=y CONFIG_ARM_THUMBEE=y -CONFIG_ARM_GIC=y CONFIG_ARM_ASM_UNIFIED=y CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_ARM_DMA_MEM_BUFFERABLE=y @@ -21,20 +26,16 @@ CONFIG_CACHE_L2X0=y CONFIG_CACHE_PL310=y CONFIG_HIGHPTE=y CONFIG_AUTO_ZRELADDR=y -CONFIG_EARLY_PRINTK=y CONFIG_ATAGS=y CONFIG_ATAGS_PROC=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_ARM_ARCH_TIMER=y CONFIG_ARCH_HAS_TICK_BROADCAST=y CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y +# CONFIG_MCPM is not set # CONFIG_OABI_COMPAT is not set -# CONFIG_FPE_NWFPE is not set -# CONFIG_FPE_FASTFPE is not set # CONFIG_APM_EMULATION is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set @@ -50,7 +51,8 @@ CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y # CONFIG_ARM_ERRATA_326103 is not set # CONFIG_ARM_ERRATA_411920 is not set # Cortex-A8 -# CONFIG_ARM_ERRATA_430973 is not set +CONFIG_ARM_ERRATA_430973=y +# The following two don't work with MP # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set # Cortex-A9 @@ -69,8 +71,9 @@ CONFIG_ARM_ERRATA_775420=y # CONFIG_PL310_ERRATA_727915 is not set CONFIG_PL310_ERRATA_753970=y CONFIG_PL310_ERRATA_769419=y +CONFIG_PJ4B_ERRATA_4742=y # Cortex-A15 -CONFIG_ARM_ERRATA_798181=y +# CONFIG_ARM_ERRATA_798181 is not set # generic that deviates from or should be merged into config-generic CONFIG_SMP=y @@ -83,7 +86,6 @@ CONFIG_SCHED_MC=y CONFIG_SCHED_SMT=y CONFIG_RCU_FANOUT=32 -CONFIG_RCU_FANOUT_LEAF=16 # 2013/04/19 - disable due to stability issues in 3.9 for the moment # CONFIG_CPU_IDLE is not set @@ -91,12 +93,11 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_CPU_IDLE_GOV_MENU is not set # CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set + CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_LSM_MMAP_MIN_ADDR=32768 -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - CONFIG_SECCOMP=y CONFIG_STRICT_DEVMEM=y @@ -109,7 +110,6 @@ CONFIG_SUSPEND=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_LOCAL_TIMERS=y -CONFIG_HW_PERF_EVENTS=y CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_CC_STACKPROTECTOR=y @@ -118,30 +118,19 @@ CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # Root as NFS, different from mainline -CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y CONFIG_LBDAF=y -CONFIG_COMMON_CLK=y - # Device tree -CONFIG_DTC=y -CONFIG_OF=y CONFIG_USE_OF=y -CONFIG_OF_DEVICE=y -CONFIG_OF_IRQ=y -CONFIG_DMA_OF=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set CONFIG_SERIAL_OF_PLATFORM=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y -CONFIG_OF_GPIO=y CONFIG_I2C_MUX_PINCTRL=m CONFIG_OF_MDIO=m @@ -149,21 +138,18 @@ CONFIG_OF_DISPLAY_TIMING=y CONFIG_OF_VIDEOMODE=y # General vexpress ARM drivers -CONFIG_ARM_AMBA=y CONFIG_ARM_TIMER_SP804=y CONFIG_SERIO_AMBAKMI=m CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_MRST_MAX3110=m CONFIG_RTC_DRV_PL030=y CONFIG_RTC_DRV_PL031=y -# disable because it's currently broken on highbank :-/ -# CONFIG_PL330_DMA is not set +CONFIG_PL330_DMA=m CONFIG_AMBA_PL08X=y CONFIG_ARM_SP805_WATCHDOG=m CONFIG_I2C_VERSATILE=m @@ -183,6 +169,7 @@ CONFIG_SMC91X=m CONFIG_SMC911X=m CONFIG_SMSC911X=m CONFIG_USB_ISP1760_HCD=m +# CONFIG_USB_EHCI_HCD_ORION is not set # Multifunction Devices CONFIG_MFD_SYSCON=y @@ -203,8 +190,6 @@ CONFIG_PINCTRL_SINGLE=m # GPIO CONFIG_GPIO_GENERIC_PLATFORM=m CONFIG_EXTCON_GPIO=m -CONFIG_GENERIC_GPIO=y -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIO_EM is not set CONFIG_GPIO_ADNP=m CONFIG_GPIO_MCP23S08=m @@ -215,15 +200,16 @@ CONFIG_INPUT_GPIO_TILT_POLLED=m CONFIG_MDIO_BUS_MUX_GPIO=m CONFIG_MDIO_BUS_MUX_MMIOREG=m CONFIG_LEDS_GPIO=m -CONFIG_GPIOLIB=y CONFIG_GPIO_MAX7301=m CONFIG_GPIO_MC33880=m CONFIG_GPIO_74X164=m CONFIG_GPIO_TPS65912=m +# CONFIG_GPIO_RCAR is not set CONFIG_W1_MASTER_GPIO=m CONFIG_CHARGER_GPIO=m CONFIG_SPI=y +CONFIG_SPI_MASTER=y CONFIG_SPI_GPIO=m CONFIG_SPI_BITBANG=m CONFIG_SPI_PL022=m @@ -238,6 +224,7 @@ CONFIG_SPI_XCOMM=m CONFIG_SPI_XILINX=m CONFIG_SPI_DESIGNWARE=m CONFIG_SPI_TLE62X0=m +# CONFIG_SPI_FSL_SPI is not set # HW crypto and rng CONFIG_CRYPTO_SHA1_ARM=m @@ -268,14 +255,12 @@ CONFIG_EEPROM_AT25=m CONFIG_EEPROM_93XX46=m # MMC/SD -CONFIG_MMC=y -CONFIG_MMC_ARMMMCI=y -CONFIG_MMC_SDHCI_PLTFM=m CONFIG_MMC_SPI=m CONFIG_MMC_DW=m CONFIG_MMC_DW_PLTFM=m CONFIG_MMC_DW_PCI=m CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_DW_PCI=m # CONFIG_MMC_DW_EXYNOS is not set # CONFIG_MMC_DW_IDMAC is not set @@ -288,14 +273,11 @@ CONFIG_SND_DESIGNWARE_I2S=m CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_SOC_CACHE_LZO=y CONFIG_SND_SOC_ALL_CODECS=m +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y # CONFIG_SND_ATMEL_SOC is not set # Displays -CONFIG_FB_SSD1307=m - -# PWM -CONFIG_PWM=y -CONFIG_BACKLIGHT_PWM=m # RTC CONFIG_RTC_DRV_M41T93=m @@ -348,6 +330,7 @@ CONFIG_SENSORS_GPIO_FAN=m CONFIG_LCD_L4F00242T03=m CONFIG_LCD_LMS283GF05=m CONFIG_LCD_LTV350QV=m +CONFIG_LCD_ILI922X=m CONFIG_LCD_ILI9320=m CONFIG_LCD_TDO24M=m CONFIG_LCD_VGG2432A4=m @@ -357,12 +340,11 @@ CONFIG_LCD_AMS369FG06=m CONFIG_LCD_LMS501KF03=m CONFIG_LCD_HX8357=m -CONFIG_INPUT_PWM_BEEPER=m +# Input CONFIG_INPUT_GP2A=m CONFIG_INPUT_ARIZONA_HAPTICS=m CONFIG_INPUT_MC13783_PWRBUTTON=m - CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_TOUCHSCREEN_AD7877=m CONFIG_TOUCHSCREEN_MC13783=m @@ -372,6 +354,18 @@ CONFIG_LEDS_DAC124S085=m CONFIG_LEDS_PWM=m CONFIG_BMP085_SPI=m +# Display + +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 + # Ethernet CONFIG_KS8851=m CONFIG_ENC28J60=m @@ -406,27 +400,20 @@ CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_DEBUG is not set # Should be in generic -CONFIG_ETHERNET=y CONFIG_BPF_JIT=y # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_PATA_PLATFORM is not set -CONFIG_PERF_EVENTS=y -# CONFIG_RTC_DRV_SNVS is not set # CONFIG_DRM_EXYNOS is not set # CONFIG_DRM_TILCDC is not set # CONFIG_DRM_IMX is not set -# CONFIG_MMC_SDHCI_PXAV3 is not set -# CONFIG_MMC_SDHCI_PXAV2 is not set # CONFIG_CS89x0 is not set # CONFIG_DM9000 is not set # CONFIG_HW_RANDOM_ATMEL is not set # CONFIG_HW_RANDOM_EXYNOS is not set -# CONFIG_I2C_NOMADIK is not set -# CONFIG_LEDS_RENESAS_TPU is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_TI_DAC7512 is not set @@ -436,14 +423,16 @@ CONFIG_PERF_EVENTS=y # CONFIG_ARM_CHARLCD is not set # CONFIG_MTD_AFS_PARTS is not set # CONFIG_IP_PNP_RARP is not set -# CONFIG_ASYMMETRIC_KEY_TYPE is not set -# CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_DEPRECATED_PARAM_STRUCT is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set # CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_PXA2XX is not set # these modules all fail with missing __bad_udelay # http://www.spinics.net/lists/arm/msg15615.html provides some background @@ -462,8 +451,7 @@ CONFIG_PERF_EVENTS=y # CONFIG_MLX4_EN is not set # Debug options. We need to deal with them at some point like x86 -# CONFIG_COMMON_CLK_DEBUG is not set # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_LL is not set -# CONFIG_IRQ_DOMAIN_DEBUG is not set # CONFIG_DEBUG_PINCTRL is not set +# CONFIG_ARM_DT_BL_CPUFREQ is not set diff --git a/config-armv7-tegra b/config-armv7-tegra deleted file mode 100644 index 20cda8a7b..000000000 --- a/config-armv7-tegra +++ /dev/null @@ -1,108 +0,0 @@ -CONFIG_ARCH_TEGRA=y - -CONFIG_ARCH_TEGRA_2x_SOC=y -# CONFIG_ARCH_TEGRA_3x_SOC is not set -# CONFIG_ARCH_TEGRA_114_SOC is not set - -# CONFIG_NEON is not set -# These are supported in the LPAE kernel -# CONFIG_ARM_LPAE is not set -# CONFIG_XEN is not set -# CONFIG_VIRTIO_CONSOLE is not set -# CONFIG_ARM_VIRT_EXT is not set -# CONFIG_VIRTUALIZATION is not set - -# CONFIG_MACH_HARMONY is not set -CONFIG_MACH_KAEN=y -CONFIG_MACH_PAZ00=y -CONFIG_MACH_SEABOARD=y -CONFIG_MACH_TEGRA_DT=y -CONFIG_MACH_TRIMSLICE=y -CONFIG_MACH_WARIO=y -CONFIG_MACH_VENTANA=y - -CONFIG_TEGRA_PCI=y -CONFIG_TEGRA_IOMMU_GART=y -CONFIG_TEGRA_IOMMU_SMMU=y - -CONFIG_I2C_TEGRA=m - -# This block is temporary until we work out why the MMC modules don't work as modules -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF=y -CONFIG_MMC_SDHCI_TEGRA=y - -CONFIG_TEGRA_SYSTEM_DMA=y -CONFIG_TEGRA_EMC_SCALING_ENABLE=y -CONFIG_TEGRA_AHB=y -CONFIG_TEGRA20_APB_DMA=y -CONFIG_SPI_TEGRA20_SFLASH=m -CONFIG_SPI_TEGRA20_SLINK=m - -CONFIG_KEYBOARD_TEGRA=m -CONFIG_PINCTRL_TEGRA=y -CONFIG_PINCTRL_TEGRA20=y -CONFIG_PINCTRL_TEGRA30=y -CONFIG_USB_EHCI_TEGRA=y -CONFIG_RTC_DRV_TEGRA=y - -CONFIG_SND_SOC_TEGRA=m -CONFIG_SND_SOC_TEGRA_ALC5632=m -CONFIG_SND_SOC_TEGRA_WM8753=m -CONFIG_SND_SOC_TEGRA_WM8903=m -CONFIG_SND_SOC_TEGRA_WM9712=m -CONFIG_SND_SOC_TEGRA_TRIMSLICE=m -CONFIG_SND_SOC_TEGRA30_AHUB=m -CONFIG_SND_SOC_TEGRA30_I2S=m -CONFIG_SND_SOC_TEGRA20_AC97=m - -# AC100 (PAZ00) -CONFIG_MFD_NVEC=y -CONFIG_MFD_TPS80031=y -CONFIG_KEYBOARD_NVEC=y -CONFIG_SERIO_NVEC_PS2=y -CONFIG_NVEC_POWER=y -CONFIG_POWER_SUPPLY=y -CONFIG_NVEC_LEDS=y -CONFIG_NVEC_PAZ00=y - -# CONFIG_MFD_TPS6586X is not set -# CONFIG_RTC_DRV_TPS6586X is not set - -CONFIG_PWM_TEGRA=m - -CONFIG_CMA=y -# CONFIG_CMA_DEBUG is not set -CONFIG_CMA_SIZE_MBYTES=16 -CONFIG_CMA_SIZE_SEL_MBYTES=y -# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -# CONFIG_CMA_SIZE_SEL_MIN is not set -# CONFIG_CMA_SIZE_SEL_MAX is not set -CONFIG_CMA_ALIGNMENT=8 -CONFIG_CMA_AREAS=7 - -CONFIG_DRM_TEGRA=m - -CONFIG_CRYPTO_DEV_TEGRA_AES=m - -CONFIG_LEDS_RENESAS_TPU=y - -CONFIG_OF=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIAL_TEGRA=y -CONFIG_OF_GPIO=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y - -# CONFIG_DRM_TEGRA_DEBUG is not set -# CONFIG_TI_DAC7512 is not set -# CONFIG_SPI_TOPCLIFF_PCH is not set -# CONFIG_SPI_DW_PCI is not set -# CONFIG_SPI_PXA2XX is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_PINCTRL_EXYNOS is not set -# CONFIG_PINCTRL_EXYNOS5440 is not set diff --git a/kernel.spec b/kernel.spec index 9098ef4e9..e2322f77f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -132,8 +132,6 @@ Summary: The Linux kernel %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} -# kernel-tegra (only valid for arm) -%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} # kernel-kirkwood (only valid for arm) %define with_kirkwood %{?_without_kirkwood: 0} %{?!_without_kirkwood: 1} # @@ -252,11 +250,6 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel up (mutliplatform inc VExpress, highbank, omap), and tegra are only built on armv7 hfp/sfp -%ifnarch armv7hl armv7l -%define with_tegra 0 -%endif - # kernel-kirkwood is only built for armv5 %ifnarch armv5tel %define with_kirkwood 0 @@ -486,6 +479,8 @@ Provides: kernel-highbank\ Provides: kernel-highbank-uname-r = %{KVERREL}%{?1:.%{1}}\ Provides: kernel-omap\ Provides: kernel-omap-uname-r = %{KVERREL}%{?1:.%{1}}\ +Provides: kernel-tegra\ +Provides: kernel-tegra-uname-r = %{KVERREL}%{?1:.%{1}}\ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ @@ -580,13 +575,12 @@ Source54: config-powerpc64p7 Source70: config-s390x # Unified ARM kernels -Source100: config-armv7 -Source101: config-armv7-generic -Source102: config-armv7-tegra +Source100: config-arm-generic +Source101: config-armv7 +Source102: config-armv7-generic # Legacy ARM kernels -Source104: config-arm-generic -Source105: config-arm-kirkwood +Source103: config-arm-kirkwood # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -714,7 +708,11 @@ Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch # ARM Patch21000: arm-export-read_current_timer.patch +# lpae +Patch21001: arm-lpae-ax88796.patch + # ARM omap +Patch21003: arm-omap-load-tfp410.patch # ARM tegra Patch21005: arm-tegra-usb-no-reset-linux33.patch @@ -1076,12 +1074,6 @@ on kernel bugs, as some of these options impact performance noticably. This package includes a version of the Linux kernel with support for marvell kirkwood based systems, i.e., guruplug, sheevaplug -%define variant_summary The Linux kernel compiled for tegra boards -%kernel_variant_package tegra -%description tegra -This package includes a version of the Linux kernel with support for -nvidia tegra based systems, i.e., trimslice, ac-100. - %prep # do a few sanity-checks for --with *only builds @@ -1343,6 +1335,8 @@ ApplyPatch vmbugon-warnon.patch # ARM # ApplyPatch arm-export-read_current_timer.patch +ApplyPatch arm-lpae-ax88796.patch +ApplyPatch arm-omap-load-tfp410.patch ApplyPatch arm-tegra-usb-no-reset-linux33.patch # @@ -1872,10 +1866,6 @@ BuildKernel %make_target %kernel_image PAE BuildKernel %make_target %kernel_image kirkwood %endif -%if %{with_tegra} -BuildKernel %make_target %kernel_image tegra -%endif - %if %{with_up} BuildKernel %make_target %kernel_image %endif @@ -2202,9 +2192,6 @@ fi}\ %kernel_variant_preun kirkwood %kernel_variant_post -v kirkwood -%kernel_variant_preun tegra -%kernel_variant_post -v tegra - if [ -x /sbin/ldconfig ] then /sbin/ldconfig -X || exit $? @@ -2349,7 +2336,6 @@ fi %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug %kernel_variant_files %{with_kirkwood} kirkwood -%kernel_variant_files %{with_tegra} tegra # plz don't put in a version string unless you're going to tag # and build. @@ -2364,6 +2350,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 1 2013 Peter Robinson +- Rebase ARM config + * Thu Aug 01 2013 Justin M. Forbes - Rebase to 3.10.4 dropped: From 1ff229fcea9f046a6d770c7f0cb7232e43d59e4b Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 2 Aug 2013 16:38:47 -0500 Subject: [PATCH 389/492] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index c229fb977..2b3fd5535 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2350,7 +2350,7 @@ fi # ||----w | # || || %changelog -* Thu Aug 1 2013 Peter Robinson +* Thu Aug 1 2013 Peter Robinson - 3.10.4-100 - Rebase ARM config * Thu Aug 01 2013 Justin M. Forbes From 9a45702091ae0c9cf0b06ba37339b11b7373414e Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 5 Aug 2013 09:30:05 -0500 Subject: [PATCH 390/492] Linux v3.10.5 --- ...ly-restore-fences-with-objects-attac.patch | 113 ------------------ kernel.spec | 17 +-- sources | 1 + ...k-device-permissions-before-allowing.patch | 54 --------- 4 files changed, 5 insertions(+), 180 deletions(-) delete mode 100644 drm-i915-correctly-restore-fences-with-objects-attac.patch delete mode 100644 xen-blkback-Check-device-permissions-before-allowing.patch diff --git a/drm-i915-correctly-restore-fences-with-objects-attac.patch b/drm-i915-correctly-restore-fences-with-objects-attac.patch deleted file mode 100644 index 69bb93fa5..000000000 --- a/drm-i915-correctly-restore-fences-with-objects-attac.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 94a335dba34ff47cad3d6d0c29b452d43a1be3c8 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Wed, 17 Jul 2013 14:51:28 +0200 -Subject: [PATCH] drm/i915: correctly restore fences with objects attached -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To avoid stalls we delay tiling changes and especially hold of -committing the new fence state for as long as possible. -Synchronization points are in the execbuf code and in our gtt fault -handler. - -Unfortunately we've missed that tricky detail when adding proper fence -restore code in - -commit 19b2dbde5732170a03bd82cc8bd442cf88d856f7 -Author: Chris Wilson -Date: Wed Jun 12 10:15:12 2013 +0100 - - drm/i915: Restore fences after resume and GPU resets - -The result was that we've restored fences for objects with no tiling, -since the object<->fence link still existed after resume. Now that -wouldn't have been too bad since any subsequent access would have -fixed things up, but if we've changed from tiled to untiled real havoc -happened: - -The tiling stride is stored -1 in the fence register, so a stride of 0 -resulted in all 1s in the top 32bits, and so a completely bogus fence -spanning everything from the start of the object to the top of the -GTT. The tell-tale in the register dumps looks like: - - FENCE START 2: 0x0214d001 - FENCE END 2: 0xfffff3ff - -Bit 11 isn't set since the hw doesn't store it, even when writing all -1s (at least on my snb here). - -To prevent such a gaffle in the future add a sanity check for fences -with an untiled object attached in i915_gem_write_fence. - -v2: Fix the WARN, spotted by Chris. - -v3: Trying to reuse get_fences looked ugly and obfuscated the code. -Instead reuse update_fence and to make it really dtrt also move the -fence dirty state clearing into update_fence. - -Cc: Chris Wilson -Cc: Stéphane Marchesin -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60530 -Cc: stable@vger.kernel.org (for 3.10 only) -Reviewed-by: Chris Wilson -Tested-by: Matthew Garrett -Tested-by: Björn Bidar -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c -index 97afd26..d9e2208 100644 ---- a/drivers/gpu/drm/i915/i915_gem.c -+++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -2258,7 +2258,17 @@ void i915_gem_restore_fences(struct drm_device *dev) - - for (i = 0; i < dev_priv->num_fence_regs; i++) { - struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; -- i915_gem_write_fence(dev, i, reg->obj); -+ -+ /* -+ * Commit delayed tiling changes if we have an object still -+ * attached to the fence, otherwise just clear the fence. -+ */ -+ if (reg->obj) { -+ i915_gem_object_update_fence(reg->obj, reg, -+ reg->obj->tiling_mode); -+ } else { -+ i915_gem_write_fence(dev, i, NULL); -+ } - } - } - -@@ -2795,6 +2805,10 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg, - if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj)) - mb(); - -+ WARN(obj && (!obj->stride || !obj->tiling_mode), -+ "bogus fence setup with stride: 0x%x, tiling mode: %i\n", -+ obj->stride, obj->tiling_mode); -+ - switch (INTEL_INFO(dev)->gen) { - case 7: - case 6: -@@ -2836,6 +2850,7 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, - fence->obj = NULL; - list_del_init(&fence->lru_list); - } -+ obj->fence_dirty = false; - } - - static int -@@ -2965,7 +2980,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj) - return 0; - - i915_gem_object_update_fence(obj, reg, enable); -- obj->fence_dirty = false; - - return 0; - } --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index 2b3fd5535..8dee4b343 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -737,9 +737,6 @@ Patch25007: fix-child-thread-introspection.patch #rhbz 948262 Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#CVE-2013-2140 rhbz 971146 971148 -Patch25031: xen-blkback-Check-device-permissions-before-allowing.patch - #CVE-2013-2147 rhbz 971242 971249 Patch25032: cve-2013-2147-ciss-info-leak.patch @@ -778,9 +775,6 @@ Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch -#rhbz 989093 -Patch25071: drm-i915-correctly-restore-fences-with-objects-attac.patch - #rhbz 977053 Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch @@ -1461,9 +1455,6 @@ ApplyPatch fix-child-thread-introspection.patch #rhbz 948262 ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch -#CVE-2013-2140 rhbz 971146 971148 -ApplyPatch xen-blkback-Check-device-permissions-before-allowing.patch - #CVE-2013-2147 rhbz 971242 971249 ApplyPatch cve-2013-2147-ciss-info-leak.patch @@ -1502,9 +1493,6 @@ ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch -#rhbz 989093 -ApplyPatch drm-i915-correctly-restore-fences-with-objects-attac.patch - #rhbz 977053 ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch @@ -2350,6 +2338,9 @@ fi # ||----w | # || || %changelog +* Mon Aug 04 2013 Justin M. Forbes +- Linux v3.10.5 + * Thu Aug 1 2013 Peter Robinson - 3.10.4-100 - Rebase ARM config diff --git a/sources b/sources index a87e5a10a..f0c5c03a6 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz 2e46ab138670b3171b52b849568cb42f patch-3.10.4.xz +6366a8d4b0429ab6836c296ba298fb0e patch-3.10.5.xz diff --git a/xen-blkback-Check-device-permissions-before-allowing.patch b/xen-blkback-Check-device-permissions-before-allowing.patch deleted file mode 100644 index 933e82890..000000000 --- a/xen-blkback-Check-device-permissions-before-allowing.patch +++ /dev/null @@ -1,54 +0,0 @@ -From e029d62efa5eb46831a9e1414468e582379b743f Mon Sep 17 00:00:00 2001 -From: Konrad Rzeszutek Wilk -Date: Wed, 16 Jan 2013 11:33:52 -0500 -Subject: [PATCH] xen/blkback: Check device permissions before allowing - OP_DISCARD - -We need to make sure that the device is not RO or that -the request is not past the number of sectors we want to -issue the DISCARD operation for. - -Cc: stable () vger kernel org -Acked-by: Jan Beulich -Acked-by: Ian Campbell -[v1: Made it pr_warn instead of pr_debug] -Signed-off-by: Konrad Rzeszutek Wilk ---- - drivers/block/xen-blkback/blkback.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c -index e79ab45..4119bcd 100644 ---- a/drivers/block/xen-blkback/blkback.c -+++ b/drivers/block/xen-blkback/blkback.c -@@ -876,7 +876,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif, - int status = BLKIF_RSP_OKAY; - struct block_device *bdev = blkif->vbd.bdev; - unsigned long secure; -+ struct phys_req preq; -+ -+ preq.sector_number = req->u.discard.sector_number; -+ preq.nr_sects = req->u.discard.nr_sectors; - -+ err = xen_vbd_translate(&preq, blkif, WRITE); -+ if (err) { -+ pr_warn(DRV_PFX "access denied: DISCARD [%llu->%llu] on dev=%04x\n", -+ preq.sector_number, -+ preq.sector_number + preq.nr_sects, blkif->vbd.pdevice); -+ goto fail_response; -+ } - blkif->st_ds_req++; - - xen_blkif_get(blkif); -@@ -887,7 +898,7 @@ static int dispatch_discard_io(struct xen_blkif *blkif, - err = blkdev_issue_discard(bdev, req->u.discard.sector_number, - req->u.discard.nr_sectors, - GFP_KERNEL, secure); -- -+fail_response: - if (err == -EOPNOTSUPP) { - pr_debug(DRV_PFX "discard op failed, not supported\n"); - status = BLKIF_RSP_EOPNOTSUPP; --- -1.8.1.4 - From 3d16a9f5323f293d37dd8541068222bb5e1f509f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Aug 2013 11:13:57 -0400 Subject: [PATCH 391/492] Build MEI_ME as a module. Upstream changed it to a module from an add-on option to the MEI driver. Build it as a module so that people can blacklist it because it's a piece of crap. --- config-x86-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-x86-generic b/config-x86-generic index 911455e40..064063020 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -431,7 +431,7 @@ CONFIG_DRM_GMA3600=y CONFIG_RCU_FANOUT_LEAF=16 CONFIG_INTEL_MEI=m -CONFIG_INTEL_MEI_ME=y +CONFIG_INTEL_MEI_ME=m # Maybe enable in debug kernels? # CONFIG_DEBUG_NMI_SELFTEST is not set From 87eb30dc9a3ef23e0f09e64b60996e58b4599346 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 6 Aug 2013 15:58:28 -0500 Subject: [PATCH 392/492] update s390x config --- config-s390x | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config-s390x b/config-s390x index ec4fd04e5..35aec886f 100644 --- a/config-s390x +++ b/config-s390x @@ -250,6 +250,7 @@ CONFIG_EADM_SCH=m CONFIG_SCM_BLOCK=m CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_S390_PTDUMP is not set +# CONFIG_SCSI_UFSHCD is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set # CONFIG_PCI is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set @@ -271,6 +272,8 @@ CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_ACCESSIBILITY is not set # CONFIG_AUXDISPLAY is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_PTP_1588_CLOCK_PCH is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_STAGING is not set # CONFIG_MEMSTICK is not set From eee591ee954dbaa524be5ff2c636a967b600dfc4 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 6 Aug 2013 15:59:08 -0500 Subject: [PATCH 393/492] Add the spec --- kernel.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel.spec b/kernel.spec index 8dee4b343..39f0afa15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2338,6 +2338,9 @@ fi # ||----w | # || || %changelog +* Tue Aug 06 2013 Justin M. Forbes 3.10.5-100 +- update s390x config [Dan Horák] + * Mon Aug 04 2013 Justin M. Forbes - Linux v3.10.5 From 48fa95f9c8db360b20d0f341592b1b3aff75b2d8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Aug 2013 09:45:49 -0400 Subject: [PATCH 394/492] Add zero file length check to make sure pesign didn't fail (rhbz 991808) --- kernel.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel.spec b/kernel.spec index 39f0afa15..e7251c73e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1658,6 +1658,10 @@ BuildKernel() { %if %{signmodules} # Sign the image if we're using EFI %pesign -s -i $KernelImage -o vmlinuz.signed + if [ ! -s vmlinuz.signed ]; then + echo "pesigning failed" + exit 1 + fi mv vmlinuz.signed $KernelImage %endif $CopyKernel $KernelImage \ @@ -2338,6 +2342,9 @@ fi # ||----w | # || || %changelog +* Wed Aug 07 2013 Josh Boyer +- Add zero file length check to make sure pesign didn't fail (rhbz 991808) + * Tue Aug 06 2013 Justin M. Forbes 3.10.5-100 - update s390x config [Dan Horák] From 15b4ccaab8987c490f8d35e649539c71b934dc53 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 7 Aug 2013 09:54:50 -0500 Subject: [PATCH 395/492] Bump for rebuild after koji hiccup --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index e7251c73e..e51555152 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2342,6 +2342,9 @@ fi # ||----w | # || || %changelog +* Wed Aug 07 2013 Justin M. Forbes 3.10.5-101 +- Bump for rebuild after koji hiccup + * Wed Aug 07 2013 Josh Boyer - Add zero file length check to make sure pesign didn't fail (rhbz 991808) From 781a64a27cd42228f08cc31b2ae758303698be8a Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 12 Aug 2013 09:24:58 -0500 Subject: [PATCH 396/492] Linux v3.10.6 --- ath3k-dont-use-stack-memory-for-DMA.patch | 72 ------------------- config-arm-generic | 1 + ...tify-info-leak-in-copy_event_to_user.patch | 14 ---- ...nd-BT_CONFIG-on-devices-wo-Bluetooth.patch | 32 --------- kernel.spec | 25 ++----- sources | 3 +- 6 files changed, 7 insertions(+), 140 deletions(-) delete mode 100644 ath3k-dont-use-stack-memory-for-DMA.patch delete mode 100644 fanotify-info-leak-in-copy_event_to_user.patch delete mode 100644 iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch diff --git a/ath3k-dont-use-stack-memory-for-DMA.patch b/ath3k-dont-use-stack-memory-for-DMA.patch deleted file mode 100644 index 610a00067..000000000 --- a/ath3k-dont-use-stack-memory-for-DMA.patch +++ /dev/null @@ -1,72 +0,0 @@ -Memory allocated by vmalloc (including stack) can not be used for DMA, -i.e. data pointer on usb_control_msg() should not point to stack memory. - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=977558 - -Reported-and-tested-by: Andy Lawrence -Signed-off-by: Stanislaw Gruszka ---- - drivers/bluetooth/ath3k.c | 38 +++++++++++++++++++++++++++++--------- - 1 file changed, 29 insertions(+), 9 deletions(-) - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index 11f467c..81b636c 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -193,24 +193,44 @@ error: - - static int ath3k_get_state(struct usb_device *udev, unsigned char *state) - { -- int pipe = 0; -+ int ret, pipe = 0; -+ char *buf; -+ -+ buf = kmalloc(1, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; - - pipe = usb_rcvctrlpipe(udev, 0); -- return usb_control_msg(udev, pipe, ATH3K_GETSTATE, -- USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -- state, 0x01, USB_CTRL_SET_TIMEOUT); -+ ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE, -+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -+ buf, 1, USB_CTRL_SET_TIMEOUT); -+ -+ *state = *buf; -+ kfree(buf); -+ -+ return ret; - } - - static int ath3k_get_version(struct usb_device *udev, - struct ath3k_version *version) - { -- int pipe = 0; -+ int ret, pipe = 0; -+ char *buf; -+ const int size = sizeof(struct ath3k_version); -+ -+ buf = kmalloc(size, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; - - pipe = usb_rcvctrlpipe(udev, 0); -- return usb_control_msg(udev, pipe, ATH3K_GETVERSION, -- USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, -- sizeof(struct ath3k_version), -- USB_CTRL_SET_TIMEOUT); -+ ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION, -+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -+ buf, size, USB_CTRL_SET_TIMEOUT); -+ -+ memcpy(version, buf, size); -+ kfree(buf); -+ -+ return ret; - } - - static int ath3k_load_fwfile(struct usb_device *udev, --- -1.7.11.7 diff --git a/config-arm-generic b/config-arm-generic index efce65434..7aa5a852a 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -41,3 +41,4 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_AMBA_PL011=y # CONFIG_CRYPTO_TEST is not set +CONFIG_KUSER_HELPERS=y diff --git a/fanotify-info-leak-in-copy_event_to_user.patch b/fanotify-info-leak-in-copy_event_to_user.patch deleted file mode 100644 index 92b218b1c..000000000 --- a/fanotify-info-leak-in-copy_event_to_user.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c -index 6c80083..77cc85d 100644 ---- a/fs/notify/fanotify/fanotify_user.c -+++ b/fs/notify/fanotify/fanotify_user.c -@@ -122,6 +122,7 @@ static int fill_event_metadata(struct fsnotify_group *group, - metadata->event_len = FAN_EVENT_METADATA_LEN; - metadata->metadata_len = FAN_EVENT_METADATA_LEN; - metadata->vers = FANOTIFY_METADATA_VERSION; -+ metadata->reserved = 0; - metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS; - metadata->pid = pid_vnr(event->tgid); - if (unlikely(event->mask & FAN_Q_OVERFLOW)) - - \ No newline at end of file diff --git a/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch b/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch deleted file mode 100644 index aa2ca7035..000000000 --- a/iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 7b29fdb8cd8f92e31f550611a8c031986dba2e8f Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Fri, 03 May 2013 16:58:16 +0000 -Subject: iwlwifi: dvm: don't send BT_CONFIG on devices w/o Bluetooth - -The BT_CONFIG command that is sent to the device during -startup will enable BT coex unless the module parameter -turns it off, but on devices without Bluetooth this may -cause problems, as reported in Redhat BZ 885407. - -Fix this by sending the BT_CONFIG command only when the -device has Bluetooth. - -Cc: stable@vger.kernel.org -Reviewed-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg ---- -diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c -index 3952ddf..1531a4f 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/main.c -+++ b/drivers/net/wireless/iwlwifi/dvm/main.c -@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv) - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - if (ret) - return ret; -- } else { -+ } else if (priv->cfg->bt_params) { - /* - * default is 2-wire BT coexexistence support - */ --- -cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index e51555152..129f89d7c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -740,9 +740,6 @@ Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.pa #CVE-2013-2147 rhbz 971242 971249 Patch25032: cve-2013-2147-ciss-info-leak.patch -#CVE-2013-2148 rhbz 971258 971261 -Patch25033: fanotify-info-leak-in-copy_event_to_user.patch - #rhbz 969644 Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -756,9 +753,6 @@ Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch Patch25061: bridge-timer-fix.patch Patch25066: bridge-do-not-call-setup_timer-multiple-times.patch -#rhbz 977558 -Patch25055: ath3k-dont-use-stack-memory-for-DMA.patch - #rhbz 977040 Patch25056: iwl3945-better-skb-management-in-rx-path.patch Patch25057: iwl4965-better-skb-management-in-rx-path.patch @@ -766,9 +760,6 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #rhbz 959721 Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch -#rhbz 885407 -Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch - #rhbz 979581 Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch @@ -1458,9 +1449,6 @@ ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.pat #CVE-2013-2147 rhbz 971242 971249 ApplyPatch cve-2013-2147-ciss-info-leak.patch -#CVE-2013-2148 rhbz 971258 971261 -ApplyPatch fanotify-info-leak-in-copy_event_to_user.patch - #rhbz 969644 ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -1474,9 +1462,6 @@ ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch ApplyPatch bridge-timer-fix.patch ApplyPatch bridge-do-not-call-setup_timer-multiple-times.patch -#rhbz 977558 -ApplyPatch ath3k-dont-use-stack-memory-for-DMA.patch - #rhbz 977040 ApplyPatch iwl3945-better-skb-management-in-rx-path.patch ApplyPatch iwl4965-better-skb-management-in-rx-path.patch @@ -1484,9 +1469,6 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #rhbz 959721 ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch -#rhbz 885407 -ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch - #rhbz 979581 ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch @@ -2342,6 +2324,9 @@ fi # ||----w | # || || %changelog +* Mon Aug 12 2013 Justin M. Forbes 3.10.6-100 +- Linux v3.10.6 + * Wed Aug 07 2013 Justin M. Forbes 3.10.5-101 - Bump for rebuild after koji hiccup diff --git a/sources b/sources index f0c5c03a6..c11108ab4 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -2e46ab138670b3171b52b849568cb42f patch-3.10.4.xz -6366a8d4b0429ab6836c296ba298fb0e patch-3.10.5.xz +b41c06c1154592045cc2a9d88363de14 patch-3.10.6.xz From a5e751aa971f1ec48fc1a092a78b41edabc4c01f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Aug 2013 09:05:43 -0400 Subject: [PATCH 397/492] Linux v3.10.7 --- kernel.spec | 5 ++++- sources | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 129f89d7c..02f787a29 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2324,6 +2324,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 15 2013 Josh Boyer - 3.10.7-100 +- Linux v3.10.7 + * Mon Aug 12 2013 Justin M. Forbes 3.10.6-100 - Linux v3.10.6 diff --git a/sources b/sources index c11108ab4..cc0f04112 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -b41c06c1154592045cc2a9d88363de14 patch-3.10.6.xz +6b1b6b62044fcf3624f067154d5c1666 patch-3.10.7.xz From 112c71db534428a3ee718640669c5e1ebead0455 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Aug 2013 09:08:24 -0400 Subject: [PATCH 398/492] Add patch to fix regression on TeVII S471 devices (rhbz 963715) --- kernel.spec | 7 +++++ ...ression-since-introduction-of-ts2020.patch | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch diff --git a/kernel.spec b/kernel.spec index 02f787a29..00a27d3b2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -774,6 +774,9 @@ Patch25074: mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch Patch25075: mac80211-ignore-HT-primary-channel-while-connected.patch Patch25076: mac80211-continue-using-disabled-channels-while-connected.patch +#rhbz 963715 +Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch + # END OF PATCH DEFINITIONS %endif @@ -1483,6 +1486,9 @@ ApplyPatch mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch ApplyPatch mac80211-ignore-HT-primary-channel-while-connected.patch ApplyPatch mac80211-continue-using-disabled-channels-while-connected.patch +#rhbz 963715 +ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch + # END OF PATCH APPLICATIONS %endif @@ -2325,6 +2331,7 @@ fi # || || %changelog * Thu Aug 15 2013 Josh Boyer - 3.10.7-100 +- Add patch to fix regression on TeVII S471 devices (rhbz 963715) - Linux v3.10.7 * Mon Aug 12 2013 Justin M. Forbes 3.10.6-100 diff --git a/media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch b/media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch new file mode 100644 index 000000000..2a28a2fe1 --- /dev/null +++ b/media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch @@ -0,0 +1,30 @@ +From b43ea8068d2090cb1e44632c8a938ab40d2c7419 Mon Sep 17 00:00:00 2001 +From: Johannes Koch +Date: Wed, 17 Jul 2013 17:28:16 +0000 +Subject: [media] cx23885: Fix TeVii S471 regression since introduction of ts2020 + +Patch to make TeVii S471 cards use the ts2020 tuner, since ds3000 driver no +longer contains tuning code. + +Signed-off-by: Johannes Koch +Signed-off-by: Mauro Carvalho Chehab +--- +(limited to 'drivers/media/pci/cx23885/cx23885-dvb.c') + +diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c +index 9c5ed10..bb291c6 100644 +--- a/drivers/media/pci/cx23885/cx23885-dvb.c ++++ b/drivers/media/pci/cx23885/cx23885-dvb.c +@@ -1249,6 +1249,10 @@ static int dvb_register(struct cx23885_tsport *port) + fe0->dvb.frontend = dvb_attach(ds3000_attach, + &tevii_ds3000_config, + &i2c_bus->i2c_adap); ++ if (fe0->dvb.frontend != NULL) { ++ dvb_attach(ts2020_attach, fe0->dvb.frontend, ++ &tevii_ts2020_config, &i2c_bus->i2c_adap); ++ } + break; + case CX23885_BOARD_PROF_8000: + i2c_bus = &dev->i2c_bus[0]; +-- +cgit v0.9.2 From 9238c21bb1fdf3d76b0ef0629a0d8252a22369c9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Aug 2013 09:50:52 -0400 Subject: [PATCH 399/492] Add patch from Nathanael Noblet to fix mic on Gateway LT27 (rhbz 845699) --- ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch | 25 +++++++++++++++++++++ kernel.spec | 9 ++++++++ 2 files changed, 34 insertions(+) create mode 100644 ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch diff --git a/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch b/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch new file mode 100644 index 000000000..9ce3433f9 --- /dev/null +++ b/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch @@ -0,0 +1,25 @@ +From 1801928e0f99d94c55e33c584c5eb2ff5e246ee6 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 16 Aug 2013 06:17:05 +0000 +Subject: ALSA: hda - Add a fixup for Gateway LT27 + +Gateway LT27 needs a fixup for the inverted digital mic. + +Reported-by: "Nathanael D. Noblet" +Cc: +Signed-off-by: Takashi Iwai +--- +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 5b22bf9..f303cd8 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4339,6 +4339,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), ++ SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 00a27d3b2..f201c79c1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -777,6 +777,9 @@ Patch25076: mac80211-continue-using-disabled-channels-while-connected.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch +#rhbz 845699 +Patch25078: ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch + # END OF PATCH DEFINITIONS %endif @@ -1489,6 +1492,9 @@ ApplyPatch mac80211-continue-using-disabled-channels-while-connected.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch +#rhbz 845699 +ApplyPatch ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch + # END OF PATCH APPLICATIONS %endif @@ -2330,6 +2336,9 @@ fi # ||----w | # || || %changelog +* Fri Aug 16 2013 Josh Boyer +- Add patch from Nathanael Noblet to fix mic on Gateway LT27 (rhbz 845699) + * Thu Aug 15 2013 Josh Boyer - 3.10.7-100 - Add patch to fix regression on TeVII S471 devices (rhbz 963715) - Linux v3.10.7 From 5bf1cd40d3534fb69041681055c542c3af33a0a7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Aug 2013 12:44:08 -0400 Subject: [PATCH 400/492] Linux v3.10.8 - CVE-2013-4254 ARM: perf: NULL pointer dereference in validate_event (rhbz 998878 998881) --- ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch | 25 ---- iwl4965-reset-firmware-after-rfkill-off.patch | 56 -------- kernel.spec | 28 +--- ...ng-disabled-channels-while-connected.patch | 43 ------- ...loop-in-ieee80211_determine_chantype.patch | 32 ----- ...e-HT-primary-channel-while-connected.patch | 121 ------------------ sources | 2 +- 7 files changed, 6 insertions(+), 301 deletions(-) delete mode 100644 ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch delete mode 100644 iwl4965-reset-firmware-after-rfkill-off.patch delete mode 100644 mac80211-continue-using-disabled-channels-while-connected.patch delete mode 100644 mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch delete mode 100644 mac80211-ignore-HT-primary-channel-while-connected.patch diff --git a/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch b/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch deleted file mode 100644 index 9ce3433f9..000000000 --- a/ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 1801928e0f99d94c55e33c584c5eb2ff5e246ee6 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Fri, 16 Aug 2013 06:17:05 +0000 -Subject: ALSA: hda - Add a fixup for Gateway LT27 - -Gateway LT27 needs a fixup for the inverted digital mic. - -Reported-by: "Nathanael D. Noblet" -Cc: -Signed-off-by: Takashi Iwai ---- -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 5b22bf9..f303cd8 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -4339,6 +4339,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), - SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), -+ SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), - SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), - SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), --- -cgit v0.9.2 diff --git a/iwl4965-reset-firmware-after-rfkill-off.patch b/iwl4965-reset-firmware-after-rfkill-off.patch deleted file mode 100644 index 08b360d10..000000000 --- a/iwl4965-reset-firmware-after-rfkill-off.patch +++ /dev/null @@ -1,56 +0,0 @@ -Using rfkill switch can make firmware unstable, what cause various -Microcode errors and kernel warnings. Reseting firmware just after -rfkill off (radio on) helped with that. - -Resolve: -https://bugzilla.redhat.com/show_bug.cgi?id=977053 - -Reported-and-tested-by: Justin Pearce -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlegacy/4965-mac.c | 10 +++++----- - drivers/net/wireless/iwlegacy/common.c | 1 + - 2 files changed, 6 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c -index f0b7794..f2ed62e 100644 ---- a/drivers/net/wireless/iwlegacy/4965-mac.c -+++ b/drivers/net/wireless/iwlegacy/4965-mac.c -@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il) - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ -- if (!test_bit(S_ALIVE, &il->status)) { -- if (hw_rf_kill) -- set_bit(S_RFKILL, &il->status); -- else -- clear_bit(S_RFKILL, &il->status); -+ if (hw_rf_kill) { -+ set_bit(S_RFKILL, &il->status); -+ } else { -+ clear_bit(S_RFKILL, &il->status); - wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); -+ il_force_reset(il, true); - } - - handled |= CSR_INT_BIT_RF_KILL; -diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c -index 3195aad..b03e22e 100644 ---- a/drivers/net/wireless/iwlegacy/common.c -+++ b/drivers/net/wireless/iwlegacy/common.c -@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external) - - return 0; - } -+EXPORT_SYMBOL(il_force_reset); - - int - il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, --- -1.7.11.7 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index f201c79c1..e91ac95a8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -766,20 +766,9 @@ Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch -#rhbz 977053 -Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch - -#rhbz 981445 -Patch25074: mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch -Patch25075: mac80211-ignore-HT-primary-channel-while-connected.patch -Patch25076: mac80211-continue-using-disabled-channels-while-connected.patch - #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#rhbz 845699 -Patch25078: ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch - # END OF PATCH DEFINITIONS %endif @@ -1481,20 +1470,9 @@ ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch #rhbz 969473 ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch -#rhbz 977053 -ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch - -#rhbz 981445 -ApplyPatch mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch -ApplyPatch mac80211-ignore-HT-primary-channel-while-connected.patch -ApplyPatch mac80211-continue-using-disabled-channels-while-connected.patch - #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#rhbz 845699 -ApplyPatch ALSA-hda-Add-a-fixup-for-Gateway-LT27.patch - # END OF PATCH APPLICATIONS %endif @@ -2336,6 +2314,10 @@ fi # ||----w | # || || %changelog +* Tue Aug 20 2013 Josh Boyer - 3.10.8-10 +- Linux v3.10.8 +- CVE-2013-4254 ARM: perf: NULL pointer dereference in validate_event (rhbz 998878 998881) + * Fri Aug 16 2013 Josh Boyer - Add patch from Nathanael Noblet to fix mic on Gateway LT27 (rhbz 845699) diff --git a/mac80211-continue-using-disabled-channels-while-connected.patch b/mac80211-continue-using-disabled-channels-while-connected.patch deleted file mode 100644 index 91dd1d7db..000000000 --- a/mac80211-continue-using-disabled-channels-while-connected.patch +++ /dev/null @@ -1,43 +0,0 @@ -From ddfe49b42d8ad4bfdf92d63d4a74f162660d878d Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 31 Jul 2013 18:52:03 +0000 -Subject: mac80211: continue using disabled channels while connected - -In case the AP has different regulatory information than we do, -it can happen that we connect to an AP based on e.g. the world -roaming regulatory data, and then update our database with the -AP's country information disables the channel the AP is using. -If this happens on an HT AP, the bandwidth tracking code will -hit the WARN_ON() and disconnect. Since that's not very useful, -ignore the channel-disable flag in bandwidth tracking. - -Cc: stable@vger.kernel.org -Reported-by: Chris Wright -Tested-by: Chris Wright -Signed-off-by: Johannes Berg ---- -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 077a953..cc9e02d 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -335,8 +335,17 @@ out: - if (ret & IEEE80211_STA_DISABLE_VHT) - vht_chandef = *chandef; - -+ /* -+ * Ignore the DISABLED flag when we're already connected and only -+ * tracking the APs beacon for bandwidth changes - otherwise we -+ * might get disconnected here if we connect to an AP, update our -+ * regulatory information based on the AP's country IE and the -+ * information we have is wrong/outdated and disables the channel -+ * that we're actually using for the connection to the AP. -+ */ - while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, -- IEEE80211_CHAN_DISABLED)) { -+ tracking ? 0 : -+ IEEE80211_CHAN_DISABLED)) { - if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT; --- -cgit v0.9.2 diff --git a/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch b/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch deleted file mode 100644 index 49115f969..000000000 --- a/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b56e4b857c5210e848bfb80e074e5756a36cd523 Mon Sep 17 00:00:00 2001 -From: Chris Wright -Date: Wed, 31 Jul 2013 19:12:24 +0000 -Subject: mac80211: fix infinite loop in ieee80211_determine_chantype - -Commit "3d9646d mac80211: fix channel selection bug" introduced a possible -infinite loop by moving the out target above the chandef_downgrade -while loop. When we downgrade to NL80211_CHAN_WIDTH_20_NOHT, we jump -back up to re-run the while loop...indefinitely. Replace goto with -break and carry on. This may not be sufficient to connect to the AP, -but will at least keep the cpu from livelocking. Thanks to Derek Atkins -as an extra pair of debugging eyes. - -Cc: stable@kernel.org -Signed-off-by: Chris Wright -Signed-off-by: Johannes Berg ---- -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index ae31968..e3e7d2b 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -338,7 +338,7 @@ out: - if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT; -- goto out; -+ break; - } - - ret |= chandef_downgrade(chandef); --- -cgit v0.9.2 diff --git a/mac80211-ignore-HT-primary-channel-while-connected.patch b/mac80211-ignore-HT-primary-channel-while-connected.patch deleted file mode 100644 index ba5d2a478..000000000 --- a/mac80211-ignore-HT-primary-channel-while-connected.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 5cdaed1e878d723d56d04ae0be1738124acf9f46 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 31 Jul 2013 09:23:06 +0000 -Subject: mac80211: ignore HT primary channel while connected - -While we're connected, the AP shouldn't change the primary channel -in the HT information. We checked this, and dropped the connection -if it did change it. - -Unfortunately, this is causing problems on some APs, e.g. on the -Netgear WRT610NL: the beacons seem to always contain a bad channel -and if we made a connection using a probe response (correct data) -we drop the connection immediately and can basically not connect -properly at all. - -Work around this by ignoring the HT primary channel information in -beacons if we're already connected. - -Also print out more verbose messages in the other situations to -help diagnose similar bugs quicker in the future. - -Cc: stable@vger.kernel.org [3.10] -Acked-by: Andy Isaacson -Signed-off-by: Johannes Berg ---- -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index e5c3cf4..077a953 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -211,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *channel, - const struct ieee80211_ht_operation *ht_oper, - const struct ieee80211_vht_operation *vht_oper, -- struct cfg80211_chan_def *chandef, bool verbose) -+ struct cfg80211_chan_def *chandef, bool tracking) - { -+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct cfg80211_chan_def vht_chandef; - u32 ht_cfreq, ret; - -@@ -231,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, - channel->band); - /* check that channel matches the right operating channel */ -- if (channel->center_freq != ht_cfreq) { -+ if (!tracking && channel->center_freq != ht_cfreq) { - /* - * It's possible that some APs are confused here; - * Netgear WNDR3700 sometimes reports 4 higher than -@@ -239,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - * since we look at probe response/beacon data here - * it should be OK. - */ -- if (verbose) -- sdata_info(sdata, -- "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", -- channel->center_freq, ht_cfreq, -- ht_oper->primary_chan, channel->band); -+ sdata_info(sdata, -+ "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", -+ channel->center_freq, ht_cfreq, -+ ht_oper->primary_chan, channel->band); - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; - goto out; - } -@@ -297,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - channel->band); - break; - default: -- if (verbose) -+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) - sdata_info(sdata, - "AP VHT operation IE has invalid channel width (%d), disable VHT\n", - vht_oper->chan_width); -@@ -306,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - } - - if (!cfg80211_chandef_valid(&vht_chandef)) { -- if (verbose) -+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) - sdata_info(sdata, - "AP VHT information is invalid, disable VHT\n"); - ret = IEEE80211_STA_DISABLE_VHT; -@@ -319,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, - } - - if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { -- if (verbose) -+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) - sdata_info(sdata, - "AP VHT information doesn't match HT, disable VHT\n"); - ret = IEEE80211_STA_DISABLE_VHT; -@@ -346,7 +346,7 @@ out: - ret |= chandef_downgrade(chandef); - } - -- if (chandef->width != vht_chandef.width && verbose) -+ if (chandef->width != vht_chandef.width && !tracking) - sdata_info(sdata, - "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); - -@@ -386,7 +386,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, - - /* calculate new channel (type) based on HT/VHT operation IEs */ - flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, -- vht_oper, &chandef, false); -+ vht_oper, &chandef, true); - - /* - * Downgrade the new channel if we associated with restricted -@@ -3838,7 +3838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, - ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, - cbss->channel, - ht_oper, vht_oper, -- &chandef, true); -+ &chandef, false); - - sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), - local->rx_chains); --- -cgit v0.9.2 diff --git a/sources b/sources index cc0f04112..f1361d486 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -6b1b6b62044fcf3624f067154d5c1666 patch-3.10.7.xz +f62214b2847eef5fc22cfc9f1e2d28a3 patch-3.10.8.xz From 611904c0acb905da557e77abd808cccb22011188 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Aug 2013 19:29:52 -0400 Subject: [PATCH 401/492] Linux v3.10.9 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index e91ac95a8..0f2ad954e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2314,7 +2314,10 @@ fi # ||----w | # || || %changelog -* Tue Aug 20 2013 Josh Boyer - 3.10.8-10 +* Tue Aug 20 2013 Josh Boyer - 3.10.9-200 +- Linux v3.10.9 + +* Tue Aug 20 2013 Josh Boyer - 3.10.8-100 - Linux v3.10.8 - CVE-2013-4254 ARM: perf: NULL pointer dereference in validate_event (rhbz 998878 998881) diff --git a/sources b/sources index f1361d486..25af45e94 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -f62214b2847eef5fc22cfc9f1e2d28a3 patch-3.10.8.xz +868d7f5315f95da5e48ed56691a36263 patch-3.10.9.xz From 33cc7772bf8799b7f588d0093463f749c649d692 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 21 Aug 2013 09:14:20 -0400 Subject: [PATCH 402/492] CVE-2013-0343 handling of IPv6 temporary addresses (rhbz 914664 999380) --- ...sses-check-from-ipv6_create_tempaddr.patch | 63 +++++++++++++++++++ kernel.spec | 12 +++- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch diff --git a/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch b/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch new file mode 100644 index 000000000..0c4fc2484 --- /dev/null +++ b/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch @@ -0,0 +1,63 @@ +From 2712c283acc085b5438fa1b22053423a0158468d Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Fri, 16 Aug 2013 11:02:27 +0000 +Subject: [PATCH] ipv6: remove max_addresses check from ipv6_create_tempaddr + +Because of the max_addresses check attackers were able to disable privacy +extensions on an interface by creating enough autoconfigured addresses: + + + +But the check is not actually needed: max_addresses protects the +kernel to install too many ipv6 addresses on an interface and guards +addrconf_prefix_rcv to install further addresses as soon as this limit +is reached. We only generate temporary addresses in direct response of +a new address showing up. As soon as we filled up the maximum number of +addresses of an interface, we stop installing more addresses and thus +also stop generating more temp addresses. + +Even if the attacker tries to generate a lot of temporary addresses +by announcing a prefix and removing it again (lifetime == 0) we won't +install more temp addresses, because the temporary addresses do count +to the maximum number of addresses, thus we would stop installing new +autoconfigured addresses when the limit is reached. + +This patch fixes CVE-2013-0343 (but other layer-2 attacks are still +possible). + +Thanks to Ding Tianhong to bring this topic up again. + +Cc: Ding Tianhong +Cc: George Kargiotakis +Cc: P J P +Cc: YOSHIFUJI Hideaki +Signed-off-by: Hannes Frederic Sowa +Acked-by: Ding Tianhong +Signed-off-by: David S. Miller +--- + net/ipv6/addrconf.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index fb8c94c..21b7a87 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1124,12 +1124,10 @@ retry: + if (ifp->flags & IFA_F_OPTIMISTIC) + addr_flags |= IFA_F_OPTIMISTIC; + +- ift = !max_addresses || +- ipv6_count_addresses(idev) < max_addresses ? +- ipv6_add_addr(idev, &addr, tmp_plen, ++ ift = ipv6_add_addr(idev, &addr, tmp_plen, + ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, +- addr_flags) : NULL; +- if (IS_ERR_OR_NULL(ift)) { ++ addr_flags); ++ if (IS_ERR(ift)) { + in6_ifa_put(ifp); + in6_dev_put(idev); + pr_info("%s: retry temporary address regeneration\n", __func__); +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 0f2ad954e..99c4b18f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -769,6 +769,10 @@ Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch +#CVE-2013-0343 rhbz 914664 999380 +Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch + + # END OF PATCH DEFINITIONS %endif @@ -1473,6 +1477,9 @@ ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch +#CVE-2013-0343 rhbz 914664 999380 +ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch + # END OF PATCH APPLICATIONS %endif @@ -2314,7 +2321,10 @@ fi # ||----w | # || || %changelog -* Tue Aug 20 2013 Josh Boyer - 3.10.9-200 +* Wed Aug 21 2013 Josh Boyer +- CVE-2013-0343 handling of IPv6 temporary addresses (rhbz 914664 999380) + +* Tue Aug 20 2013 Josh Boyer - Linux v3.10.9 * Tue Aug 20 2013 Josh Boyer - 3.10.8-100 From 97e85a316628695d4f4f4982c1f51957be4e40bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 21 Aug 2013 13:37:46 -0400 Subject: [PATCH 403/492] Add patch to fix brcmsmac oops (rhbz 989269) --- 3.10.-6-7-crashes-on-network-activity.patch | 140 ++++++++++++++++++++ kernel.spec | 6 + 2 files changed, 146 insertions(+) create mode 100644 3.10.-6-7-crashes-on-network-activity.patch diff --git a/3.10.-6-7-crashes-on-network-activity.patch b/3.10.-6-7-crashes-on-network-activity.patch new file mode 100644 index 000000000..2e6b0d2ec --- /dev/null +++ b/3.10.-6-7-crashes-on-network-activity.patch @@ -0,0 +1,140 @@ +From 6aeddf9d409f3d9938b05b545d65810739237b2e Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Tue, 20 Aug 2013 06:56:08 +0200 +Subject: [PATCH] 3.10.{6,7} crashes on network activity + +On 2013-08-20 2:28 AM, Greg Kroah-Hartman wrote: +> On Tue, Aug 20, 2013 at 08:26:11AM +0800, Tom Gundersen wrote: +>> On Tue, Aug 20, 2013 at 8:03 AM, Greg Kroah-Hartman +>> wrote: +>> > On Tue, Aug 20, 2013 at 07:59:47AM +0800, Tom Gundersen wrote: +>> >> Hi guys, +>> >> +>> >> Starting with 3.10.6 (and still present in .7) I get an oops on +>> >> connecting to the network. +>> >> +>> >> The attached picture shows the oops. In case it does not reach the ML, +>> >> the top of the call trace reads: +>> >> +>> >> brcms_c_compute_rtscts_dur +>> >> brcms_c_ampdu_finalize +>> >> ampdu_finalize +>> >> dma_txfast +>> >> brcms_c_txfifo +>> >> brcms_c_sendpkt_mac80211 +>> >> brcms_ops_tx +>> >> __ieee80211_tx +>> >> +>> >> I bisected the problem and the first bad commit is +>> >> +>> >> commit ef47a5e4f1aaf1d0e2e6875e34b2c9595897bef6 +>> >> Author: Felix Fietkau +>> >> Date: Fri Jun 28 21:04:35 2013 +0200 +>> >> +>> >> mac80211/minstrel_ht: fix cck rate sampling +>> >> +>> >> commit 1cd158573951f737fbc878a35cb5eb47bf9af3d5 upstream. +>> >> +>> >> Reverting it on top of .7 fixes the problem. +>> >> +>> >> I had the same (I suppose) problem on mainline some time ago, but I +>> >> have not bisected it, verified that the problem still occurs there, or +>> >> checked if reverting the upstream patch fixes it. I'd be happy to do +>> >> that if it would help though. +>> >> +>> >> Let me know if you need any more information. +>> > +>> > Do you have this same problem with 3.11-rc6 as well? +>> +>> Yes, I just confirmed. I also confirmed that reverting the mainline +>> commit on top of -rc6 fixes the problem. +> +> Great, thanks. +> +> Felix and Johannes, any chance we can get this reverted in Linus tree +> soon, and push that revert back to the 3.10 stable tree as well? +I'd like to avoid a revert, since that will simply replace one set of +issues with another. Let's limit the use of the feature that brcmsmac +can't handle to drivers that are known to work with it. Tom, Please +test this patch to see if it fixes your issue. + +- Felix +--- + drivers/net/wireless/ath/ath9k/init.c | 3 ++- + drivers/net/wireless/ath/carl9170/main.c | 3 ++- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + include/net/mac80211.h | 1 + + net/mac80211/rc80211_minstrel_ht.c | 3 +++ + 5 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c +index 2ba4945..bd126c2 100644 +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -767,7 +767,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | +- IEEE80211_HW_SUPPORTS_RC_TABLE; ++ IEEE80211_HW_SUPPORTS_RC_TABLE | ++ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) + hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; +diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c +index e9010a4..0686375 100644 +--- a/drivers/net/wireless/ath/carl9170/main.c ++++ b/drivers/net/wireless/ath/carl9170/main.c +@@ -1857,7 +1857,8 @@ void *carl9170_alloc(size_t priv_size) + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | +- IEEE80211_HW_SIGNAL_DBM; ++ IEEE80211_HW_SIGNAL_DBM | ++ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; + + if (!modparam_noht) { + /* +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 705aa33..7e66a90 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -5912,7 +5912,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_AMPDU_AGGREGATION | +- IEEE80211_HW_REPORTS_TX_ACK_STATUS; ++ IEEE80211_HW_REPORTS_TX_ACK_STATUS | ++ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; + + /* + * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 885898a..4e50d36 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1484,6 +1484,7 @@ enum ieee80211_hw_flags { + IEEE80211_HW_SUPPORTS_RC_TABLE = 1<<24, + IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, + IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, ++ IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, + }; + + /** +diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c +index f5aed96..f3bbea1 100644 +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -828,6 +828,9 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, + if (sband->band != IEEE80211_BAND_2GHZ) + return; + ++ if (!(mp->hw->flags & IEEE80211_HW_SUPPORTS_HT_CCK_RATES)) ++ return; ++ + mi->cck_supported = 0; + mi->cck_supported_short = 0; + for (i = 0; i < 4; i++) { +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 99c4b18f9..e3ea9d00c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -772,6 +772,8 @@ Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020 #CVE-2013-0343 rhbz 914664 999380 Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch +#rhbz 989269 +Patch25079: 3.10.-6-7-crashes-on-network-activity.patch # END OF PATCH DEFINITIONS @@ -1480,6 +1482,9 @@ ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020. #CVE-2013-0343 rhbz 914664 999380 ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch +#rhbz 989269 +ApplyPatch 3.10.-6-7-crashes-on-network-activity.patch + # END OF PATCH APPLICATIONS %endif @@ -2322,6 +2327,7 @@ fi # || || %changelog * Wed Aug 21 2013 Josh Boyer +- Add patch to fix brcmsmac oops (rhbz 989269) - CVE-2013-0343 handling of IPv6 temporary addresses (rhbz 914664 999380) * Tue Aug 20 2013 Josh Boyer From c6db3c33f906f0e7f3866c36a5ddbd75a9812361 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Aug 2013 14:33:47 -0400 Subject: [PATCH 404/492] Add mei patches that fix various s/r issues (rhbz 994824 989373) --- kernel.spec | 9 +- mei-3.10.y.patch | 357 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 mei-3.10.y.patch diff --git a/kernel.spec b/kernel.spec index e3ea9d00c..2cc0c12c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -775,6 +775,8 @@ Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch #rhbz 989269 Patch25079: 3.10.-6-7-crashes-on-network-activity.patch +Patch25090: mei-3.10.y.patch + # END OF PATCH DEFINITIONS %endif @@ -1485,6 +1487,8 @@ ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch #rhbz 989269 ApplyPatch 3.10.-6-7-crashes-on-network-activity.patch +ApplyPatch mei-3.10.y.patch + # END OF PATCH APPLICATIONS %endif @@ -2326,6 +2330,9 @@ fi # ||----w | # || || %changelog +* Wed Aug 28 2013 Josh Boyer +- Add mei patches that fix various s/r issues (rhbz 994824 989373) + * Wed Aug 21 2013 Josh Boyer - Add patch to fix brcmsmac oops (rhbz 989269) - CVE-2013-0343 handling of IPv6 temporary addresses (rhbz 914664 999380) diff --git a/mei-3.10.y.patch b/mei-3.10.y.patch new file mode 100644 index 000000000..210adac5a --- /dev/null +++ b/mei-3.10.y.patch @@ -0,0 +1,357 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp116476oab; + Sun, 25 Aug 2013 02:53:05 -0700 (PDT) +X-Received: by 10.68.212.37 with SMTP id nh5mr9408188pbc.16.1377424384710; + Sun, 25 Aug 2013 02:53:04 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id qf5si6944869pac.66.1969.12.31.16.00.00; + Sun, 25 Aug 2013 02:53:04 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756376Ab3HYJwV (ORCPT + + 58 others); Sun, 25 Aug 2013 05:52:21 -0400 +Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1756234Ab3HYJwM (ORCPT ); + Sun, 25 Aug 2013 05:52:12 -0400 +Received: from azsmga001.ch.intel.com ([10.2.17.19]) + by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:12 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; + d="scan'208";a="351301658" +Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) + by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:10 -0700 +From: Tomas Winkler +To: gregkh@linuxfoundation.org +Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, + Tomas Winkler , stable@vger.kernel.org +Subject: [3.10][PATCH 1/4] mei: me: fix reset state machine +Date: Sun, 25 Aug 2013 12:49:46 +0300 +Message-Id: <1377424189-5508-2-git-send-email-tomas.winkler@intel.com> +X-Mailer: git-send-email 1.8.1.2 +In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +stable: 3.10 +commit 315a383ad7dbd484fafb93ef08038e3dbafbb7a8 upstream + + +ME HW ready bit is down after hw reset was asserted or on error. +Only on error we need to enter the reset flow, additional reset +need to be prevented when reset was triggered during +initialization , power up/down or a reset is already in progress + +Cc: stable@vger.kernel.org +Tested-by: Shuah Khan +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/mei/hw-me.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c +index 822170f..0310859 100644 +--- a/drivers/misc/mei/hw-me.c ++++ b/drivers/misc/mei/hw-me.c +@@ -482,7 +482,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) + /* check if ME wants a reset */ + if (!mei_hw_is_ready(dev) && + dev->dev_state != MEI_DEV_RESETTING && +- dev->dev_state != MEI_DEV_INITIALIZING) { ++ dev->dev_state != MEI_DEV_INITIALIZING && ++ dev->dev_state != MEI_DEV_POWER_DOWN && ++ dev->dev_state != MEI_DEV_POWER_UP) { + dev_dbg(&dev->pdev->dev, "FW not ready.\n"); + mei_reset(dev, 1); + mutex_unlock(&dev->device_lock); +-- +1.8.1.2 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp116479oab; + Sun, 25 Aug 2013 02:53:12 -0700 (PDT) +X-Received: by 10.68.219.104 with SMTP id pn8mr9271522pbc.81.1377424392029; + Sun, 25 Aug 2013 02:53:12 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id ut10si6347816pbc.210.1969.12.31.16.00.00; + Sun, 25 Aug 2013 02:53:12 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756385Ab3HYJwW (ORCPT + + 58 others); Sun, 25 Aug 2013 05:52:22 -0400 +Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1756301Ab3HYJwO (ORCPT ); + Sun, 25 Aug 2013 05:52:14 -0400 +Received: from azsmga001.ch.intel.com ([10.2.17.19]) + by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:14 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; + d="scan'208";a="351301662" +Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) + by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:12 -0700 +From: Tomas Winkler +To: gregkh@linuxfoundation.org +Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, + Tomas Winkler , stable@vger.kernel.org +Subject: [3.10][PATCH 2/4] mei: don't have to clean the state on power up +Date: Sun, 25 Aug 2013 12:49:47 +0300 +Message-Id: <1377424189-5508-3-git-send-email-tomas.winkler@intel.com> +X-Mailer: git-send-email 1.8.1.2 +In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +stable: 3.10 +commit 99f22c4ef24cf87b0dae6aabe6b5e620b62961d9 upstream + +When powering up, we don't have to clean up the device state +nothing is connected. + +Cc: stable@vger.kernel.org +Tested-by: Shuah Khan +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/mei/init.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c +index f580d30..6eec689 100644 +--- a/drivers/misc/mei/init.c ++++ b/drivers/misc/mei/init.c +@@ -143,7 +143,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) + + dev->hbm_state = MEI_HBM_IDLE; + +- if (dev->dev_state != MEI_DEV_INITIALIZING) { ++ if (dev->dev_state != MEI_DEV_INITIALIZING && ++ dev->dev_state != MEI_DEV_POWER_UP) { + if (dev->dev_state != MEI_DEV_DISABLED && + dev->dev_state != MEI_DEV_POWER_DOWN) + dev->dev_state = MEI_DEV_RESETTING; +-- +1.8.1.2 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp116502oab; + Sun, 25 Aug 2013 02:54:30 -0700 (PDT) +X-Received: by 10.68.102.165 with SMTP id fp5mr9198656pbb.83.1377424469866; + Sun, 25 Aug 2013 02:54:29 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id yk3si6904106pac.244.1969.12.31.16.00.00; + Sun, 25 Aug 2013 02:54:29 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756437Ab3HYJwo (ORCPT + + 58 others); Sun, 25 Aug 2013 05:52:44 -0400 +Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1756338Ab3HYJwQ (ORCPT ); + Sun, 25 Aug 2013 05:52:16 -0400 +Received: from azsmga001.ch.intel.com ([10.2.17.19]) + by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:16 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; + d="scan'208";a="351301665" +Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) + by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:14 -0700 +From: Tomas Winkler +To: gregkh@linuxfoundation.org +Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, + Tomas Winkler , stable@vger.kernel.org +Subject: [3.10][PATCH 3/4] mei: me: fix waiting for hw ready +Date: Sun, 25 Aug 2013 12:49:48 +0300 +Message-Id: <1377424189-5508-4-git-send-email-tomas.winkler@intel.com> +X-Mailer: git-send-email 1.8.1.2 +In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +stable: 3.10 +commit dab9bf41b23fe700c4a74133e41eb6a21706031e upstream + + +1. MEI_INTEROP_TIMEOUT is in seconds not in jiffies +so we use mei_secs_to_jiffies macro +While cold boot is fast this is relevant in resume +2. wait_event_interruptible_timeout can return with +-ERESTARTSYS so do not override it with -ETIMEDOUT +3.Adjust error message + +Cc: stable@vger.kernel.org +Tested-by: Shuah Khan +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/mei/hw-me.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c +index 0310859..700fe55 100644 +--- a/drivers/misc/mei/hw-me.c ++++ b/drivers/misc/mei/hw-me.c +@@ -238,14 +238,18 @@ static int mei_me_hw_ready_wait(struct mei_device *dev) + if (mei_me_hw_is_ready(dev)) + return 0; + ++ dev->recvd_hw_ready = false; + mutex_unlock(&dev->device_lock); + err = wait_event_interruptible_timeout(dev->wait_hw_ready, +- dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT); ++ dev->recvd_hw_ready, ++ mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); + mutex_lock(&dev->device_lock); + if (!err && !dev->recvd_hw_ready) { ++ if (!err) ++ err = -ETIMEDOUT; + dev_err(&dev->pdev->dev, +- "wait hw ready failed. status = 0x%x\n", err); +- return -ETIMEDOUT; ++ "wait hw ready failed. status = %d\n", err); ++ return err; + } + + dev->recvd_hw_ready = false; +-- +1.8.1.2 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp116477oab; + Sun, 25 Aug 2013 02:53:06 -0700 (PDT) +X-Received: by 10.66.146.42 with SMTP id sz10mr8515943pab.78.1377424384757; + Sun, 25 Aug 2013 02:53:04 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id zu9si6326866pbc.308.1969.12.31.16.00.00; + Sun, 25 Aug 2013 02:53:04 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756391Ab3HYJwW (ORCPT + + 58 others); Sun, 25 Aug 2013 05:52:22 -0400 +Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1756361Ab3HYJwT (ORCPT ); + Sun, 25 Aug 2013 05:52:19 -0400 +Received: from azsmga001.ch.intel.com ([10.2.17.19]) + by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:18 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; + d="scan'208";a="351301674" +Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) + by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:16 -0700 +From: Tomas Winkler +To: gregkh@linuxfoundation.org +Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, + Tomas Winkler , + stable@vger.kernel.org, Shuah Khan , + Konstantin Khlebnikov +Subject: [3.10][PATCH 4/4] mei: me: fix hardware reset flow +Date: Sun, 25 Aug 2013 12:49:49 +0300 +Message-Id: <1377424189-5508-5-git-send-email-tomas.winkler@intel.com> +X-Mailer: git-send-email 1.8.1.2 +In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +stable: 3.10 +commit ff96066e3171acdea356b331163495957cb833d0 char-misc + + +Both H_IS and H_IE needs to be set to receive H_RDY +interrupt + +1. Assert H_IS to clear the interrupts during hw reset +and use mei_me_reg_write instead of mei_hcsr_set as the later +strips down the H_IS + +2. fix interrupt disablement embarrassing typo + hcsr |= ~H_IE -> hcsr &= ~H_IE; +this will remove the unwanted interrupt on power down + +3. remove useless debug print outs + +Cc: stable@vger.kernel.org +Cc: Shuah Khan +Cc: Konstantin Khlebnikov +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman + +Conflicts: + drivers/misc/mei/hw-me.c + +--- + drivers/misc/mei/hw-me.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c +index 700fe55..1bf3f8b 100644 +--- a/drivers/misc/mei/hw-me.c ++++ b/drivers/misc/mei/hw-me.c +@@ -176,16 +176,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); + +- dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); +- +- hcsr |= (H_RST | H_IG); ++ hcsr |= H_RST | H_IG | H_IS; + + if (intr_enable) + hcsr |= H_IE; + else +- hcsr |= ~H_IE; ++ hcsr &= ~H_IE; + +- mei_hcsr_set(hw, hcsr); ++ mei_me_reg_write(hw, H_CSR, hcsr); + + if (dev->dev_state == MEI_DEV_POWER_DOWN) + mei_me_hw_reset_release(dev); +-- +1.8.1.2 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html From 6f9dd97c292f7f853a4fe8763360fb93025b80e6 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 29 Aug 2013 13:51:49 -0500 Subject: [PATCH 405/492] Linux v3.10.10 --- devel-pekey-secure-boot-20130502.patch | 4 +- ...ng-ieee80211_chswitch_done-with-NULL.patch | 58 ---- kernel.spec | 13 +- mei-3.10.y.patch | 253 ------------------ sources | 2 +- 5 files changed, 8 insertions(+), 322 deletions(-) delete mode 100644 iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch diff --git a/devel-pekey-secure-boot-20130502.patch b/devel-pekey-secure-boot-20130502.patch index 703bbf5ad..0a5342f83 100644 --- a/devel-pekey-secure-boot-20130502.patch +++ b/devel-pekey-secure-boot-20130502.patch @@ -4670,9 +4670,9 @@ index 653668d..69a6c08 100644 --- a/arch/x86/include/asm/bootparam_utils.h +++ b/arch/x86/include/asm/bootparam_utils.h @@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params) - memset(&boot_params->olpc_ofw_header, 0, + memset(&boot_params->ext_ramdisk_image, 0, (char *)&boot_params->efi_info - - (char *)&boot_params->olpc_ofw_header); + (char *)&boot_params->ext_ramdisk_image); - memset(&boot_params->kbd_status, 0, + memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status)); + /* don't clear boot_params->secure_boot. we set that ourselves diff --git a/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch b/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch deleted file mode 100644 index 84d6aa06d..000000000 --- a/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch +++ /dev/null @@ -1,58 +0,0 @@ -If channel switch is pending and we remove interface we can -crash like showed below due to passing NULL vif to mac80211: - -BUG: unable to handle kernel paging request at fffffffffffff8cc -IP: [] strnlen+0xd/0x40 -Call Trace: - [] string.isra.3+0x3e/0xd0 - [] vsnprintf+0x219/0x640 - [] vscnprintf+0x11/0x30 - [] vprintk_emit+0x115/0x4f0 - [] printk+0x61/0x63 - [] ieee80211_chswitch_done+0xaf/0xd0 [mac80211] - [] iwl_chswitch_done+0x34/0x40 [iwldvm] - [] iwlagn_commit_rxon+0x2a3/0xdc0 [iwldvm] - [] ? iwlagn_set_rxon_chain+0x180/0x2c0 [iwldvm] - [] iwl_set_mode+0x36/0x40 [iwldvm] - [] iwlagn_mac_remove_interface+0x8d/0x1b0 [iwldvm] - [] ieee80211_do_stop+0x29d/0x7f0 [mac80211] - -This is because we nulify ctx->vif in iwlagn_mac_remove_interface() -before calling some other functions that teardown interface. To fix -just check ctx->vif on iwl_chswitch_done(). We should not call -ieee80211_chswitch_done() as channel switch works were already canceled -by mac80211 in ieee80211_do_stop() -> ieee80211_mgd_stop(). - -Resolve: -https://bugzilla.redhat.com/show_bug.cgi?id=979581 - -Cc: stable@vger.kernel.org -Reported-by: Lukasz Jagiello -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/dvm/mac80211.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c -index 323e4a3..9a817df 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c -+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c -@@ -1046,7 +1046,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - -- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) -+ if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) -+ return; -+ -+ if (ctx->vif) - ieee80211_chswitch_done(ctx->vif, is_success); - } - --- -1.7.11.7 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 2cc0c12c0..0a736f380 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -760,9 +760,6 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #rhbz 959721 Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch -#rhbz 979581 -Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch - #rhbz 969473 Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch @@ -1472,9 +1469,6 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #rhbz 959721 ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch -#rhbz 979581 -ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch - #rhbz 969473 ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch @@ -2330,6 +2324,9 @@ fi # ||----w | # || || %changelog +* Thu Aug 29 2013 Justin M. Forbes 3.10.10-100 +- Linux v3.10.10 + * Wed Aug 28 2013 Josh Boyer - Add mei patches that fix various s/r issues (rhbz 994824 989373) diff --git a/mei-3.10.y.patch b/mei-3.10.y.patch index 210adac5a..b0c6c34b5 100644 --- a/mei-3.10.y.patch +++ b/mei-3.10.y.patch @@ -1,256 +1,3 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.168.104 with SMTP id zv8csp116476oab; - Sun, 25 Aug 2013 02:53:05 -0700 (PDT) -X-Received: by 10.68.212.37 with SMTP id nh5mr9408188pbc.16.1377424384710; - Sun, 25 Aug 2013 02:53:04 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id qf5si6944869pac.66.1969.12.31.16.00.00; - Sun, 25 Aug 2013 02:53:04 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756376Ab3HYJwV (ORCPT - + 58 others); Sun, 25 Aug 2013 05:52:21 -0400 -Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1756234Ab3HYJwM (ORCPT ); - Sun, 25 Aug 2013 05:52:12 -0400 -Received: from azsmga001.ch.intel.com ([10.2.17.19]) - by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:12 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; - d="scan'208";a="351301658" -Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) - by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:10 -0700 -From: Tomas Winkler -To: gregkh@linuxfoundation.org -Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, - Tomas Winkler , stable@vger.kernel.org -Subject: [3.10][PATCH 1/4] mei: me: fix reset state machine -Date: Sun, 25 Aug 2013 12:49:46 +0300 -Message-Id: <1377424189-5508-2-git-send-email-tomas.winkler@intel.com> -X-Mailer: git-send-email 1.8.1.2 -In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -stable: 3.10 -commit 315a383ad7dbd484fafb93ef08038e3dbafbb7a8 upstream - - -ME HW ready bit is down after hw reset was asserted or on error. -Only on error we need to enter the reset flow, additional reset -need to be prevented when reset was triggered during -initialization , power up/down or a reset is already in progress - -Cc: stable@vger.kernel.org -Tested-by: Shuah Khan -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman ---- - drivers/misc/mei/hw-me.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c -index 822170f..0310859 100644 ---- a/drivers/misc/mei/hw-me.c -+++ b/drivers/misc/mei/hw-me.c -@@ -482,7 +482,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) - /* check if ME wants a reset */ - if (!mei_hw_is_ready(dev) && - dev->dev_state != MEI_DEV_RESETTING && -- dev->dev_state != MEI_DEV_INITIALIZING) { -+ dev->dev_state != MEI_DEV_INITIALIZING && -+ dev->dev_state != MEI_DEV_POWER_DOWN && -+ dev->dev_state != MEI_DEV_POWER_UP) { - dev_dbg(&dev->pdev->dev, "FW not ready.\n"); - mei_reset(dev, 1); - mutex_unlock(&dev->device_lock); --- -1.8.1.2 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.168.104 with SMTP id zv8csp116479oab; - Sun, 25 Aug 2013 02:53:12 -0700 (PDT) -X-Received: by 10.68.219.104 with SMTP id pn8mr9271522pbc.81.1377424392029; - Sun, 25 Aug 2013 02:53:12 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id ut10si6347816pbc.210.1969.12.31.16.00.00; - Sun, 25 Aug 2013 02:53:12 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756385Ab3HYJwW (ORCPT - + 58 others); Sun, 25 Aug 2013 05:52:22 -0400 -Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1756301Ab3HYJwO (ORCPT ); - Sun, 25 Aug 2013 05:52:14 -0400 -Received: from azsmga001.ch.intel.com ([10.2.17.19]) - by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:14 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; - d="scan'208";a="351301662" -Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) - by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:12 -0700 -From: Tomas Winkler -To: gregkh@linuxfoundation.org -Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, - Tomas Winkler , stable@vger.kernel.org -Subject: [3.10][PATCH 2/4] mei: don't have to clean the state on power up -Date: Sun, 25 Aug 2013 12:49:47 +0300 -Message-Id: <1377424189-5508-3-git-send-email-tomas.winkler@intel.com> -X-Mailer: git-send-email 1.8.1.2 -In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -stable: 3.10 -commit 99f22c4ef24cf87b0dae6aabe6b5e620b62961d9 upstream - -When powering up, we don't have to clean up the device state -nothing is connected. - -Cc: stable@vger.kernel.org -Tested-by: Shuah Khan -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman ---- - drivers/misc/mei/init.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c -index f580d30..6eec689 100644 ---- a/drivers/misc/mei/init.c -+++ b/drivers/misc/mei/init.c -@@ -143,7 +143,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) - - dev->hbm_state = MEI_HBM_IDLE; - -- if (dev->dev_state != MEI_DEV_INITIALIZING) { -+ if (dev->dev_state != MEI_DEV_INITIALIZING && -+ dev->dev_state != MEI_DEV_POWER_UP) { - if (dev->dev_state != MEI_DEV_DISABLED && - dev->dev_state != MEI_DEV_POWER_DOWN) - dev->dev_state = MEI_DEV_RESETTING; --- -1.8.1.2 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.168.104 with SMTP id zv8csp116502oab; - Sun, 25 Aug 2013 02:54:30 -0700 (PDT) -X-Received: by 10.68.102.165 with SMTP id fp5mr9198656pbb.83.1377424469866; - Sun, 25 Aug 2013 02:54:29 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id yk3si6904106pac.244.1969.12.31.16.00.00; - Sun, 25 Aug 2013 02:54:29 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756437Ab3HYJwo (ORCPT - + 58 others); Sun, 25 Aug 2013 05:52:44 -0400 -Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1756338Ab3HYJwQ (ORCPT ); - Sun, 25 Aug 2013 05:52:16 -0400 -Received: from azsmga001.ch.intel.com ([10.2.17.19]) - by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:16 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; - d="scan'208";a="351301665" -Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) - by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:14 -0700 -From: Tomas Winkler -To: gregkh@linuxfoundation.org -Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, - Tomas Winkler , stable@vger.kernel.org -Subject: [3.10][PATCH 3/4] mei: me: fix waiting for hw ready -Date: Sun, 25 Aug 2013 12:49:48 +0300 -Message-Id: <1377424189-5508-4-git-send-email-tomas.winkler@intel.com> -X-Mailer: git-send-email 1.8.1.2 -In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -stable: 3.10 -commit dab9bf41b23fe700c4a74133e41eb6a21706031e upstream - - -1. MEI_INTEROP_TIMEOUT is in seconds not in jiffies -so we use mei_secs_to_jiffies macro -While cold boot is fast this is relevant in resume -2. wait_event_interruptible_timeout can return with --ERESTARTSYS so do not override it with -ETIMEDOUT -3.Adjust error message - -Cc: stable@vger.kernel.org -Tested-by: Shuah Khan -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman ---- - drivers/misc/mei/hw-me.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c -index 0310859..700fe55 100644 ---- a/drivers/misc/mei/hw-me.c -+++ b/drivers/misc/mei/hw-me.c -@@ -238,14 +238,18 @@ static int mei_me_hw_ready_wait(struct mei_device *dev) - if (mei_me_hw_is_ready(dev)) - return 0; - -+ dev->recvd_hw_ready = false; - mutex_unlock(&dev->device_lock); - err = wait_event_interruptible_timeout(dev->wait_hw_ready, -- dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT); -+ dev->recvd_hw_ready, -+ mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); - mutex_lock(&dev->device_lock); - if (!err && !dev->recvd_hw_ready) { -+ if (!err) -+ err = -ETIMEDOUT; - dev_err(&dev->pdev->dev, -- "wait hw ready failed. status = 0x%x\n", err); -- return -ETIMEDOUT; -+ "wait hw ready failed. status = %d\n", err); -+ return err; - } - - dev->recvd_hw_ready = false; --- -1.8.1.2 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - Delivered-To: jwboyer@gmail.com Received: by 10.76.168.104 with SMTP id zv8csp116477oab; Sun, 25 Aug 2013 02:53:06 -0700 (PDT) diff --git a/sources b/sources index 25af45e94..0479b31a7 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -868d7f5315f95da5e48ed56691a36263 patch-3.10.9.xz +d010ef17d3e577fd1bdcb6887f2b9836 patch-3.10.10.xz From 2392a892c3ddfdac174abe96879a28e6f61419b3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Aug 2013 13:03:20 -0400 Subject: [PATCH 406/492] Fix HID CVEs. Absurd. - CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 - CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 - CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 - CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 - CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 --- HID-CVE-fixes.patch | 1405 +++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 22 + 2 files changed, 1427 insertions(+) create mode 100644 HID-CVE-fixes.patch diff --git a/HID-CVE-fixes.patch b/HID-CVE-fixes.patch new file mode 100644 index 000000000..2b52d013f --- /dev/null +++ b/HID-CVE-fixes.patch @@ -0,0 +1,1405 @@ +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 01/14] HID: validate HID report id size +Date: Wed, 28 Aug 2013 22:29:55 +0200 (CEST) +Lines: 81 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721804 9521 80.91.229.3 (28 Aug 2013 20:30:04 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:04 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:06 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmNR-0008U8-2t + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:05 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754658Ab3H1UaD (ORCPT ); + Wed, 28 Aug 2013 16:30:03 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57907 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752748Ab3H1UaD (ORCPT ); + Wed, 28 Aug 2013 16:30:03 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 1C5ACA535B; + Wed, 28 Aug 2013 22:30:01 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31652 +Archived-At: + +From: Kees Cook + +The "Report ID" field of a HID report is used to build indexes of +reports. The kernel's index of these is limited to 256 entries, so any +malicious device that sets a Report ID greater than 255 will trigger +memory corruption on the host: + +[ 1347.156239] BUG: unable to handle kernel paging request at ffff88094958a878 +[ 1347.156261] IP: [] hid_register_report+0x2a/0x8b + +CVE-2013-2888 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-core.c | 10 +++++++--- + include/linux/hid.h | 4 +++- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 36668d1..5ea7d51 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, + struct hid_report_enum *report_enum = device->report_enum + type; + struct hid_report *report; + ++ if (id >= HID_MAX_IDS) ++ return NULL; + if (report_enum->report_id_hash[id]) + return report_enum->report_id_hash[id]; + +@@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) + + case HID_GLOBAL_ITEM_TAG_REPORT_ID: + parser->global.report_id = item_udata(item); +- if (parser->global.report_id == 0) { +- hid_err(parser->device, "report_id 0 is invalid\n"); ++ if (parser->global.report_id == 0 || ++ parser->global.report_id >= HID_MAX_IDS) { ++ hid_err(parser->device, "report_id %u is invalid\n", ++ parser->global.report_id); + return -1; + } + return 0; +@@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device) + for (i = 0; i < HID_REPORT_TYPES; i++) { + struct hid_report_enum *report_enum = device->report_enum + i; + +- for (j = 0; j < 256; j++) { ++ for (j = 0; j < HID_MAX_IDS; j++) { + struct hid_report *report = report_enum->report_id_hash[j]; + if (report) + hid_free_report(report); +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 0c48991..ff545cc 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -393,10 +393,12 @@ struct hid_report { + struct hid_device *device; /* associated device */ + }; + ++#define HID_MAX_IDS 256 ++ + struct hid_report_enum { + unsigned numbered; + struct list_head report_list; +- struct hid_report *report_id_hash[256]; ++ struct hid_report *report_id_hash[HID_MAX_IDS]; + }; + + #define HID_REPORT_TYPES 3 + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 02/14] HID: provide a helper for validating hid reports +Date: Wed, 28 Aug 2013 22:30:06 +0200 (CEST) +Lines: 99 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721810 9564 80.91.229.3 (28 Aug 2013 20:30:10 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:10 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:12 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmNX-0008U8-Cg + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:11 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754750Ab3H1UaK (ORCPT ); + Wed, 28 Aug 2013 16:30:10 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57911 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752748Ab3H1UaK (ORCPT ); + Wed, 28 Aug 2013 16:30:10 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 3C054A531D; + Wed, 28 Aug 2013 22:30:09 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31653 +Archived-At: + +From: Kees Cook + +Many drivers need to validate the characteristics of their HID report +during initialization to avoid misusing the reports. This adds a common +helper to perform validation of the report, its field count, and the +value count within the fields. + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-core.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/hid.h | 4 ++++ + 2 files changed, 54 insertions(+) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 5ea7d51..55798b2 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -759,6 +759,56 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) + } + EXPORT_SYMBOL_GPL(hid_parse_report); + ++static const char * const hid_report_names[] = { ++ "HID_INPUT_REPORT", ++ "HID_OUTPUT_REPORT", ++ "HID_FEATURE_REPORT", ++}; ++/** ++ * hid_validate_report - validate existing device report ++ * ++ * @device: hid device ++ * @type: which report type to examine ++ * @id: which report ID to examine (0 for first) ++ * @fields: expected number of fields ++ * @report_counts: expected number of values per field ++ * ++ * Validate the report details after parsing. ++ */ ++struct hid_report *hid_validate_report(struct hid_device *hid, ++ unsigned int type, unsigned int id, ++ unsigned int fields, ++ unsigned int report_counts) ++{ ++ struct hid_report *report; ++ unsigned int i; ++ ++ if (type > HID_FEATURE_REPORT) { ++ hid_err(hid, "invalid HID report %u\n", type); ++ return NULL; ++ } ++ ++ report = hid->report_enum[type].report_id_hash[id]; ++ if (!report) { ++ hid_err(hid, "missing %s %u\n", hid_report_names[type], id); ++ return NULL; ++ } ++ if (report->maxfield < fields) { ++ hid_err(hid, "not enough fields in %s %u\n", ++ hid_report_names[type], id); ++ return NULL; ++ } ++ for (i = 0; i < fields; i++) { ++ if (report->field[i]->report_count < report_counts) { ++ hid_err(hid, "not enough values in %s %u fields\n", ++ hid_report_names[type], id); ++ return NULL; ++ } ++ } ++ return report; ++} ++EXPORT_SYMBOL_GPL(hid_validate_report); ++ + /** + * hid_open_report - open a driver-specific device report + * +diff --git a/include/linux/hid.h b/include/linux/hid.h +index ff545cc..76e41d8 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -749,6 +749,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); + struct hid_device *hid_allocate_device(void); + struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); + int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); ++struct hid_report *hid_validate_report(struct hid_device *hid, ++ unsigned int type, unsigned int id, ++ unsigned int fields, ++ unsigned int report_counts); + int hid_open_report(struct hid_device *device); + int hid_check_keys_pressed(struct hid_device *hid); + int hid_connect(struct hid_device *hid, unsigned int connect_mask); + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 03/14] HID: zeroplus: validate output report details +Date: Wed, 28 Aug 2013 22:30:15 +0200 (CEST) +Lines: 57 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721819 9648 80.91.229.3 (28 Aug 2013 20:30:19 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:19 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:21 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmNg-0008U8-24 + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:21 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754896Ab3H1UaT (ORCPT ); + Wed, 28 Aug 2013 16:30:19 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57913 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752748Ab3H1UaS (ORCPT ); + Wed, 28 Aug 2013 16:30:18 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id A94ACA531D; + Wed, 28 Aug 2013 22:30:17 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31654 +Archived-At: + +From: Kees Cook + +The zeroplus HID driver was not checking the size of allocated values +in fields it used. A HID device could send a malicious output report +that would cause the driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 1442.728680] usb 1-1: New USB device found, idVendor=0c12, idProduct=0005 +... +[ 1466.243173] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2889 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-zpff.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c +index 6ec28a3..b124991 100644 +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -68,22 +68,12 @@ static int zpff_init(struct hid_device *hid) + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); ++ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 4, 1); ++ if (!report) + return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 4) { +- hid_err(hid, "not enough fields in report\n"); +- return -ENODEV; +- } + + zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); + if (!zpff) + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 05/14] HID: steelseries: validate output report details +Date: Wed, 28 Aug 2013 22:30:37 +0200 (CEST) +Lines: 43 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721849 9885 80.91.229.3 (28 Aug 2013 20:30:49 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:49 +0000 (UTC) +Cc: Kees Cook , Simon Wood +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:51 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmO7-0000cl-Po + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:48 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1755238Ab3H1Uam (ORCPT ); + Wed, 28 Aug 2013 16:30:42 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57942 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754222Ab3H1Uak (ORCPT ); + Wed, 28 Aug 2013 16:30:40 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id EFDE1A531D; + Wed, 28 Aug 2013 22:30:39 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31656 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +steelseries HID driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 167.981534] usb 1-1: New USB device found, idVendor=1038, idProduct=1410 +... +[ 182.050547] BUG kmalloc-256 (Tainted: G W ): Redzone overwritten + +CVE-2013-2891 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-steelseries.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c +index d164911..ef42e86 100644 +--- a/drivers/hid/hid-steelseries.c ++++ b/drivers/hid/hid-steelseries.c +@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, + goto err_free; + } + ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 16)) { ++ ret = -ENODEV; ++ goto err_free; ++ } ++ + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 06/14] HID: pantherlord: validate output report details +Date: Wed, 28 Aug 2013 22:30:49 +0200 (CEST) +Lines: 47 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721853 9919 80.91.229.3 (28 Aug 2013 20:30:53 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:53 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:55 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOD-0000cl-Qd + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:54 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754500Ab3H1Uax (ORCPT ); + Wed, 28 Aug 2013 16:30:53 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57948 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1753468Ab3H1Uaw (ORCPT ); + Wed, 28 Aug 2013 16:30:52 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 21315A531D; + Wed, 28 Aug 2013 22:30:52 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31657 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +pantherlord HID driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 310.939483] usb 1-1: New USB device found, idVendor=0e8f, idProduct=0003 +... +[ 315.980774] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2892 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-pl.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c +index d29112f..2dcd7d9 100644 +--- a/drivers/hid/hid-pl.c ++++ b/drivers/hid/hid-pl.c +@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid) + strong = &report->field[0]->value[2]; + weak = &report->field[0]->value[3]; + debug("detected single-field device"); +- } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && +- report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { ++ } else if (report->field[0]->maxusage == 1 && ++ report->field[0]->usage[0].hid == ++ (HID_UP_LED | 0x43) && ++ report->maxfield >= 4 && ++ report->field[0]->report_count >= 1 && ++ report->field[1]->report_count >= 1 && ++ report->field[2]->report_count >= 1 && ++ report->field[3]->report_count >= 1) { + report->field[0]->value[0] = 0x00; + report->field[1]->value[0] = 0x00; + strong = &report->field[2]->value[0]; +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 07/14] HID: LG: validate HID output report details +Date: Wed, 28 Aug 2013 22:31:00 +0200 (CEST) +Lines: 194 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721865 10099 80.91.229.3 (28 Aug 2013 20:31:05 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:05 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:07 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOQ-0000cl-Fi + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:06 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753468Ab3H1UbF (ORCPT ); + Wed, 28 Aug 2013 16:31:05 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57957 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752780Ab3H1UbE (ORCPT ); + Wed, 28 Aug 2013 16:31:04 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 5F1F5A531D; + Wed, 28 Aug 2013 22:31:03 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31658 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +lg, lg3, and lg4 HID drivers to write beyond the output report allocation +during an event, causing a heap overflow: + +[ 325.245240] usb 1-1: New USB device found, idVendor=046d, idProduct=c287 +... +[ 414.518960] BUG kmalloc-4096 (Not tainted): Redzone overwritten + +Additionally, while lg2 did correctly validate the report details, it was +cleaned up and shortened. + +CVE-2013-2893 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-lg2ff.c | 19 +++---------------- + drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- + drivers/hid/hid-lg4ff.c | 20 +------------------- + drivers/hid/hid-lgff.c | 17 ++--------------- + 4 files changed, 12 insertions(+), 73 deletions(-) + +diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c +index b3cd150..9805197 100644 +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); ++ /* Check that the report looks ok */ ++ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7); ++ if (!report) + return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 1) { +- hid_err(hid, "output report is empty\n"); +- return -ENODEV; +- } +- if (report->field[0]->report_count < 7) { +- hid_err(hid, "not enough values in the field\n"); +- return -ENODEV; +- } + + lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); + if (!lg2ff) +diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c +index e52f181..53ac79b 100644 +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, + int x, y; + + /* +- * Maxusage should always be 63 (maximum fields) +- * likely a better way to ensure this data is clean ++ * Available values in the field should always be 63, but we only use up to ++ * 35. Instead, clear the entire area, however big it is. + */ +- memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); ++ memset(report->field[0]->value, 0, ++ sizeof(__s32) * report->field[0]->report_count); + + switch (effect->type) { + case FF_CONSTANT: +@@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { + int lg3ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); +- return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 35)) ++ return -ENODEV; + + /* Assume single fixed device G940 */ + for (i = 0; ff_bits[i] >= 0; i++) +diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c +index 0ddae2a..8b89f0f 100644 +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde + int lg4ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + struct usb_device_descriptor *udesc; + int error, i, j; + __u16 bcdDevice, rev_maj, rev_min; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) + return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } + + /* Check what wheel has been connected */ + for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { +diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c +index d7ea8c8..a84fb40 100644 +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) + int lgff_init(struct hid_device* hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff_joystick; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) ++ return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(devices); i++) { + if (dev->id.vendor == devices[i].idVendor && +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 08/14] HID: lenovo-tpkbd: validate output report details +Date: Wed, 28 Aug 2013 22:31:10 +0200 (CEST) +Lines: 42 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721874 10167 80.91.229.3 (28 Aug 2013 20:31:14 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:14 +0000 (UTC) +Cc: Kees Cook , + Bernhard Seibold +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:16 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOY-0000cl-HM + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:14 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754122Ab3H1UbN (ORCPT ); + Wed, 28 Aug 2013 16:31:13 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57965 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752780Ab3H1UbN (ORCPT ); + Wed, 28 Aug 2013 16:31:13 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 982A1A531D; + Wed, 28 Aug 2013 22:31:12 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31659 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +lenovo-tpkbd HID driver to write just beyond the output report allocation +during initialization, causing a heap overflow: + +[ 76.109807] usb 1-1: New USB device found, idVendor=17ef, idProduct=6009 +... +[ 80.462540] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2894 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-lenovo-tpkbd.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c +index 07837f5..b697ada 100644 +--- a/drivers/hid/hid-lenovo-tpkbd.c ++++ b/drivers/hid/hid-lenovo-tpkbd.c +@@ -341,6 +341,11 @@ static int tpkbd_probe_tp(struct hid_device *hdev) + char *name_mute, *name_micmute; + int ret; + ++ /* Validate required reports. */ ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 4, 4, 1) || ++ !hid_validate_report(hdev, HID_OUTPUT_REPORT, 3, 1, 2)) ++ return -ENODEV; ++ + if (sysfs_create_group(&hdev->dev.kobj, + &tpkbd_attr_group_pointer)) { + hid_warn(hdev, "Could not create sysfs group\n"); +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 09/14] HID: logitech-dj: validate output report details +Date: Wed, 28 Aug 2013 22:31:18 +0200 (CEST) +Lines: 65 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721883 10249 80.91.229.3 (28 Aug 2013 20:31:23 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:23 +0000 (UTC) +Cc: Kees Cook , + Nestor Lopez Casado +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:25 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOg-0000cl-O9 + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:23 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1752780Ab3H1UbW (ORCPT ); + Wed, 28 Aug 2013 16:31:22 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57976 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751971Ab3H1UbV (ORCPT ); + Wed, 28 Aug 2013 16:31:21 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id D53F8A531D; + Wed, 28 Aug 2013 22:31:20 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31660 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +logitech-dj HID driver to leak kernel memory contents to the device, or +trigger a NULL dereference during initialization: + +[ 304.424553] usb 1-1: New USB device found, idVendor=046d, idProduct=c52b +... +[ 304.780467] BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 +[ 304.781409] IP: [] logi_dj_recv_send_report.isra.11+0x1a/0x90 + +CVE-2013-2895 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index cd33084..7b99c2a 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, + struct hid_report *report; + struct hid_report_enum *output_report_enum; + u8 *data = (u8 *)(&dj_report->device_index); +- int i; ++ unsigned int i, length; + + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; +@@ -471,7 +471,9 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, + return -ENODEV; + } + +- for (i = 0; i < report->field[0]->report_count; i++) ++ length = min_t(size_t, sizeof(*dj_report) - 1, ++ report->field[0]->report_count); ++ for (i = 0; i < length; i++) + report->field[0]->value[i] = data[i]; + + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); +@@ -783,6 +785,12 @@ static int logi_dj_probe(struct hid_device *hdev, + goto hid_parse_fail; + } + ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, ++ 1, 3)) { ++ retval = -ENODEV; ++ goto hid_parse_fail; ++ } ++ + /* Starts the usb device and connects to upper interfaces hiddev and + * hidraw */ + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 10/14] HID: ntrig: validate feature report details +Date: Wed, 28 Aug 2013 22:31:28 +0200 (CEST) +Lines: 41 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721895 10362 80.91.229.3 (28 Aug 2013 20:31:35 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:35 +0000 (UTC) +Cc: Kees Cook , Rafi Rubin +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:36 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOq-0000cl-KK + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:32 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753024Ab3H1Ubc (ORCPT ); + Wed, 28 Aug 2013 16:31:32 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57985 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751971Ab3H1Ubb (ORCPT ); + Wed, 28 Aug 2013 16:31:31 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id C4DDAA531D; + Wed, 28 Aug 2013 22:31:30 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31661 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious feature report that would cause the +ntrig HID driver to trigger a NULL dereference during initialization: + +[57383.031190] usb 3-1: New USB device found, idVendor=1b96, idProduct=0001 +... +[57383.315193] BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 +[57383.315308] IP: [] ntrig_probe+0x25e/0x420 [hid_ntrig] + +CVE-2013-2896 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-ntrig.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c +index ef95102..5482156 100644 +--- a/drivers/hid/hid-ntrig.c ++++ b/drivers/hid/hid-ntrig.c +@@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) + struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. + report_id_hash[0x0d]; + +- if (!report) ++ if (!report || report->maxfield < 1 || ++ report->field[0]->report_count < 1) + return -EINVAL; + + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 11/14] HID: multitouch: validate feature report details +Date: Wed, 28 Aug 2013 22:31:37 +0200 (CEST) +Lines: 77 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721900 10409 80.91.229.3 (28 Aug 2013 20:31:40 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:40 +0000 (UTC) +Cc: Kees Cook , + Henrik Rydberg , + Benjamin Tissoires +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:42 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmOz-0000cl-Ku + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:42 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754253Ab3H1Ubl (ORCPT ); + Wed, 28 Aug 2013 16:31:41 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:57991 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754222Ab3H1Ubk (ORCPT ); + Wed, 28 Aug 2013 16:31:40 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id BA511A535B; + Wed, 28 Aug 2013 22:31:39 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31662 +Archived-At: + +From: Kees Cook + +When working on report indexes, always validate that they are in bounds. +Without this, a HID device could report a malicious feature report that +could trick the driver into a heap overflow: + +[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 +... +[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2897 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-multitouch.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index cb0e361..2aa275e 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -330,9 +330,18 @@ static void mt_feature_mapping(struct hid_device *hdev, + break; + } + } ++ /* Ignore if value index is out of bounds. */ ++ if (td->inputmode_index < 0 || ++ td->inputmode_index >= field->report_count) { ++ dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); ++ td->inputmode = -1; ++ } + + break; + case HID_DG_CONTACTMAX: ++ /* Ignore if value count is out of bounds. */ ++ if (field->report_count < 1) ++ break; + td->maxcontact_report_id = field->report->id; + td->maxcontacts = field->value[0]; + if (!td->maxcontacts && +@@ -743,15 +752,21 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) + unsigned count; + int r, n; + ++ if (report->maxfield == 0) ++ return; ++ + /* + * Includes multi-packet support where subsequent + * packets are sent with zero contactcount. + */ +- if (td->cc_index >= 0) { +- struct hid_field *field = report->field[td->cc_index]; +- int value = field->value[td->cc_value_index]; +- if (value) +- td->num_expected = value; ++ if (td->cc_index >= 0 && td->cc_index < report->maxfield) { ++ field = report->field[td->cc_index]; ++ if (td->cc_value_index >= 0 && ++ td->cc_value_index < field->report_count) { ++ int value = field->value[td->cc_value_index]; ++ if (value) ++ td->num_expected = value; ++ } + } + + for (r = 0; r < report->maxfield; r++) { + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 12/14] HID: sensor-hub: validate feature report details +Date: Wed, 28 Aug 2013 22:31:44 +0200 (CEST) +Lines: 36 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721907 10489 80.91.229.3 (28 Aug 2013 20:31:47 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:47 +0000 (UTC) +Cc: Kees Cook , + Mika Westerberg , + srinivas pandruvada +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:51 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmP8-0000cl-9D + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:50 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754788Ab3H1Ubt (ORCPT ); + Wed, 28 Aug 2013 16:31:49 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:58000 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754228Ab3H1Ubt (ORCPT ); + Wed, 28 Aug 2013 16:31:49 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id BBD85A535B; + Wed, 28 Aug 2013 22:31:47 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31663 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious feature report that would cause the +sensor-hub HID driver to read past the end of heap allocation, leaking +kernel memory contents to the caller. + +CVE-2013-2898 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-sensor-hub.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c +index ca749810..aa34755 100644 +--- a/drivers/hid/hid-sensor-hub.c ++++ b/drivers/hid/hid-sensor-hub.c +@@ -221,7 +221,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, + + mutex_lock(&data->mutex); + report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); +- if (!report || (field_index >= report->maxfield)) { ++ if (!report || (field_index >= report->maxfield) || ++ report->field[field_index]->report_count < 1) { + ret = -EINVAL; + goto done_proc; + } +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 13/14] HID: picolcd_core: validate output report details +Date: Wed, 28 Aug 2013 22:31:52 +0200 (CEST) +Lines: 34 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721917 10573 80.91.229.3 (28 Aug 2013 20:31:57 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:57 +0000 (UTC) +Cc: Kees Cook , + =?ISO-8859-15?Q?Bruno_Pr=E9mont?= +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:59 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmPE-0000cl-T8 + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:57 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754901Ab3H1Ub4 (ORCPT ); + Wed, 28 Aug 2013 16:31:56 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:58006 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754228Ab3H1Ub4 (ORCPT ); + Wed, 28 Aug 2013 16:31:56 -0400 +Original-Received: from relay2.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 2720DA531D; + Wed, 28 Aug 2013 22:31:55 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31664 +Archived-At: + +From: Kees Cook + +A HID device could send a malicious output report that would cause the +picolcd HID driver to trigger a NULL dereference during attr file writing. + +CVE-2013-2899 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-picolcd_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c +index b48092d..72bba1e 100644 +--- a/drivers/hid/hid-picolcd_core.c ++++ b/drivers/hid/hid-picolcd_core.c +@@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, + buf += 10; + cnt -= 10; + } +- if (!report) ++ if (!report || report->maxfield < 1) + return -EINVAL; + + while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + +Path: news.gmane.org!not-for-mail +From: Jiri Kosina +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH 14/14] HID: check for NULL field when setting values +Date: Wed, 28 Aug 2013 22:32:01 +0200 (CEST) +Lines: 36 +Approved: news@gmane.org +Message-ID: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: ger.gmane.org 1377721927 10651 80.91.229.3 (28 Aug 2013 20:32:07 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 28 Aug 2013 20:32:07 +0000 (UTC) +Cc: Kees Cook +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:32:06 2013 +Return-path: +Envelope-to: glki-linux-input-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VEmPO-0000cl-40 + for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:32:06 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754959Ab3H1UcF (ORCPT ); + Wed, 28 Aug 2013 16:32:05 -0400 +Original-Received: from cantor2.suse.de ([195.135.220.15]:58016 "EHLO mx2.suse.de" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754282Ab3H1UcE (ORCPT ); + Wed, 28 Aug 2013 16:32:04 -0400 +Original-Received: from relay1.suse.de (unknown [195.135.220.254]) + by mx2.suse.de (Postfix) with ESMTP id 6D278A531D; + Wed, 28 Aug 2013 22:32:03 +0200 (CEST) +User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:31665 +Archived-At: + +From: Kees Cook + +Defensively check that the field to be worked on is not NULL. + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +--- + drivers/hid/hid-core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 55798b2..192be6b 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1206,7 +1206,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); + + int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) + { +- unsigned size = field->report_size; ++ unsigned size; ++ ++ if (!field) ++ return -1; ++ ++ size = field->report_size; + + hid_dump_input(field->report->device, field->usage + offset, value); + +-- +Jiri Kosina +SUSE Labs +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index 0a736f380..def0d5c2c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -774,6 +774,13 @@ Patch25079: 3.10.-6-7-crashes-on-network-activity.patch Patch25090: mei-3.10.y.patch +#CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 +#CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 +#CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 +#CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 +#CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 +Patch25099: HID-CVE-fixes.patch + # END OF PATCH DEFINITIONS %endif @@ -1483,6 +1490,13 @@ ApplyPatch 3.10.-6-7-crashes-on-network-activity.patch ApplyPatch mei-3.10.y.patch +#CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 +#CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 +#CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 +#CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 +#CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 +ApplyPatch HID-CVE-fixes.patch + # END OF PATCH APPLICATIONS %endif @@ -2324,6 +2338,14 @@ fi # ||----w | # || || %changelog +* Fri Aug 30 2013 Josh Boyer +- Fix HID CVEs. Absurd. +- CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 +- CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 +- CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 +- CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 +- CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 + * Thu Aug 29 2013 Justin M. Forbes 3.10.10-100 - Linux v3.10.10 From e0efd044a830549790e23dc6fa03565e835a4ba2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 9 Sep 2013 07:25:31 -0500 Subject: [PATCH 407/492] Linux v3.10.11 --- 3.10.-6-7-crashes-on-network-activity.patch | 140 -------------------- kernel.spec | 15 +-- mei-3.10.y.patch | 104 --------------- sources | 2 +- 4 files changed, 5 insertions(+), 256 deletions(-) delete mode 100644 3.10.-6-7-crashes-on-network-activity.patch delete mode 100644 mei-3.10.y.patch diff --git a/3.10.-6-7-crashes-on-network-activity.patch b/3.10.-6-7-crashes-on-network-activity.patch deleted file mode 100644 index 2e6b0d2ec..000000000 --- a/3.10.-6-7-crashes-on-network-activity.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 6aeddf9d409f3d9938b05b545d65810739237b2e Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Tue, 20 Aug 2013 06:56:08 +0200 -Subject: [PATCH] 3.10.{6,7} crashes on network activity - -On 2013-08-20 2:28 AM, Greg Kroah-Hartman wrote: -> On Tue, Aug 20, 2013 at 08:26:11AM +0800, Tom Gundersen wrote: ->> On Tue, Aug 20, 2013 at 8:03 AM, Greg Kroah-Hartman ->> wrote: ->> > On Tue, Aug 20, 2013 at 07:59:47AM +0800, Tom Gundersen wrote: ->> >> Hi guys, ->> >> ->> >> Starting with 3.10.6 (and still present in .7) I get an oops on ->> >> connecting to the network. ->> >> ->> >> The attached picture shows the oops. In case it does not reach the ML, ->> >> the top of the call trace reads: ->> >> ->> >> brcms_c_compute_rtscts_dur ->> >> brcms_c_ampdu_finalize ->> >> ampdu_finalize ->> >> dma_txfast ->> >> brcms_c_txfifo ->> >> brcms_c_sendpkt_mac80211 ->> >> brcms_ops_tx ->> >> __ieee80211_tx ->> >> ->> >> I bisected the problem and the first bad commit is ->> >> ->> >> commit ef47a5e4f1aaf1d0e2e6875e34b2c9595897bef6 ->> >> Author: Felix Fietkau ->> >> Date: Fri Jun 28 21:04:35 2013 +0200 ->> >> ->> >> mac80211/minstrel_ht: fix cck rate sampling ->> >> ->> >> commit 1cd158573951f737fbc878a35cb5eb47bf9af3d5 upstream. ->> >> ->> >> Reverting it on top of .7 fixes the problem. ->> >> ->> >> I had the same (I suppose) problem on mainline some time ago, but I ->> >> have not bisected it, verified that the problem still occurs there, or ->> >> checked if reverting the upstream patch fixes it. I'd be happy to do ->> >> that if it would help though. ->> >> ->> >> Let me know if you need any more information. ->> > ->> > Do you have this same problem with 3.11-rc6 as well? ->> ->> Yes, I just confirmed. I also confirmed that reverting the mainline ->> commit on top of -rc6 fixes the problem. -> -> Great, thanks. -> -> Felix and Johannes, any chance we can get this reverted in Linus tree -> soon, and push that revert back to the 3.10 stable tree as well? -I'd like to avoid a revert, since that will simply replace one set of -issues with another. Let's limit the use of the feature that brcmsmac -can't handle to drivers that are known to work with it. Tom, Please -test this patch to see if it fixes your issue. - -- Felix ---- - drivers/net/wireless/ath/ath9k/init.c | 3 ++- - drivers/net/wireless/ath/carl9170/main.c | 3 ++- - drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- - include/net/mac80211.h | 1 + - net/mac80211/rc80211_minstrel_ht.c | 3 +++ - 5 files changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c -index 2ba4945..bd126c2 100644 ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -767,7 +767,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | -- IEEE80211_HW_SUPPORTS_RC_TABLE; -+ IEEE80211_HW_SUPPORTS_RC_TABLE | -+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) - hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; -diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c -index e9010a4..0686375 100644 ---- a/drivers/net/wireless/ath/carl9170/main.c -+++ b/drivers/net/wireless/ath/carl9170/main.c -@@ -1857,7 +1857,8 @@ void *carl9170_alloc(size_t priv_size) - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | -- IEEE80211_HW_SIGNAL_DBM; -+ IEEE80211_HW_SIGNAL_DBM | -+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; - - if (!modparam_noht) { - /* -diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c -index 705aa33..7e66a90 100644 ---- a/drivers/net/wireless/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -5912,7 +5912,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_AMPDU_AGGREGATION | -- IEEE80211_HW_REPORTS_TX_ACK_STATUS; -+ IEEE80211_HW_REPORTS_TX_ACK_STATUS | -+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES; - - /* - * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices -diff --git a/include/net/mac80211.h b/include/net/mac80211.h -index 885898a..4e50d36 100644 ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1484,6 +1484,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_SUPPORTS_RC_TABLE = 1<<24, - IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, - IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, -+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, - }; - - /** -diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c -index f5aed96..f3bbea1 100644 ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -828,6 +828,9 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, - if (sband->band != IEEE80211_BAND_2GHZ) - return; - -+ if (!(mp->hw->flags & IEEE80211_HW_SUPPORTS_HT_CCK_RATES)) -+ return; -+ - mi->cck_supported = 0; - mi->cck_supported_short = 0; - for (i = 0; i < 4; i++) { --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index def0d5c2c..e5f23e74d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -769,11 +769,6 @@ Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020 #CVE-2013-0343 rhbz 914664 999380 Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch -#rhbz 989269 -Patch25079: 3.10.-6-7-crashes-on-network-activity.patch - -Patch25090: mei-3.10.y.patch - #CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 #CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 #CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 @@ -1485,11 +1480,6 @@ ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020. #CVE-2013-0343 rhbz 914664 999380 ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch -#rhbz 989269 -ApplyPatch 3.10.-6-7-crashes-on-network-activity.patch - -ApplyPatch mei-3.10.y.patch - #CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 #CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 #CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 @@ -2338,6 +2328,9 @@ fi # ||----w | # || || %changelog +* Thu Sep 09 2013 Justin M. Forbes 3.10.11-100 +- Linux v3.10.11 + * Fri Aug 30 2013 Josh Boyer - Fix HID CVEs. Absurd. - CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 diff --git a/mei-3.10.y.patch b/mei-3.10.y.patch deleted file mode 100644 index b0c6c34b5..000000000 --- a/mei-3.10.y.patch +++ /dev/null @@ -1,104 +0,0 @@ -Delivered-To: jwboyer@gmail.com -Received: by 10.76.168.104 with SMTP id zv8csp116477oab; - Sun, 25 Aug 2013 02:53:06 -0700 (PDT) -X-Received: by 10.66.146.42 with SMTP id sz10mr8515943pab.78.1377424384757; - Sun, 25 Aug 2013 02:53:04 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id zu9si6326866pbc.308.1969.12.31.16.00.00; - Sun, 25 Aug 2013 02:53:04 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756391Ab3HYJwW (ORCPT - + 58 others); Sun, 25 Aug 2013 05:52:22 -0400 -Received: from mga03.intel.com ([143.182.124.21]:34236 "EHLO mga03.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1756361Ab3HYJwT (ORCPT ); - Sun, 25 Aug 2013 05:52:19 -0400 -Received: from azsmga001.ch.intel.com ([10.2.17.19]) - by azsmga101.ch.intel.com with ESMTP; 25 Aug 2013 02:52:18 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.89,951,1367996400"; - d="scan'208";a="351301674" -Received: from twinkler-dhg.jer.intel.com ([10.12.87.84]) - by azsmga001.ch.intel.com with ESMTP; 25 Aug 2013 02:52:16 -0700 -From: Tomas Winkler -To: gregkh@linuxfoundation.org -Cc: arnd@arndb.de, linux-kernel@vger.kernel.org, - Tomas Winkler , - stable@vger.kernel.org, Shuah Khan , - Konstantin Khlebnikov -Subject: [3.10][PATCH 4/4] mei: me: fix hardware reset flow -Date: Sun, 25 Aug 2013 12:49:49 +0300 -Message-Id: <1377424189-5508-5-git-send-email-tomas.winkler@intel.com> -X-Mailer: git-send-email 1.8.1.2 -In-Reply-To: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -References: <1377424189-5508-1-git-send-email-tomas.winkler@intel.com> -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -stable: 3.10 -commit ff96066e3171acdea356b331163495957cb833d0 char-misc - - -Both H_IS and H_IE needs to be set to receive H_RDY -interrupt - -1. Assert H_IS to clear the interrupts during hw reset -and use mei_me_reg_write instead of mei_hcsr_set as the later -strips down the H_IS - -2. fix interrupt disablement embarrassing typo - hcsr |= ~H_IE -> hcsr &= ~H_IE; -this will remove the unwanted interrupt on power down - -3. remove useless debug print outs - -Cc: stable@vger.kernel.org -Cc: Shuah Khan -Cc: Konstantin Khlebnikov -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman - -Conflicts: - drivers/misc/mei/hw-me.c - ---- - drivers/misc/mei/hw-me.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c -index 700fe55..1bf3f8b 100644 ---- a/drivers/misc/mei/hw-me.c -+++ b/drivers/misc/mei/hw-me.c -@@ -176,16 +176,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) - struct mei_me_hw *hw = to_me_hw(dev); - u32 hcsr = mei_hcsr_read(hw); - -- dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); -- -- hcsr |= (H_RST | H_IG); -+ hcsr |= H_RST | H_IG | H_IS; - - if (intr_enable) - hcsr |= H_IE; - else -- hcsr |= ~H_IE; -+ hcsr &= ~H_IE; - -- mei_hcsr_set(hw, hcsr); -+ mei_me_reg_write(hw, H_CSR, hcsr); - - if (dev->dev_state == MEI_DEV_POWER_DOWN) - mei_me_hw_reset_release(dev); --- -1.8.1.2 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/sources b/sources index 0479b31a7..fb3a8ac24 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -d010ef17d3e577fd1bdcb6887f2b9836 patch-3.10.10.xz +9aadf2325fed53e971fe59bc6c7c3b89 patch-3.10.11.xz From dd3844ff41b7be10326694f195871b0b37f26022 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 9 Sep 2013 08:35:58 -0400 Subject: [PATCH 408/492] Fix system freeze due to incorrect rt2800 initialization (rhbz 1000679) --- kernel.spec | 9 +++++ ...0-rearrange-bbp-rfcsr-initialization.patch | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 rt2800-rearrange-bbp-rfcsr-initialization.patch diff --git a/kernel.spec b/kernel.spec index e5f23e74d..1e7bb2eb4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -769,6 +769,9 @@ Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020 #CVE-2013-0343 rhbz 914664 999380 Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch +#rhbz 1000679 +Patch25079: rt2800-rearrange-bbp-rfcsr-initialization.patch + #CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 #CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 #CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 @@ -1487,6 +1490,9 @@ ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch #CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 ApplyPatch HID-CVE-fixes.patch +#rhbz 1000679 +ApplyPatch rt2800-rearrange-bbp-rfcsr-initialization.patch + # END OF PATCH APPLICATIONS %endif @@ -2328,6 +2334,9 @@ fi # ||----w | # || || %changelog +* Mon Sep 09 2013 Josh Boyer +- Fix system freeze due to incorrect rt2800 initialization (rhbz 1000679) + * Thu Sep 09 2013 Justin M. Forbes 3.10.11-100 - Linux v3.10.11 diff --git a/rt2800-rearrange-bbp-rfcsr-initialization.patch b/rt2800-rearrange-bbp-rfcsr-initialization.patch new file mode 100644 index 000000000..c782fc5d4 --- /dev/null +++ b/rt2800-rearrange-bbp-rfcsr-initialization.patch @@ -0,0 +1,35 @@ +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 7e66a90..6a70c27 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4041,8 +4041,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + u8 reg_id; + u8 value; + +- if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || +- rt2800_wait_bbp_ready(rt2x00dev))) ++ if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) + return -EACCES; + + if (rt2x00_rt(rt2x00dev, RT5592)) { +@@ -5185,15 +5184,17 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) + rt2800_init_registers(rt2x00dev))) + return -EIO; + ++ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) ++ return -EIO; ++ + /* + * Send signal to firmware during boot time. + */ + rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +- if (rt2x00_is_usb(rt2x00dev)) { ++ if (rt2x00_is_usb(rt2x00dev)) + rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); +- rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +- } ++ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); + msleep(1); + + if (unlikely(rt2800_init_bbp(rt2x00dev))) From 4949ed840115a624e8fbdf1caaf2db96508c0a11 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 9 Sep 2013 07:49:11 -0500 Subject: [PATCH 409/492] Tag actual build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 1e7bb2eb4..4d2c24a49 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2334,10 +2334,10 @@ fi # ||----w | # || || %changelog -* Mon Sep 09 2013 Josh Boyer +* Mon Sep 09 2013 Josh Boyer 3.10.11-100 - Fix system freeze due to incorrect rt2800 initialization (rhbz 1000679) -* Thu Sep 09 2013 Justin M. Forbes 3.10.11-100 +* Mon Sep 09 2013 Justin M. Forbes - Linux v3.10.11 * Fri Aug 30 2013 Josh Boyer From f9abad3a38c84b4396166c8ef45e79290fbdc537 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Sep 2013 11:03:20 -0400 Subject: [PATCH 410/492] Resolves: rhbz1002351 --- crypto-fix-race-in-larval-lookup.patch | 44 ++++++++++++++++++++++++++ kernel.spec | 9 ++++++ 2 files changed, 53 insertions(+) create mode 100644 crypto-fix-race-in-larval-lookup.patch diff --git a/crypto-fix-race-in-larval-lookup.patch b/crypto-fix-race-in-larval-lookup.patch new file mode 100644 index 000000000..d1b19419e --- /dev/null +++ b/crypto-fix-race-in-larval-lookup.patch @@ -0,0 +1,44 @@ +commit 77dbd7a95e4a4f15264c333a9e9ab97ee27dc2aa +Author: Herbert Xu +Date: Sun Sep 8 14:33:50 2013 +1000 + + crypto: api - Fix race condition in larval lookup + + crypto_larval_lookup should only return a larval if it created one. + Any larval created by another entity must be processed through + crypto_larval_wait before being returned. + + Otherwise this will lead to a larval being killed twice, which + will most likely lead to a crash. + + Cc: stable@vger.kernel.org + Reported-by: Kees Cook + Tested-by: Kees Cook + Signed-off-by: Herbert Xu + +diff --git a/crypto/api.c b/crypto/api.c +index 320ea4d..a2b39c5 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -34,6 +34,8 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem); + BLOCKING_NOTIFIER_HEAD(crypto_chain); + EXPORT_SYMBOL_GPL(crypto_chain); + ++static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg); ++ + struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) + { + return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; +@@ -144,8 +146,11 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type, + } + up_write(&crypto_alg_sem); + +- if (alg != &larval->alg) ++ if (alg != &larval->alg) { + kfree(larval); ++ if (crypto_is_larval(alg)) ++ alg = crypto_larval_wait(alg); ++ } + + return alg; + } diff --git a/kernel.spec b/kernel.spec index 4d2c24a49..a1657feea 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,9 @@ Patch25079: rt2800-rearrange-bbp-rfcsr-initialization.patch #CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 Patch25099: HID-CVE-fixes.patch +#rhbz 1002351 +Patch25100: crypto-fix-race-in-larval-lookup.patch + # END OF PATCH DEFINITIONS %endif @@ -1493,6 +1496,9 @@ ApplyPatch HID-CVE-fixes.patch #rhbz 1000679 ApplyPatch rt2800-rearrange-bbp-rfcsr-initialization.patch +#rhbz1002351 +ApplyPatch crypto-fix-race-in-larval-lookup.patch + # END OF PATCH APPLICATIONS %endif @@ -2334,6 +2340,9 @@ fi # ||----w | # || || %changelog +* Wed Sep 11 2013 Neil Horman +- Fix race in crypto larval lookup + * Mon Sep 09 2013 Josh Boyer 3.10.11-100 - Fix system freeze due to incorrect rt2800 initialization (rhbz 1000679) From d84177cf02257369b627985d557b654ce83ab975 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Sep 2013 08:27:28 -0400 Subject: [PATCH 411/492] Fix spec warnings warning: Macro %kernel_modules needs whitespace before body warning: bogus date in %changelog: Mon Aug 04 2013 Justin M. Forbes --- kernel.spec | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index a1657feea..0e6b85643 100644 --- a/kernel.spec +++ b/kernel.spec @@ -975,9 +975,9 @@ against the %{?2:%{2} }kernel package.\ # # This macro creates a kernel--modules-extra package. -# %%kernel_modules-extra_package +# %%kernel_modules_extra_package # -%define kernel_modules-extra_package() \ +%define kernel_modules_extra_package() \ %package %{?1:%{1}-}modules-extra\ Summary: Extra kernel modules to match the %{?2:%{2} }kernel\ Group: System Environment/Kernel\ @@ -1003,14 +1003,14 @@ Summary: %{variant_summary}\ Group: System Environment/Kernel\ %kernel_reqprovconf\ %{expand:%%kernel_devel_package %1 %{!?-n:%1}%{?-n:%{-n*}}}\ -%{expand:%%kernel_modules-extra_package %1 %{!?-n:%1}%{?-n:%{-n*}}}\ +%{expand:%%kernel_modules_extra_package %1 %{!?-n:%1}%{?-n:%{-n*}}}\ %{expand:%%kernel_debuginfo_package %1}\ %{nil} # First the auxiliary packages of the main kernel package. %kernel_devel_package -%kernel_modules-extra_package +%kernel_modules_extra_package %kernel_debuginfo_package @@ -2118,7 +2118,7 @@ fi\ # # This macro defines a %%post script for a kernel*-modules-extra package. -# %%kernel_modules-extra_post [] +# %%kernel_modules_extra_post [] # %define kernel_modules_extra_post() \ %{expand:%%post %{?1:%{1}-}modules-extra}\ @@ -2393,7 +2393,7 @@ fi * Tue Aug 06 2013 Justin M. Forbes 3.10.5-100 - update s390x config [Dan Horák] -* Mon Aug 04 2013 Justin M. Forbes +* Mon Aug 05 2013 Justin M. Forbes - Linux v3.10.5 * Thu Aug 1 2013 Peter Robinson - 3.10.4-100 From a227754a899ae47d5c549c2e3ad08e9bcc971f86 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Sep 2013 09:29:27 -0400 Subject: [PATCH 412/492] Update HID CVE fixes to fix crash from lenovo-tpkbd driver (rhbz 1003998) --- HID-CVE-fixes.patch | 1384 +++++++++++++++++-------------------------- kernel.spec | 3 + 2 files changed, 531 insertions(+), 856 deletions(-) diff --git a/HID-CVE-fixes.patch b/HID-CVE-fixes.patch index 2b52d013f..a1fcf6da5 100644 --- a/HID-CVE-fixes.patch +++ b/HID-CVE-fixes.patch @@ -1,46 +1,7 @@ -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 01/14] HID: validate HID report id size -Date: Wed, 28 Aug 2013 22:29:55 +0200 (CEST) -Lines: 81 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721804 9521 80.91.229.3 (28 Aug 2013 20:30:04 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:04 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:06 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmNR-0008U8-2t - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:05 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754658Ab3H1UaD (ORCPT ); - Wed, 28 Aug 2013 16:30:03 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57907 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752748Ab3H1UaD (ORCPT ); - Wed, 28 Aug 2013 16:30:03 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 1C5ACA535B; - Wed, 28 Aug 2013 22:30:01 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31652 -Archived-At: - +From aab9cb0a00ecdd937273f3b9649311d81bf4f0cb Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 28 Aug 2013 22:29:55 +0200 +Subject: [PATCH 01/16] HID: validate HID report id size The "Report ID" field of a HID report is used to build indexes of reports. The kernel's index of these is limited to 256 entries, so any @@ -54,9 +15,10 @@ CVE-2013-2888 Signed-off-by: Kees Cook Cc: stable@kernel.org +Signed-off-by: Jiri Kosina --- - drivers/hid/hid-core.c | 10 +++++++--- - include/linux/hid.h | 4 +++- + drivers/hid/hid-core.c | 10 +++++++--- + include/linux/hid.h | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c @@ -112,76 +74,33 @@ index 0c48991..ff545cc 100644 }; #define HID_REPORT_TYPES 3 - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 02/14] HID: provide a helper for validating hid reports -Date: Wed, 28 Aug 2013 22:30:06 +0200 (CEST) -Lines: 99 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721810 9564 80.91.229.3 (28 Aug 2013 20:30:10 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:10 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:12 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmNX-0008U8-Cg - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:11 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754750Ab3H1UaK (ORCPT ); - Wed, 28 Aug 2013 16:30:10 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57911 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752748Ab3H1UaK (ORCPT ); - Wed, 28 Aug 2013 16:30:10 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 3C054A531D; - Wed, 28 Aug 2013 22:30:09 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31653 -Archived-At: +From ba6d8d44eaeb0ee58082f4b4c95138416e1f58a5 Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:50 +0200 +Subject: [PATCH 02/16] HID: provide a helper for validating hid reports Many drivers need to validate the characteristics of their HID report during initialization to avoid misusing the reports. This adds a common -helper to perform validation of the report, its field count, and the -value count within the fields. +helper to perform validation of the report exisitng, the field existing, +and the expected number of values within the field. Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Reviewed-by: Benjamin Tissoires --- - drivers/hid/hid-core.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/hid.h | 4 ++++ - 2 files changed, 54 insertions(+) + drivers/hid/hid-core.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/hid.h | 4 ++++ + 2 files changed, 62 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 5ea7d51..55798b2 100644 +index 5ea7d51..65ee459 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c -@@ -759,6 +759,56 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) +@@ -759,6 +759,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) } EXPORT_SYMBOL_GPL(hid_parse_report); @@ -191,120 +110,84 @@ index 5ea7d51..55798b2 100644 + "HID_FEATURE_REPORT", +}; +/** -+ * hid_validate_report - validate existing device report ++ * hid_validate_values - validate existing device report's value indexes + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) -+ * @fields: expected number of fields -+ * @report_counts: expected number of values per field ++ * @field_index: which report field to examine ++ * @report_counts: expected number of values + * -+ * Validate the report details after parsing. ++ * Validate the number of values in a given field of a given report, after ++ * parsing. + */ -+struct hid_report *hid_validate_report(struct hid_device *hid, ++struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, -+ unsigned int fields, ++ unsigned int field_index, + unsigned int report_counts) +{ + struct hid_report *report; -+ unsigned int i; + + if (type > HID_FEATURE_REPORT) { -+ hid_err(hid, "invalid HID report %u\n", type); ++ hid_err(hid, "invalid HID report type %u\n", type); + return NULL; + } + ++ if (id >= HID_MAX_IDS) { ++ hid_err(hid, "invalid HID report id %u\n", id); ++ return NULL; ++ } ++ ++ /* ++ * Explicitly not using hid_get_report() here since it depends on ++ * ->numbered being checked, which may not always be the case when ++ * drivers go to access report values. ++ */ + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + hid_err(hid, "missing %s %u\n", hid_report_names[type], id); + return NULL; + } -+ if (report->maxfield < fields) { ++ if (report->maxfield <= field_index) { + hid_err(hid, "not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } -+ for (i = 0; i < fields; i++) { -+ if (report->field[i]->report_count < report_counts) { -+ hid_err(hid, "not enough values in %s %u fields\n", -+ hid_report_names[type], id); -+ return NULL; -+ } ++ if (report->field[field_index]->report_count < report_counts) { ++ hid_err(hid, "not enough values in %s %u field %u\n", ++ hid_report_names[type], id, field_index); ++ return NULL; + } + return report; +} -+EXPORT_SYMBOL_GPL(hid_validate_report); ++EXPORT_SYMBOL_GPL(hid_validate_values); + /** * hid_open_report - open a driver-specific device report * diff --git a/include/linux/hid.h b/include/linux/hid.h -index ff545cc..76e41d8 100644 +index ff545cc..6e18550 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -749,6 +749,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); -+struct hid_report *hid_validate_report(struct hid_device *hid, ++struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, -+ unsigned int fields, ++ unsigned int field_index, + unsigned int report_counts); int hid_open_report(struct hid_device *device); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 03/14] HID: zeroplus: validate output report details -Date: Wed, 28 Aug 2013 22:30:15 +0200 (CEST) -Lines: 57 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721819 9648 80.91.229.3 (28 Aug 2013 20:30:19 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:19 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:21 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmNg-0008U8-24 - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:21 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754896Ab3H1UaT (ORCPT ); - Wed, 28 Aug 2013 16:30:19 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57913 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752748Ab3H1UaS (ORCPT ); - Wed, 28 Aug 2013 16:30:18 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id A94ACA531D; - Wed, 28 Aug 2013 22:30:17 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31654 -Archived-At: +From 51bc0244e9e62b25e4f64f7cb87764a0c0692131 Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:51 +0200 +Subject: [PATCH 03/16] HID: zeroplus: validate output report details The zeroplus HID driver was not checking the size of allocated values in fields it used. A HID device could send a malicious output report @@ -318,29 +201,29 @@ during initialization, causing a heap overflow: CVE-2013-2889 Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Reviewed-by: Benjamin Tissoires --- - drivers/hid/hid-zpff.c | 14 ++------------ - 1 file changed, 2 insertions(+), 12 deletions(-) + drivers/hid/hid-zpff.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c -index 6ec28a3..b124991 100644 +index 6ec28a3..a29756c 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c -@@ -68,22 +68,12 @@ static int zpff_init(struct hid_device *hid) +@@ -68,21 +68,13 @@ static int zpff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - int error; +- int error; ++ int i, error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); -+ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 4, 1); -+ if (!report) - return -ENODEV; +- return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); @@ -348,62 +231,21 @@ index 6ec28a3..b124991 100644 - if (report->maxfield < 4) { - hid_err(hid, "not enough fields in report\n"); - return -ENODEV; -- } ++ for (i = 0; i < 4; i++) { ++ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); ++ if (!report) ++ return -ENODEV; + } zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); - if (!zpff) - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 05/14] HID: steelseries: validate output report details -Date: Wed, 28 Aug 2013 22:30:37 +0200 (CEST) -Lines: 43 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721849 9885 80.91.229.3 (28 Aug 2013 20:30:49 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:49 +0000 (UTC) -Cc: Kees Cook , Simon Wood -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:51 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmO7-0000cl-Po - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:48 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1755238Ab3H1Uam (ORCPT ); - Wed, 28 Aug 2013 16:30:42 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57942 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754222Ab3H1Uak (ORCPT ); - Wed, 28 Aug 2013 16:30:40 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id EFDE1A531D; - Wed, 28 Aug 2013 22:30:39 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31656 -Archived-At: +From 5b029acf571f94193ff8a757340fd37a7f88ae0b Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:53 +0200 +Subject: [PATCH 05/16] HID: steelseries: validate output report details A HID device could send a malicious output report that would cause the steelseries HID driver to write beyond the output report allocation @@ -416,20 +258,21 @@ during initialization, causing a heap overflow: CVE-2013-2891 Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Reviewed-by: Benjamin Tissoires --- - drivers/hid/hid-steelseries.c | 5 +++++ + drivers/hid/hid-steelseries.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c -index d164911..ef42e86 100644 +index d164911..29f328f 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, goto err_free; } -+ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 16)) { ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) { + ret = -ENODEV; + goto err_free; + } @@ -437,147 +280,14 @@ index d164911..ef42e86 100644 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { hid_err(hdev, "hw start failed\n"); - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 06/14] HID: pantherlord: validate output report details -Date: Wed, 28 Aug 2013 22:30:49 +0200 (CEST) -Lines: 47 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721853 9919 80.91.229.3 (28 Aug 2013 20:30:53 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:53 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:55 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOD-0000cl-Qd - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:54 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754500Ab3H1Uax (ORCPT ); - Wed, 28 Aug 2013 16:30:53 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57948 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1753468Ab3H1Uaw (ORCPT ); - Wed, 28 Aug 2013 16:30:52 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 21315A531D; - Wed, 28 Aug 2013 22:30:52 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31657 -Archived-At: - -From: Kees Cook - -A HID device could send a malicious output report that would cause the -pantherlord HID driver to write beyond the output report allocation -during initialization, causing a heap overflow: - -[ 310.939483] usb 1-1: New USB device found, idVendor=0e8f, idProduct=0003 -... -[ 315.980774] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2892 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org ---- - drivers/hid/hid-pl.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c -index d29112f..2dcd7d9 100644 ---- a/drivers/hid/hid-pl.c -+++ b/drivers/hid/hid-pl.c -@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid) - strong = &report->field[0]->value[2]; - weak = &report->field[0]->value[3]; - debug("detected single-field device"); -- } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && -- report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { -+ } else if (report->field[0]->maxusage == 1 && -+ report->field[0]->usage[0].hid == -+ (HID_UP_LED | 0x43) && -+ report->maxfield >= 4 && -+ report->field[0]->report_count >= 1 && -+ report->field[1]->report_count >= 1 && -+ report->field[2]->report_count >= 1 && -+ report->field[3]->report_count >= 1) { - report->field[0]->value[0] = 0x00; - report->field[1]->value[0] = 0x00; - strong = &report->field[2]->value[0]; --- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 07/14] HID: LG: validate HID output report details -Date: Wed, 28 Aug 2013 22:31:00 +0200 (CEST) -Lines: 194 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721865 10099 80.91.229.3 (28 Aug 2013 20:31:05 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:05 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:07 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOQ-0000cl-Fi - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:06 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753468Ab3H1UbF (ORCPT ); - Wed, 28 Aug 2013 16:31:05 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57957 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752780Ab3H1UbE (ORCPT ); - Wed, 28 Aug 2013 16:31:04 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 5F1F5A531D; - Wed, 28 Aug 2013 22:31:03 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31658 -Archived-At: +From e846e9b33d65246ed807156a114c65cdfece0d12 Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:54 +0200 +Subject: [PATCH 06/16] HID: LG: validate HID output report details A HID device could send a malicious output report that would cause the lg, lg3, and lg4 HID drivers to write beyond the output report allocation @@ -593,16 +303,17 @@ cleaned up and shortened. CVE-2013-2893 Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Reviewed-by: Benjamin Tissoires --- - drivers/hid/hid-lg2ff.c | 19 +++---------------- - drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- - drivers/hid/hid-lg4ff.c | 20 +------------------- - drivers/hid/hid-lgff.c | 17 ++--------------- + drivers/hid/hid-lg2ff.c | 19 +++---------------- + drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- + drivers/hid/hid-lg4ff.c | 20 +------------------- + drivers/hid/hid-lgff.c | 17 ++--------------- 4 files changed, 12 insertions(+), 73 deletions(-) diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c -index b3cd150..9805197 100644 +index b3cd150..1a42eaa 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) @@ -617,7 +328,7 @@ index b3cd150..9805197 100644 - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); + /* Check that the report looks ok */ -+ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7); ++ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) return -ENODEV; - } @@ -636,7 +347,7 @@ index b3cd150..9805197 100644 lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); if (!lg2ff) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c -index e52f181..53ac79b 100644 +index e52f181..8c2da18 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, @@ -684,13 +395,13 @@ index e52f181..53ac79b 100644 - hid_err(hid, "NULL field\n"); - return -1; - } -+ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 35)) ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; /* Assume single fixed device G940 */ for (i = 0; ff_bits[i] >= 0; i++) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c -index 0ddae2a..8b89f0f 100644 +index 0ddae2a..8782fe1 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde @@ -717,7 +428,7 @@ index 0ddae2a..8b89f0f 100644 - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); -+ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -1; - } - @@ -730,7 +441,7 @@ index 0ddae2a..8b89f0f 100644 /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c -index d7ea8c8..a84fb40 100644 +index d7ea8c8..e1394af 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) @@ -758,61 +469,19 @@ index d7ea8c8..a84fb40 100644 - hid_err(hid, "NULL field\n"); - return -1; - } -+ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(devices); i++) { if (dev->id.vendor == devices[i].idVendor && -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 08/14] HID: lenovo-tpkbd: validate output report details -Date: Wed, 28 Aug 2013 22:31:10 +0200 (CEST) -Lines: 42 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721874 10167 80.91.229.3 (28 Aug 2013 20:31:14 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:14 +0000 (UTC) -Cc: Kees Cook , - Bernhard Seibold -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:16 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOY-0000cl-HM - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:14 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754122Ab3H1UbN (ORCPT ); - Wed, 28 Aug 2013 16:31:13 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57965 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752780Ab3H1UbN (ORCPT ); - Wed, 28 Aug 2013 16:31:13 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 982A1A531D; - Wed, 28 Aug 2013 22:31:12 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31659 -Archived-At: + +From 0317e971d90e3e2e312074386a2349b2ef48d1d0 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:55 +0200 +Subject: [PATCH 07/16] HID: lenovo-tpkbd: validate output report details From: Kees Cook @@ -827,79 +496,41 @@ during initialization, causing a heap overflow: CVE-2013-2894 Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires --- - drivers/hid/hid-lenovo-tpkbd.c | 5 +++++ - 1 file changed, 5 insertions(+) + drivers/hid/hid-lenovo-tpkbd.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c -index 07837f5..b697ada 100644 +index 07837f5..762d988 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c -@@ -341,6 +341,11 @@ static int tpkbd_probe_tp(struct hid_device *hdev) +@@ -339,7 +339,15 @@ static int tpkbd_probe_tp(struct hid_device *hdev) + struct tpkbd_data_pointer *data_pointer; + size_t name_sz = strlen(dev_name(dev)) + 16; char *name_mute, *name_micmute; - int ret; - -+ /* Validate required reports. */ -+ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 4, 4, 1) || -+ !hid_validate_report(hdev, HID_OUTPUT_REPORT, 3, 1, 2)) -+ return -ENODEV; +- int ret; ++ int i, ret; + ++ /* Validate required reports. */ ++ for (i = 0; i < 4; i++) { ++ if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) ++ return -ENODEV; ++ } ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) ++ return -ENODEV; + if (sysfs_create_group(&hdev->dev.kobj, &tpkbd_attr_group_pointer)) { - hid_warn(hdev, "Could not create sysfs group\n"); -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 09/14] HID: logitech-dj: validate output report details -Date: Wed, 28 Aug 2013 22:31:18 +0200 (CEST) -Lines: 65 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721883 10249 80.91.229.3 (28 Aug 2013 20:31:23 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:23 +0000 (UTC) -Cc: Kees Cook , - Nestor Lopez Casado -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:25 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOg-0000cl-O9 - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:23 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1752780Ab3H1UbW (ORCPT ); - Wed, 28 Aug 2013 16:31:22 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57976 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751971Ab3H1UbV (ORCPT ); - Wed, 28 Aug 2013 16:31:21 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id D53F8A531D; - Wed, 28 Aug 2013 22:31:20 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31660 -Archived-At: +From 978474c73af6764f1c2c5409585221e6d438b16c Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:56 +0200 +Subject: [PATCH 08/16] HID: logitech-dj: validate output report details A HID device could send a malicious output report that would cause the logitech-dj HID driver to leak kernel memory contents to the device, or @@ -913,13 +544,14 @@ trigger a NULL dereference during initialization: CVE-2013-2895 Signed-off-by: Kees Cook -Cc: stable@kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires --- - drivers/hid/hid-logitech-dj.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) + drivers/hid/hid-logitech-dj.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c -index cd33084..7b99c2a 100644 +index cd33084..a2469b5 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, @@ -927,27 +559,25 @@ index cd33084..7b99c2a 100644 struct hid_report_enum *output_report_enum; u8 *data = (u8 *)(&dj_report->device_index); - int i; -+ unsigned int i, length; ++ unsigned int i; output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; -@@ -471,7 +471,9 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, +@@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, return -ENODEV; } - for (i = 0; i < report->field[0]->report_count; i++) -+ length = min_t(size_t, sizeof(*dj_report) - 1, -+ report->field[0]->report_count); -+ for (i = 0; i < length; i++) ++ for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++) report->field[0]->value[i] = data[i]; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); -@@ -783,6 +785,12 @@ static int logi_dj_probe(struct hid_device *hdev, +@@ -783,6 +783,12 @@ static int logi_dj_probe(struct hid_device *hdev, goto hid_parse_fail; } -+ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, -+ 1, 3)) { ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, ++ 0, DJREPORT_SHORT_LENGTH - 1)) { + retval = -ENODEV; + goto hid_parse_fail; + } @@ -955,58 +585,374 @@ index cd33084..7b99c2a 100644 /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 10/14] HID: ntrig: validate feature report details -Date: Wed, 28 Aug 2013 22:31:28 +0200 (CEST) -Lines: 41 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721895 10362 80.91.229.3 (28 Aug 2013 20:31:35 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:35 +0000 (UTC) -Cc: Kees Cook , Rafi Rubin -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:36 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOq-0000cl-KK - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:32 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753024Ab3H1Ubc (ORCPT ); - Wed, 28 Aug 2013 16:31:32 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57985 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751971Ab3H1Ubb (ORCPT ); - Wed, 28 Aug 2013 16:31:31 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id C4DDAA531D; - Wed, 28 Aug 2013 22:31:30 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31661 -Archived-At: +From 9445e3a28eb6365c54dae729d184c4c3b6b43d60 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:57 +0200 +Subject: [PATCH 09/16] HID: validate feature and input report details + +When dealing with usage_index, be sure to properly use unsigned instead of +int to avoid overflows. + +When working on report fields, always validate that their report_counts are +in bounds. +Without this, a HID device could report a malicious feature report that +could trick the driver into a heap overflow: + +[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 +... +[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2897 + +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +--- + drivers/hid/hid-core.c | 16 +++++++--------- + drivers/hid/hid-input.c | 11 ++++++++++- + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 65ee459..08500bc 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report); + static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) + { + struct hid_field *field; +- int i; + + if (report->maxfield == HID_MAX_FIELDS) { + hid_err(report->device, "too many fields in report\n"); +@@ -113,9 +112,6 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned + field->value = (s32 *)(field->usage + usages); + field->report = report; + +- for (i = 0; i < usages; i++) +- field->usage[i].usage_index = i; +- + return field; + } + +@@ -226,9 +222,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign + { + struct hid_report *report; + struct hid_field *field; +- int usages; ++ unsigned usages; + unsigned offset; +- int i; ++ unsigned i; + + report = hid_register_report(parser->device, report_type, parser->global.report_id); + if (!report) { +@@ -255,7 +251,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign + if (!parser->local.usage_index) /* Ignore padding fields */ + return 0; + +- usages = max_t(int, parser->local.usage_index, parser->global.report_count); ++ usages = max_t(unsigned, parser->local.usage_index, ++ parser->global.report_count); + + field = hid_register_field(report, usages, parser->global.report_count); + if (!field) +@@ -266,13 +263,14 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign + field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); + + for (i = 0; i < usages; i++) { +- int j = i; ++ unsigned j = i; + /* Duplicate the last usage we parsed if we have excess values */ + if (i >= parser->local.usage_index) + j = parser->local.usage_index - 1; + field->usage[i].hid = parser->local.usage[j]; + field->usage[i].collection_index = + parser->local.collection_index[j]; ++ field->usage[i].usage_index = i; + } + + field->maxusage = usages; +@@ -1290,7 +1288,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, + goto out; + } + +- if (hid->claimed != HID_CLAIMED_HIDRAW) { ++ if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { + for (a = 0; a < report->maxfield; a++) + hid_input_field(hid, report->field[a], cdata, interrupt); + hdrv = hid->driver; +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 7480799..3ac2138 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -477,6 +477,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + if (field->flags & HID_MAIN_ITEM_CONSTANT) + goto ignore; + ++ /* Ignore if report count is out of bounds. */ ++ if (field->report_count < 1) ++ goto ignore; ++ + /* only LED usages are supported in output fields */ + if (field->report_type == HID_OUTPUT_REPORT && + (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { +@@ -1160,7 +1164,11 @@ static void report_features(struct hid_device *hid) + + rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; + list_for_each_entry(rep, &rep_enum->report_list, list) +- for (i = 0; i < rep->maxfield; i++) ++ for (i = 0; i < rep->maxfield; i++) { ++ /* Ignore if report count is out of bounds. */ ++ if (rep->field[i]->report_count < 1) ++ continue; ++ + for (j = 0; j < rep->field[i]->maxusage; j++) { + /* Verify if Battery Strength feature is available */ + hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); +@@ -1169,6 +1177,7 @@ static void report_features(struct hid_device *hid) + drv->feature_mapping(hid, rep->field[i], + rep->field[i]->usage + j); + } ++ } + } + + static struct hid_input *hidinput_allocate(struct hid_device *hid) +-- +1.8.3.1 + + +From cc8d6c5e14fbffc3349dcd35c21fa46f1143070d Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:58 +0200 +Subject: [PATCH 10/16] HID: multitouch: validate indexes details + +When working on report indexes, always validate that they are in bounds. +Without this, a HID device could report a malicious feature report that +could trick the driver into a heap overflow: + +[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 +... +[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +Note that we need to change the indexes from s8 to s16 as they can +be between -1 and 255. + +CVE-2013-2897 + +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +--- + drivers/hid/hid-multitouch.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index cb0e361..2d3677c 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -101,9 +101,9 @@ struct mt_device { + unsigned last_slot_field; /* the last field of a slot */ + unsigned mt_report_id; /* the report ID of the multitouch device */ + unsigned pen_report_id; /* the report ID of the pen device */ +- __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ +- __s8 inputmode_index; /* InputMode HID feature index in the report */ +- __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, ++ __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ ++ __s16 inputmode_index; /* InputMode HID feature index in the report */ ++ __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, + -1 if non-existent */ + __u8 num_received; /* how many contacts we received */ + __u8 num_expected; /* expected last contact index */ +@@ -317,20 +317,18 @@ static void mt_feature_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) + { + struct mt_device *td = hid_get_drvdata(hdev); +- int i; + + switch (usage->hid) { + case HID_DG_INPUTMODE: +- td->inputmode = field->report->id; +- td->inputmode_index = 0; /* has to be updated below */ +- +- for (i=0; i < field->maxusage; i++) { +- if (field->usage[i].hid == usage->hid) { +- td->inputmode_index = i; +- break; +- } ++ /* Ignore if value index is out of bounds. */ ++ if (usage->usage_index >= field->report_count) { ++ dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); ++ break; + } + ++ td->inputmode = field->report->id; ++ td->inputmode_index = usage->usage_index; ++ + break; + case HID_DG_CONTACTMAX: + td->maxcontact_report_id = field->report->id; +@@ -536,6 +534,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, + mt_store_field(usage, td, hi); + return 1; + case HID_DG_CONTACTCOUNT: ++ /* Ignore if indexes are out of bounds. */ ++ if (field->index >= field->report->maxfield || ++ usage->usage_index >= field->report_count) ++ return 1; + td->cc_index = field->index; + td->cc_value_index = usage->usage_index; + return 1; +-- +1.8.3.1 + + +From 01b52229ddc746c56b2a7756eed46b1f98673bea Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:59 +0200 +Subject: [PATCH 11/16] HID: lenovo-tpkbd: fix leak if tpkbd_probe_tp fails + +If tpkbd_probe_tp() bails out, the probe() function return an error, +but hid_hw_stop() is never called. + +fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1003998 + +Cc: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +--- + drivers/hid/hid-lenovo-tpkbd.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c +index 762d988..31cf29a 100644 +--- a/drivers/hid/hid-lenovo-tpkbd.c ++++ b/drivers/hid/hid-lenovo-tpkbd.c +@@ -414,22 +414,27 @@ static int tpkbd_probe(struct hid_device *hdev, + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "hid_parse failed\n"); +- goto err_free; ++ goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hid_hw_start failed\n"); +- goto err_free; ++ goto err; + } + + uhdev = (struct usbhid_device *) hdev->driver_data; + +- if (uhdev->ifnum == 1) +- return tpkbd_probe_tp(hdev); ++ if (uhdev->ifnum == 1) { ++ ret = tpkbd_probe_tp(hdev); ++ if (ret) ++ goto err_hid; ++ } + + return 0; +-err_free: ++err_hid: ++ hid_hw_stop(hdev); ++err: + return ret; + } + +-- +1.8.3.1 + + +From b2438ded3cdd8d6d6af77d9bce38d2d8f353a790 Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 28 Aug 2013 22:32:01 +0200 +Subject: [PATCH 12/16] HID: check for NULL field when setting values + +Defensively check that the field to be worked on is not NULL. + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 08500bc..e331cb1 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1212,7 +1212,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); + + int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) + { +- unsigned size = field->report_size; ++ unsigned size; ++ ++ if (!field) ++ return -1; ++ ++ size = field->report_size; + + hid_dump_input(field->report->device, field->usage + offset, value); + +-- +1.8.3.1 + + +From d0502783cdafcdb0a677492c43a373748d900d50 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 28 Aug 2013 22:30:49 +0200 +Subject: [PATCH 13/16] HID: pantherlord: validate output report details + +A HID device could send a malicious output report that would cause the +pantherlord HID driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 310.939483] usb 1-1: New USB device found, idVendor=0e8f, idProduct=0003 +... +[ 315.980774] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2892 + +Signed-off-by: Kees Cook +Cc: stable@kernel.org +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-pl.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c +index d29112f..2dcd7d9 100644 +--- a/drivers/hid/hid-pl.c ++++ b/drivers/hid/hid-pl.c +@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid) + strong = &report->field[0]->value[2]; + weak = &report->field[0]->value[3]; + debug("detected single-field device"); +- } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && +- report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { ++ } else if (report->field[0]->maxusage == 1 && ++ report->field[0]->usage[0].hid == ++ (HID_UP_LED | 0x43) && ++ report->maxfield >= 4 && ++ report->field[0]->report_count >= 1 && ++ report->field[1]->report_count >= 1 && ++ report->field[2]->report_count >= 1 && ++ report->field[3]->report_count >= 1) { + report->field[0]->value[0] = 0x00; + report->field[1]->value[0] = 0x00; + strong = &report->field[2]->value[0]; +-- +1.8.3.1 + + +From dc4db3b624cc7bf6972817615af88e250a8526cc Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 28 Aug 2013 22:31:28 +0200 +Subject: [PATCH 14/16] HID: ntrig: validate feature report details A HID device could send a malicious feature report that would cause the ntrig HID driver to trigger a NULL dereference during initialization: @@ -1020,8 +966,10 @@ CVE-2013-2896 Signed-off-by: Kees Cook Cc: stable@kernel.org +Signed-off-by: Rafi Rubin +Signed-off-by: Jiri Kosina --- - drivers/hid/hid-ntrig.c | 3 ++- + drivers/hid/hid-ntrig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c @@ -1038,181 +986,14 @@ index ef95102..5482156 100644 return -EINVAL; hid_hw_request(hdev, report, HID_REQ_GET_REPORT); - -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 11/14] HID: multitouch: validate feature report details -Date: Wed, 28 Aug 2013 22:31:37 +0200 (CEST) -Lines: 77 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721900 10409 80.91.229.3 (28 Aug 2013 20:31:40 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:40 +0000 (UTC) -Cc: Kees Cook , - Henrik Rydberg , - Benjamin Tissoires -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:42 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmOz-0000cl-Ku - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:42 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754253Ab3H1Ubl (ORCPT ); - Wed, 28 Aug 2013 16:31:41 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:57991 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754222Ab3H1Ubk (ORCPT ); - Wed, 28 Aug 2013 16:31:40 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id BA511A535B; - Wed, 28 Aug 2013 22:31:39 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31662 -Archived-At: - -From: Kees Cook - -When working on report indexes, always validate that they are in bounds. -Without this, a HID device could report a malicious feature report that -could trick the driver into a heap overflow: - -[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 -... -[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2897 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org ---- - drivers/hid/hid-multitouch.c | 25 ++++++++++++++++++++----- - 1 file changed, 20 insertions(+), 5 deletions(-) - -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index cb0e361..2aa275e 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -330,9 +330,18 @@ static void mt_feature_mapping(struct hid_device *hdev, - break; - } - } -+ /* Ignore if value index is out of bounds. */ -+ if (td->inputmode_index < 0 || -+ td->inputmode_index >= field->report_count) { -+ dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); -+ td->inputmode = -1; -+ } - - break; - case HID_DG_CONTACTMAX: -+ /* Ignore if value count is out of bounds. */ -+ if (field->report_count < 1) -+ break; - td->maxcontact_report_id = field->report->id; - td->maxcontacts = field->value[0]; - if (!td->maxcontacts && -@@ -743,15 +752,21 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) - unsigned count; - int r, n; - -+ if (report->maxfield == 0) -+ return; -+ - /* - * Includes multi-packet support where subsequent - * packets are sent with zero contactcount. - */ -- if (td->cc_index >= 0) { -- struct hid_field *field = report->field[td->cc_index]; -- int value = field->value[td->cc_value_index]; -- if (value) -- td->num_expected = value; -+ if (td->cc_index >= 0 && td->cc_index < report->maxfield) { -+ field = report->field[td->cc_index]; -+ if (td->cc_value_index >= 0 && -+ td->cc_value_index < field->report_count) { -+ int value = field->value[td->cc_value_index]; -+ if (value) -+ td->num_expected = value; -+ } - } - - for (r = 0; r < report->maxfield; r++) { - --- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 12/14] HID: sensor-hub: validate feature report details -Date: Wed, 28 Aug 2013 22:31:44 +0200 (CEST) -Lines: 36 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721907 10489 80.91.229.3 (28 Aug 2013 20:31:47 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:47 +0000 (UTC) -Cc: Kees Cook , - Mika Westerberg , - srinivas pandruvada -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:51 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmP8-0000cl-9D - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:50 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754788Ab3H1Ubt (ORCPT ); - Wed, 28 Aug 2013 16:31:49 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:58000 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754228Ab3H1Ubt (ORCPT ); - Wed, 28 Aug 2013 16:31:49 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id BBD85A535B; - Wed, 28 Aug 2013 22:31:47 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31663 -Archived-At: +From 34490675479f16680a60726632ad2e808eab54bd Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 28 Aug 2013 22:31:44 +0200 +Subject: [PATCH 15/16] HID: sensor-hub: validate feature report details A HID device could send a malicious feature report that would cause the sensor-hub HID driver to read past the end of heap allocation, leaking @@ -1222,8 +1003,10 @@ CVE-2013-2898 Signed-off-by: Kees Cook Cc: stable@kernel.org +Reviewed-by: Mika Westerberg +Signed-off-by: Jiri Kosina --- - drivers/hid/hid-sensor-hub.c | 3 ++- + drivers/hid/hid-sensor-hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c @@ -1241,71 +1024,43 @@ index ca749810..aa34755 100644 goto done_proc; } -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 13/14] HID: picolcd_core: validate output report details -Date: Wed, 28 Aug 2013 22:31:52 +0200 (CEST) -Lines: 34 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721917 10573 80.91.229.3 (28 Aug 2013 20:31:57 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:57 +0000 (UTC) -Cc: Kees Cook , - =?ISO-8859-15?Q?Bruno_Pr=E9mont?= -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:59 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmPE-0000cl-T8 - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:57 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754901Ab3H1Ub4 (ORCPT ); - Wed, 28 Aug 2013 16:31:56 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:58006 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754228Ab3H1Ub4 (ORCPT ); - Wed, 28 Aug 2013 16:31:56 -0400 -Original-Received: from relay2.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 2720DA531D; - Wed, 28 Aug 2013 22:31:55 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31664 -Archived-At: +From a0155e41d3a7a9bd901368271d86ee1bb28d100f Mon Sep 17 00:00:00 2001 From: Kees Cook +Date: Wed, 28 Aug 2013 22:31:52 +0200 +Subject: [PATCH 16/16] HID: picolcd_core: validate output report details +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit A HID device could send a malicious output report that would cause the picolcd HID driver to trigger a NULL dereference during attr file writing. +[jkosina@suse.cz: changed + + report->maxfield < 1 + +to + + report->maxfield != 1 + +as suggested by Bruno]. + CVE-2013-2899 Signed-off-by: Kees Cook Cc: stable@kernel.org +Reviewed-by: Bruno Prémont +Acked-by: Bruno Prémont +Signed-off-by: Jiri Kosina --- - drivers/hid/hid-picolcd_core.c | 2 +- + drivers/hid/hid-picolcd_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c -index b48092d..72bba1e 100644 +index b48092d..acbb0210 100644 --- a/drivers/hid/hid-picolcd_core.c +++ b/drivers/hid/hid-picolcd_core.c @@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, @@ -1313,93 +1068,10 @@ index b48092d..72bba1e 100644 cnt -= 10; } - if (!report) -+ if (!report || report->maxfield < 1) ++ if (!report || report->maxfield != 1) return -EINVAL; while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) -- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -Path: news.gmane.org!not-for-mail -From: Jiri Kosina -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH 14/14] HID: check for NULL field when setting values -Date: Wed, 28 Aug 2013 22:32:01 +0200 (CEST) -Lines: 36 -Approved: news@gmane.org -Message-ID: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: ger.gmane.org 1377721927 10651 80.91.229.3 (28 Aug 2013 20:32:07 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 28 Aug 2013 20:32:07 +0000 (UTC) -Cc: Kees Cook -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:32:06 2013 -Return-path: -Envelope-to: glki-linux-input-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VEmPO-0000cl-40 - for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:32:06 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754959Ab3H1UcF (ORCPT ); - Wed, 28 Aug 2013 16:32:05 -0400 -Original-Received: from cantor2.suse.de ([195.135.220.15]:58016 "EHLO mx2.suse.de" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754282Ab3H1UcE (ORCPT ); - Wed, 28 Aug 2013 16:32:04 -0400 -Original-Received: from relay1.suse.de (unknown [195.135.220.254]) - by mx2.suse.de (Postfix) with ESMTP id 6D278A531D; - Wed, 28 Aug 2013 22:32:03 +0200 (CEST) -User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:31665 -Archived-At: - -From: Kees Cook - -Defensively check that the field to be worked on is not NULL. - -Signed-off-by: Kees Cook -Cc: stable@kernel.org ---- - drivers/hid/hid-core.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 55798b2..192be6b 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -1206,7 +1206,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); - - int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) - { -- unsigned size = field->report_size; -+ unsigned size; -+ -+ if (!field) -+ return -1; -+ -+ size = field->report_size; - - hid_dump_input(field->report->device, field->usage + offset, value); - --- -Jiri Kosina -SUSE Labs --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html +1.8.3.1 diff --git a/kernel.spec b/kernel.spec index 0e6b85643..ec89fa12a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2340,6 +2340,9 @@ fi # ||----w | # || || %changelog +* Thu Sep 12 2013 Josh Boyer +- Update HID CVE fixes to fix crash from lenovo-tpkbd driver (rhbz 1003998) + * Wed Sep 11 2013 Neil Horman - Fix race in crypto larval lookup From b5802b6a1f974d0244515e718403beb9c9e07140 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Sep 2013 07:38:51 -0400 Subject: [PATCH 413/492] CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) --- kernel.spec | 9 +++ ...orrectly-handle-error-in-tun_set_iff.patch | 57 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 tuntap-correctly-handle-error-in-tun_set_iff.patch diff --git a/kernel.spec b/kernel.spec index ec89fa12a..2ee86cad7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -782,6 +782,9 @@ Patch25099: HID-CVE-fixes.patch #rhbz 1002351 Patch25100: crypto-fix-race-in-larval-lookup.patch +#CVE-2013-4343 rhbz 1007733 1007741 +Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch + # END OF PATCH DEFINITIONS %endif @@ -1499,6 +1502,9 @@ ApplyPatch rt2800-rearrange-bbp-rfcsr-initialization.patch #rhbz1002351 ApplyPatch crypto-fix-race-in-larval-lookup.patch +#CVE-2013-4343 rhbz 1007733 1007741 +ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch + # END OF PATCH APPLICATIONS %endif @@ -2340,6 +2346,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 13 2013 Josh Boyer +- CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) + * Thu Sep 12 2013 Josh Boyer - Update HID CVE fixes to fix crash from lenovo-tpkbd driver (rhbz 1003998) diff --git a/tuntap-correctly-handle-error-in-tun_set_iff.patch b/tuntap-correctly-handle-error-in-tun_set_iff.patch new file mode 100644 index 000000000..563526765 --- /dev/null +++ b/tuntap-correctly-handle-error-in-tun_set_iff.patch @@ -0,0 +1,57 @@ +From dff4e504b2addc8053fc47712d44a21f733ef51b Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Wed, 11 Sep 2013 18:09:48 +0800 +Subject: [PATCH] tuntap: correctly handle error in tun_set_iff() + +Commit c8d68e6be1c3b242f1c598595830890b65cea64a +(tuntap: multiqueue support) only call free_netdev() on error in +tun_set_iff(). This causes several issues: + +- memory of tun security were leaked +- use after free since the flow gc timer was not deleted and the tfile + were not detached + +This patch solves the above issues. + +Reported-by: Wannes Rombouts +Cc: Michael S. Tsirkin +Signed-off-by: Jason Wang +--- + drivers/net/tun.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 71af122..68b9aa3 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1691,11 +1691,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + INIT_LIST_HEAD(&tun->disabled); + err = tun_attach(tun, file); + if (err < 0) +- goto err_free_dev; ++ goto err_free_flow; + + err = register_netdevice(tun->dev); + if (err < 0) +- goto err_free_dev; ++ goto err_detach; + + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || + device_create_file(&tun->dev->dev, &dev_attr_owner) || +@@ -1739,7 +1739,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + strcpy(ifr->ifr_name, tun->dev->name); + return 0; + +- err_free_dev: ++err_detach: ++ tun_detach_all(dev); ++err_free_flow: ++ tun_flow_uninit(tun); ++ security_tun_dev_free_security(tun->security); ++err_free_dev: + free_netdev(dev); + return err; + } +-- +1.8.3.1 + From b1e0725fa639a1fe73c07d6706c23e87e8e8e6e1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Sep 2013 11:16:43 -0400 Subject: [PATCH 414/492] CVE-2013-XXXX net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) --- kernel.spec | 7 + ...ipsec-encryption-bug-in-sctp_v6_xmit.patch | 190 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch diff --git a/kernel.spec b/kernel.spec index 2ee86cad7..801080e98 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,9 @@ Patch25100: crypto-fix-race-in-larval-lookup.patch #CVE-2013-4343 rhbz 1007733 1007741 Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch +#CVE-2013-XXXX rhbz 1007872 1007903 +Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch + # END OF PATCH DEFINITIONS %endif @@ -1505,6 +1508,9 @@ ApplyPatch crypto-fix-race-in-larval-lookup.patch #CVE-2013-4343 rhbz 1007733 1007741 ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch +#CVE-2013-XXXX rhbz 1007872 1007903 +ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch + # END OF PATCH APPLICATIONS %endif @@ -2347,6 +2353,7 @@ fi # || || %changelog * Fri Sep 13 2013 Josh Boyer +- CVE-2013-XXXX net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) - CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) * Thu Sep 12 2013 Josh Boyer diff --git a/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch b/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch new file mode 100644 index 000000000..bba16ee6b --- /dev/null +++ b/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch @@ -0,0 +1,190 @@ +From 9ecce5d19bce6d423342cee4348c3a44ed9edc02 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Wed, 11 Sep 2013 14:58:36 +0000 +Subject: [PATCH] net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit + +Alan Chester reported an issue with IPv6 on SCTP that IPsec traffic is not +being encrypted, whereas on IPv4 it is. Setting up an AH + ESP transport +does not seem to have the desired effect: + +SCTP + IPv4: + + 22:14:20.809645 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 116) + 192.168.0.2 > 192.168.0.5: AH(spi=0x00000042,sumlen=16,seq=0x1): ESP(spi=0x00000044,seq=0x1), length 72 + 22:14:20.813270 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 340) + 192.168.0.5 > 192.168.0.2: AH(spi=0x00000043,sumlen=16,seq=0x1): + +SCTP + IPv6: + + 22:31:19.215029 IP6 (class 0x02, hlim 64, next-header SCTP (132) payload length: 364) + fe80::222:15ff:fe87:7fc.3333 > fe80::92e6:baff:fe0d:5a54.36767: sctp + 1) [INIT ACK] [init tag: 747759530] [rwnd: 62464] [OS: 10] [MIS: 10] + +Moreover, Alan says: + + This problem was seen with both Racoon and Racoon2. Other people have seen + this with OpenSwan. When IPsec is configured to encrypt all upper layer + protocols the SCTP connection does not initialize. After using Wireshark to + follow packets, this is because the SCTP packet leaves Box A unencrypted and + Box B believes all upper layer protocols are to be encrypted so it drops + this packet, causing the SCTP connection to fail to initialize. When IPsec + is configured to encrypt just SCTP, the SCTP packets are observed unencrypted. + +In fact, using `socat sctp6-listen:3333 -` on one end and transferring "plaintext" +string on the other end, results in cleartext on the wire where SCTP eventually +does not report any errors, thus in the latter case that Alan reports, the +non-paranoid user might think he's communicating over an encrypted transport on +SCTP although he's not (tcpdump ... -X): + + ... + 0x0030: 5d70 8e1a 0003 001a 177d eb6c 0000 0000 ]p.......}.l.... + 0x0040: 0000 0000 706c 6169 6e74 6578 740a 0000 ....plaintext... + +Only in /proc/net/xfrm_stat we can see XfrmInTmplMismatch increasing on the +receiver side. Initial follow-up analysis from Alan's bug report was done by +Alexey Dobriyan. Also thanks to Vlad Yasevich for feedback on this. + +SCTP has its own implementation of sctp_v6_xmit() not calling inet6_csk_xmit(). +This has the implication that it probably never really got updated along with +changes in inet6_csk_xmit() and therefore does not seem to invoke xfrm handlers. + +SCTP's IPv4 xmit however, properly calls ip_queue_xmit() to do the work. Since +a call to inet6_csk_xmit() would solve this problem, but result in unecessary +route lookups, let us just use the cached flowi6 instead that we got through +sctp_v6_get_dst(). Since all SCTP packets are being sent through sctp_packet_transmit(), +we do the route lookup / flow caching in sctp_transport_route(), hold it in +tp->dst and skb_dst_set() right after that. If we would alter fl6->daddr in +sctp_v6_xmit() to np->opt->srcrt, we possibly could run into the same effect +of not having xfrm layer pick it up, hence, use fl6_update_dst() in sctp_v6_get_dst() +instead to get the correct source routed dst entry, which we assign to the skb. + +Also source address routing example from 625034113 ("sctp: fix sctp to work with +ipv6 source address routing") still works with this patch! Nevertheless, in RFC5095 +it is actually 'recommended' to not use that anyway due to traffic amplification [1]. +So it seems we're not supposed to do that anyway in sctp_v6_xmit(). Moreover, if +we overwrite the flow destination here, the lower IPv6 layer will be unable to +put the correct destination address into IP header, as routing header is added in +ipv6_push_nfrag_opts() but then probably with wrong final destination. Things aside, +result of this patch is that we do not have any XfrmInTmplMismatch increase plus on +the wire with this patch it now looks like: + +SCTP + IPv6: + + 08:17:47.074080 IP6 2620:52:0:102f:7a2b:cbff:fe27:1b0a > 2620:52:0:102f:213:72ff:fe32:7eba: + AH(spi=0x00005fb4,seq=0x1): ESP(spi=0x00005fb5,seq=0x1), length 72 + 08:17:47.074264 IP6 2620:52:0:102f:213:72ff:fe32:7eba > 2620:52:0:102f:7a2b:cbff:fe27:1b0a: + AH(spi=0x00003d54,seq=0x1): ESP(spi=0x00003d55,seq=0x1), length 296 + +This fixes Kernel Bugzilla 24412. This security issue seems to be present since +2.6.18 kernels. Lets just hope some big passive adversary in the wild didn't have +its fun with that. lksctp-tools IPv6 regression test suite passes as well with +this patch. + + [1] http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf + +Reported-by: Alan Chester +Reported-by: Alexey Dobriyan +Signed-off-by: Daniel Borkmann +Cc: Steffen Klassert +Cc: Hannes Frederic Sowa +Acked-by: Vlad Yasevich +Signed-off-by: David S. Miller +--- + net/sctp/ipv6.c | 41 ++++++++++++----------------------------- + 1 file changed, 12 insertions(+), 29 deletions(-) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 391a245..cc86f2c 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -210,45 +210,23 @@ out: + in6_dev_put(idev); + } + +-/* Based on tcp_v6_xmit() in tcp_ipv6.c. */ + static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) + { + struct sock *sk = skb->sk; + struct ipv6_pinfo *np = inet6_sk(sk); +- struct flowi6 fl6; +- +- memset(&fl6, 0, sizeof(fl6)); +- +- fl6.flowi6_proto = sk->sk_protocol; +- +- /* Fill in the dest address from the route entry passed with the skb +- * and the source address from the transport. +- */ +- fl6.daddr = transport->ipaddr.v6.sin6_addr; +- fl6.saddr = transport->saddr.v6.sin6_addr; +- +- fl6.flowlabel = np->flow_label; +- IP6_ECN_flow_xmit(sk, fl6.flowlabel); +- if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL) +- fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id; +- else +- fl6.flowi6_oif = sk->sk_bound_dev_if; +- +- if (np->opt && np->opt->srcrt) { +- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; +- fl6.daddr = *rt0->addr; +- } ++ struct flowi6 *fl6 = &transport->fl.u.ip6; + + SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", + __func__, skb, skb->len, +- &fl6.saddr, &fl6.daddr); ++ &fl6->saddr, &fl6->daddr); + +- SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); ++ IP6_ECN_flow_xmit(sk, fl6->flowlabel); + + if (!(transport->param_flags & SPP_PMTUD_ENABLE)) + skb->local_df = 1; + +- return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); ++ return ip6_xmit(sk, skb, fl6, np->opt, np->tclass); + } + + /* Returns the dst cache entry for the given source and destination ip +@@ -261,10 +239,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + struct dst_entry *dst = NULL; + struct flowi6 *fl6 = &fl->u.ip6; + struct sctp_bind_addr *bp; ++ struct ipv6_pinfo *np = inet6_sk(sk); + struct sctp_sockaddr_entry *laddr; + union sctp_addr *baddr = NULL; + union sctp_addr *daddr = &t->ipaddr; + union sctp_addr dst_saddr; ++ struct in6_addr *final_p, final; + __u8 matchlen = 0; + __u8 bmatchlen; + sctp_scope_t scope; +@@ -287,7 +267,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); + } + +- dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); ++ final_p = fl6_update_dst(fl6, np->opt, &final); ++ dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); + if (!asoc || saddr) + goto out; + +@@ -339,10 +320,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + } + } + rcu_read_unlock(); ++ + if (baddr) { + fl6->saddr = baddr->v6.sin6_addr; + fl6->fl6_sport = baddr->v6.sin6_port; +- dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); ++ final_p = fl6_update_dst(fl6, np->opt, &final); ++ dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); + } + + out: +-- +1.8.3.1 + From 7e1766f2cde790191a00b41a71feb86f01e64e37 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Sep 2013 15:47:37 -0400 Subject: [PATCH 415/492] Correct CVE number for sctp IPv6 issue --- kernel.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 801080e98..2c757cb0c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,7 +785,7 @@ Patch25100: crypto-fix-race-in-larval-lookup.patch #CVE-2013-4343 rhbz 1007733 1007741 Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch -#CVE-2013-XXXX rhbz 1007872 1007903 +#CVE-2013-4053 rhbz 1007872 1007903 Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch # END OF PATCH DEFINITIONS @@ -1508,7 +1508,7 @@ ApplyPatch crypto-fix-race-in-larval-lookup.patch #CVE-2013-4343 rhbz 1007733 1007741 ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch -#CVE-2013-XXXX rhbz 1007872 1007903 +#CVE-2013-4350 rhbz 1007872 1007903 ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch # END OF PATCH APPLICATIONS @@ -2353,7 +2353,7 @@ fi # || || %changelog * Fri Sep 13 2013 Josh Boyer -- CVE-2013-XXXX net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) +- CVE-2013-4053 net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) - CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) * Thu Sep 12 2013 Josh Boyer From cddf6d836f327913025dab5ebd22df25b8b27a37 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Sep 2013 15:51:15 -0400 Subject: [PATCH 416/492] 1/3 is a crappy correction rate --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2c757cb0c..97781bc8b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,7 +785,7 @@ Patch25100: crypto-fix-race-in-larval-lookup.patch #CVE-2013-4343 rhbz 1007733 1007741 Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch -#CVE-2013-4053 rhbz 1007872 1007903 +#CVE-2013-4350 rhbz 1007872 1007903 Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch # END OF PATCH DEFINITIONS @@ -2353,7 +2353,7 @@ fi # || || %changelog * Fri Sep 13 2013 Josh Boyer -- CVE-2013-4053 net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) +- CVE-2013-4350 net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) - CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) * Thu Sep 12 2013 Josh Boyer From ef6fcfd7b8cb18a00eed9e02a2949c6ef34bbbb7 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 16 Sep 2013 07:50:18 -0500 Subject: [PATCH 417/492] Linux v3.10.12 --- ...sses-check-from-ipv6_create_tempaddr.patch | 63 ------------------- kernel.spec | 11 ++-- sources | 2 +- 3 files changed, 5 insertions(+), 71 deletions(-) delete mode 100644 ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch diff --git a/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch b/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch deleted file mode 100644 index 0c4fc2484..000000000 --- a/ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 2712c283acc085b5438fa1b22053423a0158468d Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Fri, 16 Aug 2013 11:02:27 +0000 -Subject: [PATCH] ipv6: remove max_addresses check from ipv6_create_tempaddr - -Because of the max_addresses check attackers were able to disable privacy -extensions on an interface by creating enough autoconfigured addresses: - - - -But the check is not actually needed: max_addresses protects the -kernel to install too many ipv6 addresses on an interface and guards -addrconf_prefix_rcv to install further addresses as soon as this limit -is reached. We only generate temporary addresses in direct response of -a new address showing up. As soon as we filled up the maximum number of -addresses of an interface, we stop installing more addresses and thus -also stop generating more temp addresses. - -Even if the attacker tries to generate a lot of temporary addresses -by announcing a prefix and removing it again (lifetime == 0) we won't -install more temp addresses, because the temporary addresses do count -to the maximum number of addresses, thus we would stop installing new -autoconfigured addresses when the limit is reached. - -This patch fixes CVE-2013-0343 (but other layer-2 attacks are still -possible). - -Thanks to Ding Tianhong to bring this topic up again. - -Cc: Ding Tianhong -Cc: George Kargiotakis -Cc: P J P -Cc: YOSHIFUJI Hideaki -Signed-off-by: Hannes Frederic Sowa -Acked-by: Ding Tianhong -Signed-off-by: David S. Miller ---- - net/ipv6/addrconf.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index fb8c94c..21b7a87 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -1124,12 +1124,10 @@ retry: - if (ifp->flags & IFA_F_OPTIMISTIC) - addr_flags |= IFA_F_OPTIMISTIC; - -- ift = !max_addresses || -- ipv6_count_addresses(idev) < max_addresses ? -- ipv6_add_addr(idev, &addr, tmp_plen, -+ ift = ipv6_add_addr(idev, &addr, tmp_plen, - ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, -- addr_flags) : NULL; -- if (IS_ERR_OR_NULL(ift)) { -+ addr_flags); -+ if (IS_ERR(ift)) { - in6_ifa_put(ifp); - in6_dev_put(idev); - pr_info("%s: retry temporary address regeneration\n", __func__); --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index 97781bc8b..ee6e15d30 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 12 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -766,9 +766,6 @@ Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-0343 rhbz 914664 999380 -Patch25078: ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch - #rhbz 1000679 Patch25079: rt2800-rearrange-bbp-rfcsr-initialization.patch @@ -1489,9 +1486,6 @@ ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-0343 rhbz 914664 999380 -ApplyPatch ipv6-remove-max_addresses-check-from-ipv6_create_tempaddr.patch - #CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 #CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 #CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 @@ -2352,6 +2346,9 @@ fi # ||----w | # || || %changelog +* Mon Sep 16 2013 Justin M. Forbes 3.10.12-100 +- Linux v3.10.12 + * Fri Sep 13 2013 Josh Boyer - CVE-2013-4350 net: sctp: ipv6 ipsec encryption bug in sctp_v6_xmit (rhbz 1007872 1007903) - CVE-2013-4343 net: use-after-free TUNSETIFF (rhbz 1007733 1007741) diff --git a/sources b/sources index fb3a8ac24..ec45c22e9 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -9aadf2325fed53e971fe59bc6c7c3b89 patch-3.10.11.xz +9bfba28fef36c6a7fc16fd896eab131b patch-3.10.12.xz From 83627137df927ccbbbf8617c12342ea2c516fb6a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Sep 2013 15:57:07 -0400 Subject: [PATCH 418/492] CVE-2013-4345 ansi_cprng: off by one error in non-block size request (rhbz 1007690 1009136) --- ...-one-error-in-non-block-size-request.patch | 40 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 49 insertions(+) create mode 100644 ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch diff --git a/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch b/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch new file mode 100644 index 000000000..c8d015491 --- /dev/null +++ b/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch @@ -0,0 +1,40 @@ +Stephan Mueller reported to me recently a error in random number generation in +the ansi cprng. If several small requests are made that are less than the +instances block size, the remainder for loop code doesn't increment +rand_data_valid in the last iteration, meaning that the last bytes in the +rand_data buffer gets reused on the subsequent smaller-than-a-block request for +random data. + +The fix is pretty easy, just re-code the for loop to make sure that +rand_data_valid gets incremented appropriately + +Signed-off-by: Neil Horman +Reported-by: Stephan Mueller +CC: Stephan Mueller +CC: Petr Matousek +CC: Herbert Xu +CC: "David S. Miller" +--- + crypto/ansi_cprng.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c +index c0bb377..666f196 100644 +--- a/crypto/ansi_cprng.c ++++ b/crypto/ansi_cprng.c +@@ -230,11 +230,11 @@ remainder: + */ + if (byte_count < DEFAULT_BLK_SZ) { + empty_rbuf: +- for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; +- ctx->rand_data_valid++) { ++ while (ctx->rand_data_valid < DEFAULT_BLK_SZ) { + *ptr = ctx->rand_data[ctx->rand_data_valid]; + ptr++; + byte_count--; ++ ctx->rand_data_valid++; + if (byte_count == 0) + goto done; + } +-- +1.8.3.1 diff --git a/kernel.spec b/kernel.spec index ee6e15d30..3ef40b18a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,9 @@ Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch #CVE-2013-4350 rhbz 1007872 1007903 Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch +#CVE-2013-4345 rhbz 1007690 1009136 +Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch + # END OF PATCH DEFINITIONS %endif @@ -1505,6 +1508,9 @@ ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch #CVE-2013-4350 rhbz 1007872 1007903 ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch +#CVE-2013-4345 rhbz 1007690 1009136 +ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch + # END OF PATCH APPLICATIONS %endif @@ -2346,6 +2352,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 17 2013 Josh Boyer +- CVE-2013-4345 ansi_cprng: off by one error in non-block size request (rhbz 1007690 1009136) + * Mon Sep 16 2013 Justin M. Forbes 3.10.12-100 - Linux v3.10.12 From b3ab68051bcdf75e8ac02bb9b0615b9dbed754be Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Sep 2013 10:15:09 -0400 Subject: [PATCH 419/492] Fix multimedia keys on Genius GX keyboard (rhbz 928561) --- ...rt-fixup-for-Genius-Gx-Imperator-Key.patch | 118 ++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 127 insertions(+) create mode 100644 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch diff --git a/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch b/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch new file mode 100644 index 000000000..b7bbf77b6 --- /dev/null +++ b/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch @@ -0,0 +1,118 @@ +From 0adb9c2c5ed42f199cb2a630c37d18dee385fae2 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Mon, 15 Jul 2013 10:12:18 +0200 +Subject: [PATCH] HID: kye: Add report fixup for Genius Gx Imperator Keyboard + +Genius Gx Imperator Keyboard presents the same problem in its report +descriptors than Genius Gila Gaming Mouse. +Use the same fixup for both. + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=928561 + +Reported-and-tested-by: Honza Brazdil +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-core.c | 1 + + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-kye.c | 45 ++++++++++++++++++++++++++++----------------- + 3 files changed, 30 insertions(+), 17 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 8de5cb8..b0f2f45 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1594,6 +1594,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index c5aea29..0288531 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -479,6 +479,7 @@ + #define USB_VENDOR_ID_KYE 0x0458 + #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 + #define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 ++#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR 0x4018 + #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 + #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 +diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c +index 1e2ee2aa..7384512 100644 +--- a/drivers/hid/hid-kye.c ++++ b/drivers/hid/hid-kye.c +@@ -268,6 +268,26 @@ static __u8 easypen_m610x_rdesc_fixed[] = { + 0xC0 /* End Collection */ + }; + ++static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize, int offset, const char *device_name) { ++ /* ++ * the fixup that need to be done: ++ * - change Usage Maximum in the Comsumer Control ++ * (report ID 3) to a reasonable value ++ */ ++ if (*rsize >= offset + 31 && ++ /* Usage Page (Consumer Devices) */ ++ rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c && ++ /* Usage (Consumer Control) */ ++ rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 && ++ /* Usage Maximum > 12287 */ ++ rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) { ++ hid_info(hdev, "fixing up %s report descriptor\n", device_name); ++ rdesc[offset + 12] = 0x2f; ++ } ++ return rdesc; ++} ++ + static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +@@ -315,23 +335,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + } + break; + case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: +- /* +- * the fixup that need to be done: +- * - change Usage Maximum in the Comsumer Control +- * (report ID 3) to a reasonable value +- */ +- if (*rsize >= 135 && +- /* Usage Page (Consumer Devices) */ +- rdesc[104] == 0x05 && rdesc[105] == 0x0c && +- /* Usage (Consumer Control) */ +- rdesc[106] == 0x09 && rdesc[107] == 0x01 && +- /* Usage Maximum > 12287 */ +- rdesc[114] == 0x2a && rdesc[116] > 0x2f) { +- hid_info(hdev, +- "fixing up Genius Gila Gaming Mouse " +- "report descriptor\n"); +- rdesc[116] = 0x2f; +- } ++ rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104, ++ "Genius Gila Gaming Mouse"); ++ break; ++ case USB_DEVICE_ID_GENIUS_GX_IMPERATOR: ++ rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83, ++ "Genius Gx Imperator Keyboard"); + break; + } + return rdesc; +@@ -428,6 +437,8 @@ static const struct hid_device_id kye_devices[] = { + USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, ++ USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, + { } + }; + MODULE_DEVICE_TABLE(hid, kye_devices); +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 3ef40b18a..1d141cff7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,9 @@ Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch #CVE-2013-4345 rhbz 1007690 1009136 Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch +#rhbz 928561 +Patch25105: 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch + # END OF PATCH DEFINITIONS %endif @@ -1511,6 +1514,9 @@ ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch #CVE-2013-4345 rhbz 1007690 1009136 ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch +#rhbz 928561 +ApplyPatch 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch + # END OF PATCH APPLICATIONS %endif @@ -2352,6 +2358,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 20 2013 Josh Boyer +- Fix multimedia keys on Genius GX keyboard (rhbz 928561) + * Tue Sep 17 2013 Josh Boyer - CVE-2013-4345 ansi_cprng: off by one error in non-block size request (rhbz 1007690 1009136) From 38d9b677795aeb13e94af13b282f4ea7f6212b20 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 23 Sep 2013 10:46:25 -0400 Subject: [PATCH 420/492] Resolves: rhbz 971893 --- bonding-driver-alb-learning.patch | 155 ++++++++++++++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 164 insertions(+) create mode 100644 bonding-driver-alb-learning.patch diff --git a/bonding-driver-alb-learning.patch b/bonding-driver-alb-learning.patch new file mode 100644 index 000000000..c7f8e8f6b --- /dev/null +++ b/bonding-driver-alb-learning.patch @@ -0,0 +1,155 @@ +commit 7eacd03810960823393521063734fc8188446bca +Author: Neil Horman +Date: Fri Sep 13 11:05:33 2013 -0400 + + bonding: Make alb learning packet interval configurable + + running bonding in ALB mode requires that learning packets be sent periodically, + so that the switch knows where to send responding traffic. However, depending + on switch configuration, there may not be any need to send traffic at the + default rate of 3 packets per second, which represents little more than wasted + data. Allow the ALB learning packet interval to be made configurable via sysfs + + Signed-off-by: Neil Horman + Acked-by: Acked-by: Veaceslav Falico + CC: Jay Vosburgh + CC: Andy Gospodarek + CC: "David S. Miller" + Signed-off-by: Andy Gospodarek + Signed-off-by: David S. Miller + +diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt +index 87bbcfe..9b28e71 100644 +--- a/Documentation/networking/bonding.txt ++++ b/Documentation/networking/bonding.txt +@@ -1362,6 +1362,12 @@ To add ARP targets: + To remove an ARP target: + # echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target + ++To configure the interval between learning packet transmits: ++# echo 12 > /sys/class/net/bond0/bonding/lp_interval ++ NOTE: the lp_inteval is the number of seconds between instances where ++the bonding driver sends learning packets to each slaves peer switch. The ++default interval is 1 second. ++ + Example Configuration + --------------------- + We begin with the same example that is shown in section 3.3, +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index 91f179d..f428ef57 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1472,7 +1472,7 @@ void bond_alb_monitor(struct work_struct *work) + bond_info->lp_counter++; + + /* send learning packets */ +- if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) { ++ if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) { + /* change of curr_active_slave involves swapping of mac addresses. + * in order to avoid this swapping from happening while + * sending the learning packets, the curr_slave_lock must be held for +diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h +index 28d8e4c..c5eff5d 100644 +--- a/drivers/net/bonding/bond_alb.h ++++ b/drivers/net/bonding/bond_alb.h +@@ -36,14 +36,15 @@ struct slave; + * Used for division - never set + * to zero !!! + */ +-#define BOND_ALB_LP_INTERVAL 1 /* In seconds, periodic send of +- * learning packets to the switch +- */ ++#define BOND_ALB_DEFAULT_LP_INTERVAL 1 ++#define BOND_ALB_LP_INTERVAL(bond) (bond->params.lp_interval) /* In seconds, periodic send of ++ * learning packets to the switch ++ */ + + #define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \ + * ALB_TIMER_TICKS_PER_SEC) + +-#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \ ++#define BOND_ALB_LP_TICKS(bond) (BOND_ALB_LP_INTERVAL(bond) \ + * ALB_TIMER_TICKS_PER_SEC) + + #define TLB_HASH_TABLE_SIZE 256 /* The size of the clients hash table. +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 72df399..55bbb8b 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -4416,6 +4416,7 @@ static int bond_check_params(struct bond_params *params) + params->all_slaves_active = all_slaves_active; + params->resend_igmp = resend_igmp; + params->min_links = min_links; ++ params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL; + + if (primary) { + strncpy(params->primary, primary, IFNAMSIZ); +diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c +index eeab40b..c29b836 100644 +--- a/drivers/net/bonding/bond_sysfs.c ++++ b/drivers/net/bonding/bond_sysfs.c +@@ -1699,6 +1699,44 @@ out: + static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR, + bonding_show_resend_igmp, bonding_store_resend_igmp); + ++ ++static ssize_t bonding_show_lp_interval(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct bonding *bond = to_bond(d); ++ return sprintf(buf, "%d\n", bond->params.lp_interval); ++} ++ ++static ssize_t bonding_store_lp_interval(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct bonding *bond = to_bond(d); ++ int new_value, ret = count; ++ ++ if (sscanf(buf, "%d", &new_value) != 1) { ++ pr_err("%s: no lp interval value specified.\n", ++ bond->dev->name); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (new_value <= 0) { ++ pr_err ("%s: lp_interval must be between 1 and %d\n", ++ bond->dev->name, INT_MAX); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ bond->params.lp_interval = new_value; ++out: ++ return ret; ++} ++ ++static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR, ++ bonding_show_lp_interval, bonding_store_lp_interval); ++ + static struct attribute *per_bond_attrs[] = { + &dev_attr_slaves.attr, + &dev_attr_mode.attr, +@@ -1729,6 +1767,7 @@ static struct attribute *per_bond_attrs[] = { + &dev_attr_all_slaves_active.attr, + &dev_attr_resend_igmp.attr, + &dev_attr_min_links.attr, ++ &dev_attr_lp_interval.attr, + NULL, + }; + +diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h +index 7ad8bd5..03cf3fd 100644 +--- a/drivers/net/bonding/bonding.h ++++ b/drivers/net/bonding/bonding.h +@@ -176,6 +176,7 @@ struct bond_params { + int tx_queues; + int all_slaves_active; + int resend_igmp; ++ int lp_interval; + }; + + struct bond_parm_tbl { diff --git a/kernel.spec b/kernel.spec index 1d141cff7..97cd19315 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,9 @@ Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch #rhbz 928561 Patch25105: 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch +#rhbz 971893 +Patch25106: bonding-driver-alb-learning.patch + # END OF PATCH DEFINITIONS %endif @@ -1517,6 +1520,9 @@ ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch #rhbz 928561 ApplyPatch 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch +#rhbz 971893 +ApplyPatch bonding-driver-alb-learning.patch + # END OF PATCH APPLICATIONS %endif @@ -2358,6 +2364,9 @@ fi # ||----w | # || || %changelog +* Mon Sep 23 2013 Neil Horman +- Add alb learning packet config knob (rhbz 971893) + * Fri Sep 20 2013 Josh Boyer - Fix multimedia keys on Genius GX keyboard (rhbz 928561) From 2838ee09693c116be7a14174b047a302a992b055 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 27 Sep 2013 08:07:02 -0500 Subject: [PATCH 421/492] Linux v3.10.13 --- HID-CVE-fixes.patch | 291 ------------------ ...ODATA-if-reading-battery-attrs-fails.patch | 1 + crypto-fix-race-in-larval-lookup.patch | 44 --- kernel.spec | 11 +- sources | 2 +- 5 files changed, 6 insertions(+), 343 deletions(-) delete mode 100644 crypto-fix-race-in-larval-lookup.patch diff --git a/HID-CVE-fixes.patch b/HID-CVE-fixes.patch index a1fcf6da5..921ad9cb0 100644 --- a/HID-CVE-fixes.patch +++ b/HID-CVE-fixes.patch @@ -1,83 +1,3 @@ -From aab9cb0a00ecdd937273f3b9649311d81bf4f0cb Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:29:55 +0200 -Subject: [PATCH 01/16] HID: validate HID report id size - -The "Report ID" field of a HID report is used to build indexes of -reports. The kernel's index of these is limited to 256 entries, so any -malicious device that sets a Report ID greater than 255 will trigger -memory corruption on the host: - -[ 1347.156239] BUG: unable to handle kernel paging request at ffff88094958a878 -[ 1347.156261] IP: [] hid_register_report+0x2a/0x8b - -CVE-2013-2888 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-core.c | 10 +++++++--- - include/linux/hid.h | 4 +++- - 2 files changed, 10 insertions(+), 4 deletions(-) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 36668d1..5ea7d51 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, - struct hid_report_enum *report_enum = device->report_enum + type; - struct hid_report *report; - -+ if (id >= HID_MAX_IDS) -+ return NULL; - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - -@@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) - - case HID_GLOBAL_ITEM_TAG_REPORT_ID: - parser->global.report_id = item_udata(item); -- if (parser->global.report_id == 0) { -- hid_err(parser->device, "report_id 0 is invalid\n"); -+ if (parser->global.report_id == 0 || -+ parser->global.report_id >= HID_MAX_IDS) { -+ hid_err(parser->device, "report_id %u is invalid\n", -+ parser->global.report_id); - return -1; - } - return 0; -@@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device) - for (i = 0; i < HID_REPORT_TYPES; i++) { - struct hid_report_enum *report_enum = device->report_enum + i; - -- for (j = 0; j < 256; j++) { -+ for (j = 0; j < HID_MAX_IDS; j++) { - struct hid_report *report = report_enum->report_id_hash[j]; - if (report) - hid_free_report(report); -diff --git a/include/linux/hid.h b/include/linux/hid.h -index 0c48991..ff545cc 100644 ---- a/include/linux/hid.h -+++ b/include/linux/hid.h -@@ -393,10 +393,12 @@ struct hid_report { - struct hid_device *device; /* associated device */ - }; - -+#define HID_MAX_IDS 256 -+ - struct hid_report_enum { - unsigned numbered; - struct list_head report_list; -- struct hid_report *report_id_hash[256]; -+ struct hid_report *report_id_hash[HID_MAX_IDS]; - }; - - #define HID_REPORT_TYPES 3 --- -1.8.3.1 - - From ba6d8d44eaeb0ee58082f4b4c95138416e1f58a5 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 11 Sep 2013 21:56:50 +0200 @@ -864,214 +784,3 @@ index 762d988..31cf29a 100644 -- 1.8.3.1 - - -From b2438ded3cdd8d6d6af77d9bce38d2d8f353a790 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:32:01 +0200 -Subject: [PATCH 12/16] HID: check for NULL field when setting values - -Defensively check that the field to be worked on is not NULL. - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-core.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 08500bc..e331cb1 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -1212,7 +1212,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); - - int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) - { -- unsigned size = field->report_size; -+ unsigned size; -+ -+ if (!field) -+ return -1; -+ -+ size = field->report_size; - - hid_dump_input(field->report->device, field->usage + offset, value); - --- -1.8.3.1 - - -From d0502783cdafcdb0a677492c43a373748d900d50 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:30:49 +0200 -Subject: [PATCH 13/16] HID: pantherlord: validate output report details - -A HID device could send a malicious output report that would cause the -pantherlord HID driver to write beyond the output report allocation -during initialization, causing a heap overflow: - -[ 310.939483] usb 1-1: New USB device found, idVendor=0e8f, idProduct=0003 -... -[ 315.980774] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2892 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-pl.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c -index d29112f..2dcd7d9 100644 ---- a/drivers/hid/hid-pl.c -+++ b/drivers/hid/hid-pl.c -@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid) - strong = &report->field[0]->value[2]; - weak = &report->field[0]->value[3]; - debug("detected single-field device"); -- } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && -- report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { -+ } else if (report->field[0]->maxusage == 1 && -+ report->field[0]->usage[0].hid == -+ (HID_UP_LED | 0x43) && -+ report->maxfield >= 4 && -+ report->field[0]->report_count >= 1 && -+ report->field[1]->report_count >= 1 && -+ report->field[2]->report_count >= 1 && -+ report->field[3]->report_count >= 1) { - report->field[0]->value[0] = 0x00; - report->field[1]->value[0] = 0x00; - strong = &report->field[2]->value[0]; --- -1.8.3.1 - - -From dc4db3b624cc7bf6972817615af88e250a8526cc Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:31:28 +0200 -Subject: [PATCH 14/16] HID: ntrig: validate feature report details - -A HID device could send a malicious feature report that would cause the -ntrig HID driver to trigger a NULL dereference during initialization: - -[57383.031190] usb 3-1: New USB device found, idVendor=1b96, idProduct=0001 -... -[57383.315193] BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 -[57383.315308] IP: [] ntrig_probe+0x25e/0x420 [hid_ntrig] - -CVE-2013-2896 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Signed-off-by: Rafi Rubin -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-ntrig.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c -index ef95102..5482156 100644 ---- a/drivers/hid/hid-ntrig.c -+++ b/drivers/hid/hid-ntrig.c -@@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) - struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. - report_id_hash[0x0d]; - -- if (!report) -+ if (!report || report->maxfield < 1 || -+ report->field[0]->report_count < 1) - return -EINVAL; - - hid_hw_request(hdev, report, HID_REQ_GET_REPORT); --- -1.8.3.1 - - -From 34490675479f16680a60726632ad2e808eab54bd Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:31:44 +0200 -Subject: [PATCH 15/16] HID: sensor-hub: validate feature report details - -A HID device could send a malicious feature report that would cause the -sensor-hub HID driver to read past the end of heap allocation, leaking -kernel memory contents to the caller. - -CVE-2013-2898 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Reviewed-by: Mika Westerberg -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-sensor-hub.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c -index ca749810..aa34755 100644 ---- a/drivers/hid/hid-sensor-hub.c -+++ b/drivers/hid/hid-sensor-hub.c -@@ -221,7 +221,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, - - mutex_lock(&data->mutex); - report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); -- if (!report || (field_index >= report->maxfield)) { -+ if (!report || (field_index >= report->maxfield) || -+ report->field[field_index]->report_count < 1) { - ret = -EINVAL; - goto done_proc; - } --- -1.8.3.1 - - -From a0155e41d3a7a9bd901368271d86ee1bb28d100f Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 28 Aug 2013 22:31:52 +0200 -Subject: [PATCH 16/16] HID: picolcd_core: validate output report details -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A HID device could send a malicious output report that would cause the -picolcd HID driver to trigger a NULL dereference during attr file writing. - -[jkosina@suse.cz: changed - - report->maxfield < 1 - -to - - report->maxfield != 1 - -as suggested by Bruno]. - -CVE-2013-2899 - -Signed-off-by: Kees Cook -Cc: stable@kernel.org -Reviewed-by: Bruno Prémont -Acked-by: Bruno Prémont -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-picolcd_core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c -index b48092d..acbb0210 100644 ---- a/drivers/hid/hid-picolcd_core.c -+++ b/drivers/hid/hid-picolcd_core.c -@@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, - buf += 10; - cnt -= 10; - } -- if (!report) -+ if (!report || report->maxfield != 1) - return -EINVAL; - - while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) --- -1.8.3.1 - diff --git a/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch b/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch index acdd66d48..d0a021c4c 100644 --- a/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch +++ b/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch @@ -45,6 +45,7 @@ index 945b815..c526a3c 100644 - if (ret >= 0) - ret = -EINVAL; + ret = -ENODATA; + kfree(buf); break; } + ret = 0; diff --git a/crypto-fix-race-in-larval-lookup.patch b/crypto-fix-race-in-larval-lookup.patch deleted file mode 100644 index d1b19419e..000000000 --- a/crypto-fix-race-in-larval-lookup.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 77dbd7a95e4a4f15264c333a9e9ab97ee27dc2aa -Author: Herbert Xu -Date: Sun Sep 8 14:33:50 2013 +1000 - - crypto: api - Fix race condition in larval lookup - - crypto_larval_lookup should only return a larval if it created one. - Any larval created by another entity must be processed through - crypto_larval_wait before being returned. - - Otherwise this will lead to a larval being killed twice, which - will most likely lead to a crash. - - Cc: stable@vger.kernel.org - Reported-by: Kees Cook - Tested-by: Kees Cook - Signed-off-by: Herbert Xu - -diff --git a/crypto/api.c b/crypto/api.c -index 320ea4d..a2b39c5 100644 ---- a/crypto/api.c -+++ b/crypto/api.c -@@ -34,6 +34,8 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem); - BLOCKING_NOTIFIER_HEAD(crypto_chain); - EXPORT_SYMBOL_GPL(crypto_chain); - -+static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg); -+ - struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) - { - return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; -@@ -144,8 +146,11 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type, - } - up_write(&crypto_alg_sem); - -- if (alg != &larval->alg) -+ if (alg != &larval->alg) { - kfree(larval); -+ if (crypto_is_larval(alg)) -+ alg = crypto_larval_wait(alg); -+ } - - return alg; - } diff --git a/kernel.spec b/kernel.spec index 97cd19315..6c3e98e14 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 12 +%define stable_update 13 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -776,9 +776,6 @@ Patch25079: rt2800-rearrange-bbp-rfcsr-initialization.patch #CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 Patch25099: HID-CVE-fixes.patch -#rhbz 1002351 -Patch25100: crypto-fix-race-in-larval-lookup.patch - #CVE-2013-4343 rhbz 1007733 1007741 Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch @@ -1505,9 +1502,6 @@ ApplyPatch HID-CVE-fixes.patch #rhbz 1000679 ApplyPatch rt2800-rearrange-bbp-rfcsr-initialization.patch -#rhbz1002351 -ApplyPatch crypto-fix-race-in-larval-lookup.patch - #CVE-2013-4343 rhbz 1007733 1007741 ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch @@ -2364,6 +2358,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 27 2013 Justin M. Forbes 3.10.13-100 +- Linux v3.10.13 + * Mon Sep 23 2013 Neil Horman - Add alb learning packet config knob (rhbz 971893) diff --git a/sources b/sources index ec45c22e9..de04b8620 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -9bfba28fef36c6a7fc16fd896eab131b patch-3.10.12.xz +573f2c972015880ba5d52e5b123b37d7 patch-3.10.13.xz From 9827a322e04fb95e55642d59f601c9fe66481a0f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 27 Sep 2013 09:22:47 -0400 Subject: [PATCH 422/492] Add patches to fix soft lockup from elevator changes (rhbz 902012) --- ...-a-race-in-elevator-switching-and-md.patch | 162 ++++++++++++++++++ ...uire-q-sysfs_lock-in-elevator_change.patch | 121 +++++++++++++ kernel.spec | 11 ++ 3 files changed, 294 insertions(+) create mode 100644 elevator-Fix-a-race-in-elevator-switching-and-md.patch create mode 100644 elevator-acquire-q-sysfs_lock-in-elevator_change.patch diff --git a/elevator-Fix-a-race-in-elevator-switching-and-md.patch b/elevator-Fix-a-race-in-elevator-switching-and-md.patch new file mode 100644 index 000000000..5517687ff --- /dev/null +++ b/elevator-Fix-a-race-in-elevator-switching-and-md.patch @@ -0,0 +1,162 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp55663oab; + Fri, 30 Aug 2013 15:52:46 -0700 (PDT) +X-Received: by 10.68.244.168 with SMTP id xh8mr12419215pbc.3.1377903166373; + Fri, 30 Aug 2013 15:52:46 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id qc9si280431pac.269.1969.12.31.16.00.00; + Fri, 30 Aug 2013 15:52:46 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@hds.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753535Ab3H3WrV (ORCPT + + 99 others); Fri, 30 Aug 2013 18:47:21 -0400 +Received: from usindpps04.hds.com ([207.126.252.17]:35636 "EHLO + usindpps04.hds.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1752650Ab3H3WrU (ORCPT + ); + Fri, 30 Aug 2013 18:47:20 -0400 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hds.com; h=subject : to : from : cc + : date : message-id : mime-version : content-type : + content-transfer-encoding; s=mail1; + bh=VofHN8IMnygn2hbqnFjLmX0PPEPbvpzE377u1RxpGOY=; + b=piW6J78W57qDXBPJJuodWw/tvf0T//JbxKX6sLPvpuaOG2nBLMHzDqUeTYwFEQqUvdmf + ZTkiwsKi0WEku3MKcxJ7veR7wvTZcQ4fGMETFTf1c2J/1JOKpXLnft4ERuW89/FAxw25 + wQM1ulsuQ3Cncl0I/sIaqMlaMOtvuQ/C8rsHorp+75eFiL6yx1jU5wMbuti4D/NprIET + 3r57cPZ0YCh6sLjvOgjay6mKyktMToyjHPx6X1TWCSWcwes33Popc1hpadxUdFI/0npL + mN3Tttbe7e2RcmkXAZbwg8xj+FwSu3nIRC4G9UpFCsMz518C/AWZj4puwWE6VHZWVvVZ Rg== +Received: from usindmail01.hds.com (usindmail03 [207.126.252.22]) + by usindpps04.hds.com (8.14.5/8.14.5) with ESMTP id r7UMlBjr025492; + Fri, 30 Aug 2013 18:47:11 -0400 +Received: from hds.com (usindnetf5d-vlan47float.corp.hds.com [10.74.73.11]) + by usindmail01.hds.com (8.14.1/8.14.1) with ESMTP id r7UMl8SG058466; + Fri, 30 Aug 2013 18:47:10 -0400 (EDT) +Subject: [PATCH v2 1/2] elevator: Fix a race in elevator switching and md + device initialization +To: linux-kernel@vger.kernel.org +From: Tomoki Sekiyama +Cc: axboe@kernel.dk, tj@kernel.org, seiji.aguchi@hds.com, + vgoyal@redhat.com, majianpeng@gmail.com +Date: Fri, 30 Aug 2013 18:47:07 -0400 +Message-ID: <20130830224707.21812.63516.stgit@hds.com> +User-Agent: StGit/0.16 +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Proofpoint-SPF-Result: pass +X-Proofpoint-SPF-Record: v=spf1 mx ip4:207.126.244.0/26 ip4:207.126.252.0/25 include:mktomail.com + include:cloud.hds.com ~all +X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.10.8794,1.0.431,0.0.0000 + definitions=2013-08-30_09:2013-08-30,2013-08-30,1970-01-01 signatures=0 +X-Proofpoint-Spam-Details: rule=notspam policy=outbound_policy score=0 spamscore=0 suspectscore=1 + phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx + scancount=1 engine=7.0.1-1305240000 definitions=main-1308300162 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +The soft lockup below happens at the boot time of the system using dm +multipath and the udev rules to switch scheduler. + +[ 356.127001] BUG: soft lockup - CPU#3 stuck for 22s! [sh:483] +[ 356.127001] RIP: 0010:[] [] lock_timer_base.isra.35+0x1d/0x50 +... +[ 356.127001] Call Trace: +[ 356.127001] [] try_to_del_timer_sync+0x20/0x70 +[ 356.127001] [] ? kmem_cache_alloc_node_trace+0x20a/0x230 +[ 356.127001] [] del_timer_sync+0x52/0x60 +[ 356.127001] [] cfq_exit_queue+0x32/0xf0 +[ 356.127001] [] elevator_exit+0x2f/0x50 +[ 356.127001] [] elevator_change+0xf1/0x1c0 +[ 356.127001] [] elv_iosched_store+0x20/0x50 +[ 356.127001] [] queue_attr_store+0x59/0xb0 +[ 356.127001] [] sysfs_write_file+0xc6/0x140 +[ 356.127001] [] vfs_write+0xbd/0x1e0 +[ 356.127001] [] SyS_write+0x49/0xa0 +[ 356.127001] [] system_call_fastpath+0x16/0x1b + +This is caused by a race between md device initialization by multipathd and +shell script to switch the scheduler using sysfs. + + - multipathd: + SyS_ioctl -> do_vfs_ioctl -> dm_ctl_ioctl -> ctl_ioctl -> table_load + -> dm_setup_md_queue -> blk_init_allocated_queue -> elevator_init + q->elevator = elevator_alloc(q, e); // not yet initialized + + - sh -c 'echo deadline > /sys/$DEVPATH/queue/scheduler': + elevator_switch (in the call trace above) + struct elevator_queue *old = q->elevator; + q->elevator = elevator_alloc(q, new_e); + elevator_exit(old); // lockup! (*) + + - multipathd: (cont.) + err = e->ops.elevator_init_fn(q); // init fails; q->elevator is modified + +(*) When del_timer_sync() is called, lock_timer_base() will loop infinitely +while timer->base == NULL. In this case, as timer will never initialized, +it results in lockup. + +This patch introduces acquisition of q->sysfs_lock around elevator_init() +into blk_init_allocated_queue(), to provide mutual exclusion between +initialization of the q->scheduler and switching of the scheduler. + +This should fix this bugzilla: +https://bugzilla.redhat.com/show_bug.cgi?id=902012 + +Signed-off-by: Tomoki Sekiyama +--- + block/blk-core.c | 10 +++++++++- + block/elevator.c | 6 ++++++ + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 93a18d1..2f6275f 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -739,9 +739,17 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, + + q->sg_reserved_size = INT_MAX; + ++ /* Protect q->elevator from elevator_change */ ++ mutex_lock(&q->sysfs_lock); ++ + /* init elevator */ +- if (elevator_init(q, NULL)) ++ if (elevator_init(q, NULL)) { ++ mutex_unlock(&q->sysfs_lock); + return NULL; ++ } ++ ++ mutex_unlock(&q->sysfs_lock); ++ + return q; + } + EXPORT_SYMBOL(blk_init_allocated_queue); +diff --git a/block/elevator.c b/block/elevator.c +index 668394d..02d4390 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -186,6 +186,12 @@ int elevator_init(struct request_queue *q, char *name) + struct elevator_type *e = NULL; + int err; + ++ /* ++ * q->sysfs_lock must be held to provide mutual exclusion between ++ * elevator_switch() and here. ++ */ ++ lockdep_assert_held(&q->sysfs_lock); ++ + if (unlikely(q->elevator)) + return 0; + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/elevator-acquire-q-sysfs_lock-in-elevator_change.patch b/elevator-acquire-q-sysfs_lock-in-elevator_change.patch new file mode 100644 index 000000000..6f112b81c --- /dev/null +++ b/elevator-acquire-q-sysfs_lock-in-elevator_change.patch @@ -0,0 +1,121 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.168.104 with SMTP id zv8csp55623oab; + Fri, 30 Aug 2013 15:51:42 -0700 (PDT) +X-Received: by 10.67.30.70 with SMTP id kc6mr13149193pad.32.1377903101609; + Fri, 30 Aug 2013 15:51:41 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id gg2si304840pac.217.1969.12.31.16.00.00; + Fri, 30 Aug 2013 15:51:41 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@hds.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756106Ab3H3WrX (ORCPT + + 99 others); Fri, 30 Aug 2013 18:47:23 -0400 +Received: from usindpps04.hds.com ([207.126.252.17]:35640 "EHLO + usindpps04.hds.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1752650Ab3H3WrW (ORCPT + ); + Fri, 30 Aug 2013 18:47:22 -0400 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hds.com; h=subject : to : from : cc + : date : message-id : in-reply-to : references : mime-version : + content-type : content-transfer-encoding; s=mail1; + bh=xbQuWVaSJrPfWG5E7bXFAbOFjf/sBaRZsPmpVgy0CYk=; + b=NW/A8Imu32MXoBi5FLrQ0FsK66RTWMQo1bFRtgQplVEQQIAXyf1XhCaAZyTkTplc0iEx + ovyGZHvLbmGL6w3I3pxkCFz1BPJCqoZtvQITir/WvfzyadYOK1cz+vuBUQSCmfkacvS/ + w37h1jLAjsvWXkl0GY7pxB9HJMXdeLnhhuWxtNU8m8rKZ7t3LSByMeQi5/3OTkNojDEe + 70cKeZXCPQ/UIDJAF4cpSVXia5FwoJISjXvQIrvqkYhFelzq3OHMcC482PdpqNB475h3 + yHHJ83HFOLRulUQdOG5ZVTB9qRg0zxRx/oedeXwzturFke68noRRa4f4izQ8sCwsWOCI Dw== +Received: from usindmail01.hds.com (usindmail03 [207.126.252.22]) + by usindpps04.hds.com (8.14.5/8.14.5) with ESMTP id r7UMlHIc025543; + Fri, 30 Aug 2013 18:47:17 -0400 +Received: from hds.com (usindnetf5d-vlan47float.corp.hds.com [10.74.73.11]) + by usindmail01.hds.com (8.14.1/8.14.1) with ESMTP id r7UMlGiC058545; + Fri, 30 Aug 2013 18:47:17 -0400 (EDT) +Subject: [PATCH v2 2/2] elevator: acquire q->sysfs_lock in elevator_change() +To: linux-kernel@vger.kernel.org +From: Tomoki Sekiyama +Cc: axboe@kernel.dk, tj@kernel.org, seiji.aguchi@hds.com, + vgoyal@redhat.com, majianpeng@gmail.com +Date: Fri, 30 Aug 2013 18:47:16 -0400 +Message-ID: <20130830224716.21812.99333.stgit@hds.com> +In-Reply-To: <20130830224707.21812.63516.stgit@hds.com> +References: <20130830224707.21812.63516.stgit@hds.com> +User-Agent: StGit/0.16 +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Proofpoint-SPF-Result: pass +X-Proofpoint-SPF-Record: v=spf1 mx ip4:207.126.244.0/26 ip4:207.126.252.0/25 include:mktomail.com + include:cloud.hds.com ~all +X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.10.8794,1.0.431,0.0.0000 + definitions=2013-08-30_09:2013-08-30,2013-08-30,1970-01-01 signatures=0 +X-Proofpoint-Spam-Details: rule=notspam policy=outbound_policy score=0 spamscore=0 suspectscore=1 + phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx + scancount=1 engine=7.0.1-1305240000 definitions=main-1308300162 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +Add locking of q->sysfs_lock into elevator_change() (an exported function) +to ensure it is held to protect q->elevator from elevator_init(), even if +elevator_change() is called from non-sysfs paths. +sysfs path (elv_iosched_store) uses __elevator_change(), non-locking +version, as the lock is already taken by elv_iosched_store(). + +Signed-off-by: Tomoki Sekiyama +--- + block/elevator.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/block/elevator.c b/block/elevator.c +index 02d4390..6d765f7 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -965,7 +965,7 @@ fail_init: + /* + * Switch this queue to the given IO scheduler. + */ +-int elevator_change(struct request_queue *q, const char *name) ++static int __elevator_change(struct request_queue *q, const char *name) + { + char elevator_name[ELV_NAME_MAX]; + struct elevator_type *e; +@@ -987,6 +987,18 @@ int elevator_change(struct request_queue *q, const char *name) + + return elevator_switch(q, e); + } ++ ++int elevator_change(struct request_queue *q, const char *name) ++{ ++ int ret; ++ ++ /* Protect q->elevator from elevator_init() */ ++ mutex_lock(&q->sysfs_lock); ++ ret = __elevator_change(q, name); ++ mutex_unlock(&q->sysfs_lock); ++ ++ return ret; ++} + EXPORT_SYMBOL(elevator_change); + + ssize_t elv_iosched_store(struct request_queue *q, const char *name, +@@ -997,7 +1009,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, + if (!q->elevator) + return count; + +- ret = elevator_change(q, name); ++ ret = __elevator_change(q, name); + if (!ret) + return count; + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/kernel.spec b/kernel.spec index 6c3e98e14..35ecf5332 100644 --- a/kernel.spec +++ b/kernel.spec @@ -791,6 +791,10 @@ Patch25105: 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch #rhbz 971893 Patch25106: bonding-driver-alb-learning.patch +#rhbz 902012 +Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch +Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch + # END OF PATCH DEFINITIONS %endif @@ -1517,6 +1521,10 @@ ApplyPatch 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch #rhbz 971893 ApplyPatch bonding-driver-alb-learning.patch +#rhbz 902012 +ApplyPatch elevator-Fix-a-race-in-elevator-switching-and-md.patch +ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch + # END OF PATCH APPLICATIONS %endif @@ -2358,6 +2366,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 27 2013 Josh Boyer +- Add patches to fix soft lockup from elevator changes (rhbz 902012) + * Fri Sep 27 2013 Justin M. Forbes 3.10.13-100 - Linux v3.10.13 From 945a21dc10296de1e3fc1d28e1ec612c2e4c9f59 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 27 Sep 2013 12:18:06 -0400 Subject: [PATCH 423/492] Add HID revert patch to fix logitech unifying devices (rhbz 1013000) --- ...ech-dj-missing-Unifying-device-issue.patch | 172 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 179 insertions(+) create mode 100644 HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch diff --git a/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch b/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch new file mode 100644 index 000000000..1c112ccde --- /dev/null +++ b/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch @@ -0,0 +1,172 @@ +From c63e0e370028d7e4033bd40165f18499872b5183 Mon Sep 17 00:00:00 2001 +From: Nestor Lopez Casado +Date: Thu, 18 Jul 2013 13:21:30 +0000 +Subject: HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue"" + +This reverts commit 8af6c08830b1ae114d1a8b548b1f8b056e068887. + +This patch re-adds the workaround introduced by 596264082f10dd4 +which was reverted by 8af6c08830b1ae114. + +The original patch 596264 was needed to overcome a situation where +the hid-core would drop incoming reports while probe() was being +executed. + +This issue was solved by c849a6143bec520af which added +hid_device_io_start() and hid_device_io_stop() that enable a specific +hid driver to opt-in for input reports while its probe() is being +executed. + +Commit a9dd22b730857347 modified hid-logitech-dj so as to use the +functionality added to hid-core. Having done that, workaround 596264 +was no longer necessary and was reverted by 8af6c08. + +We now encounter a different problem that ends up 'again' thwarting +the Unifying receiver enumeration. The problem is time and usb controller +dependent. Ocasionally the reports sent to the usb receiver to start +the paired devices enumeration fail with -EPIPE and the receiver never +gets to enumerate the paired devices. + +With dcd9006b1b053c7b1c the problem was "hidden" as the call to the usb +driver became asynchronous and none was catching the error from the +failing URB. + +As the root cause for this failing SET_REPORT is not understood yet, +-possibly a race on the usb controller drivers or a problem with the +Unifying receiver- reintroducing this workaround solves the problem. + +Overall what this workaround does is: If an input report from an +unknown device is received, then a (re)enumeration is performed. + +related bug: +https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1194649 + +Signed-off-by: Nestor Lopez Casado +Signed-off-by: Jiri Kosina +--- +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 5207591a..cd33084 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver; + static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, + size_t count, + unsigned char report_type); ++static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); + + static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, + struct dj_report *dj_report) +@@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, + if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & + SPFUNCTION_DEVICE_LIST_EMPTY) { + dbg_hid("%s: device list is empty\n", __func__); ++ djrcv_dev->querying_devices = false; + return; + } + +@@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, + return; + } + ++ if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { ++ /* The device is already known. No need to reallocate it. */ ++ dbg_hid("%s: device is already known\n", __func__); ++ return; ++ } ++ + dj_hiddev = hid_allocate_device(); + if (IS_ERR(dj_hiddev)) { + dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", +@@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work) + struct dj_report dj_report; + unsigned long flags; + int count; ++ int retval; + + dbg_hid("%s\n", __func__); + +@@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work) + logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); + break; + default: ++ /* A normal report (i. e. not belonging to a pair/unpair notification) ++ * arriving here, means that the report arrived but we did not have a ++ * paired dj_device associated to the report's device_index, this ++ * means that the original "device paired" notification corresponding ++ * to this dj_device never arrived to this driver. The reason is that ++ * hid-core discards all packets coming from a device while probe() is ++ * executing. */ ++ if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { ++ /* ok, we don't know the device, just re-ask the ++ * receiver for the list of connected devices. */ ++ retval = logi_dj_recv_query_paired_devices(djrcv_dev); ++ if (!retval) { ++ /* everything went fine, so just leave */ ++ break; ++ } ++ dev_err(&djrcv_dev->hdev->dev, ++ "%s:logi_dj_recv_query_paired_devices " ++ "error:%d\n", __func__, retval); ++ } + dbg_hid("%s: unexpected report type\n", __func__); + } + } +@@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, + if (!djdev) { + dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" + " is NULL, index %d\n", dj_report->device_index); ++ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); ++ ++ if (schedule_work(&djrcv_dev->work) == 0) { ++ dbg_hid("%s: did not schedule the work item, was already " ++ "queued\n", __func__); ++ } + return; + } + +@@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, + if (dj_device == NULL) { + dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" + " is NULL, index %d\n", dj_report->device_index); ++ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); ++ ++ if (schedule_work(&djrcv_dev->work) == 0) { ++ dbg_hid("%s: did not schedule the work item, was already " ++ "queued\n", __func__); ++ } + return; + } + +@@ -444,6 +484,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) + struct dj_report *dj_report; + int retval; + ++ /* no need to protect djrcv_dev->querying_devices */ ++ if (djrcv_dev->querying_devices) ++ return 0; ++ + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); + if (!dj_report) + return -ENOMEM; +@@ -455,6 +499,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) + return retval; + } + ++ + static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, + unsigned timeout) + { +diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h +index fd28a5e..4a40003 100644 +--- a/drivers/hid/hid-logitech-dj.h ++++ b/drivers/hid/hid-logitech-dj.h +@@ -101,6 +101,7 @@ struct dj_receiver_dev { + struct work_struct work; + struct kfifo notif_fifo; + spinlock_t lock; ++ bool querying_devices; + }; + + struct dj_device { +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 35ecf5332..ec660841e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -795,6 +795,9 @@ Patch25106: bonding-driver-alb-learning.patch Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch +#rhbz 1013000 +Patch25116: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch + # END OF PATCH DEFINITIONS %endif @@ -1525,6 +1528,9 @@ ApplyPatch bonding-driver-alb-learning.patch ApplyPatch elevator-Fix-a-race-in-elevator-switching-and-md.patch ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch +#rhbz 1013000 +ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch + # END OF PATCH APPLICATIONS %endif @@ -2367,6 +2373,7 @@ fi # || || %changelog * Fri Sep 27 2013 Josh Boyer +- Add HID revert patch to fix logitech unifying devices (rhbz 1013000) - Add patches to fix soft lockup from elevator changes (rhbz 902012) * Fri Sep 27 2013 Justin M. Forbes 3.10.13-100 From 1fdfb5206b7295e70c9e406fe6c7c47f4165cf7d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 27 Sep 2013 14:23:02 -0500 Subject: [PATCH 424/492] Bump and tag for build --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index ec660841e..5141a19f6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2372,6 +2372,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 27 2013 Justin M. Forbes 3.10.13-101 +- Bump and tag for build + * Fri Sep 27 2013 Josh Boyer - Add HID revert patch to fix logitech unifying devices (rhbz 1013000) - Add patches to fix soft lockup from elevator changes (rhbz 902012) From 5023d7a8b835c489e534c2aaba0620888dc3e7d4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 30 Sep 2013 09:28:54 -0400 Subject: [PATCH 425/492] Drop VC_MUTE (rhbz 859485) systemd doesn't muck with VTs underneath of Xorg any longer, so this shouldn't be needed. It's in git if that turns out to be wrong. --- kernel.spec | 9 +- vt-Drop-K_OFF-for-VC_MUTE.patch | 250 -------------------------------- 2 files changed, 3 insertions(+), 256 deletions(-) delete mode 100644 vt-Drop-K_OFF-for-VC_MUTE.patch diff --git a/kernel.spec b/kernel.spec index 5141a19f6..f5c2a1a90 100644 --- a/kernel.spec +++ b/kernel.spec @@ -725,9 +725,6 @@ Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions Patch22001: selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 859485 -Patch22226: vt-Drop-K_OFF-for-VC_MUTE.patch - #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch @@ -1458,9 +1455,6 @@ ApplyPatch weird-root-dentry-name-debug.patch #selinux ptrace child permissions ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch -#rhbz 859485 -ApplyPatch vt-Drop-K_OFF-for-VC_MUTE.patch - #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch @@ -2372,6 +2366,9 @@ fi # ||----w | # || || %changelog +* Mon Sep 30 2013 Josh Boyer +- Drop VC_MUTE patch (rhbz 859485) + * Fri Sep 27 2013 Justin M. Forbes 3.10.13-101 - Bump and tag for build diff --git a/vt-Drop-K_OFF-for-VC_MUTE.patch b/vt-Drop-K_OFF-for-VC_MUTE.patch deleted file mode 100644 index e9bc4fffa..000000000 --- a/vt-Drop-K_OFF-for-VC_MUTE.patch +++ /dev/null @@ -1,250 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Adam Jackson -Newsgroups: gmane.linux.kernel -Subject: [PATCH] vt: Drop K_OFF for VC_MUTE -Date: Fri, 16 Nov 2012 13:32:34 -0500 -Lines: 205 -Approved: news@gmane.org -Message-ID: <1353090754-30233-1-git-send-email-ajax@redhat.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: ger.gmane.org 1353090772 20663 80.91.229.3 (16 Nov 2012 18:32:52 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Fri, 16 Nov 2012 18:32:52 +0000 (UTC) -Cc: Arthur Taylor , - Greg Kroah-Hartman -To: linux-kernel@vger.kernel.org -Original-X-From: linux-kernel-owner@vger.kernel.org Fri Nov 16 19:33:03 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1TZQim-0000aG-BI - for glk-linux-kernel-3@plane.gmane.org; Fri, 16 Nov 2012 19:32:56 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753232Ab2KPSck (ORCPT ); - Fri, 16 Nov 2012 13:32:40 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:32172 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752810Ab2KPSci (ORCPT ); - Fri, 16 Nov 2012 13:32:38 -0500 -Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qAGIWaM7020116 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Fri, 16 Nov 2012 13:32:36 -0500 -Original-Received: from ihatethathostname.lab.bos.redhat.com (ihatethathostname.lab.bos.redhat.com [10.16.43.238]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id qAGIWZD7010099; - Fri, 16 Nov 2012 13:32:35 -0500 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1395620 -Archived-At: - -The "don't enqueue stuff" semantics of K_OFF shouldn't be a function of -the keyboard map state; we should be able to switch among cooked/raw/ -unicode without changing whether events are delivered. Otherwise - if -changing to K_UNICODE undoes K_OFF - then suddenly Alt-F2 under -Gnome will switch VT instead of summoning the "run command" dialog. - -Drop the K_OFF handling and replace it with a new "mute" ioctl pair. -Anybody using K_OFF would already need to be prepared to handle it -throwing -EINVAL for old kernel compatibility, so userspace will degrade -gracefully. - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=859485 -Cc: Arthur Taylor -Cc: Greg Kroah-Hartman -Tested-by: Josh Boyer -Signed-off-by: Adam Jackson ---- - drivers/tty/vt/keyboard.c | 40 +++++++++++++++++++++++++++++++++------- - drivers/tty/vt/vt_ioctl.c | 13 +++++++++++++ - include/linux/kbd_kern.h | 6 +++--- - include/linux/vt_kern.h | 2 ++ - include/uapi/linux/kd.h | 5 +++++ - 5 files changed, 56 insertions(+), 10 deletions(-) - -diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c -index 681765b..08d1d57 100644 ---- a/drivers/tty/vt/keyboard.c -+++ b/drivers/tty/vt/keyboard.c -@@ -657,7 +657,7 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) - return; - if ((kbd->kbdmode == VC_RAW || - kbd->kbdmode == VC_MEDIUMRAW || -- kbd->kbdmode == VC_OFF) && -+ vc_kbd_mode(kbd, VC_MUTE)) && - value != KVAL(K_SAK)) - return; /* SAK is allowed even in raw mode */ - fn_handler[value](vc); -@@ -1381,7 +1381,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) - if (rc == NOTIFY_STOP) - return; - -- if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT) -+ if ((raw_mode || vc_kbd_mode(kbd, VC_MUTE)) && type != KT_SPEC && type != KT_SHIFT) - return; - - (*k_handler[type])(vc, keysym & 0xff, !down); -@@ -1731,9 +1731,6 @@ int vt_do_kdskbmode(int console, unsigned int arg) - kbd->kbdmode = VC_UNICODE; - do_compute_shiftstate(); - break; -- case K_OFF: -- kbd->kbdmode = VC_OFF; -- break; - default: - ret = -EINVAL; - } -@@ -1742,6 +1739,30 @@ int vt_do_kdskbmode(int console, unsigned int arg) - } - - /** -+ * vt_do_kdskbmute - set keyboard event mute -+ * @console: the console to use -+ * @arg: the requested mode -+ * -+ * Update the keyboard mute state while holding the correct locks. -+ * Return 0 for success or an error code. -+ */ -+int vt_do_kdskbmute(int console, unsigned int arg) -+{ -+ struct kbd_struct * kbd = kbd_table + console; -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&kbd_event_lock, flags); -+ if (arg) -+ set_vc_kbd_mode(kbd, VC_MUTE); -+ else -+ clr_vc_kbd_mode(kbd, VC_MUTE); -+ spin_unlock_irqrestore(&kbd_event_lock, flags); -+ return ret; -+} -+ -+ -+/** - * vt_do_kdskbmeta - set keyboard meta state - * @console: the console to use - * @arg: the requested meta state -@@ -2068,13 +2089,18 @@ int vt_do_kdgkbmode(int console) - return K_MEDIUMRAW; - case VC_UNICODE: - return K_UNICODE; -- case VC_OFF: -- return K_OFF; - default: - return K_XLATE; - } - } - -+int vt_do_kdgkbmute(int console) -+{ -+ struct kbd_struct * kbd = kbd_table + console; -+ /* This is a spot read so needs no locking */ -+ return vc_kbd_mode(kbd, VC_MUTE); -+} -+ - /** - * vt_do_kdgkbmeta - report meta status - * @console: console to report -diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c -index b841f56..f0951e2 100644 ---- a/drivers/tty/vt/vt_ioctl.c -+++ b/drivers/tty/vt/vt_ioctl.c -@@ -477,6 +477,19 @@ int vt_ioctl(struct tty_struct *tty, - ret = put_user(uival, (int __user *)arg); - break; - -+ case KDSKBMUTE: -+ if (!perm) -+ return -EPERM; -+ ret = vt_do_kdskbmute(console, arg); -+ if (ret == 0) -+ tty_ldisc_flush(tty); -+ break; -+ -+ case KDGKBMUTE: -+ uival = vt_do_kdgkbmute(console); -+ ret = put_user(uival, (int __user *)arg); -+ break; -+ - /* this could be folded into KDSKBMODE, but for compatibility - reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ - case KDSKBMETA: -diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h -index b7c8cdc..9386143 100644 ---- a/include/linux/kbd_kern.h -+++ b/include/linux/kbd_kern.h -@@ -48,19 +48,19 @@ struct kbd_struct { - #define VC_CAPSLOCK 2 /* capslock mode */ - #define VC_KANALOCK 3 /* kanalock mode */ - -- unsigned char kbdmode:3; /* one 3-bit value */ -+ unsigned char kbdmode:2; /* one 2-bit value */ - #define VC_XLATE 0 /* translate keycodes using keymap */ - #define VC_MEDIUMRAW 1 /* medium raw (keycode) mode */ - #define VC_RAW 2 /* raw (scancode) mode */ - #define VC_UNICODE 3 /* Unicode mode */ --#define VC_OFF 4 /* disabled mode */ - -- unsigned char modeflags:5; -+ unsigned char modeflags:6; - #define VC_APPLIC 0 /* application key mode */ - #define VC_CKMODE 1 /* cursor key mode */ - #define VC_REPEAT 2 /* keyboard repeat */ - #define VC_CRLF 3 /* 0 - enter sends CR, 1 - enter sends CRLF */ - #define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */ -+#define VC_MUTE 5 /* don't generate events */ - }; - - extern int kbd_init(void); -diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h -index 50ae7d0..a886915 100644 ---- a/include/linux/vt_kern.h -+++ b/include/linux/vt_kern.h -@@ -168,6 +168,7 @@ extern void hide_boot_cursor(bool hide); - - /* keyboard provided interfaces */ - extern int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm); -+extern int vt_do_kdskbmute(int console, unsigned int arg); - extern int vt_do_kdskbmode(int console, unsigned int arg); - extern int vt_do_kdskbmeta(int console, unsigned int arg); - extern int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, -@@ -177,6 +178,7 @@ extern int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, - extern int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, - int perm); - extern int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm); -+extern int vt_do_kdgkbmute(int console); - extern int vt_do_kdgkbmode(int console); - extern int vt_do_kdgkbmeta(int console); - extern void vt_reset_unicode(int console); -diff --git a/include/uapi/linux/kd.h b/include/uapi/linux/kd.h -index 87b7cc4..c3de63c 100644 ---- a/include/uapi/linux/kd.h -+++ b/include/uapi/linux/kd.h -@@ -81,6 +81,7 @@ struct unimapinit { - #define K_XLATE 0x01 - #define K_MEDIUMRAW 0x02 - #define K_UNICODE 0x03 -+/* K_OFF is no longer implemented, but preserved for source compatibility */ - #define K_OFF 0x04 - #define KDGKBMODE 0x4B44 /* gets current keyboard mode */ - #define KDSKBMODE 0x4B45 /* sets current keyboard mode */ -@@ -150,6 +151,10 @@ struct kbd_repeat { - /* earlier this field was misnamed "rate" */ - }; - -+/* get/set event mute */ -+#define KDGKBMUTE 0x4B50 -+#define KDSKBMUTE 0x4B51 -+ - #define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate; - * actually used values are returned */ - --- -1.7.11.7 - From 00be9c0df6034e54f5294a3874363c4c641de6e9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Oct 2013 10:47:31 -0400 Subject: [PATCH 426/492] CVE-2013-4387 ipv6: panic when UFO=On for an interface (rhbz 1011927 1015166) --- ...-following-an-UFO-enqueued-packet-ne.patch | 123 ++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 132 insertions(+) create mode 100644 ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch diff --git a/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch b/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch new file mode 100644 index 000000000..9310e05a7 --- /dev/null +++ b/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch @@ -0,0 +1,123 @@ +From 2811ebac2521ceac84f2bdae402455baa6a7fb47 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Sat, 21 Sep 2013 06:27:00 +0200 +Subject: [PATCH] ipv6: udp packets following an UFO enqueued packet need also + be handled by UFO + +In the following scenario the socket is corked: +If the first UDP packet is larger then the mtu we try to append it to the +write queue via ip6_ufo_append_data. A following packet, which is smaller +than the mtu would be appended to the already queued up gso-skb via +plain ip6_append_data. This causes random memory corruptions. + +In ip6_ufo_append_data we also have to be careful to not queue up the +same skb multiple times. So setup the gso frame only when no first skb +is available. + +This also fixes a shortcoming where we add the current packet's length to +cork->length but return early because of a packet > mtu with dontfrag set +(instead of sutracting it again). + +Found with trinity. + +Cc: YOSHIFUJI Hideaki +Signed-off-by: Hannes Frederic Sowa +Reported-by: Dmitry Vyukov +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 53 +++++++++++++++++++++------------------------------ + 1 file changed, 22 insertions(+), 31 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 3a692d5..a54c45c 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk, + * udp datagram + */ + if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { ++ struct frag_hdr fhdr; ++ + skb = sock_alloc_send_skb(sk, + hh_len + fragheaderlen + transhdrlen + 20, + (flags & MSG_DONTWAIT), &err); +@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, + skb->protocol = htons(ETH_P_IPV6); + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; +- } +- +- err = skb_append_datato_frags(sk,skb, getfrag, from, +- (length - transhdrlen)); +- if (!err) { +- struct frag_hdr fhdr; + + /* Specify the length of each IPv6 datagram fragment. + * It has to be a multiple of 8. +@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk, + ipv6_select_ident(&fhdr, rt); + skb_shinfo(skb)->ip6_frag_id = fhdr.identification; + __skb_queue_tail(&sk->sk_write_queue, skb); +- +- return 0; + } +- /* There is not enough support do UPD LSO, +- * so follow normal path +- */ +- kfree_skb(skb); + +- return err; ++ return skb_append_datato_frags(sk, skb, getfrag, from, ++ (length - transhdrlen)); + } + + static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, +@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + * --yoshfuji + */ + +- cork->length += length; +- if (length > mtu) { +- int proto = sk->sk_protocol; +- if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ +- ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); +- return -EMSGSIZE; +- } +- +- if (proto == IPPROTO_UDP && +- (rt->dst.dev->features & NETIF_F_UFO)) { ++ if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || ++ sk->sk_protocol == IPPROTO_RAW)) { ++ ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); ++ return -EMSGSIZE; ++ } + +- err = ip6_ufo_append_data(sk, getfrag, from, length, +- hh_len, fragheaderlen, +- transhdrlen, mtu, flags, rt); +- if (err) +- goto error; +- return 0; +- } ++ skb = skb_peek_tail(&sk->sk_write_queue); ++ cork->length += length; ++ if (((length > mtu) || ++ (skb && skb_is_gso(skb))) && ++ (sk->sk_protocol == IPPROTO_UDP) && ++ (rt->dst.dev->features & NETIF_F_UFO)) { ++ err = ip6_ufo_append_data(sk, getfrag, from, length, ++ hh_len, fragheaderlen, ++ transhdrlen, mtu, flags, rt); ++ if (err) ++ goto error; ++ return 0; + } + +- if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) ++ if (!skb) + goto alloc_new_skb; + + while (length > 0) { +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index f5c2a1a90..5d52aefef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -795,6 +795,9 @@ Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch #rhbz 1013000 Patch25116: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch +#CVE-2013-4387 rhbz 1011927 1015166 +Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch + # END OF PATCH DEFINITIONS %endif @@ -1525,6 +1528,9 @@ ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch #rhbz 1013000 ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch +#CVE-2013-4387 rhbz 1011927 1015166 +ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch + # END OF PATCH APPLICATIONS %endif @@ -2366,6 +2372,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 3 2013 Josh Boyer +- CVE-2013-4387 ipv6: panic when UFO=On for an interface (rhbz 1011927 1015166) + * Mon Sep 30 2013 Josh Boyer - Drop VC_MUTE patch (rhbz 859485) From 7d5ba3763f19768433ec07aa531cd8defb5f64d4 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 4 Oct 2013 10:41:22 -0500 Subject: [PATCH 427/492] Linux v3.10.14 --- HID-CVE-fixes.patch | 786 ------------------ kernel.spec | 27 +- ...0-rearrange-bbp-rfcsr-initialization.patch | 35 - sources | 2 +- 4 files changed, 6 insertions(+), 844 deletions(-) delete mode 100644 HID-CVE-fixes.patch delete mode 100644 rt2800-rearrange-bbp-rfcsr-initialization.patch diff --git a/HID-CVE-fixes.patch b/HID-CVE-fixes.patch deleted file mode 100644 index 921ad9cb0..000000000 --- a/HID-CVE-fixes.patch +++ /dev/null @@ -1,786 +0,0 @@ -From ba6d8d44eaeb0ee58082f4b4c95138416e1f58a5 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:50 +0200 -Subject: [PATCH 02/16] HID: provide a helper for validating hid reports - -Many drivers need to validate the characteristics of their HID report -during initialization to avoid misusing the reports. This adds a common -helper to perform validation of the report exisitng, the field existing, -and the expected number of values within the field. - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Reviewed-by: Benjamin Tissoires ---- - drivers/hid/hid-core.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/hid.h | 4 ++++ - 2 files changed, 62 insertions(+) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 5ea7d51..65ee459 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -759,6 +759,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) - } - EXPORT_SYMBOL_GPL(hid_parse_report); - -+static const char * const hid_report_names[] = { -+ "HID_INPUT_REPORT", -+ "HID_OUTPUT_REPORT", -+ "HID_FEATURE_REPORT", -+}; -+/** -+ * hid_validate_values - validate existing device report's value indexes -+ * -+ * @device: hid device -+ * @type: which report type to examine -+ * @id: which report ID to examine (0 for first) -+ * @field_index: which report field to examine -+ * @report_counts: expected number of values -+ * -+ * Validate the number of values in a given field of a given report, after -+ * parsing. -+ */ -+struct hid_report *hid_validate_values(struct hid_device *hid, -+ unsigned int type, unsigned int id, -+ unsigned int field_index, -+ unsigned int report_counts) -+{ -+ struct hid_report *report; -+ -+ if (type > HID_FEATURE_REPORT) { -+ hid_err(hid, "invalid HID report type %u\n", type); -+ return NULL; -+ } -+ -+ if (id >= HID_MAX_IDS) { -+ hid_err(hid, "invalid HID report id %u\n", id); -+ return NULL; -+ } -+ -+ /* -+ * Explicitly not using hid_get_report() here since it depends on -+ * ->numbered being checked, which may not always be the case when -+ * drivers go to access report values. -+ */ -+ report = hid->report_enum[type].report_id_hash[id]; -+ if (!report) { -+ hid_err(hid, "missing %s %u\n", hid_report_names[type], id); -+ return NULL; -+ } -+ if (report->maxfield <= field_index) { -+ hid_err(hid, "not enough fields in %s %u\n", -+ hid_report_names[type], id); -+ return NULL; -+ } -+ if (report->field[field_index]->report_count < report_counts) { -+ hid_err(hid, "not enough values in %s %u field %u\n", -+ hid_report_names[type], id, field_index); -+ return NULL; -+ } -+ return report; -+} -+EXPORT_SYMBOL_GPL(hid_validate_values); -+ - /** - * hid_open_report - open a driver-specific device report - * -diff --git a/include/linux/hid.h b/include/linux/hid.h -index ff545cc..6e18550 100644 ---- a/include/linux/hid.h -+++ b/include/linux/hid.h -@@ -749,6 +749,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); - struct hid_device *hid_allocate_device(void); - struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); - int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); -+struct hid_report *hid_validate_values(struct hid_device *hid, -+ unsigned int type, unsigned int id, -+ unsigned int field_index, -+ unsigned int report_counts); - int hid_open_report(struct hid_device *device); - int hid_check_keys_pressed(struct hid_device *hid); - int hid_connect(struct hid_device *hid, unsigned int connect_mask); --- -1.8.3.1 - - -From 51bc0244e9e62b25e4f64f7cb87764a0c0692131 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:51 +0200 -Subject: [PATCH 03/16] HID: zeroplus: validate output report details - -The zeroplus HID driver was not checking the size of allocated values -in fields it used. A HID device could send a malicious output report -that would cause the driver to write beyond the output report allocation -during initialization, causing a heap overflow: - -[ 1442.728680] usb 1-1: New USB device found, idVendor=0c12, idProduct=0005 -... -[ 1466.243173] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2889 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Reviewed-by: Benjamin Tissoires ---- - drivers/hid/hid-zpff.c | 18 +++++------------- - 1 file changed, 5 insertions(+), 13 deletions(-) - -diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c -index 6ec28a3..a29756c 100644 ---- a/drivers/hid/hid-zpff.c -+++ b/drivers/hid/hid-zpff.c -@@ -68,21 +68,13 @@ static int zpff_init(struct hid_device *hid) - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); -- struct list_head *report_list = -- &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; -- int error; -+ int i, error; - -- if (list_empty(report_list)) { -- hid_err(hid, "no output report found\n"); -- return -ENODEV; -- } -- -- report = list_entry(report_list->next, struct hid_report, list); -- -- if (report->maxfield < 4) { -- hid_err(hid, "not enough fields in report\n"); -- return -ENODEV; -+ for (i = 0; i < 4; i++) { -+ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); -+ if (!report) -+ return -ENODEV; - } - - zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); --- -1.8.3.1 - - -From 5b029acf571f94193ff8a757340fd37a7f88ae0b Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:53 +0200 -Subject: [PATCH 05/16] HID: steelseries: validate output report details - -A HID device could send a malicious output report that would cause the -steelseries HID driver to write beyond the output report allocation -during initialization, causing a heap overflow: - -[ 167.981534] usb 1-1: New USB device found, idVendor=1038, idProduct=1410 -... -[ 182.050547] BUG kmalloc-256 (Tainted: G W ): Redzone overwritten - -CVE-2013-2891 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Reviewed-by: Benjamin Tissoires ---- - drivers/hid/hid-steelseries.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c -index d164911..29f328f 100644 ---- a/drivers/hid/hid-steelseries.c -+++ b/drivers/hid/hid-steelseries.c -@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, - goto err_free; - } - -+ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) { -+ ret = -ENODEV; -+ goto err_free; -+ } -+ - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); --- -1.8.3.1 - - -From e846e9b33d65246ed807156a114c65cdfece0d12 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:54 +0200 -Subject: [PATCH 06/16] HID: LG: validate HID output report details - -A HID device could send a malicious output report that would cause the -lg, lg3, and lg4 HID drivers to write beyond the output report allocation -during an event, causing a heap overflow: - -[ 325.245240] usb 1-1: New USB device found, idVendor=046d, idProduct=c287 -... -[ 414.518960] BUG kmalloc-4096 (Not tainted): Redzone overwritten - -Additionally, while lg2 did correctly validate the report details, it was -cleaned up and shortened. - -CVE-2013-2893 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Reviewed-by: Benjamin Tissoires ---- - drivers/hid/hid-lg2ff.c | 19 +++---------------- - drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- - drivers/hid/hid-lg4ff.c | 20 +------------------- - drivers/hid/hid-lgff.c | 17 ++--------------- - 4 files changed, 12 insertions(+), 73 deletions(-) - -diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c -index b3cd150..1a42eaa 100644 ---- a/drivers/hid/hid-lg2ff.c -+++ b/drivers/hid/hid-lg2ff.c -@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); -- struct list_head *report_list = -- &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - -- if (list_empty(report_list)) { -- hid_err(hid, "no output report found\n"); -+ /* Check that the report looks ok */ -+ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); -+ if (!report) - return -ENODEV; -- } -- -- report = list_entry(report_list->next, struct hid_report, list); -- -- if (report->maxfield < 1) { -- hid_err(hid, "output report is empty\n"); -- return -ENODEV; -- } -- if (report->field[0]->report_count < 7) { -- hid_err(hid, "not enough values in the field\n"); -- return -ENODEV; -- } - - lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); - if (!lg2ff) -diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c -index e52f181..8c2da18 100644 ---- a/drivers/hid/hid-lg3ff.c -+++ b/drivers/hid/hid-lg3ff.c -@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, - int x, y; - - /* -- * Maxusage should always be 63 (maximum fields) -- * likely a better way to ensure this data is clean -+ * Available values in the field should always be 63, but we only use up to -+ * 35. Instead, clear the entire area, however big it is. - */ -- memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); -+ memset(report->field[0]->value, 0, -+ sizeof(__s32) * report->field[0]->report_count); - - switch (effect->type) { - case FF_CONSTANT: -@@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { - int lg3ff_init(struct hid_device *hid) - { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; -- struct hid_report *report; -- struct hid_field *field; - const signed short *ff_bits = ff3_joystick_ac; - int error; - int i; - -- /* Find the report to use */ -- if (list_empty(report_list)) { -- hid_err(hid, "No output report found\n"); -- return -1; -- } -- - /* Check that the report looks ok */ -- report = list_entry(report_list->next, struct hid_report, list); -- if (!report) { -- hid_err(hid, "NULL output report\n"); -- return -1; -- } -- -- field = report->field[0]; -- if (!field) { -- hid_err(hid, "NULL field\n"); -- return -1; -- } -+ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) -+ return -ENODEV; - - /* Assume single fixed device G940 */ - for (i = 0; ff_bits[i] >= 0; i++) -diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c -index 0ddae2a..8782fe1 100644 ---- a/drivers/hid/hid-lg4ff.c -+++ b/drivers/hid/hid-lg4ff.c -@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde - int lg4ff_init(struct hid_device *hid) - { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; -- struct hid_report *report; -- struct hid_field *field; - struct lg4ff_device_entry *entry; - struct lg_drv_data *drv_data; - struct usb_device_descriptor *udesc; - int error, i, j; - __u16 bcdDevice, rev_maj, rev_min; - -- /* Find the report to use */ -- if (list_empty(report_list)) { -- hid_err(hid, "No output report found\n"); -- return -1; -- } -- - /* Check that the report looks ok */ -- report = list_entry(report_list->next, struct hid_report, list); -- if (!report) { -- hid_err(hid, "NULL output report\n"); -+ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) - return -1; -- } -- -- field = report->field[0]; -- if (!field) { -- hid_err(hid, "NULL field\n"); -- return -1; -- } - - /* Check what wheel has been connected */ - for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { -diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c -index d7ea8c8..e1394af 100644 ---- a/drivers/hid/hid-lgff.c -+++ b/drivers/hid/hid-lgff.c -@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) - int lgff_init(struct hid_device* hid) - { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); -- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; -- struct hid_report *report; -- struct hid_field *field; - const signed short *ff_bits = ff_joystick; - int error; - int i; - -- /* Find the report to use */ -- if (list_empty(report_list)) { -- hid_err(hid, "No output report found\n"); -- return -1; -- } -- - /* Check that the report looks ok */ -- report = list_entry(report_list->next, struct hid_report, list); -- field = report->field[0]; -- if (!field) { -- hid_err(hid, "NULL field\n"); -- return -1; -- } -+ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) -+ return -ENODEV; - - for (i = 0; i < ARRAY_SIZE(devices); i++) { - if (dev->id.vendor == devices[i].idVendor && --- -1.8.3.1 - - -From 0317e971d90e3e2e312074386a2349b2ef48d1d0 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:55 +0200 -Subject: [PATCH 07/16] HID: lenovo-tpkbd: validate output report details - -From: Kees Cook - -A HID device could send a malicious output report that would cause the -lenovo-tpkbd HID driver to write just beyond the output report allocation -during initialization, causing a heap overflow: - -[ 76.109807] usb 1-1: New USB device found, idVendor=17ef, idProduct=6009 -... -[ 80.462540] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2894 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Signed-off-by: Benjamin Tissoires ---- - drivers/hid/hid-lenovo-tpkbd.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c -index 07837f5..762d988 100644 ---- a/drivers/hid/hid-lenovo-tpkbd.c -+++ b/drivers/hid/hid-lenovo-tpkbd.c -@@ -339,7 +339,15 @@ static int tpkbd_probe_tp(struct hid_device *hdev) - struct tpkbd_data_pointer *data_pointer; - size_t name_sz = strlen(dev_name(dev)) + 16; - char *name_mute, *name_micmute; -- int ret; -+ int i, ret; -+ -+ /* Validate required reports. */ -+ for (i = 0; i < 4; i++) { -+ if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) -+ return -ENODEV; -+ } -+ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) -+ return -ENODEV; - - if (sysfs_create_group(&hdev->dev.kobj, - &tpkbd_attr_group_pointer)) { --- -1.8.3.1 - - -From 978474c73af6764f1c2c5409585221e6d438b16c Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 11 Sep 2013 21:56:56 +0200 -Subject: [PATCH 08/16] HID: logitech-dj: validate output report details - -A HID device could send a malicious output report that would cause the -logitech-dj HID driver to leak kernel memory contents to the device, or -trigger a NULL dereference during initialization: - -[ 304.424553] usb 1-1: New USB device found, idVendor=046d, idProduct=c52b -... -[ 304.780467] BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 -[ 304.781409] IP: [] logi_dj_recv_send_report.isra.11+0x1a/0x90 - -CVE-2013-2895 - -Signed-off-by: Kees Cook -Cc: stable@vger.kernel.org -Signed-off-by: Benjamin Tissoires ---- - drivers/hid/hid-logitech-dj.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c -index cd33084..a2469b5 100644 ---- a/drivers/hid/hid-logitech-dj.c -+++ b/drivers/hid/hid-logitech-dj.c -@@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, - struct hid_report *report; - struct hid_report_enum *output_report_enum; - u8 *data = (u8 *)(&dj_report->device_index); -- int i; -+ unsigned int i; - - output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; - report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; -@@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, - return -ENODEV; - } - -- for (i = 0; i < report->field[0]->report_count; i++) -+ for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++) - report->field[0]->value[i] = data[i]; - - hid_hw_request(hdev, report, HID_REQ_SET_REPORT); -@@ -783,6 +783,12 @@ static int logi_dj_probe(struct hid_device *hdev, - goto hid_parse_fail; - } - -+ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, -+ 0, DJREPORT_SHORT_LENGTH - 1)) { -+ retval = -ENODEV; -+ goto hid_parse_fail; -+ } -+ - /* Starts the usb device and connects to upper interfaces hiddev and - * hidraw */ - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); --- -1.8.3.1 - - -From 9445e3a28eb6365c54dae729d184c4c3b6b43d60 Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Wed, 11 Sep 2013 21:56:57 +0200 -Subject: [PATCH 09/16] HID: validate feature and input report details - -When dealing with usage_index, be sure to properly use unsigned instead of -int to avoid overflows. - -When working on report fields, always validate that their report_counts are -in bounds. -Without this, a HID device could report a malicious feature report that -could trick the driver into a heap overflow: - -[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 -... -[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -CVE-2013-2897 - -Cc: stable@vger.kernel.org -Signed-off-by: Benjamin Tissoires ---- - drivers/hid/hid-core.c | 16 +++++++--------- - drivers/hid/hid-input.c | 11 ++++++++++- - 2 files changed, 17 insertions(+), 10 deletions(-) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 65ee459..08500bc 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report); - static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) - { - struct hid_field *field; -- int i; - - if (report->maxfield == HID_MAX_FIELDS) { - hid_err(report->device, "too many fields in report\n"); -@@ -113,9 +112,6 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned - field->value = (s32 *)(field->usage + usages); - field->report = report; - -- for (i = 0; i < usages; i++) -- field->usage[i].usage_index = i; -- - return field; - } - -@@ -226,9 +222,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign - { - struct hid_report *report; - struct hid_field *field; -- int usages; -+ unsigned usages; - unsigned offset; -- int i; -+ unsigned i; - - report = hid_register_report(parser->device, report_type, parser->global.report_id); - if (!report) { -@@ -255,7 +251,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign - if (!parser->local.usage_index) /* Ignore padding fields */ - return 0; - -- usages = max_t(int, parser->local.usage_index, parser->global.report_count); -+ usages = max_t(unsigned, parser->local.usage_index, -+ parser->global.report_count); - - field = hid_register_field(report, usages, parser->global.report_count); - if (!field) -@@ -266,13 +263,14 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign - field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); - - for (i = 0; i < usages; i++) { -- int j = i; -+ unsigned j = i; - /* Duplicate the last usage we parsed if we have excess values */ - if (i >= parser->local.usage_index) - j = parser->local.usage_index - 1; - field->usage[i].hid = parser->local.usage[j]; - field->usage[i].collection_index = - parser->local.collection_index[j]; -+ field->usage[i].usage_index = i; - } - - field->maxusage = usages; -@@ -1290,7 +1288,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, - goto out; - } - -- if (hid->claimed != HID_CLAIMED_HIDRAW) { -+ if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { - for (a = 0; a < report->maxfield; a++) - hid_input_field(hid, report->field[a], cdata, interrupt); - hdrv = hid->driver; -diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c -index 7480799..3ac2138 100644 ---- a/drivers/hid/hid-input.c -+++ b/drivers/hid/hid-input.c -@@ -477,6 +477,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - if (field->flags & HID_MAIN_ITEM_CONSTANT) - goto ignore; - -+ /* Ignore if report count is out of bounds. */ -+ if (field->report_count < 1) -+ goto ignore; -+ - /* only LED usages are supported in output fields */ - if (field->report_type == HID_OUTPUT_REPORT && - (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { -@@ -1160,7 +1164,11 @@ static void report_features(struct hid_device *hid) - - rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; - list_for_each_entry(rep, &rep_enum->report_list, list) -- for (i = 0; i < rep->maxfield; i++) -+ for (i = 0; i < rep->maxfield; i++) { -+ /* Ignore if report count is out of bounds. */ -+ if (rep->field[i]->report_count < 1) -+ continue; -+ - for (j = 0; j < rep->field[i]->maxusage; j++) { - /* Verify if Battery Strength feature is available */ - hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); -@@ -1169,6 +1177,7 @@ static void report_features(struct hid_device *hid) - drv->feature_mapping(hid, rep->field[i], - rep->field[i]->usage + j); - } -+ } - } - - static struct hid_input *hidinput_allocate(struct hid_device *hid) --- -1.8.3.1 - - -From cc8d6c5e14fbffc3349dcd35c21fa46f1143070d Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Wed, 11 Sep 2013 21:56:58 +0200 -Subject: [PATCH 10/16] HID: multitouch: validate indexes details - -When working on report indexes, always validate that they are in bounds. -Without this, a HID device could report a malicious feature report that -could trick the driver into a heap overflow: - -[ 634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500 -... -[ 676.469629] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten - -Note that we need to change the indexes from s8 to s16 as they can -be between -1 and 255. - -CVE-2013-2897 - -Cc: stable@vger.kernel.org -Signed-off-by: Benjamin Tissoires ---- - drivers/hid/hid-multitouch.c | 26 ++++++++++++++------------ - 1 file changed, 14 insertions(+), 12 deletions(-) - -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index cb0e361..2d3677c 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -101,9 +101,9 @@ struct mt_device { - unsigned last_slot_field; /* the last field of a slot */ - unsigned mt_report_id; /* the report ID of the multitouch device */ - unsigned pen_report_id; /* the report ID of the pen device */ -- __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ -- __s8 inputmode_index; /* InputMode HID feature index in the report */ -- __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, -+ __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ -+ __s16 inputmode_index; /* InputMode HID feature index in the report */ -+ __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, - -1 if non-existent */ - __u8 num_received; /* how many contacts we received */ - __u8 num_expected; /* expected last contact index */ -@@ -317,20 +317,18 @@ static void mt_feature_mapping(struct hid_device *hdev, - struct hid_field *field, struct hid_usage *usage) - { - struct mt_device *td = hid_get_drvdata(hdev); -- int i; - - switch (usage->hid) { - case HID_DG_INPUTMODE: -- td->inputmode = field->report->id; -- td->inputmode_index = 0; /* has to be updated below */ -- -- for (i=0; i < field->maxusage; i++) { -- if (field->usage[i].hid == usage->hid) { -- td->inputmode_index = i; -- break; -- } -+ /* Ignore if value index is out of bounds. */ -+ if (usage->usage_index >= field->report_count) { -+ dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); -+ break; - } - -+ td->inputmode = field->report->id; -+ td->inputmode_index = usage->usage_index; -+ - break; - case HID_DG_CONTACTMAX: - td->maxcontact_report_id = field->report->id; -@@ -536,6 +534,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, - mt_store_field(usage, td, hi); - return 1; - case HID_DG_CONTACTCOUNT: -+ /* Ignore if indexes are out of bounds. */ -+ if (field->index >= field->report->maxfield || -+ usage->usage_index >= field->report_count) -+ return 1; - td->cc_index = field->index; - td->cc_value_index = usage->usage_index; - return 1; --- -1.8.3.1 - - -From 01b52229ddc746c56b2a7756eed46b1f98673bea Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Wed, 11 Sep 2013 21:56:59 +0200 -Subject: [PATCH 11/16] HID: lenovo-tpkbd: fix leak if tpkbd_probe_tp fails - -If tpkbd_probe_tp() bails out, the probe() function return an error, -but hid_hw_stop() is never called. - -fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=1003998 - -Cc: stable@vger.kernel.org -Signed-off-by: Benjamin Tissoires ---- - drivers/hid/hid-lenovo-tpkbd.c | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) - -diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c -index 762d988..31cf29a 100644 ---- a/drivers/hid/hid-lenovo-tpkbd.c -+++ b/drivers/hid/hid-lenovo-tpkbd.c -@@ -414,22 +414,27 @@ static int tpkbd_probe(struct hid_device *hdev, - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "hid_parse failed\n"); -- goto err_free; -+ goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hid_hw_start failed\n"); -- goto err_free; -+ goto err; - } - - uhdev = (struct usbhid_device *) hdev->driver_data; - -- if (uhdev->ifnum == 1) -- return tpkbd_probe_tp(hdev); -+ if (uhdev->ifnum == 1) { -+ ret = tpkbd_probe_tp(hdev); -+ if (ret) -+ goto err_hid; -+ } - - return 0; --err_free: -+err_hid: -+ hid_hw_stop(hdev); -+err: - return ret; - } - --- -1.8.3.1 diff --git a/kernel.spec b/kernel.spec index 5d52aefef..f23e8e5ca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 13 +%define stable_update 14 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -763,16 +763,6 @@ Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#rhbz 1000679 -Patch25079: rt2800-rearrange-bbp-rfcsr-initialization.patch - -#CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 -#CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 -#CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 -#CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 -#CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 -Patch25099: HID-CVE-fixes.patch - #CVE-2013-4343 rhbz 1007733 1007741 Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch @@ -1496,16 +1486,6 @@ ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-2888 rhbz 1000451 1002543 CVE-2013-2889 rhbz 999890 1002548 -#CVE-2013-2891 rhbz 999960 1002555 CVE-2013-2892 rhbz 1000429 1002570 -#CVE-2013-2893 rhbz 1000414 1002575 CVE-2013-2894 rhbz 1000137 1002579 -#CVE-2013-2895 rhbz 1000360 1002581 CVE-2013-2896 rhbz 1000494 1002594 -#CVE-2013-2897 rhbz 1000536 1002600 CVE-2013-2899 rhbz 1000373 1002604 -ApplyPatch HID-CVE-fixes.patch - -#rhbz 1000679 -ApplyPatch rt2800-rearrange-bbp-rfcsr-initialization.patch - #CVE-2013-4343 rhbz 1007733 1007741 ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch @@ -2372,6 +2352,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 4 2013 Justin M. Forbes 3.10.14-100 +- Linux v3.10.14 + * Thu Oct 3 2013 Josh Boyer - CVE-2013-4387 ipv6: panic when UFO=On for an interface (rhbz 1011927 1015166) diff --git a/rt2800-rearrange-bbp-rfcsr-initialization.patch b/rt2800-rearrange-bbp-rfcsr-initialization.patch deleted file mode 100644 index c782fc5d4..000000000 --- a/rt2800-rearrange-bbp-rfcsr-initialization.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c -index 7e66a90..6a70c27 100644 ---- a/drivers/net/wireless/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -4041,8 +4041,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) - u8 reg_id; - u8 value; - -- if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || -- rt2800_wait_bbp_ready(rt2x00dev))) -+ if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - if (rt2x00_rt(rt2x00dev, RT5592)) { -@@ -5185,15 +5184,17 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) - rt2800_init_registers(rt2x00dev))) - return -EIO; - -+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) -+ return -EIO; -+ - /* - * Send signal to firmware during boot time. - */ - rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); -- if (rt2x00_is_usb(rt2x00dev)) { -+ if (rt2x00_is_usb(rt2x00dev)) - rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); -- rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); -- } -+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - msleep(1); - - if (unlikely(rt2800_init_bbp(rt2x00dev))) diff --git a/sources b/sources index de04b8620..77727a57c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -573f2c972015880ba5d52e5b123b37d7 patch-3.10.13.xz +3c2ce4933f210fef16664dfa16028de1 patch-3.10.14.xz From 57b26ca924bf40bf17a9ac60e46036a9b33c81f7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 5 Oct 2013 10:08:07 -0400 Subject: [PATCH 428/492] Drop long carried selinux ptraceme patch Nobody is working on this in Fedora at the moment, and it really needs to come from upstream. --- kernel.spec | 6 - ...different-permission-to-ptrace-child.patch | 162 ------------------ 2 files changed, 168 deletions(-) delete mode 100644 selinux-apply-different-permission-to-ptrace-child.patch diff --git a/kernel.spec b/kernel.spec index f23e8e5ca..cb25b464f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -722,9 +722,6 @@ Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch Patch22000: weird-root-dentry-name-debug.patch -#selinux ptrace child permissions -Patch22001: selinux-apply-different-permission-to-ptrace-child.patch - #rhbz 892811 Patch22247: ath9k_rx_dma_stop_check.patch @@ -1445,9 +1442,6 @@ ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch ApplyPatch weird-root-dentry-name-debug.patch -#selinux ptrace child permissions -ApplyPatch selinux-apply-different-permission-to-ptrace-child.patch - #rhbz 892811 ApplyPatch ath9k_rx_dma_stop_check.patch diff --git a/selinux-apply-different-permission-to-ptrace-child.patch b/selinux-apply-different-permission-to-ptrace-child.patch deleted file mode 100644 index 90baad840..000000000 --- a/selinux-apply-different-permission-to-ptrace-child.patch +++ /dev/null @@ -1,162 +0,0 @@ -Some applications, like gdb, are able to ptrace both children or other -completely unrelated tasks. We would like to be able to discern these two -things and to be able to allow gdb to ptrace it's children, but not to be -able to ptrace unrelated tasks for security reasons. - -Upstream is a bit weary of this patch as it may be incomplete. They are -not fundamentally opposed to the patch, I was just ask to see if I could -flush out any needed refinement in Fedora where we already had the -problem. We may find that we need to emulate the YAMA non-child -registration module in order to completely deal with 'normal' ptrace on -a system. At the moment however, this patch will at least let us get -gdb working for many users in Fedora (See fedora-devel-list for a -discussion of the current issues people are complaining about in F17 -without this) - ---- - - security/selinux/hooks.c | 38 +++++++++++++++++++++++++++++++++++ - security/selinux/include/classmap.h | 2 +- - security/selinux/include/security.h | 2 ++ - security/selinux/selinuxfs.c | 3 ++- - security/selinux/ss/services.c | 3 +++ - 5 files changed, 46 insertions(+), 2 deletions(-) - -diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c -index 1a4acf4..b226f26 100644 ---- a/security/selinux/hooks.c -+++ b/security/selinux/hooks.c -@@ -1805,6 +1805,39 @@ static inline u32 open_file_to_av(struct file *file) - - /* Hook functions begin here. */ - -+/** -+ * task_is_descendant - walk up a process family tree looking for a match -+ * @parent: the process to compare against while walking up from child -+ * @child: the process to start from while looking upwards for parent -+ * -+ * Returns 1 if child is a descendant of parent, 0 if not. -+ */ -+static int task_is_descendant(struct task_struct *parent, -+ struct task_struct *child) -+{ -+ int rc = 0; -+ struct task_struct *walker = child; -+ -+ if (!parent || !child) -+ return 0; -+ -+ rcu_read_lock(); -+ if (!thread_group_leader(parent)) -+ parent = rcu_dereference(parent->group_leader); -+ while (walker->pid > 0) { -+ if (!thread_group_leader(walker)) -+ walker = rcu_dereference(walker->group_leader); -+ if (walker == parent) { -+ rc = 1; -+ break; -+ } -+ walker = rcu_dereference(walker->real_parent); -+ } -+ rcu_read_unlock(); -+ -+ return rc; -+} -+ - static int selinux_ptrace_access_check(struct task_struct *child, - unsigned int mode) - { -@@ -1820,6 +1853,9 @@ static int selinux_ptrace_access_check(struct task_struct *child, - return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); - } - -+ -+ if (selinux_policycap_ptrace_child && task_is_descendant(current, child)) -+ return current_has_perm(child, PROCESS__PTRACE_CHILD); - return current_has_perm(child, PROCESS__PTRACE); - } - -@@ -1831,6 +1867,8 @@ static int selinux_ptrace_traceme(struct task_struct *parent) - if (rc) - return rc; - -+ if (selinux_policycap_ptrace_child && task_is_descendant(parent, current)) -+ return task_has_perm(parent, current, PROCESS__PTRACE_CHILD); - return task_has_perm(parent, current, PROCESS__PTRACE); - } - -diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index 39e678c..72c08b9 100644 ---- a/security/selinux/include/classmap.h -+++ b/security/selinux/include/classmap.h -@@ -29,7 +29,7 @@ struct security_class_mapping secclass_map[] = { - "getattr", "setexec", "setfscreate", "noatsecure", "siginh", - "setrlimit", "rlimitinh", "dyntransition", "setcurrent", - "execmem", "execstack", "execheap", "setkeycreate", -- "setsockcreate", NULL } }, -+ "setsockcreate", "ptrace_child", NULL } }, - { "system", - { "ipc_info", "syslog_read", "syslog_mod", - "syslog_console", "module_request", NULL } }, -diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h -index dde2005..ac14b0a 100644 ---- a/security/selinux/include/security.h -+++ b/security/selinux/include/security.h -@@ -68,12 +68,14 @@ extern int selinux_enabled; - enum { - POLICYDB_CAPABILITY_NETPEER, - POLICYDB_CAPABILITY_OPENPERM, -+ POLICYDB_CAPABILITY_PTRACE_CHILD, - __POLICYDB_CAPABILITY_MAX - }; - #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) - - extern int selinux_policycap_netpeer; - extern int selinux_policycap_openperm; -+extern int selinux_policycap_ptrace_child; - - /* - * type_datum properties -diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c -index 4e93f9e..3379765 100644 ---- a/security/selinux/selinuxfs.c -+++ b/security/selinux/selinuxfs.c -@@ -44,7 +44,8 @@ - /* Policy capability filenames */ - static char *policycap_names[] = { - "network_peer_controls", -- "open_perms" -+ "open_perms", -+ "ptrace_child", - }; - - unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; -diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c -index 9b7e7ed..4d12a6e 100644 ---- a/security/selinux/ss/services.c -+++ b/security/selinux/ss/services.c -@@ -72,6 +72,7 @@ - - int selinux_policycap_netpeer; - int selinux_policycap_openperm; -+int selinux_policycap_ptrace_child; - - static DEFINE_RWLOCK(policy_rwlock); - -@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void) - POLICYDB_CAPABILITY_NETPEER); - selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, - POLICYDB_CAPABILITY_OPENPERM); -+ selinux_policycap_ptrace_child = ebitmap_get_bit(&policydb.policycaps, -+ POLICYDB_CAPABILITY_PTRACE_CHILD); - } - - static int security_preserve_bools(struct policydb *p); - - - - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel From 088b8c8ab7687ec499763eb93fcbcb78616f282c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Oct 2013 08:39:57 -0400 Subject: [PATCH 429/492] Use RCU safe kfree for conntrack (rhbz 1015989) --- kernel.spec | 11 +++++- ...ntrack-use-RCU-safe-kfree-for-conntr.patch | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch diff --git a/kernel.spec b/kernel.spec index cb25b464f..3334a0641 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -785,6 +785,9 @@ Patch25116: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue. #CVE-2013-4387 rhbz 1011927 1015166 Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch +#rhbz 1015989 +Patch25122: netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch + # END OF PATCH DEFINITIONS %endif @@ -1505,6 +1508,9 @@ ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.p #CVE-2013-4387 rhbz 1011927 1015166 ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch +#rhbz 1015989 +ApplyPatch netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch + # END OF PATCH APPLICATIONS %endif @@ -2346,6 +2352,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 08 2013 Josh Boyer +- Use RCU safe kfree for conntrack (rhbz 1015989) + * Fri Oct 4 2013 Justin M. Forbes 3.10.14-100 - Linux v3.10.14 diff --git a/netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch b/netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch new file mode 100644 index 000000000..fd8351fa4 --- /dev/null +++ b/netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch @@ -0,0 +1,35 @@ +From c13a84a830a208fb3443628773c8ca0557773cc7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= +Date: Wed, 11 Sep 2013 10:17:27 +0200 +Subject: [PATCH] netfilter: nf_conntrack: use RCU safe kfree for conntrack + extensions + +Commit 68b80f11 (netfilter: nf_nat: fix RCU races) introduced +RCU protection for freeing extension data when reallocation +moves them to a new location. We need the same protection when +freeing them in nf_ct_ext_free() in order to prevent a +use-after-free by other threads referencing a NAT extension data +via bysource list. + +Signed-off-by: Michal Kubecek +Signed-off-by: Pablo Neira Ayuso +--- + include/net/netfilter/nf_conntrack_extend.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h +index ff95434..88a1d40 100644 +--- a/include/net/netfilter/nf_conntrack_extend.h ++++ b/include/net/netfilter/nf_conntrack_extend.h +@@ -86,7 +86,7 @@ static inline void nf_ct_ext_destroy(struct nf_conn *ct) + static inline void nf_ct_ext_free(struct nf_conn *ct) + { + if (ct->ext) +- kfree(ct->ext); ++ kfree_rcu(ct->ext, rcu); + } + + /* Add this type, returns pointer to data or NULL. */ +-- +1.8.3.1 + From 6fdf37f0eb1619a2d506873b06c444e1562a9e3f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Oct 2013 08:43:27 -0400 Subject: [PATCH 430/492] Quiet irq remapping stack trace (rhbz 982153) - Use RCU safe kfree for conntrack (rhbz 1015989) --- ...ce-from-broken-irq-remapping-warning.patch | 47 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 54 insertions(+) create mode 100644 iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch diff --git a/iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch b/iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch new file mode 100644 index 000000000..9e88893ae --- /dev/null +++ b/iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch @@ -0,0 +1,47 @@ +From 05104a4e8713b27291c7bb49c1e7e68b4e243571 Mon Sep 17 00:00:00 2001 +From: Neil Horman +Date: Fri, 27 Sep 2013 16:53:35 +0000 +Subject: iommu: Remove stack trace from broken irq remapping warning + +The warning for the irq remapping broken check in intel_irq_remapping.c is +pretty pointless. We need the warning, but we know where its comming from, the +stack trace will always be the same, and it needlessly triggers things like +Abrt. This changes the warning to just print a text warning about BIOS being +broken, without the stack trace, then sets the appropriate taint bit. Since we +automatically disable irq remapping, theres no need to contiue making Abrt jump +at this problem + +Signed-off-by: Neil Horman +CC: Joerg Roedel +CC: Bjorn Helgaas +CC: Andy Lutomirski +CC: Konrad Rzeszutek Wilk +CC: Sebastian Andrzej Siewior +Signed-off-by: Joerg Roedel +--- +diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c +index f71673d..b97d70b 100644 +--- a/drivers/iommu/intel_irq_remapping.c ++++ b/drivers/iommu/intel_irq_remapping.c +@@ -525,12 +525,13 @@ static int __init intel_irq_remapping_supported(void) + if (disable_irq_remap) + return 0; + if (irq_remap_broken) { +- WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, +- "This system BIOS has enabled interrupt remapping\n" +- "on a chipset that contains an erratum making that\n" +- "feature unstable. To maintain system stability\n" +- "interrupt remapping is being disabled. Please\n" +- "contact your BIOS vendor for an update\n"); ++ printk(KERN_WARNING ++ "This system BIOS has enabled interrupt remapping\n" ++ "on a chipset that contains an erratum making that\n" ++ "feature unstable. To maintain system stability\n" ++ "interrupt remapping is being disabled. Please\n" ++ "contact your BIOS vendor for an update\n"); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + disable_irq_remap = 1; + return 0; + } +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 3334a0641..e4ea0fa87 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,9 @@ Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch #rhbz 1015989 Patch25122: netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch +#rhbz 982153 +Patch25123: iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch + # END OF PATCH DEFINITIONS %endif @@ -1511,6 +1514,9 @@ ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch #rhbz 1015989 ApplyPatch netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch +#rhbz 982153 +ApplyPatch iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch + # END OF PATCH APPLICATIONS %endif @@ -2353,6 +2359,7 @@ fi # || || %changelog * Tue Oct 08 2013 Josh Boyer +- Quiet irq remapping stack trace (rhbz 982153) - Use RCU safe kfree for conntrack (rhbz 1015989) * Fri Oct 4 2013 Justin M. Forbes 3.10.14-100 From 4e941e3a2fa2ad396c03bd2bdc6eb946d7581c52 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 8 Oct 2013 09:13:07 -0500 Subject: [PATCH 431/492] Linux v3.11.4 rebase --- ...rt-fixup-for-Genius-Gx-Imperator-Key.patch | 118 ---------- ...ech-dj-missing-Unifying-device-issue.patch | 172 -------------- ...ODATA-if-reading-battery-attrs-fails.patch | 56 ----- ...t-fixup-for-Genius-Gila-Gaming-mouse.patch | 98 -------- ...h-fix-for-newer-hardware-versions-v7.patch | 70 ------ ...andle-idiv-overflow-at-kvm_write_tsc.patch | 45 ---- acpi-video-dos.patch | 17 -- ...-not-call-setup_timer-multiple-times.patch | 50 ----- ...the-mdb-entry-when-query-is-received.patch | 159 ------------- ...d-query-as-soon-as-leave-is-received.patch | 57 ----- bridge-timer-fix.patch | 13 -- config-arm-generic | 115 +++++++--- config-arm-kirkwood | 14 ++ config-armv7 | 209 +++++++++++------- config-armv7-generic | 62 +++--- config-debug | 12 +- config-generic | 209 ++++++++++++------ config-nodebug | 14 +- config-powerpc-generic | 20 +- config-powerpc32-generic | 6 - config-powerpc32-smp | 1 - config-powerpc64 | 14 +- config-powerpc64p7 | 14 +- config-s390x | 25 +-- config-x86-32-generic | 4 +- config-x86-generic | 48 ++-- config-x86_64-generic | 20 +- efi-dont-map-boot-services-on-32bit.patch | 22 -- ...ning-if-enabling-irq-remapping-fails.patch | 25 --- kernel.spec | 73 +----- ...ipsec-encryption-bug-in-sctp_v6_xmit.patch | 32 ++- 31 files changed, 485 insertions(+), 1309 deletions(-) delete mode 100644 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch delete mode 100644 HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch delete mode 100644 HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch delete mode 100644 HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch delete mode 100644 Input-elantech-fix-for-newer-hardware-versions-v7.patch delete mode 100644 KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch delete mode 100644 acpi-video-dos.patch delete mode 100644 bridge-do-not-call-setup_timer-multiple-times.patch delete mode 100644 bridge-only-expire-the-mdb-entry-when-query-is-received.patch delete mode 100644 bridge-send-query-as-soon-as-leave-is-received.patch delete mode 100644 bridge-timer-fix.patch delete mode 100644 efi-dont-map-boot-services-on-32bit.patch delete mode 100644 intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch diff --git a/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch b/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch deleted file mode 100644 index b7bbf77b6..000000000 --- a/0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0adb9c2c5ed42f199cb2a630c37d18dee385fae2 Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Mon, 15 Jul 2013 10:12:18 +0200 -Subject: [PATCH] HID: kye: Add report fixup for Genius Gx Imperator Keyboard - -Genius Gx Imperator Keyboard presents the same problem in its report -descriptors than Genius Gila Gaming Mouse. -Use the same fixup for both. - -Fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=928561 - -Reported-and-tested-by: Honza Brazdil -Signed-off-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-core.c | 1 + - drivers/hid/hid-ids.h | 1 + - drivers/hid/hid-kye.c | 45 ++++++++++++++++++++++++++++----------------- - 3 files changed, 30 insertions(+), 17 deletions(-) - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 8de5cb8..b0f2f45 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -1594,6 +1594,7 @@ static const struct hid_device_id hid_have_special_driver[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index c5aea29..0288531 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -479,6 +479,7 @@ - #define USB_VENDOR_ID_KYE 0x0458 - #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 - #define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 -+#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR 0x4018 - #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 - #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 - #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 -diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c -index 1e2ee2aa..7384512 100644 ---- a/drivers/hid/hid-kye.c -+++ b/drivers/hid/hid-kye.c -@@ -268,6 +268,26 @@ static __u8 easypen_m610x_rdesc_fixed[] = { - 0xC0 /* End Collection */ - }; - -+static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc, -+ unsigned int *rsize, int offset, const char *device_name) { -+ /* -+ * the fixup that need to be done: -+ * - change Usage Maximum in the Comsumer Control -+ * (report ID 3) to a reasonable value -+ */ -+ if (*rsize >= offset + 31 && -+ /* Usage Page (Consumer Devices) */ -+ rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c && -+ /* Usage (Consumer Control) */ -+ rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 && -+ /* Usage Maximum > 12287 */ -+ rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) { -+ hid_info(hdev, "fixing up %s report descriptor\n", device_name); -+ rdesc[offset + 12] = 0x2f; -+ } -+ return rdesc; -+} -+ - static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) - { -@@ -315,23 +335,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, - } - break; - case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: -- /* -- * the fixup that need to be done: -- * - change Usage Maximum in the Comsumer Control -- * (report ID 3) to a reasonable value -- */ -- if (*rsize >= 135 && -- /* Usage Page (Consumer Devices) */ -- rdesc[104] == 0x05 && rdesc[105] == 0x0c && -- /* Usage (Consumer Control) */ -- rdesc[106] == 0x09 && rdesc[107] == 0x01 && -- /* Usage Maximum > 12287 */ -- rdesc[114] == 0x2a && rdesc[116] > 0x2f) { -- hid_info(hdev, -- "fixing up Genius Gila Gaming Mouse " -- "report descriptor\n"); -- rdesc[116] = 0x2f; -- } -+ rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104, -+ "Genius Gila Gaming Mouse"); -+ break; -+ case USB_DEVICE_ID_GENIUS_GX_IMPERATOR: -+ rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83, -+ "Genius Gx Imperator Keyboard"); - break; - } - return rdesc; -@@ -428,6 +437,8 @@ static const struct hid_device_id kye_devices[] = { - USB_DEVICE_ID_KYE_EASYPEN_M610X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, - USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, -+ USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, - { } - }; - MODULE_DEVICE_TABLE(hid, kye_devices); --- -1.8.3.1 - diff --git a/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch b/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch deleted file mode 100644 index 1c112ccde..000000000 --- a/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch +++ /dev/null @@ -1,172 +0,0 @@ -From c63e0e370028d7e4033bd40165f18499872b5183 Mon Sep 17 00:00:00 2001 -From: Nestor Lopez Casado -Date: Thu, 18 Jul 2013 13:21:30 +0000 -Subject: HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue"" - -This reverts commit 8af6c08830b1ae114d1a8b548b1f8b056e068887. - -This patch re-adds the workaround introduced by 596264082f10dd4 -which was reverted by 8af6c08830b1ae114. - -The original patch 596264 was needed to overcome a situation where -the hid-core would drop incoming reports while probe() was being -executed. - -This issue was solved by c849a6143bec520af which added -hid_device_io_start() and hid_device_io_stop() that enable a specific -hid driver to opt-in for input reports while its probe() is being -executed. - -Commit a9dd22b730857347 modified hid-logitech-dj so as to use the -functionality added to hid-core. Having done that, workaround 596264 -was no longer necessary and was reverted by 8af6c08. - -We now encounter a different problem that ends up 'again' thwarting -the Unifying receiver enumeration. The problem is time and usb controller -dependent. Ocasionally the reports sent to the usb receiver to start -the paired devices enumeration fail with -EPIPE and the receiver never -gets to enumerate the paired devices. - -With dcd9006b1b053c7b1c the problem was "hidden" as the call to the usb -driver became asynchronous and none was catching the error from the -failing URB. - -As the root cause for this failing SET_REPORT is not understood yet, --possibly a race on the usb controller drivers or a problem with the -Unifying receiver- reintroducing this workaround solves the problem. - -Overall what this workaround does is: If an input report from an -unknown device is received, then a (re)enumeration is performed. - -related bug: -https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1194649 - -Signed-off-by: Nestor Lopez Casado -Signed-off-by: Jiri Kosina ---- -diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c -index 5207591a..cd33084 100644 ---- a/drivers/hid/hid-logitech-dj.c -+++ b/drivers/hid/hid-logitech-dj.c -@@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver; - static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, - size_t count, - unsigned char report_type); -+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); - - static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) -@@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, - if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & - SPFUNCTION_DEVICE_LIST_EMPTY) { - dbg_hid("%s: device list is empty\n", __func__); -+ djrcv_dev->querying_devices = false; - return; - } - -@@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, - return; - } - -+ if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { -+ /* The device is already known. No need to reallocate it. */ -+ dbg_hid("%s: device is already known\n", __func__); -+ return; -+ } -+ - dj_hiddev = hid_allocate_device(); - if (IS_ERR(dj_hiddev)) { - dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", -@@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work) - struct dj_report dj_report; - unsigned long flags; - int count; -+ int retval; - - dbg_hid("%s\n", __func__); - -@@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work) - logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); - break; - default: -+ /* A normal report (i. e. not belonging to a pair/unpair notification) -+ * arriving here, means that the report arrived but we did not have a -+ * paired dj_device associated to the report's device_index, this -+ * means that the original "device paired" notification corresponding -+ * to this dj_device never arrived to this driver. The reason is that -+ * hid-core discards all packets coming from a device while probe() is -+ * executing. */ -+ if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { -+ /* ok, we don't know the device, just re-ask the -+ * receiver for the list of connected devices. */ -+ retval = logi_dj_recv_query_paired_devices(djrcv_dev); -+ if (!retval) { -+ /* everything went fine, so just leave */ -+ break; -+ } -+ dev_err(&djrcv_dev->hdev->dev, -+ "%s:logi_dj_recv_query_paired_devices " -+ "error:%d\n", __func__, retval); -+ } - dbg_hid("%s: unexpected report type\n", __func__); - } - } -@@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, - if (!djdev) { - dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" - " is NULL, index %d\n", dj_report->device_index); -+ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); -+ -+ if (schedule_work(&djrcv_dev->work) == 0) { -+ dbg_hid("%s: did not schedule the work item, was already " -+ "queued\n", __func__); -+ } - return; - } - -@@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, - if (dj_device == NULL) { - dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" - " is NULL, index %d\n", dj_report->device_index); -+ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); -+ -+ if (schedule_work(&djrcv_dev->work) == 0) { -+ dbg_hid("%s: did not schedule the work item, was already " -+ "queued\n", __func__); -+ } - return; - } - -@@ -444,6 +484,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) - struct dj_report *dj_report; - int retval; - -+ /* no need to protect djrcv_dev->querying_devices */ -+ if (djrcv_dev->querying_devices) -+ return 0; -+ - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); - if (!dj_report) - return -ENOMEM; -@@ -455,6 +499,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) - return retval; - } - -+ - static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, - unsigned timeout) - { -diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h -index fd28a5e..4a40003 100644 ---- a/drivers/hid/hid-logitech-dj.h -+++ b/drivers/hid/hid-logitech-dj.h -@@ -101,6 +101,7 @@ struct dj_receiver_dev { - struct work_struct work; - struct kfifo notif_fifo; - spinlock_t lock; -+ bool querying_devices; - }; - - struct dj_device { --- -cgit v0.9.2 diff --git a/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch b/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch deleted file mode 100644 index d0a021c4c..000000000 --- a/HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch +++ /dev/null @@ -1,56 +0,0 @@ -From d0a934b764c67b4bf626f5b7cf725a6e3066afd2 Mon Sep 17 00:00:00 2001 -From: David Herrmann -Date: Mon, 13 May 2013 15:01:30 +0000 -Subject: HID: input: return ENODATA if reading battery attrs fails - -power_supply core has the bad habit of calling our battery callbacks -from within power_supply_register(). Furthermore, if the callbacks -fail with an unhandled error code, it will skip any uevent that it -might currently process. -So if HID-core registers battery devices, an "add" uevent is generated -and the battery callbacks are called. These will gracefully fail due -to timeouts as they might still hold locks on event processing. One -could argue that this should be fixed in power_supply core, but the -least we can do is to signal ENODATA so power_supply core will just -skip the property and continue with the uevent. - -This fixes a bug where "add" and "remove" uevents are skipped for -battery devices. upower is unable to track these devices and currently -needs to ignore them. - -This patch also overwrites any other error code. I cannot see any reason -why we should forward protocol- or I/O-errors to the power_supply core. -We handle these errors in hid_ll_driver later, anyway, so just skip -them. power_supply core cannot do anything useful with them, anyway, -and we avoid skipping important uevents and confusing user-space. - -Thanks a lot to Daniel Nicoletti for pushing and investigating -on this. - -Cc: Jiri Kosina -Cc: Anton Vorontsov -Cc: David Woodhouse -Reported-by: Daniel Nicoletti -Signed-off-by: David Herrmann -Signed-off-by: Jiri Kosina ---- -diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c -index 945b815..c526a3c 100644 ---- a/drivers/hid/hid-input.c -+++ b/drivers/hid/hid-input.c -@@ -354,10 +354,10 @@ static int hidinput_get_battery_property(struct power_supply *psy, - dev->battery_report_type); - - if (ret != 2) { -- if (ret >= 0) -- ret = -EINVAL; -+ ret = -ENODATA; - kfree(buf); - break; - } -+ ret = 0; - - if (dev->battery_min < dev->battery_max && - buf[1] >= dev->battery_min && --- -cgit v0.9.2 diff --git a/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch b/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch deleted file mode 100644 index 6913eb520..000000000 --- a/HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 3685c18e17f12438d0a83331c1b6a5b00fade7a1 Mon Sep 17 00:00:00 2001 -From: Benjamin Tissoires -Date: Tue, 02 Jul 2013 16:10:09 +0000 -Subject: HID: kye: Add report fixup for Genius Gila Gaming mouse - -Genius Gila Gaming Mouse presents an obviously wrong report descriptor. -the Consumer control (report ID 3) is the following: -0x05, 0x0c, // Usage Page (Consumer Devices) 105 -0x09, 0x01, // Usage (Consumer Control) 107 -0xa1, 0x01, // Collection (Application) 109 -0x85, 0x03, // Report ID (3) 111 -0x19, 0x00, // Usage Minimum (0) 113 -0x2a, 0xff, 0x7f, // Usage Maximum (32767) 115 -0x15, 0x00, // Logical Minimum (0) 118 -0x26, 0xff, 0x7f, // Logical Maximum (32767) 120 -0x75, 0x10, // Report Size (16) 123 -0x95, 0x03, // Report Count (3) 125 -0x81, 0x00, // Input (Data,Arr,Abs) 127 -0x75, 0x08, // Report Size (8) 129 -0x95, 0x01, // Report Count (1) 131 -0x81, 0x01, // Input (Cnst,Arr,Abs) 133 -0xc0, // End Collection 135 - -So the first input whithin this report has a count of 3 but a usage range -of 32768. So this value is obviously wrong as it should not be greater than -the report count. - -Fixes: -https://bugzilla.redhat.com/show_bug.cgi?id=959721 - -Signed-off-by: Benjamin Tissoires -Signed-off-by: Jiri Kosina ---- -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 8f616bd..27aa7c7 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -1589,6 +1589,7 @@ static const struct hid_device_id hid_have_special_driver[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 3da75dd..b2b692e 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -474,6 +474,7 @@ - - #define USB_VENDOR_ID_KYE 0x0458 - #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 -+#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 - #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 - #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 - #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 -diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c -index 6af90db..1e2ee2aa 100644 ---- a/drivers/hid/hid-kye.c -+++ b/drivers/hid/hid-kye.c -@@ -314,6 +314,25 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, - *rsize = sizeof(easypen_m610x_rdesc_fixed); - } - break; -+ case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: -+ /* -+ * the fixup that need to be done: -+ * - change Usage Maximum in the Comsumer Control -+ * (report ID 3) to a reasonable value -+ */ -+ if (*rsize >= 135 && -+ /* Usage Page (Consumer Devices) */ -+ rdesc[104] == 0x05 && rdesc[105] == 0x0c && -+ /* Usage (Consumer Control) */ -+ rdesc[106] == 0x09 && rdesc[107] == 0x01 && -+ /* Usage Maximum > 12287 */ -+ rdesc[114] == 0x2a && rdesc[116] > 0x2f) { -+ hid_info(hdev, -+ "fixing up Genius Gila Gaming Mouse " -+ "report descriptor\n"); -+ rdesc[116] = 0x2f; -+ } -+ break; - } - return rdesc; - } -@@ -407,6 +426,8 @@ static const struct hid_device_id kye_devices[] = { - USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, - USB_DEVICE_ID_KYE_EASYPEN_M610X) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, -+ USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, - { } - }; - MODULE_DEVICE_TABLE(hid, kye_devices); --- -cgit v0.9.2 diff --git a/Input-elantech-fix-for-newer-hardware-versions-v7.patch b/Input-elantech-fix-for-newer-hardware-versions-v7.patch deleted file mode 100644 index b9495d75d..000000000 --- a/Input-elantech-fix-for-newer-hardware-versions-v7.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 9eebed7de660c0b5ab129a9de4f89d20b60de68c Mon Sep 17 00:00:00 2001 -From: Matteo Delfino -Date: Sat, 6 Jul 2013 21:52:26 -0700 -Subject: [PATCH] Input: elantech - fix for newer hardware versions (v7) - -* Fix version recognition in elantech_set_properties - - The new hardware reports itself as v7 but the packets' - structure is unaltered. - -* Fix packet type recognition in elantech_packet_check_v4 - - The bitmask used for v6 is too wide, only the last three bits of - the third byte in a packet (packet[3] & 0x03) are actually used to - distinguish between packet types. - Starting from v7, additional information (to be interpreted) is - stored in the remaining bits (packets[3] & 0x1c). - In addition, the value stored in (packet[0] & 0x0c) is no longer - a constant but contains additional information yet to be deciphered. - This change should be backwards compatible with v6 hardware. - -Additional-author: Giovanni Frigione -Signed-off-by: Matteo Delfino -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 1e8e42f..57b2637 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -694,18 +694,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) - static int elantech_packet_check_v4(struct psmouse *psmouse) - { - unsigned char *packet = psmouse->packet; -+ unsigned char packet_type = packet[3] & 0x03; - -- if ((packet[0] & 0x0c) == 0x04 && -- (packet[3] & 0x1f) == 0x11) -+ switch (packet_type) { -+ case 0: -+ return PACKET_V4_STATUS; -+ -+ case 1: - return PACKET_V4_HEAD; - -- if ((packet[0] & 0x0c) == 0x04 && -- (packet[3] & 0x1f) == 0x12) -+ case 2: - return PACKET_V4_MOTION; -- -- if ((packet[0] & 0x0c) == 0x04 && -- (packet[3] & 0x1f) == 0x10) -- return PACKET_V4_STATUS; -+ } - - return PACKET_UNKNOWN; - } -@@ -1282,6 +1282,7 @@ static int elantech_set_properties(struct elantech_data *etd) - etd->hw_version = 3; - break; - case 6: -+ case 7: - etd->hw_version = 4; - break; - default: --- -1.8.3.1 - diff --git a/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch b/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch deleted file mode 100644 index 678e82953..000000000 --- a/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 094b5d9..64a4b03 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -1194,20 +1194,37 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) - elapsed = ns - kvm->arch.last_tsc_nsec; - - if (vcpu->arch.virtual_tsc_khz) { -+ int faulted = 0; -+ - /* n.b - signed multiplication and division required */ - usdiff = data - kvm->arch.last_tsc_write; - #ifdef CONFIG_X86_64 - usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; - #else - /* do_div() only does unsigned */ -- asm("idivl %2; xor %%edx, %%edx" -- : "=A"(usdiff) -- : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); -+ asm("1: idivl %[divisor]\n" -+ "2: xor %%edx, %%edx\n" -+ " movl $0, %[faulted]\n" -+ "3:\n" -+ ".section .fixup,\"ax\"\n" -+ "4: movl $1, %[faulted]\n" -+ " jmp 3b\n" -+ ".previous\n" -+ -+ _ASM_EXTABLE(1b, 4b) -+ -+ : "=A"(usdiff), [faulted] "=r" (faulted) -+ : "A"(usdiff * 1000), [divisor] "rm"(vcpu->arch.virtual_tsc_khz)); -+ - #endif - do_div(elapsed, 1000); - usdiff -= elapsed; - if (usdiff < 0) - usdiff = -usdiff; -+ -+ /* idivl overflow => difference is larger than USEC_PER_SEC */ -+ if (faulted) -+ usdiff = USEC_PER_SEC; - } else - usdiff = USEC_PER_SEC; /* disable TSC match window below */ - diff --git a/acpi-video-dos.patch b/acpi-video-dos.patch deleted file mode 100644 index 3e2085193..000000000 --- a/acpi-video-dos.patch +++ /dev/null @@ -1,17 +0,0 @@ -Disable firmware video brightness change on AC/Battery switch by default - --- mjg59 - -diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c -index bac2901..93b1a9e 100644 ---- a/drivers/acpi/video.c -+++ b/drivers/acpi/video.c -@@ -1818,7 +1818,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) - - static int acpi_video_bus_start_devices(struct acpi_video_bus *video) - { -- return acpi_video_bus_DOS(video, 0, 0); -+ return acpi_video_bus_DOS(video, 0, 1); - } - - static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) diff --git a/bridge-do-not-call-setup_timer-multiple-times.patch b/bridge-do-not-call-setup_timer-multiple-times.patch deleted file mode 100644 index c8c7bf747..000000000 --- a/bridge-do-not-call-setup_timer-multiple-times.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 1faabf2aab1fdaa1ace4e8c829d1b9cf7bfec2f1 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sat, 20 Jul 2013 03:07:16 +0000 -Subject: bridge: do not call setup_timer() multiple times - -commit 9f00b2e7cf24 ("bridge: only expire the mdb entry when query is -received") added a nasty bug as an active timer can be reinitialized. - -setup_timer() must be done once, no matter how many time mod_timer() -is called. br_multicast_new_group() is the right place to do this. - -Reported-by: Srivatsa S. Bhat -Diagnosed-by: Thomas Gleixner -Signed-off-by: Eric Dumazet -Tested-by: Srivatsa S. Bhat -Cc: Cong Wang -Signed-off-by: David S. Miller ---- -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index 69af490..4b99c9a 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -619,6 +619,9 @@ rehash: - mp->br = br; - mp->addr = *group; - -+ setup_timer(&mp->timer, br_multicast_group_expired, -+ (unsigned long)mp); -+ - hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); - mdb->size++; - -@@ -1126,7 +1129,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -- setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); - mod_timer(&mp->timer, now + br->multicast_membership_interval); - mp->timer_armed = true; - -@@ -1204,7 +1206,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -- setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); - mod_timer(&mp->timer, now + br->multicast_membership_interval); - mp->timer_armed = true; - --- -cgit v0.9.2 diff --git a/bridge-only-expire-the-mdb-entry-when-query-is-received.patch b/bridge-only-expire-the-mdb-entry-when-query-is-received.patch deleted file mode 100644 index b58b57083..000000000 --- a/bridge-only-expire-the-mdb-entry-when-query-is-received.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b Mon Sep 17 00:00:00 2001 -From: Cong Wang -Date: Tue, 21 May 2013 21:52:55 +0000 -Subject: bridge: only expire the mdb entry when query is received - -Currently we arm the expire timer when the mdb entry is added, -however, this causes problem when there is no querier sent -out after that. - -So we should only arm the timer when a corresponding query is -received, as suggested by Herbert. - -And he also mentioned "if there is no querier then group -subscriptions shouldn't expire. There has to be at least one querier -in the network for this thing to work. Otherwise it just degenerates -into a non-snooping switch, which is OK." - -Cc: Herbert Xu -Cc: Stephen Hemminger -Cc: "David S. Miller" -Cc: Adam Baker -Signed-off-by: Cong Wang -Acked-by: Herbert Xu -Signed-off-by: David S. Miller ---- -(limited to 'net/bridge') - -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index 2475147..40bda80 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -617,8 +617,6 @@ rehash: - - mp->br = br; - mp->addr = *group; -- setup_timer(&mp->timer, br_multicast_group_expired, -- (unsigned long)mp); - - hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); - mdb->size++; -@@ -656,7 +654,6 @@ static int br_multicast_add_group(struct net_bridge *br, - struct net_bridge_mdb_entry *mp; - struct net_bridge_port_group *p; - struct net_bridge_port_group __rcu **pp; -- unsigned long now = jiffies; - int err; - - spin_lock(&br->multicast_lock); -@@ -671,7 +668,6 @@ static int br_multicast_add_group(struct net_bridge *br, - - if (!port) { - mp->mglist = true; -- mod_timer(&mp->timer, now + br->multicast_membership_interval); - goto out; - } - -@@ -679,7 +675,7 @@ static int br_multicast_add_group(struct net_bridge *br, - (p = mlock_dereference(*pp, br)) != NULL; - pp = &p->next) { - if (p->port == port) -- goto found; -+ goto out; - if ((unsigned long)p->port < (unsigned long)port) - break; - } -@@ -690,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br, - rcu_assign_pointer(*pp, p); - br_mdb_notify(br->dev, port, group, RTM_NEWMDB); - --found: -- mod_timer(&p->timer, now + br->multicast_membership_interval); - out: - err = 0; - -@@ -1131,6 +1125,10 @@ static int br_ip4_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -+ setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); -+ mod_timer(&mp->timer, now + br->multicast_membership_interval); -+ mp->timer_armed = true; -+ - max_delay *= br->multicast_last_member_count; - - if (mp->mglist && -@@ -1205,6 +1203,10 @@ static int br_ip6_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -+ setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); -+ mod_timer(&mp->timer, now + br->multicast_membership_interval); -+ mp->timer_armed = true; -+ - max_delay *= br->multicast_last_member_count; - if (mp->mglist && - (timer_pending(&mp->timer) ? -@@ -1263,7 +1265,7 @@ static void br_multicast_leave_group(struct net_bridge *br, - call_rcu_bh(&p->rcu, br_multicast_free_pg); - br_mdb_notify(br->dev, port, group, RTM_DELMDB); - -- if (!mp->ports && !mp->mglist && -+ if (!mp->ports && !mp->mglist && mp->timer_armed && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - } -@@ -1275,30 +1277,12 @@ static void br_multicast_leave_group(struct net_bridge *br, - br->multicast_last_member_interval; - - if (!port) { -- if (mp->mglist && -+ if (mp->mglist && mp->timer_armed && - (timer_pending(&mp->timer) ? - time_after(mp->timer.expires, time) : - try_to_del_timer_sync(&mp->timer) >= 0)) { - mod_timer(&mp->timer, time); - } -- -- goto out; -- } -- -- for (p = mlock_dereference(mp->ports, br); -- p != NULL; -- p = mlock_dereference(p->next, br)) { -- if (p->port != port) -- continue; -- -- if (!hlist_unhashed(&p->mglist) && -- (timer_pending(&p->timer) ? -- time_after(p->timer.expires, time) : -- try_to_del_timer_sync(&p->timer) >= 0)) { -- mod_timer(&p->timer, time); -- } -- -- break; - } - - out: -@@ -1674,6 +1658,7 @@ void br_multicast_stop(struct net_bridge *br) - hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], - hlist[ver]) { - del_timer(&mp->timer); -+ mp->timer_armed = false; - call_rcu_bh(&mp->rcu, br_multicast_free_group); - } - } -diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h -index e260710..1b0ac95 100644 ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -112,6 +112,7 @@ struct net_bridge_mdb_entry - struct timer_list timer; - struct br_ip addr; - bool mglist; -+ bool timer_armed; - }; - - struct net_bridge_mdb_htable --- -cgit v0.9.2 diff --git a/bridge-send-query-as-soon-as-leave-is-received.patch b/bridge-send-query-as-soon-as-leave-is-received.patch deleted file mode 100644 index 8b6652e7e..000000000 --- a/bridge-send-query-as-soon-as-leave-is-received.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 6b7df111ece130fa979a0c4f58e53674c1e47d3e Mon Sep 17 00:00:00 2001 -From: Cong Wang -Date: Tue, 21 May 2013 21:52:56 +0000 -Subject: bridge: send query as soon as leave is received - -Continue sending queries when leave is received if the user marks -it as a querier. - -Cc: Herbert Xu -Cc: Stephen Hemminger -Cc: "David S. Miller" -Cc: Adam Baker -Signed-off-by: Cong Wang -Acked-by: Herbert Xu -Signed-off-by: David S. Miller ---- -(limited to 'net/bridge') - -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index 40bda80..37a4676 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -1250,6 +1250,32 @@ static void br_multicast_leave_group(struct net_bridge *br, - if (!mp) - goto out; - -+ if (br->multicast_querier && -+ !timer_pending(&br->multicast_querier_timer)) { -+ __br_multicast_send_query(br, port, &mp->addr); -+ -+ time = jiffies + br->multicast_last_member_count * -+ br->multicast_last_member_interval; -+ mod_timer(port ? &port->multicast_query_timer : -+ &br->multicast_query_timer, time); -+ -+ for (p = mlock_dereference(mp->ports, br); -+ p != NULL; -+ p = mlock_dereference(p->next, br)) { -+ if (p->port != port) -+ continue; -+ -+ if (!hlist_unhashed(&p->mglist) && -+ (timer_pending(&p->timer) ? -+ time_after(p->timer.expires, time) : -+ try_to_del_timer_sync(&p->timer) >= 0)) { -+ mod_timer(&p->timer, time); -+ } -+ -+ break; -+ } -+ } -+ - if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { - struct net_bridge_port_group __rcu **pp; - --- -cgit v0.9.2 diff --git a/bridge-timer-fix.patch b/bridge-timer-fix.patch deleted file mode 100644 index 888a6f009..000000000 --- a/bridge-timer-fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index d6448e3..aadb596 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -269,7 +269,7 @@ static void br_multicast_del_pg(struct net_bridge *br, - del_timer(&p->timer); - call_rcu_bh(&p->rcu, br_multicast_free_pg); - -- if (!mp->ports && !mp->mglist && -+ if (!mp->ports && !mp->mglist && mp->timer_armed && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - diff --git a/config-arm-generic b/config-arm-generic index 7aa5a852a..5000b5b5a 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -1,44 +1,103 @@ -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -# CONFIG_ARM_DT_BL_CPUFREQ is not set -CONFIG_ARM_GIC=y +CONFIG_KUSER_HELPERS=y # CONFIG_ASYMMETRIC_KEY_TYPE is not set -CONFIG_BACKLIGHT_PWM=m # CONFIG_COMMON_CLK_DEBUG is not set CONFIG_COMMON_CLK=y -CONFIG_DMA_OF=y -CONFIG_DTC=y CONFIG_EARLY_PRINTK=y -CONFIG_ETHERNET=y CONFIG_FB_SSD1307=m -CONFIG_GENERIC_GPIO=y -CONFIG_GPIOLIB=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_HW_PERF_EVENTS=y -# CONFIG_I2C_NOMADIK is not set -CONFIG_INPUT_PWM_BEEPER=m -# CONFIG_IRQ_DOMAIN_DEBUG is not set -# CONFIG_LEDS_RENESAS_TPU is not set -CONFIG_MMC_ARMMMCI=y -# CONFIG_MMC_SDHCI_PXAV2 is not set -# CONFIG_MMC_SDHCI_PXAV3 is not set CONFIG_MMC=y CONFIG_NFS_FS=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NO_HZ=y -CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -# CONFIG_OF_SELFTEST is not set -CONFIG_OF=y -CONFIG_PERF_EVENTS=y # CONFIG_PID_IN_CONTEXTIDR is not set CONFIG_PWM=y CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RTC_DRV_SNVS is not set +CONFIG_BACKLIGHT_PWM=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_ARM_SP805_WATCHDOG=m +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_DT_BL_CPUFREQ is not set +CONFIG_NR_CPUS=8 +CONFIG_ARM_DMA_USE_IOMMU=y + +# ARM AMBA generic HW +CONFIG_ARM_AMBA=y +CONFIG_ARM_GIC=y +CONFIG_MMC_ARMMMCI=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_OC_ETM=y + +# ARM VExpress +CONFIG_ARCH_VEXPRESS=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_COMMON_CLK_VERSATILE=y +CONFIG_I2C_VERSATILE=m +CONFIG_POWER_RESET_VEXPRESS=y +CONFIG_REGULATOR_VEXPRESS=m +CONFIG_SENSORS_VEXPRESS=m + +# Device tree +CONFIG_DTC=y +CONFIG_DMA_OF=y +CONFIG_PROC_DEVICETREE=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DEVICE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=m +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=m +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI_IRQ=m +CONFIG_OF_PCI=m +# CONFIG_OF_SELFTEST is not set +CONFIG_SERIAL_OF_PLATFORM=y + +# MTD +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_CFI=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_OF_PARTS=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_OF=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_OF_MTD=y + +# GPIO +CONFIG_GENERIC_GPIO=y +CONFIG_GPIOLIB=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_MDIO_GPIO=m +CONFIG_POWER_RESET_GPIO=y +CONFIG_RFKILL_GPIO=m + +# MFD +CONFIG_MFD_CORE=m + +CONFIG_SMC91X=m +CONFIG_SMC911X=m # CONFIG_CRYPTO_TEST is not set -CONFIG_KUSER_HELPERS=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_XEN is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_MMC_DW_SOCFPGA is not set +# CONFIG_ARM_SMMU is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_PCIEPORTBUS is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index ac240358f..143f647f5 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -607,3 +607,17 @@ CONFIG_COMMON_CLK_SI5351=m # CONFIG_SPI is not set CONFIG_FB_XGI=m + +# FIXME +# CONFIG_MACH_DB88F628X_BP_DT is not set +# CONFIG_MACH_SHEEVAPLUG_DT is not set +# CONFIG_PCI_MVEBU is not set +# CONFIG_NFC_NCI_SPI is not set +# CONFIG_ARM_CCI is not set +# CONFIG_AHCI_IMX is not set +# CONFIG_POWER_RESET_VEXPRESS is not set +# CONFIG_MFD_WM8997 is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_MMC_DW_SOCFPGA is not set diff --git a/config-armv7 b/config-armv7 index 1bbb3d524..5fb4e9380 100644 --- a/config-armv7 +++ b/config-armv7 @@ -1,21 +1,17 @@ # ARM unified arch kernel -# CONFIG_ARCH_BCM is not set -CONFIG_ARCH_HIGHBANK=y +# CONFIG_ARCH_EXYNOS_MULTI is not set +# CONFIG_ARCH_KEYSTONE is not set CONFIG_ARCH_MVEBU=y CONFIG_ARCH_MXC=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_ARCH_PICOXCELL=y -# CONFIG_ARCH_SIRF is not set +CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SOCFPGA=y -# CONFIG_PLAT_SPEAR is not set CONFIG_ARCH_SUNXI=y CONFIG_ARCH_TEGRA=y # CONFIG_ARCH_U8500 is not set -CONFIG_ARCH_VEXPRESS_CA9X4=y -CONFIG_ARCH_VEXPRESS=y # CONFIG_ARCH_VIRT is not set -# CONFIG_ARCH_WM8850 is not set CONFIG_ARCH_ZYNQ=y # These are supported in the LPAE kernel @@ -27,16 +23,7 @@ CONFIG_ARCH_ZYNQ=y # Generic CONFIG_REMOTEPROC=m -# highbank -# 2013/04/19 - stability issues -# CONFIG_CPU_IDLE_CALXEDA is not set -CONFIG_EDAC_HIGHBANK_MC=m -CONFIG_EDAC_HIGHBANK_L2=m -CONFIG_SATA_HIGHBANK=m -CONFIG_ARM_HIGHBANK_CPUFREQ=m - -# versatile -CONFIG_VEXPRESS_CONFIG=y +# FIXME should be generic (I think it's enabled by default) CONFIG_FB=y CONFIG_FB_ARMCLCD=m CONFIG_FB_CFB_COPYAREA=m @@ -45,13 +32,14 @@ CONFIG_FB_CFB_IMAGEBLIT=m CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_OC_ETM=y -CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y # mvebu CONFIG_MACH_ARMADA_370_XP=y CONFIG_MACH_ARMADA_370=y CONFIG_MACH_ARMADA_XP=y +CONFIG_MVEBU_DEVBUS=y +CONFIG_PCI_MVEBU=y CONFIG_CACHE_TAUROS2=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m @@ -86,6 +74,7 @@ CONFIG_SOC_OMAP5=y CONFIG_SOC_OMAP3430=y CONFIG_SOC_TI81XX=y CONFIG_SOC_AM33XX=y +CONFIG_SOC_AM43XX=y CONFIG_MACH_OMAP_GENERIC=y CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y @@ -111,8 +100,6 @@ CONFIG_MACH_SBC3530=y CONFIG_MACH_OMAP_3630SDP=y CONFIG_MACH_TI8168EVM=y CONFIG_MACH_TI8148EVM=y -CONFIG_MACH_OMAP_4430SDP=y -CONFIG_MACH_OMAP4_PANDA=y CONFIG_SOC_HAS_REALTIME_COUNTER=y CONFIG_OMAP_RESET_CLOCKS=y @@ -123,17 +110,23 @@ CONFIG_OMAP_32K_TIMER_HZ=128 # CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set CONFIG_OMAP_MCBSP=y +CONFIG_OMAP2PLUS_MBOX=m CONFIG_OMAP_MBOX_FWK=m CONFIG_OMAP_MBOX_KFIFO_SIZE=256 CONFIG_OMAP_DM_TIMER=y CONFIG_OMAP_PM_NOOP=y +CONFIG_DMA_OMAP=y CONFIG_OMAP_IOMMU=y CONFIG_OMAP_IOVMM=m +CONFIG_HWSPINLOCK_OMAP=m CONFIG_OMAP3_EMU=y # CONFIG_OMAP3_SDRC_AC_TIMING is not set -CONFIG_ARM_OMAP2PLUS_CPUFREQ=y +CONFIG_OMAP_WATCHDOG=m +CONFIG_TWL4030_WATCHDOG=m CONFIG_TI_ST=m +CONFIG_TI_EDMA=y +CONFIG_TI_SOC_THERMAL=m CONFIG_TI_DAC7512=m CONFIG_TI_DAVINCI_EMAC=m CONFIG_TI_DAVINCI_MDIO=m @@ -142,6 +135,7 @@ CONFIG_TI_CPSW=m CONFIG_TI_CPTS=y CONFIG_TI_EMIF=m CONFIG_MFD_TPS65217=m +CONFIG_REGULATOR_TI_ABB=y CONFIG_REGULATOR_TPS65217=m CONFIG_BACKLIGHT_TPS65217=m @@ -156,7 +150,6 @@ CONFIG_OMAP_WATCHDOG=m CONFIG_TWL4030_CORE=y CONFIG_TWL4030_MADC=m CONFIG_TWL4030_POWER=y -CONFIG_TWL4030_CODEC=y CONFIG_TWL4030_WATCHDOG=m CONFIG_TWL4030_USB=m CONFIG_TWL6030_USB=m @@ -172,8 +165,10 @@ CONFIG_HDQ_MASTER_OMAP=m CONFIG_REGULATOR_TWL4030=y CONFIG_BACKLIGHT_PANDORA=m CONFIG_OMAP_OCP2SCP=m -CONFIG_USB_EHCI_HCD_OMAP=y -CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_OMAP_USB2=m +CONFIG_OMAP_USB3=m +CONFIG_USB_EHCI_HCD_OMAP=m +CONFIG_USB_OHCI_HCD_PLATFORM=m CONFIG_USB_OHCI_HCD_OMAP3=y CONFIG_USB_MUSB_AM35X=m CONFIG_USB_MUSB_OMAP2PLUS=m @@ -182,17 +177,12 @@ CONFIG_USB_GADGET_MUSB_HDRC=m # CONFIG_MUSB_PIO_ONLY is not set # CONFIG_USB_MUSB_DEBUG is not set CONFIG_OMAP_CONTROL_USB=m -CONFIG_NOP_USB_XCEIV=m CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_RTC_DRV_MAX8907=m # CONFIG_RTC_DRV_TWL92330 is not set -CONFIG_RTC_DRV_TWL4030=m -CONFIG_RTC_DRV_OMAP=m -# Note needs to be compiled in until we build MMC modular -CONFIG_DMA_OMAP=y -CONFIG_OMAP_IOVMM=m -CONFIG_HWSPINLOCK_OMAP=m +CONFIG_RTC_DRV_TWL4030=y +CONFIG_RTC_DRV_OMAP=y CONFIG_SENSORS_TWL4030_MADC=m CONFIG_WL_TI=y @@ -206,9 +196,7 @@ CONFIG_WILINK_PLATFORM_DATA=y CONFIG_MFD_WL1273_CORE=m CONFIG_NFC_WILINK=m -CONFIG_MTD_NAND_OMAP2=y -CONFIG_MTD_NAND_OMAP_PREFETCH=y -CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y +CONFIG_MTD_NAND_OMAP2=m CONFIG_SPI_DAVINCI=m CONFIG_SPI_OMAP24XX=m CONFIG_MFD_TI_SSP=m @@ -245,8 +233,6 @@ CONFIG_HW_RANDOM_OMAP=m CONFIG_DRM_TILCDC=m CONFIG_DRM_OMAP=m CONFIG_DRM_OMAP_NUM_CRTCS=2 -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRAM_SIZE=0 CONFIG_OMAP2_VRFB=y # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set # CONFIG_FB_OMAP_LCD_VGA is not set @@ -278,6 +264,19 @@ CONFIG_PANEL_LGPHILIPS_LB035Q02=m CONFIG_PANEL_ACX565AKM=m # CONFIG_PANEL_N8X0 is not set +CONFIG_DISPLAY_ENCODER_TFP410=m +CONFIG_DISPLAY_ENCODER_TPD12S015=m +CONFIG_DISPLAY_CONNECTOR_DVI=m +CONFIG_DISPLAY_CONNECTOR_HDMI=m +CONFIG_DISPLAY_CONNECTOR_ANALOG_TV=m +CONFIG_DISPLAY_PANEL_DPI=m +CONFIG_DISPLAY_PANEL_DSI_CM=m +CONFIG_DISPLAY_PANEL_SONY_ACX565AKM=m +CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02=m +CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01=m +CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1=m +CONFIG_DISPLAY_PANEL_NEC_NL8048HL11=m + # Enable V4L2 drivers for OMAP2+ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y @@ -320,6 +319,7 @@ CONFIG_SND_SOC_TLV320AIC23=m CONFIG_SND_SOC_TLV320AIC3X=m CONFIG_SND_SOC_TWL4030=m CONFIG_SND_SOC_TWL6040=m +CONFIG_SND_SOC_PCM1792A=m CONFIG_RADIO_WL128X=m CONFIG_OMAP_REMOTEPROC=m @@ -341,40 +341,9 @@ CONFIG_OMAP_REMOTEPROC=m # Allwinner a1x CONFIG_PINCTRL_SUNXI=y -# CONFIG_SUNXI_RFKILL=y -# CONFIG_SUNXI_NAND=y -# CONFIG_SUNXI_DBGREG=m -# CONFIG_WEMAC_SUN4I=y -# CONFIG_KEYBOARD_SUN4IKEYPAD=m -# CONFIG_KEYBOARD_SUN4I_KEYBOARD=m -# CONFIG_IR_SUN4I=m -# CONFIG_TOUCHSCREEN_SUN4I_TS=m -# CONFIG_SUN4I_G2D=y -# CONFIG_I2C_SUN4I=y -# CONFIG_DRM_MALI=m -# CONFIG_MALI=m -# CONFIG_FB_SUNXI=m -# CONFIG_FB_SUNXI_UMP=y -# CONFIG_FB_SUNXI_LCD=m -# CONFIG_FB_SUNXI_HDMI=m -# CONFIG_SOUND_SUN4I=y -# CONFIG_SND_SUN4I_SOC_CODEC=y -# CONFIG_SND_SUN4I_SOC_HDMIAUDIO=y -# CONFIG_SND_SUN4I_SOC_SPDIF=m -# CONFIG_SND_SUN4I_SOC_I2S_INTERFACE=m -# CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_USB_SW_SUN4I_HCD=y -# CONFIG_USB_SW_SUN4I_HCD0=y -# CONFIG_USB_SW_SUN4I_HCI=y -# CONFIG_USB_SW_SUN4I_EHCI0=y -# CONFIG_USB_SW_SUN4I_EHCI1=y -# CONFIG_USB_SW_SUN4I_OHCI0=y -# CONFIG_USB_SW_SUN4I_OHCI1=y -# CONFIG_USB_SW_SUN4I_USB=y -# CONFIG_USB_SW_SUN4I_USB_MANAGER=y -# CONFIG_MMC_SUNXI_POWER_CONTROL=y -# CONFIG_MMC_SUNXI=y -# CONFIG_RTC_DRV_SUN4I=y +CONFIG_MDIO_SUN4I=m +CONFIG_NET_VENDOR_ALLWINNER=y +CONFIG_SUN4I_EMAC=m # imx CONFIG_MXC_IRQ_PRIOR=y @@ -384,7 +353,12 @@ CONFIG_MACH_IMX51_DT=y # CONFIG_MACH_EUKREA_CPUIMX51SD is not set CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y CONFIG_PATA_IMX=m +CONFIG_USB_CHIPIDEA=m +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +# CONFIG_USB_CHIPIDEA_DEBUG is not set CONFIG_NET_VENDOR_FREESCALE=y CONFIG_FEC=m CONFIG_KEYBOARD_IMX=m @@ -392,11 +366,23 @@ CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y CONFIG_I2C_IMX=m CONFIG_SPI_IMX=m +CONFIG_MFD_MC13783=m +CONFIG_MFD_MC13XXX_SPI=m CONFIG_W1_MASTER_MXC=m +CONFIG_IMX_WEIM=y CONFIG_IMX2_WDT=m +CONFIG_CRYPTO_DEV_SAHARA=m # CONFIG_FB_MX3 is not set CONFIG_SND_IMX_SOC=m +CONFIG_SND_SOC_FSL_SSI=m +CONFIG_SND_SOC_FSL_UTILS=m +CONFIG_SND_SOC_IMX_SSI=m +CONFIG_SND_SOC_IMX_AUDMUX=m +CONFIG_SND_SOC_IMX_PCM_FIQ=m +CONFIG_SND_SOC_IMX_PCM_DMA=m CONFIG_SND_SOC_IMX_SGTL5000=m +CONFIG_SND_SOC_IMX_WM8962=m +CONFIG_SND_SOC_IMX_MC13783=m CONFIG_USB_EHCI_MXC=m CONFIG_USB_IMX21_HCD=m CONFIG_USB_MXS_PHY=m @@ -409,16 +395,23 @@ CONFIG_RTC_DRV_MXC=m # CONFIG_MX3_IPU_IRQS is not set CONFIG_IMX_SDMA=m CONFIG_IMX_DMA=m +CONFIG_AHCI_IMX=m # CONFIG_MXS_DMA is not set CONFIG_PWM_IMX=m CONFIG_BACKLIGHT_PWM=m CONFIG_DRM_IMX=m CONFIG_DRM_IMX_FB_HELPER=m -CONFIG_DRM_IMX_PARALLEL_DISPLAY=m CONFIG_DRM_IMX_IPUV3_CORE=m CONFIG_DRM_IMX_IPUV3=m +# CONFIG_DRM_IMX_LDB is not set +CONFIG_DRM_IMX_PARALLEL_DISPLAY=m CONFIG_DRM_IMX_TVE=m CONFIG_VIDEO_CODA=m +CONFIG_SENSORS_MC13783_ADC=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_MC13892=m +CONFIG_LEDS_MC13783=m +CONFIG_RTC_DRV_MC13XXX=m CONFIG_INPUT_PWM_BEEPER=m CONFIG_INPUT_88PM80X_ONKEY=m @@ -467,11 +460,18 @@ CONFIG_AB8500_BM=y CONFIG_AB8500_GPADC=y CONFIG_SENSORS_AB8500=m CONFIG_STE_MODEM_RPROC=m +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m +CONFIG_UX500_WATCHDOG=m # tegra CONFIG_ARCH_TEGRA_2x_SOC=y CONFIG_ARCH_TEGRA_3x_SOC=y # CONFIG_ARCH_TEGRA_114_SOC is not set +CONFIG_ARM_TEGRA_CPUFREQ=y +CONFIG_TEGRA20_MC=y +CONFIG_TEGRA30_MC=y CONFIG_SERIAL_TEGRA=y @@ -494,18 +494,19 @@ CONFIG_KEYBOARD_TEGRA=m CONFIG_PINCTRL_TEGRA=y CONFIG_PINCTRL_TEGRA20=y CONFIG_PINCTRL_TEGRA30=y -CONFIG_USB_EHCI_TEGRA=y -CONFIG_RTC_DRV_TEGRA=y +CONFIG_USB_EHCI_TEGRA=m +CONFIG_RTC_DRV_TEGRA=m CONFIG_SND_SOC_TEGRA=m CONFIG_SND_SOC_TEGRA_ALC5632=m +CONFIG_SND_SOC_TEGRA_RT5640=m +CONFIG_SND_SOC_TEGRA_TRIMSLICE=m CONFIG_SND_SOC_TEGRA_WM8753=m CONFIG_SND_SOC_TEGRA_WM8903=m CONFIG_SND_SOC_TEGRA_WM9712=m -CONFIG_SND_SOC_TEGRA_TRIMSLICE=m +CONFIG_SND_SOC_TEGRA20_AC97=m CONFIG_SND_SOC_TEGRA30_AHUB=m CONFIG_SND_SOC_TEGRA30_I2S=m -CONFIG_SND_SOC_TEGRA20_AC97=m # AC100 (PAZ00) CONFIG_MFD_NVEC=y @@ -534,8 +535,21 @@ CONFIG_CRYPTO_DEV_TEGRA_AES=m CONFIG_LEDS_RENESAS_TPU=y -# ZYNQ +# OLPC XO +CONFIG_SERIO_OLPC_APSP=m + +# Zynq-7xxx +# likely needs usb/mmc still +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_COMMON_CLK_AXI_CLKGEN=m +CONFIG_CPU_IDLE_ZYNQ=y CONFIG_LATTICE_ECP3_CONFIG=m +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=m +CONFIG_GPIO_XILINX=y +CONFIG_I2C_XILINX=m +CONFIG_SPI_XILINX=m # MMC/SD CONFIG_MMC_TMIO=m @@ -543,8 +557,6 @@ CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m # Multi function devices -CONFIG_MFD_CORE=m -CONFIG_MFD_SYSCON=y CONFIG_MFD_88PM800=m CONFIG_MFD_88PM805=m CONFIG_MFD_T7L66XB=y @@ -575,12 +587,39 @@ CONFIG_REGULATOR_MAX8907=m CONFIG_REGULATOR_LP872X=y CONFIG_REGULATOR_LP8755=m +# usb gadget +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_VBUS_DRAW=100 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_RENESAS_USBHS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +# CONFIG_USB_GADGET_VBUS_DRAW is not set +# CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_ETH_RNDIS is not set +# CONFIG_USB_ETH_EEM is not set + # Needs work/investigation # CONFIG_ARM_CHARLCD is not set # CONFIG_MTD_AFS_PARTS is not set # CONFIG_IP_PNP_RARP is not set -# CONFIG_ASYMMETRIC_KEY_TYPE is not set # CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_DEPRECATED_PARAM_STRUCT is not set @@ -588,10 +627,6 @@ CONFIG_REGULATOR_LP8755=m # Defined config options we don't use yet # CONFIG_PINCTRL_IMX35 is not set -# CONFIG_DRM_IMX_FB_HELPER is not set -# CONFIG_DRM_IMX_PARALLEL_DISPLAY is not set -# CONFIG_DRM_IMX_IPUV3_CORE is not set -# CONFIG_DRM_IMX_IPUV3 is not set # CONFIG_REGULATOR_ANATOP is not set # CONFIG_BATTERY_RX51 is not set @@ -619,8 +654,6 @@ CONFIG_REGULATOR_LP8755=m # CONFIG_PMIC_ADP5520 is not set # CONFIG_REGULATOR_LP3972 is not set # CONFIG_REGULATOR_LP872X is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_DVB_USB_PCTV452E is not set # We need to fix these as they should be either generic includes or kconfig fixes @@ -637,3 +670,9 @@ CONFIG_REGULATOR_LP8755=m # CONFIG_DRM_TEGRA_DEBUG is not set # CONFIG_CRYPTO_DEV_UX500_DEBUG is not set # CONFIG_AB8500_DEBUG is not set + +# CONFIG_SOC_VF610 is not set +# CONFIG_ARM_CCI is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_SERIAL_UARTLITE is not set + diff --git a/config-armv7-generic b/config-armv7-generic index 897a7e3ee..663f86b82 100644 --- a/config-armv7-generic +++ b/config-armv7-generic @@ -46,6 +46,25 @@ CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y # CONFIG_XIP_KERNEL is not set # CONFIG_ARM_VIRT_EXT is not set +# Platforms enabled/disabled globally on ARMv7 +CONFIG_ARCH_HIGHBANK=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y +# CONFIG_ARCH_BCM is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_WM8850 is not set + +# highbank +# 2013/04/19 - stability issues +# CONFIG_CPU_IDLE_CALXEDA is not set +CONFIG_EDAC_HIGHBANK_MC=m +CONFIG_EDAC_HIGHBANK_L2=m +CONFIG_SATA_HIGHBANK=m +CONFIG_ARM_HIGHBANK_CPUFREQ=m + # errata # v5/v6 # CONFIG_ARM_ERRATA_326103 is not set @@ -76,8 +95,6 @@ CONFIG_PJ4B_ERRATA_4742=y # CONFIG_ARM_ERRATA_798181 is not set # generic that deviates from or should be merged into config-generic -CONFIG_SMP=y -CONFIG_NR_CPUS=8 CONFIG_SMP_ON_UP=y CONFIG_HIGHMEM=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -98,15 +115,8 @@ CONFIG_RCU_FANOUT=32 CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_LSM_MMAP_MIN_ADDR=32768 -CONFIG_SECCOMP=y -CONFIG_STRICT_DEVMEM=y - CONFIG_XZ_DEC_ARM=y -CONFIG_OC_ETM=y -CONFIG_PM=y -CONFIG_PM_STD_PARTITION="" -CONFIG_SUSPEND=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_LOCAL_TIMERS=y @@ -119,7 +129,6 @@ CONFIG_IP_PNP_BOOTP=y # Root as NFS, different from mainline CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y CONFIG_LBDAF=y @@ -127,15 +136,7 @@ CONFIG_LBDAF=y CONFIG_USE_OF=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_ARM_APPENDED_DTB=y -CONFIG_PROC_DEVICETREE=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y CONFIG_I2C_MUX_PINCTRL=m -CONFIG_OF_MDIO=m - -CONFIG_OF_DISPLAY_TIMING=y -CONFIG_OF_VIDEOMODE=y # General vexpress ARM drivers CONFIG_ARM_TIMER_SP804=y @@ -152,11 +153,8 @@ CONFIG_RTC_DRV_PL031=y CONFIG_PL330_DMA=m CONFIG_AMBA_PL08X=y CONFIG_ARM_SP805_WATCHDOG=m -CONFIG_I2C_VERSATILE=m CONFIG_GPIO_PL061=y -CONFIG_SENSORS_VEXPRESS=m CONFIG_FB_ARMCLCD=m -CONFIG_REGULATOR_VEXPRESS=m # usb CONFIG_USB_OTG=y @@ -165,9 +163,6 @@ CONFIG_USB_OTG=y CONFIG_USB_ULPI=y CONFIG_AX88796=m CONFIG_AX88796_93CX6=y -CONFIG_SMC91X=m -CONFIG_SMC911X=m -CONFIG_SMSC911X=m CONFIG_USB_ISP1760_HCD=m # CONFIG_USB_EHCI_HCD_ORION is not set @@ -183,7 +178,7 @@ CONFIG_MFD_TPS65912_SPI=y CONFIG_PINMUX=y CONFIG_PINCONF=y CONFIG_PINCTRL=y -CONFIG_PINCTRL_SINGLE=m +CONFIG_PINCTRL_SINGLE=y # CONFIG_PINCTRL_SAMSUNG is not set # CONFIG_PINCTRL_EXYNOS4 is not set @@ -194,7 +189,6 @@ CONFIG_EXTCON_GPIO=m CONFIG_GPIO_ADNP=m CONFIG_GPIO_MCP23S08=m CONFIG_POWER_RESET_GPIO=y -CONFIG_RFKILL_GPIO=m CONFIG_SERIAL_8250_EM=m CONFIG_INPUT_GPIO_TILT_POLLED=m CONFIG_MDIO_BUS_MUX_GPIO=m @@ -226,6 +220,8 @@ CONFIG_SPI_DESIGNWARE=m CONFIG_SPI_TLE62X0=m # CONFIG_SPI_FSL_SPI is not set +CONFIG_NFC_NCI_SPI=y + # HW crypto and rng CONFIG_CRYPTO_SHA1_ARM=m CONFIG_CRYPTO_AES_ARM=m @@ -244,7 +240,6 @@ CONFIG_POWER_RESET_RESTART=y CONFIG_ARM_PSCI=y # MTD -CONFIG_MTD_OF_PARTS=y # CONFIG_MG_DISK is not set CONFIG_MTD_DATAFLASH=m CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y @@ -256,13 +251,20 @@ CONFIG_EEPROM_93XX46=m # MMC/SD CONFIG_MMC_SPI=m + +# Designware (used by numerous devices) CONFIG_MMC_DW=m CONFIG_MMC_DW_PLTFM=m CONFIG_MMC_DW_PCI=m CONFIG_SPI_DW_MMIO=m CONFIG_SPI_DW_PCI=m +CONFIG_MMC_DW_SOCFPGA=m # CONFIG_MMC_DW_EXYNOS is not set # CONFIG_MMC_DW_IDMAC is not set +CONFIG_USB_DWC2=m +CONFIG_USB_DWC3=m +# CONFIG_USB_DWC3_DEBUG is not set +CONFIG_DW_WATCHDOG=m # Sound CONFIG_SND_ARM=y @@ -401,7 +403,6 @@ CONFIG_UBIFS_FS_ZLIB=y # Should be in generic CONFIG_BPF_JIT=y -# CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_MICROCHIP is not set @@ -410,6 +411,7 @@ CONFIG_BPF_JIT=y # CONFIG_DRM_EXYNOS is not set # CONFIG_DRM_TILCDC is not set # CONFIG_DRM_IMX is not set +# CONFIG_AHCI_IMX is not set # CONFIG_CS89x0 is not set # CONFIG_DM9000 is not set # CONFIG_HW_RANDOM_ATMEL is not set @@ -429,7 +431,6 @@ CONFIG_BPF_JIT=y # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set # CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_AXI_CLKGEN is not set # CONFIG_SPI_TOPCLIFF_PCH is not set # CONFIG_SPI_PXA2XX is not set @@ -455,3 +456,6 @@ CONFIG_BPF_JIT=y # CONFIG_DEBUG_LL is not set # CONFIG_DEBUG_PINCTRL is not set # CONFIG_ARM_DT_BL_CPUFREQ is not set + +# FIX ME +# CONFIG_FB_XILINX is not set diff --git a/config-debug b/config-debug index e7f7ce147..fb7df3e38 100644 --- a/config-debug +++ b/config-debug @@ -5,6 +5,7 @@ CONFIG_SND_PCM_XRUN_DEBUG=y CONFIG_DEBUG_ATOMIC_SLEEP=y CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y @@ -64,6 +65,8 @@ CONFIG_DEBUG_CREDENTIALS=y CONFIG_EXT4_DEBUG=y +CONFIG_XFS_WARN=y + CONFIG_DEBUG_PERF_USE_VMALLOC=y # off in both production debug and nodebug builds, @@ -82,6 +85,8 @@ CONFIG_ATH_DEBUG=y CONFIG_CARL9170_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_TRACING=y +CONFIG_RTLWIFI_DEBUG=y + CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DMADEVICES_DEBUG=y @@ -100,6 +105,7 @@ CONFIG_KDB_CONTINUE_CATASTROPHIC=0 CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y +CONFIG_TEST_STRING_HELPERS=m CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 @@ -115,9 +121,7 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y CONFIG_MAC80211_MESSAGE_TRACING=y CONFIG_EDAC_DEBUG=y + +CONFIG_X86_DEBUG_STATIC_CPU_HAS=y CONFIG_LATENCYTOP=y CONFIG_SCHEDSTATS=y - -CONFIG_TEST_STRING_HELPERS=m -CONFIG_XFS_WARN=y - diff --git a/config-generic b/config-generic index e80eb3172..3e29d7f02 100644 --- a/config-generic +++ b/config-generic @@ -35,6 +35,7 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_COMPILE_TEST is not set CONFIG_FHANDLE=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y @@ -67,6 +68,7 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_SLUB=y +CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SLUB_STATS is not set # CONFIG_AD525X_DPOT is not set @@ -101,6 +103,9 @@ CONFIG_PCIEAER_INJECT=m CONFIG_HOTPLUG_PCI_PCIE=y CONFIG_HOTPLUG_PCI_FAKE=m +# CONFIG_SGI_IOC4 is not set +# + # CONFIG_ISA is not set # CONFIG_SCx200 is not set @@ -156,6 +161,7 @@ CONFIG_INFINIBAND_USER_MAD=m CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_INFINIBAND_IPATH=m CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_ISERT=m CONFIG_INFINIBAND_AMSO1100=m # CONFIG_INFINIBAND_AMSO1100_DEBUG is not set CONFIG_INFINIBAND_CXGB3=m @@ -164,9 +170,11 @@ CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_SCSI_CXGB4_ISCSI=m # CONFIG_INFINIBAND_CXGB3_DEBUG is not set CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m CONFIG_INFINIBAND_NES=m # CONFIG_INFINIBAND_NES_DEBUG is not set CONFIG_INFINIBAND_QIB=m +CONFIG_INFINIBAND_QIB_DCA=y # CONFIG_INFINIBAND_OCRDMA is not set # @@ -175,6 +183,7 @@ CONFIG_INFINIBAND_QIB=m CONFIG_BINFMT_ELF=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y # CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_SCRIPT=y CONFIG_BINFMT_MISC=m # @@ -298,6 +307,7 @@ CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y CONFIG_BLK_DEV_DAC960=m +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y @@ -337,6 +347,7 @@ CONFIG_HW_RANDOM_VIRTIO=m CONFIG_VIRTIO_CONSOLE=y CONFIG_VHOST_NET=m CONFIG_TCM_VHOST=m +CONFIG_VHOST_SCSI=m # # SCSI device support @@ -434,6 +445,7 @@ CONFIG_SCSI_MPT3SAS_LOGGING=y CONFIG_SCSI_UFSHCD=m CONFIG_SCSI_UFSHCD_PCI=m +# CONFIG_SCSI_UFSHCD_PLATFORM is not set CONFIG_SCSI_MVUMI=m @@ -510,6 +522,7 @@ CONFIG_SATA_NV=m CONFIG_SATA_PMP=y CONFIG_SATA_PROMISE=m CONFIG_SATA_QSTOR=m +CONFIG_SATA_RCAR=m CONFIG_SATA_SIL=m CONFIG_SATA_SIL24=m CONFIG_SATA_SIS=m @@ -587,6 +600,12 @@ CONFIG_MD_RAID10=m CONFIG_MD_RAID456=m # CONFIG_MULTICORE_RAID456 is not set CONFIG_ASYNC_RAID6_TEST=m + +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_EDEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set + CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m CONFIG_DM_DEBUG=y @@ -608,6 +627,7 @@ CONFIG_DM_MULTIPATH_ST=m CONFIG_DM_RAID=m CONFIG_DM_FLAKEY=m CONFIG_DM_VERITY=m +CONFIG_DM_SWITCH=m # # Fusion MPT device support @@ -654,6 +674,9 @@ CONFIG_NET=y CONFIG_NET_DMA=y +CONFIG_NETLINK_MMAP=y +CONFIG_NETLINK_DIAG=m + CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_CONG_BIC=m CONFIG_TCP_CONG_CUBIC=y @@ -1039,6 +1062,7 @@ CONFIG_IP_DCCP_CCID3=y # CONFIG_TIPC=m CONFIG_TIPC_PORTS=8192 +# CONFIG_TIPC_MEDIA_IB is not set # CONFIG_TIPC_ADVANCED is not set # CONFIG_TIPC_DEBUG is not set @@ -1109,8 +1133,10 @@ CONFIG_DNS_RESOLVER=m CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=y +CONFIG_BATMAN_ADV_NC=y # CONFIG_BATMAN_ADV_DEBUG is not set CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=y CONFIG_VSOCKETS=m CONFIG_NETPRIO_CGROUP=m @@ -1135,6 +1161,7 @@ CONFIG_NET_TEAM_MODE_ROUNDROBIN=m CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_RANDOM=m CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m @@ -1143,6 +1170,7 @@ CONFIG_VXLAN=m CONFIG_EQUALIZER=m CONFIG_TUN=m CONFIG_VETH=m +CONFIG_NLMON=m # # ATM @@ -1199,6 +1227,8 @@ CONFIG_L2TP_ETH=m CONFIG_RFKILL=m CONFIG_RFKILL_INPUT=y +CONFIG_ETHERNET=y + # # Ethernet (10 or 100Mbit) # @@ -1215,7 +1245,11 @@ CONFIG_PCNET32=m CONFIG_AMD8111_ETH=m CONFIG_PCMCIA_NMCLAN=m +CONFIG_NET_VENDOR_ARC=y +CONFIG_ARC_EMAC=m + CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ALX=m CONFIG_ATL2=m CONFIG_ATL1=m CONFIG_ATL1C=m @@ -1334,6 +1368,7 @@ CONFIG_YELLOWFIN=m CONFIG_NET_VENDOR_QLOGIC=y CONFIG_QLA3XXX=m CONFIG_QLCNIC=m +CONFIG_QLCNIC_SRIOV=y CONFIG_QLGE=m CONFIG_NETXEN_NIC=m @@ -1347,6 +1382,8 @@ CONFIG_8139TOO_8129=y # CONFIG_8139_OLD_RX_RESET is not set CONFIG_R8169=m +CONFIG_SH_ETH=m + CONFIG_NET_VENDOR_RDC=y CONFIG_R6040=m @@ -1362,6 +1399,7 @@ CONFIG_SIS190=m CONFIG_NET_VENDOR_SMSC=y CONFIG_PCMCIA_SMC91C92=m CONFIG_EPIC100=m +CONFIG_SMSC911X=m CONFIG_SMSC9420=m CONFIG_NET_VENDOR_STMICRO=y @@ -1420,6 +1458,7 @@ CONFIG_VITESSE_PHY=m CONFIG_MICREL_PHY=m CONFIG_MII=m +CONFIG_NET_CORE=y CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=m CONFIG_TYPHOON=m @@ -1524,6 +1563,7 @@ CONFIG_ATH6KL=m CONFIG_ATH6KL_DEBUG=y CONFIG_ATH6KL_SDIO=m CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_TRACING is not set CONFIG_AR5523=m CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y @@ -1534,9 +1574,15 @@ CONFIG_ATH9K_DEBUGFS=y CONFIG_ATH9K_HTC=m CONFIG_ATH9K_BTCOEX_SUPPORT=y # CONFIG_ATH9K_HTC_DEBUGFS is not set -CONFIG_ATH9K_LEGACY_RATE_CONTROL=y +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set +CONFIG_ATH10K=m +CONFIG_ATH10K_PCI=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_TRACING is not set +CONFIG_ATH10K_DEBUGFS=y CONFIG_WIL6210=m CONFIG_WIL6210_ISR_COR=y +# CONFIG_WIL6210_TRACING is not set CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y # CONFIG_CARL9170_HWRNG is not set @@ -1544,6 +1590,7 @@ CONFIG_AT76C50X_USB=m # CONFIG_AIRO is not set # CONFIG_AIRO_CS is not set # CONFIG_ATMEL is not set +CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y @@ -1580,6 +1627,9 @@ CONFIG_PCMCIA_HERMES=m CONFIG_ORINOCO_USB=m # CONFIG_TMD_HERMES is not set # CONFIG_PCMCIA_SPECTRUM is not set +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m # CONFIG_HOSTAP is not set # CONFIG_IPW2100 is not set # CONFIG_IPW2200 is not set @@ -1628,6 +1678,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800PCI=m CONFIG_RT2800PCI_RT3290=y @@ -1657,13 +1708,14 @@ CONFIG_WL1251=m CONFIG_WL1251_SPI=m CONFIG_WL1251_SDIO=m +CONFIG_RTL_CARDS=m CONFIG_RTLWIFI=m -# CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m CONFIG_RTL8192DE=m CONFIG_RTL8723AE=m +CONFIG_RTL8188EE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -1715,6 +1767,7 @@ CONFIG_NFC_NCI=m CONFIG_NFC_HCI=m CONFIG_NFC_SHDLC=y CONFIG_NFC_LLCP=y +CONFIG_NFC_SIM=m # # Near Field Communication (NFC) devices @@ -1959,6 +2012,7 @@ CONFIG_INPUT_POLLDEV=m CONFIG_INPUT_SPARSEKMAP=m # CONFIG_INPUT_ADXL34X is not set # CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_IMS_PCU is not set CONFIG_INPUT_CMA3000=m CONFIG_INPUT_CMA3000_I2C=m @@ -1977,8 +2031,10 @@ CONFIG_SERIO_RAW=m CONFIG_SERIO_ALTERA_PS2=m # CONFIG_SERIO_PS2MULT is not set CONFIG_SERIO_ARC_PS2=m +# CONFIG_SERIO_APBPS2 is not set # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_OLPC_APSP is not set # CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set @@ -2056,6 +2112,7 @@ CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_AD7879_I2C=m # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set CONFIG_TOUCHSCREEN_DYNAPRO=m CONFIG_TOUCHSCREEN_EDT_FT5X06=m CONFIG_TOUCHSCREEN_EETI=m @@ -2130,6 +2187,7 @@ CONFIG_N_HDLC=m CONFIG_N_GSM=m # CONFIG_TRACE_SINK is not set # CONFIG_STALDRV is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set CONFIG_TIFM_CORE=m CONFIG_TIFM_7XX1=m @@ -2264,6 +2322,7 @@ CONFIG_SENSORS_ADM1026=m CONFIG_SENSORS_ADM1029=m CONFIG_SENSORS_ADM1031=m CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7310=m CONFIG_SENSORS_ADT7410=m CONFIG_SENSORS_ADS7828=m CONFIG_SENSORS_ADT7462=m @@ -2281,6 +2340,7 @@ CONFIG_SENSORS_F71882FG=m CONFIG_SENSORS_F75375S=m CONFIG_SENSORS_FSCHMD=m CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_G762=m CONFIG_SENSORS_GL518SM=m CONFIG_SENSORS_GL520SM=m CONFIG_SENSORS_HDAPS=m @@ -2305,11 +2365,13 @@ CONFIG_SENSORS_LM87=m CONFIG_SENSORS_LM90=m CONFIG_SENSORS_LM92=m CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95234=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m CONFIG_SENSORS_MAX6697=m CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_NCT6775=m CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m @@ -2394,9 +2456,11 @@ CONFIG_SENSORS_MAX197=m # CONFIG_PCH_PHUB is not set # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set CONFIG_SERIAL_ARC=m CONFIG_SERIAL_ARC_NR_PORTS=1 # CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set CONFIG_W1=m CONFIG_W1_CON=y @@ -2408,6 +2472,7 @@ CONFIG_W1_MASTER_DS1WM=m CONFIG_W1_SLAVE_THERM=m CONFIG_W1_SLAVE_SMEM=m CONFIG_W1_SLAVE_DS2408=m +# CONFIG_W1_SLAVE_DS2408_READBACK is not set CONFIG_W1_SLAVE_DS2413=m CONFIG_W1_SLAVE_DS2423=m CONFIG_W1_SLAVE_DS2431=m @@ -2474,6 +2539,7 @@ CONFIG_WM831X_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_DW_WATCHDOG is not set CONFIG_W83697UG_WDT=m +# CONFIG_MEN_A21_WDT is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m @@ -2505,6 +2571,7 @@ CONFIG_RTC_DRV_M41T80_WDT=y CONFIG_RTC_DRV_M48T59=m CONFIG_RTC_DRV_MAX6900=m # CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_PCF2127=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m CONFIG_RTC_DRV_RS5C372=m @@ -2698,6 +2765,7 @@ CONFIG_VIDEO_TLG2300=m # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set # CONFIG_EXYNOS_VIDEO is not set +CONFIG_VIDEO_USBTV=m CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y @@ -2742,6 +2810,7 @@ CONFIG_DVB_BUDGET_CORE=m CONFIG_DVB_PLUTO2=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set CONFIG_MEDIA_SUBDRV_AUTOSELECT=y CONFIG_SMS_USB_DRV=m CONFIG_SMS_SDIO_DRV=m @@ -2918,6 +2987,7 @@ CONFIG_FB_I810_I2C=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIMPLE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_SM501 is not set # CONFIG_FB_SMSCUFX is not set @@ -2987,6 +3057,7 @@ CONFIG_SND_PCM_OSS=y CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_RTCTIMER=y CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 # CONFIG_SND_SUPPORT_OLD_API is not set # @@ -3062,6 +3133,7 @@ CONFIG_SND_HDA_CODEC_CONEXANT=y CONFIG_SND_HDA_CODEC_CMEDIA=y CONFIG_SND_HDA_CODEC_SI3054=y CONFIG_SND_HDA_CODEC_HDMI=y +CONFIG_SND_HDA_I915=y CONFIG_SND_HDA_CODEC_CA0132=y CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=y @@ -3109,6 +3181,7 @@ CONFIG_SND_USB_USX2Y=m CONFIG_SND_USB_US122L=m CONFIG_SND_USB_UA101=m CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m # # PCMCIA devices @@ -3143,6 +3216,7 @@ CONFIG_USB_SUPPORT=y # Deprecated. # CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set CONFIG_USB_SUSPEND=y @@ -3155,6 +3229,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_EHCI_MV is not set # CONFIG_USB_EHCI_HCD_PLATFORM is not set CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_UHCI_HCD=y @@ -3165,6 +3240,7 @@ CONFIG_USB_SL811_HCD_ISO=y CONFIG_USB_XHCI_HCD=y # CONFIG_USB_XHCI_HCD_DEBUGGING is not set CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_FUSBH200_HCD=m # # USB Device Class drivers @@ -3256,9 +3332,10 @@ CONFIG_HID_THINGM=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m -# CONFIG_HID_SENSOR_HUB is not set +CONFIG_HID_SENSOR_HUB=m CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m CONFIG_HID_UCLOGIC=m CONFIG_HID_WALTOP=m CONFIG_HID_ROCCAT_PYRA=m @@ -3273,6 +3350,7 @@ CONFIG_HID_ROCCAT_ISKU=m CONFIG_HID_ROCCAT_KOVAPLUS=m CONFIG_HID_HOLTEK=m CONFIG_HOLTEK_FF=y +CONFIG_HID_HUION=m CONFIG_HID_SPEEDLINK=m CONFIG_HID_WIIMOTE=m CONFIG_HID_WIIMOTE_EXT=y @@ -3281,6 +3359,7 @@ CONFIG_HID_SAITEK=m CONFIG_HID_TIVO=m CONFIG_HID_GENERIC=y CONFIG_HID_AUREAL=m +CONFIG_HID_APPLEIR=m # @@ -3358,6 +3437,7 @@ CONFIG_USB_HSO=m CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_NET_AX8817X=m @@ -3450,6 +3530,7 @@ CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_SERIAL_MOS7720=m CONFIG_USB_SERIAL_MOS7715_PARPORT=y # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_MOTOROLA=m @@ -3475,7 +3556,8 @@ CONFIG_USB_SERIAL_XSENS_MT=m CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m CONFIG_USB_SERIAL_QT2=m - +CONFIG_USB_SERIAL_FLASHLOADER=m +CONFIG_USB_SERIAL_SUUNTO=m CONFIG_USB_SERIAL_CONSOLE=y CONFIG_USB_EZUSB=y @@ -3492,9 +3574,16 @@ CONFIG_USB_ADUTUX=m CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m + +# Physical Layer USB driver +CONFIG_USB_PHY=y + # CONFIG_OMAP_USB2 is not set # CONFIG_OMAP_USB3 is not set # CONFIG_OMAP_CONTROL_USB is not set +# CONFIG_SAMSUNG_USBPHY is not set +# CONFIG_SAMSUNG_USB2PHY is not set +# CONFIG_SAMSUNG_USB3PHY is not set CONFIG_USB_RCAR_PHY=m CONFIG_USB_ATM=m CONFIG_USB_CXACRU=m @@ -3542,6 +3631,8 @@ CONFIG_USB_UEAGLEATM=m CONFIG_USB_XUSBATM=m CONFIG_USB_ZERO=m +# CONFIG_USB_DWC2 is not set + CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # CONFIG_USB_ISP1301 is not set @@ -3595,6 +3686,7 @@ CONFIG_MFD_VIPERBOARD=m # CONFIG_ABX500_CORE is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_CS5535 is not set # CONFIG_MFD_STMPE is not set @@ -3607,6 +3699,10 @@ CONFIG_MFD_VIPERBOARD=m # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_ARIZONA is not set # CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_SYSCON is not set # # File systems @@ -3735,6 +3831,7 @@ CONFIG_UFS_FS=m CONFIG_9P_FS=m CONFIG_9P_FSCACHE=y CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y CONFIG_FUSE_FS=m # CONFIG_OMFS_FS is not set CONFIG_CUSE=m @@ -3749,13 +3846,15 @@ CONFIG_NFS_V2=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y -# CONFIG_NFS_SWAP is not set +CONFIG_NFS_SWAP=y CONFIG_NFS_V4_1=y CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" +CONFIG_NFS_V4_2=y CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y +CONFIG_NFSD_V4_SECURITY_LABEL=y CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_LEGACY_DNS is not set CONFIG_PNFS_OBJLAYOUT=m @@ -3806,6 +3905,8 @@ CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y # Maybe see if we want this on for debug kernels? # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set CONFIG_CONFIGFS_FS=y @@ -3825,6 +3926,7 @@ CONFIG_UBIFS_FS_XATTR=y # CONFIG_PARTITION_ADVANCED=y # CONFIG_ACORN_PARTITION is not set +CONFIG_AIX_PARTITION=y CONFIG_AMIGA_PARTITION=y # CONFIG_ATARI_PARTITION is not set CONFIG_BSD_DISKLABEL=y @@ -4002,6 +4104,11 @@ CONFIG_AUDITSYSCALL=y # http://lists.fedoraproject.org/pipermail/kernel/2013-February/004125.html CONFIG_AUDIT_LOGINUID_IMMUTABLE=y +CONFIG_SECCOMP=y +CONFIG_STRICT_DEVMEM=y + +# CONFIG_SSBI is not set + # # Cryptographic options # @@ -4035,10 +4142,13 @@ CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_FCRYPT=m CONFIG_CRYPTO_GCM=m CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_CMAC=m CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_MICHAEL_MIC=m @@ -4097,6 +4207,8 @@ CONFIG_ZLIB_DEFLATE=m CONFIG_INITRAMFS_SOURCE="" CONFIG_KEYS=y +CONFIG_PERSISTENT_KEYRINGS=y +CONFIG_BIG_KEYS=m CONFIG_TRUSTED_KEYS=m CONFIG_ENCRYPTED_KEYS=m CONFIG_KEYS_DEBUG_PROC_KEYS=y @@ -4183,6 +4295,8 @@ CONFIG_PROC_EVENTS=y CONFIG_IBMASR=m +CONFIG_PM=y +CONFIG_PM_STD_PARTITION="" CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y CONFIG_PM_TRACE_RTC=y @@ -4191,6 +4305,9 @@ CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set # CONFIG_PM_AUTOSLEEP is not set # CONFIG_PM_WAKELOCKS is not set +CONFIG_HIBERNATION=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_SUSPEND=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y @@ -4248,6 +4365,7 @@ CONFIG_SND_INDIGODJX=m CONFIG_BALLOON_COMPACTION=y CONFIG_COMPACTION=y CONFIG_MIGRATION=y +CONFIG_BOUNCE=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y # CONFIG_LEDS_AMS_DELTA is not set @@ -4273,6 +4391,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=m # CONFIG_LEDS_TRIGGER_CPU is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m CONFIG_LEDS_ALIX2=m CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m @@ -4283,6 +4402,7 @@ CONFIG_LEDS_BLINKM=m CONFIG_LEDS_LP3944=m CONFIG_LEDS_LP5521=m CONFIG_LEDS_LP5523=m +CONFIG_LEDS_LP5562=m CONFIG_LEDS_LT3593=m CONFIG_LEDS_REGULATOR=m CONFIG_LEDS_TRIGGER_GPIO=m @@ -4291,7 +4411,9 @@ CONFIG_LEDS_WM831X_STATUS=m CONFIG_DMADEVICES=y CONFIG_DMA_ENGINE=y +CONFIG_DW_DMAC_CORE=m CONFIG_DW_DMAC=m +CONFIG_DW_DMAC_PCI=m # CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set # CONFIG_TIMB_DMA is not set # CONFIG_DMATEST is not set @@ -4307,12 +4429,14 @@ CONFIG_DYNAMIC_FTRACE=y CONFIG_SCHED_TRACER=y CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_TRACER_SNAPSHOT=y +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set CONFIG_FTRACE_SYSCALLS=y CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_TRACE_BRANCH_PROFILING is not set CONFIG_FUNCTION_PROFILER=y CONFIG_RING_BUFFER_BENCHMARK=m +# CONFIG_RING_BUFFER_STARTUP_TEST is not set # CONFIG_RBTREE_TEST is not set # CONFIG_INTERVAL_TREE_TEST is not set CONFIG_FUNCTION_TRACER=y @@ -4326,8 +4450,12 @@ CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y CONFIG_HZ_1000=y +CONFIG_NO_HZ=y CONFIG_TIMER_STATS=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PERF_EVENTS=y +CONFIG_PERF_COUNTERS=y # Auxillary displays CONFIG_KS0108=m @@ -4519,6 +4647,7 @@ CONFIG_R8712U=m # Larry Finger maintains this (rhbz 699618) # CONFIG_ATH6K_LEGACY is not set # CONFIG_USB_ENESTORAGE is not set # CONFIG_BCM_WIMAX is not set +# CONFIG_USB_BTMTK is not set # CONFIG_FT1000 is not set # CONFIG_SPEAKUP is not set # CONFIG_DX_SEP is not set @@ -4567,6 +4696,7 @@ CONFIG_IMA_LSM_RULES=y # CONFIG_EVM is not set # CONFIG_PWM is not set +# CONFIG_PWM_PCA9685 is not set CONFIG_LSM_MMAP_MIN_ADDR=65536 @@ -4580,6 +4710,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TRACE is not set # CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_USER_QS is not set CONFIG_SPARSE_RCU_POINTER=y CONFIG_KSM=y @@ -4596,6 +4727,7 @@ CONFIG_IEEE802154_FAKEHARD=m CONFIG_IEEE802154_FAKELB=m CONFIG_MAC802154=m +CONFIG_NET_MPLS_GSO=m # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -4614,6 +4746,7 @@ CONFIG_PTP_1588_CLOCK_PCH=m CONFIG_CLEANCACHE=y CONFIG_FRONTSWAP=y +CONFIG_ZSWAP=y # CONFIG_MDIO_GPIO is not set # CONFIG_KEYBOARD_GPIO is not set @@ -4649,6 +4782,7 @@ CONFIG_GPIO_VIPERBOARD=m # CONFIG_GPIO_AMD8111 is not set # CONFIG_GPIO_BT8XX is not set # CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_GRGPIO is not set # FIXME: Why? CONFIG_EVENT_POWER_TRACING_DEPRECATED=y @@ -4703,6 +4837,14 @@ CONFIG_IOMMU_SUPPORT=y # CONFIG_MAILBOX is not set +# CONFIG_RESET_CONTROLLER is not set + +CONFIG_FMC=m +CONFIG_FMC_FAKEDEV=m +CONFIG_FMC_TRIVIAL=m +CONFIG_FMC_WRITE_EEPROM=m +CONFIG_FMC_CHARDEV=m + # CONFIG_HSI is not set # CONFIG_PM_DEVFREQ is not set @@ -4713,60 +4855,3 @@ CONFIG_IOMMU_SUPPORT=y # CONFIG_CRYPTO_KEY_TYPE is not set # CONFIG_PGP_LIBRARY is not set # CONFIG_PGP_PRELOAD is not set - - -# F18 3.10 rebase options below - -# CONFIG_ATH6KL_TRACING is not set -CONFIG_BATMAN_ADV_NC=y -# CONFIG_BCACHE_CLOSURES_DEBUG is not set -# CONFIG_BCACHE_DEBUG is not set -# CONFIG_BCACHE_EDEBUG is not set -CONFIG_BCACHE=m -CONFIG_BINFMT_SCRIPT=y -CONFIG_BOUNCE=y -# CONFIG_BTRFS_DEBUG is not set -# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set -CONFIG_CRYPTO_CMAC=m -# CONFIG_DUMMY_IRQ is not set -# CONFIG_FB_SIMPLE is not set -# CONFIG_GPIO_GRGPIO is not set -CONFIG_HID_APPLEIR=m -# CONFIG_INPUT_IMS_PCU is not set -CONFIG_LEDS_LP5562=m -CONFIG_LEDS_TRIGGER_CAMERA=m -# CONFIG_MFD_CROS_EC is not set -# CONFIG_MFD_SI476X_CORE is not set -CONFIG_NETLINK_DIAG=m -CONFIG_NETLINK_MMAP=y -CONFIG_NET_TEAM_MODE_RANDOM=m -# CONFIG_RCU_USER_QS is not set -# CONFIG_RESET_CONTROLLER is not set -# CONFIG_RING_BUFFER_STARTUP_TEST is not set -CONFIG_RT2800USB_RT55XX=y -# CONFIG_SCSI_UFSHCD_PLATFORM is not set -CONFIG_SENSORS_ADT7310=m -CONFIG_SENSORS_LM95234=m -CONFIG_SENSORS_NCT6775=m -# CONFIG_SERIO_APBPS2 is not set -# CONFIG_SMS_SIANO_DEBUGFS is not set -# CONFIG_SRAM is not set -# CONFIG_SSBI is not set -# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set -CONFIG_USB_DEFAULT_PERSIST=y -CONFIG_USB_PHY=y -CONFIG_USB_RTL8152=m -# CONFIG_USB_SERIAL_WISHBONE is not set -# CONFIG_W1_SLAVE_DS2408_READBACK is not set -# CONFIG_SAMSUNG_USB2PHY is not set -# CONFIG_SAMSUNG_USB3PHY is not set -CONFIG_ALX=m -CONFIG_INFINIBAND_ISERT=m -CONFIG_QLCNIC_SRIOV=y -CONFIG_RTL8188EE=m -# CONFIG_SAMSUNG_USBPHY is not set -# CONFIG_TIPC_MEDIA_IB is not set -# CONFIG_USB_DWC2 is not set -CONFIG_VHOST_SCSI=m -# CONFIG_MFD_TPS65912 is not set -# CONFIG_MFD_SYSCON is not set diff --git a/config-nodebug b/config-nodebug index 12ecfcc29..75fc2200b 100644 --- a/config-nodebug +++ b/config-nodebug @@ -5,6 +5,7 @@ CONFIG_SND_PCM_XRUN_DEBUG=y # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set @@ -68,6 +69,8 @@ CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_EXT4_DEBUG is not set +# CONFIG_XFS_WARN is not set + # CONFIG_DEBUG_PERF_USE_VMALLOC is not set # CONFIG_JBD2_DEBUG is not set @@ -82,6 +85,8 @@ CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_CARL9170_DEBUGFS is not set # CONFIG_IWLWIFI_DEVICE_TRACING is not set +# CONFIG_RTLWIFI_DEBUG is not set + # CONFIG_DEBUG_OBJECTS_WORK is not set # CONFIG_DMADEVICES_DEBUG is not set @@ -100,6 +105,7 @@ CONFIG_KDB_CONTINUE_CATASTROPHIC=0 # CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set # CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 @@ -117,9 +123,9 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y # CONFIG_EDAC_DEBUG is not set # CONFIG_SPI_DEBUG is not set -# CONFIG_LATENCYTOP is not set + +# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set + # CONFIG_SCHEDSTATS is not set - -# CONFIG_TEST_STRING_HELPERS is not set -# CONFIG_XFS_WARN is not set +# CONFIG_LATENCYTOP is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index e8617230e..2f26fb4ba 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -1,5 +1,4 @@ # Most PowerPC kernels we build are SMP -CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y CONFIG_PPC=y CONFIG_WATCHDOG_RTAS=m @@ -11,14 +10,6 @@ CONFIG_TAU=y # CONFIG_TAU_INT is not set CONFIG_TAU_AVERAGE=y -CONFIG_SECCOMP=y - -CONFIG_PM=y - -CONFIG_PM_STD_PARTITION="" - -CONFIG_SUSPEND=y -CONFIG_HIBERNATION=y # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set # CONFIG_GEN_RTC_X is not set @@ -100,9 +91,6 @@ CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_GPIO=m -# FIXME: Should depend on IA64/x86 -# CONFIG_SGI_IOC4 is not set - CONFIG_PPC_EFIKA=y CONFIG_PPC_MEDIA5200=y @@ -363,7 +351,6 @@ CONFIG_RFKILL_GPIO=m # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set -CONFIG_STRICT_DEVMEM=y CONFIG_RCU_FANOUT_LEAF=16 @@ -371,9 +358,10 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_MPIC_MSGR is not set # CONFIG_FA_DUMP is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_FAIL_IOMMU is not set +# CONFIG_SPAPR_TCE_IOMMU is not set +# CONFIG_TRANSPARENT_HUGEPAGE is not set # CONFIG_PPC_DENORMALISATION is not set # CONFIG_MDIO_BUS_MUX_MMIOREG is not set @@ -385,6 +373,8 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_OF_DISPLAY_TIMING is not set # CONFIG_OF_VIDEOMODE is not set +# CONFIG_POWERNV_MSI is not set + CONFIG_POWER_RESET_GPIO=y CONFIG_FB_SSD1307=m CONFIG_INPUT_PWM_BEEPER=m @@ -392,5 +382,3 @@ CONFIG_BACKLIGHT_PWM=m CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=n CONFIG_XZ_DEC_POWERPC=y - -# CONFIG_POWERNV_MSI is not set diff --git a/config-powerpc32-generic b/config-powerpc32-generic index 935aab420..61e3236b1 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -95,8 +95,6 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_EMBEDDED6xx is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set # CONFIG_BLK_DEV_4DRIVES is not set @@ -175,10 +173,6 @@ CONFIG_CRYPTO_DEV_TALITOS=m CONFIG_RCU_FANOUT=32 -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - CONFIG_KVM_BOOK3S_32=m # CONFIG_SCSI_QLA_ISCSI is not set diff --git a/config-powerpc32-smp b/config-powerpc32-smp index e60f59cdf..5dbe87f7f 100644 --- a/config-powerpc32-smp +++ b/config-powerpc32-smp @@ -1,4 +1,3 @@ -CONFIG_SMP=y # CONFIG_HOTPLUG_CPU is not set CONFIG_NR_CPUS=4 # CONFIG_BATTERY_PMU is not set diff --git a/config-powerpc64 b/config-powerpc64 index 02a44d888..705a7ea2b 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -12,6 +12,7 @@ CONFIG_PPC_MAPLE=y CONFIG_PPC_PSERIES=y CONFIG_PPC_PMAC=y CONFIG_PPC_POWERNV=y +CONFIG_POWERNV_MSI=y CONFIG_PPC_POWERNV_RTAS=y # CONFIG_PPC_PASEMI is not set # CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set @@ -110,11 +111,7 @@ CONFIG_XMON_DISASSEMBLY=y CONFIG_SCSI_IBMVSCSIS=m -CONFIG_SECCOMP=y - # CONFIG_TUNE_CELL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set # CONFIG_VIRQ_DEBUG is not set @@ -137,13 +134,10 @@ CONFIG_RELOCATABLE=y CONFIG_RCU_FANOUT=64 -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - CONFIG_KVM_BOOK3S_64=m CONFIG_KVM_BOOK3S_64_HV=y # CONFIG_KVM_EXIT_TIMING is not set +CONFIG_KVM_XICS=y #-- bz#607175 #-- active memory sharing @@ -176,11 +170,7 @@ CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y # CONFIG_PPC_ICSWX_PID is not set # CONFIG_PPC_ICSWX_USE_SIGILL is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_PCIEPORTBUS is not set # CONFIG_PPC_TRANSACTIONAL_MEM is not set # CONFIG_SND_HDA_INTEL is not set CONFIG_BLK_DEV_RSXX=m - -CONFIG_POWERNV_MSI=y -CONFIG_KVM_XICS=y diff --git a/config-powerpc64p7 b/config-powerpc64p7 index ff4471037..7ab19187b 100644 --- a/config-powerpc64p7 +++ b/config-powerpc64p7 @@ -8,6 +8,7 @@ CONFIG_POWER7_CPU=y CONFIG_PPC_PSERIES=y # CONFIG_PPC_PMAC is not set CONFIG_PPC_POWERNV=y +CONFIG_POWERNV_MSI=y CONFIG_PPC_POWERNV_RTAS=y # CONFIG_PPC_PASEMI is not set # CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set @@ -101,11 +102,7 @@ CONFIG_XMON_DISASSEMBLY=y CONFIG_SCSI_IBMVSCSIS=m -CONFIG_SECCOMP=y - # CONFIG_TUNE_CELL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set # CONFIG_VIRQ_DEBUG is not set @@ -128,13 +125,10 @@ CONFIG_RELOCATABLE=y CONFIG_RCU_FANOUT=64 -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - CONFIG_KVM_BOOK3S_64=m CONFIG_KVM_BOOK3S_64_HV=y # CONFIG_KVM_EXIT_TIMING is not set +CONFIG_KVM_XICS=y #-- bz#607175 #-- active memory sharing @@ -167,10 +161,6 @@ CONFIG_CRYPTO_DEV_NX_COMPRESS=m CONFIG_BPF_JIT=y # CONFIG_PPC_ICSWX_PID is not set # CONFIG_PPC_ICSWX_USE_SIGILL is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_PCIEPORTBUS is not set # CONFIG_SND_HDA_INTEL is not set CONFIG_BLK_DEV_RSXX=m - -CONFIG_POWERNV_MSI=y -CONFIG_KVM_XICS=y diff --git a/config-s390x b/config-s390x index 35aec886f..a292f425e 100644 --- a/config-s390x +++ b/config-s390x @@ -13,13 +13,9 @@ CONFIG_HZ_100=y # See bug 496605 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_MMU=y - CONFIG_LOG_BUF_SHIFT=16 CONFIG_NO_IDLE_HZ=y -CONFIG_SMP=y - # # I/O subsystem configuration # @@ -190,8 +186,6 @@ CONFIG_S390_VMUR=m # CONFIG_THERMAL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_CTCM=m CONFIG_QETH_L2=m CONFIG_QETH_L3=m @@ -214,15 +208,7 @@ CONFIG_HVC_IUCV=y CONFIG_RCU_FANOUT=64 CONFIG_RCU_FANOUT_LEAF=16 -CONFIG_SECCOMP=y - -CONFIG_PM=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="/dev/jokes" - -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y +# CONFIG_SUSPEND is not set CONFIG_SMSGIUCV_EVENT=m @@ -235,13 +221,9 @@ CONFIG_ZFCP_DIF=y CONFIG_SCHED_MC=y CONFIG_SCHED_BOOK=y -CONFIG_STRICT_DEVMEM=y - # CONFIG_WARN_DYNAMIC_STACK is not set CONFIG_CRYPTO_GHASH_S390=m -CONFIG_NET_CORE=y -CONFIG_ETHERNET=y CONFIG_BPF_JIT=y # CONFIG_TRANSPARENT_HUGEPAGE is not set @@ -250,11 +232,8 @@ CONFIG_EADM_SCH=m CONFIG_SCM_BLOCK=m CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_S390_PTDUMP is not set -# CONFIG_SCSI_UFSHCD is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set # CONFIG_PCI is not set -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_SGI_IOC4 is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set @@ -272,8 +251,6 @@ CONFIG_SCM_BLOCK_CLUSTER_WRITE=y # CONFIG_ACCESSIBILITY is not set # CONFIG_AUXDISPLAY is not set -# CONFIG_PTP_1588_CLOCK is not set -# CONFIG_PTP_1588_CLOCK_PCH is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_STAGING is not set # CONFIG_MEMSTICK is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index 6b6c60d30..3cd496569 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -122,8 +122,6 @@ CONFIG_SND_ES18XX=m CONFIG_HW_RANDOM_GEODE=m -# CONFIG_SGI_IOC4 is not set - CONFIG_TC1100_WMI=m CONFIG_IB700_WDT=m @@ -230,3 +228,5 @@ CONFIG_BACKLIGHT_PWM=m # CONFIG_RTC_DRV_SNVS is not set # CONFIG_OF_DISPLAY_TIMING is not set # CONFIG_OF_VIDEOMODE is not set + +# CONFIG_MLX5_INFINIBAND is not set diff --git a/config-x86-generic b/config-x86-generic index 064063020..c21bf1989 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -2,8 +2,6 @@ CONFIG_UID16=y CONFIG_X86_EXTENDED_PLATFORM=y -CONFIG_SMP=y - CONFIG_X86_GENERIC=y CONFIG_HPET=y @@ -37,6 +35,7 @@ CONFIG_X86_PM_TIMER=y CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_EFI_VARS=y +CONFIG_EFIVAR_FS=y CONFIG_EFI_VARS_PSTORE=y CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y CONFIG_EFI_PCDP=y @@ -51,8 +50,6 @@ CONFIG_INTEL_IOMMU_FLOPPY_WA=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m -CONFIG_SECCOMP=y - CONFIG_CAPI_EICON=y # @@ -102,6 +99,7 @@ CONFIG_X86_ACPI_CPUFREQ=m CONFIG_X86_PCC_CPUFREQ=m CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_AMD_FREQ_SENSITIVITY=m CONFIG_X86_P4_CLOCKMOD=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set @@ -115,10 +113,6 @@ CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_GENERIC_ISA_DMA=y -CONFIG_SUSPEND=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" - CONFIG_PCI_MMCONFIG=y CONFIG_PCI_BIOS=y CONFIG_PCI_IOAPIC=y @@ -129,8 +123,6 @@ CONFIG_HOTPLUG_PCI_COMPAQ=m CONFIG_HOTPLUG_PCI_IBM=m # CONFIG_HOTPLUG_PCI_CPCI is not set -CONFIG_PM=y - CONFIG_IPW2100=m CONFIG_IPW2100_MONITOR=y CONFIG_IPW2200=m @@ -211,7 +203,6 @@ CONFIG_SAMSUNG_LAPTOP=m CONFIG_SONY_LAPTOP=m CONFIG_TOPSTAR_LAPTOP=m - CONFIG_ACPI_WMI=m CONFIG_ACER_WMI=m CONFIG_ACERHDF=m @@ -226,6 +217,9 @@ CONFIG_INTEL_OAKTRAIL=m CONFIG_SAMSUNG_Q10=m CONFIG_APPLE_GMUX=m CONFIG_XO15_EBOOK=m +CONFIG_INTEL_RST=m +CONFIG_INTEL_SMARTCONNECT=y +CONFIG_PVPANIC=m # CONFIG_TOUCHSCREEN_INTEL_MID is not set @@ -242,10 +236,11 @@ CONFIG_VIRTUALIZATION=y CONFIG_KVM=m CONFIG_KVM_INTEL=m CONFIG_KVM_AMD=m +CONFIG_KVM_DEVICE_ASSIGNMENT=y CONFIG_LGUEST=m CONFIG_LGUEST_GUEST=y -CONFIG_PARAVIRT_GUEST=y +CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_PARAVIRT_DEBUG is not set @@ -286,8 +281,6 @@ CONFIG_XEN_ACPI_PROCESSOR=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_CPU_IDLE=y # CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set # CONFIG_CPU_IDLE_GOV_LADDER is not set @@ -322,8 +315,6 @@ CONFIG_HP_WATCHDOG=m CONFIG_NV_TCO=m CONFIG_SP5100_TCO=m -CONFIG_STRICT_DEVMEM=y - # CONFIG_NO_BOOTMEM is not set # CONFIG_MEMTEST is not set @@ -346,9 +337,6 @@ CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y # CONFIG_IOMMU_STRESS is not set -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y - CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y CONFIG_X86_MCE_AMD=y @@ -420,6 +408,7 @@ CONFIG_HID_HYPERV_MOUSE=m CONFIG_HYPERV_NET=m CONFIG_HYPERV_STORAGE=m CONFIG_HYPERV_BALLOON=m +CONFIG_FB_HYPERV=m # Depends on HOTPLUG_PCI_PCIE CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m @@ -433,12 +422,17 @@ CONFIG_RCU_FANOUT_LEAF=16 CONFIG_INTEL_MEI=m CONFIG_INTEL_MEI_ME=m +CONFIG_NFC_MEI_PHY=m +CONFIG_NFC_PN544_MEI=m +CONFIG_NFC_MICROREAD_MEI=m + # Maybe enable in debug kernels? # CONFIG_DEBUG_NMI_SELFTEST is not set # CONFIG_X86_INTEL_LPSS is not set # CONFIG_INTEL_POWERCLAMP is not set +CONFIG_X86_PKG_TEMP_THERMAL=m CONFIG_VMWARE_VMCI=m CONFIG_VMWARE_VMCI_VSOCKETS=m @@ -449,26 +443,18 @@ CONFIG_MPILIB=y CONFIG_PKCS7_MESSAGE_PARSER=y CONFIG_EFI_SIGNATURE_LIST_PARSER=y CONFIG_PE_FILE_PARSER=y +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_BLACKLIST_KEYRING=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_ALL=y # CONFIG_MODULE_SIG_SHA1 is not set CONFIG_MODULE_SIG_SHA256=y # CONFIG_MODULE_SIG_FORCE is not set CONFIG_MODULE_SIG_BLACKLIST=y -CONFIG_SYSTEM_BLACKLIST_KEYRING=y +CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE=y +CONFIG_EFI_SIGNATURE_LIST_PARSER=y CONFIG_MODULE_SIG_UEFI=y CONFIG_VMXNET3=m CONFIG_VFIO_PCI_VGA=y - -CONFIG_EFIVAR_FS=y -CONFIG_HYPERVISOR_GUEST=y -CONFIG_KVM_DEVICE_ASSIGNMENT=y -CONFIG_NFC_MEI_PHY=m -CONFIG_PVPANIC=m -CONFIG_X86_AMD_FREQ_SENSITIVITY=m -CONFIG_FB_HYPERV=m -CONFIG_NFC_MICROREAD_MEI=m -CONFIG_NFC_PN544_MEI=m - diff --git a/config-x86_64-generic b/config-x86_64-generic index 0c460722f..85f588bc1 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -30,11 +30,12 @@ CONFIG_SWIOTLB=y # CONFIG_CALGARY_IOMMU is not set CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_MEM_SOFT_DIRTY=y CONFIG_KEXEC_JUMP=y CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_HOTPLUG_MEMORY=m +CONFIG_ACPI_HOTPLUG_MEMORY=y # CONFIG_INTEL_SCU_IPC is not set @@ -47,14 +48,21 @@ CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m CONFIG_CRYPTO_SHA1_SSSE3=m +CONFIG_CRYPTO_SHA256_SSSE3=m +CONFIG_CRYPTO_SHA512_SSSE3=m CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_BLOWFISH_AVX2_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m CONFIG_CRYPTO_CAMELLIA_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m CONFIG_CRYPTO_CAST5_AVX_X86_64=m CONFIG_CRYPTO_CAST6_AVX_X86_64=m +CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m CONFIG_CRYPTO_SERPENT_AVX_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m -CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m +CONFIG_CRYPTO_TWOFISH_AVX2_X86_64=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set @@ -128,6 +136,9 @@ CONFIG_I7300_IDLE=m CONFIG_BPF_JIT=y +# https://fedoraproject.org/wiki/Features/Checkpoint_Restore +CONFIG_CHECKPOINT_RESTORE=y + # Should be 32bit only, but lacks KConfig depends # CONFIG_XO15_EBOOK is not set @@ -154,8 +165,3 @@ CONFIG_SFC_MTD=y CONFIG_MTD_CHAR=m CONFIG_MTD_BLOCK=m -CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m -CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m -CONFIG_CRYPTO_SHA256_SSSE3=m -CONFIG_CRYPTO_SHA512_SSSE3=m - diff --git a/efi-dont-map-boot-services-on-32bit.patch b/efi-dont-map-boot-services-on-32bit.patch deleted file mode 100644 index 7cc614992..000000000 --- a/efi-dont-map-boot-services-on-32bit.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 3ae4128..ff7dc70 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -659,10 +659,13 @@ void __init efi_enter_virtual_mode(void) - - for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; -- if (!(md->attribute & EFI_MEMORY_RUNTIME) && -- md->type != EFI_BOOT_SERVICES_CODE && -- md->type != EFI_BOOT_SERVICES_DATA) -- continue; -+ if (!(md->attribute & EFI_MEMORY_RUNTIME)) { -+#ifdef CONFIG_X86_64 -+ if (md->type != EFI_BOOT_SERVICES_CODE && -+ md->type != EFI_BOOT_SERVICES_DATA) -+#endif -+ continue; -+ } - - size = md->num_pages << EFI_PAGE_SHIFT; - end = md->phys_addr + size; diff --git a/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch b/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch deleted file mode 100644 index 424d60350..000000000 --- a/intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch +++ /dev/null @@ -1,25 +0,0 @@ -This triggers on a MacBook Pro. - -Signed-off-by: Andy Lutomirski -https://bugzilla.redhat.com/show_bug.cgi?id=948262 ---- - drivers/iommu/intel_irq_remapping.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c -index f3b8f23..a7e0ad1 100644 ---- a/drivers/iommu/intel_irq_remapping.c -+++ b/drivers/iommu/intel_irq_remapping.c -@@ -654,8 +654,7 @@ error: - */ - - if (x2apic_present) -- WARN(1, KERN_WARNING -- "Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); -+ pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); - - return -1; - } --- -1.8.1.4 - diff --git a/kernel.spec b/kernel.spec index e4ea0fa87..10da03400 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,19 +62,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base, # which yields a base_sublevel of 0. -%define base_sublevel 10 +%define base_sublevel 11 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 14 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -483,7 +483,7 @@ Provides: kernel-tegra\ Provides: kernel-tegra-uname-r = %{KVERREL}%{?1:.%{1}}\ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ -Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ +Requires(pre): linux-firmware >= 20130724-29.git31f6b30\ Requires(post): /sbin/new-kernel-pkg\ Requires(preun): /sbin/new-kernel-pkg\ Conflicts: %{kernel_dot_org_conflicts}\ @@ -644,7 +644,6 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch Patch390: defaults-acpi-video.patch -Patch391: acpi-video-dos.patch Patch394: acpi-debug-infinite-loop.patch Patch396: acpi-sony-nonvs-blacklist.patch @@ -695,8 +694,6 @@ Patch10000: fs-proc-devtree-remove_proc_entry.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch13003: efi-dont-map-boot-services-on-32bit.patch - Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch @@ -728,35 +725,13 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -#rhbz 948262 -Patch25024: intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch - #CVE-2013-2147 rhbz 971242 971249 Patch25032: cve-2013-2147-ciss-info-leak.patch -#rhbz 969644 -Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch - -#rhbz 903741 -Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch - -#rhbz 880035 -Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch -Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch -#rhbz 980254 -Patch25061: bridge-timer-fix.patch -Patch25066: bridge-do-not-call-setup_timer-multiple-times.patch - #rhbz 977040 Patch25056: iwl3945-better-skb-management-in-rx-path.patch Patch25057: iwl4965-better-skb-management-in-rx-path.patch -#rhbz 959721 -Patch25063: HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch - -#rhbz 969473 -Patch25070: Input-elantech-fix-for-newer-hardware-versions-v7.patch - #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch @@ -769,9 +744,6 @@ Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch #CVE-2013-4345 rhbz 1007690 1009136 Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch -#rhbz 928561 -Patch25105: 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch - #rhbz 971893 Patch25106: bonding-driver-alb-learning.patch @@ -779,9 +751,6 @@ Patch25106: bonding-driver-alb-learning.patch Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch -#rhbz 1013000 -Patch25116: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch - #CVE-2013-4387 rhbz 1011927 1015166 Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch @@ -1361,7 +1330,6 @@ ApplyPatch arm-tegra-usb-no-reset-linux33.patch # ACPI ApplyPatch defaults-acpi-video.patch -ApplyPatch acpi-video-dos.patch ApplyPatch acpi-debug-infinite-loop.patch ApplyPatch acpi-sony-nonvs-blacklist.patch @@ -1433,8 +1401,6 @@ ApplyPatch fs-proc-devtree-remove_proc_entry.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch efi-dont-map-boot-services-on-32bit.patch - # FIXME: REBASE #ApplyPatch hibernate-freeze-filesystems.patch @@ -1454,35 +1420,13 @@ ApplyPatch ath9k_rx_dma_stop_check.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -#rhbz 948262 -ApplyPatch intel_iommu-Downgrade-the-warning-if-enabling-irq-remapping-fails.patch - #CVE-2013-2147 rhbz 971242 971249 ApplyPatch cve-2013-2147-ciss-info-leak.patch -#rhbz 969644 -ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch - -#rhbz 903741 -ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch - -#rhbz 880035 -ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch -ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch -#rhbz 980254 -ApplyPatch bridge-timer-fix.patch -ApplyPatch bridge-do-not-call-setup_timer-multiple-times.patch - #rhbz 977040 ApplyPatch iwl3945-better-skb-management-in-rx-path.patch ApplyPatch iwl4965-better-skb-management-in-rx-path.patch -#rhbz 959721 -ApplyPatch HID-kye-Add-report-fixup-for-Genius-Gila-Gaming-mouse.patch - -#rhbz 969473 -ApplyPatch Input-elantech-fix-for-newer-hardware-versions-v7.patch - #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch @@ -1495,9 +1439,6 @@ ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch #CVE-2013-4345 rhbz 1007690 1009136 ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch -#rhbz 928561 -ApplyPatch 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch - #rhbz 971893 ApplyPatch bonding-driver-alb-learning.patch @@ -1505,9 +1446,6 @@ ApplyPatch bonding-driver-alb-learning.patch ApplyPatch elevator-Fix-a-race-in-elevator-switching-and-md.patch ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch -#rhbz 1013000 -ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch - #CVE-2013-4387 rhbz 1011927 1015166 ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch @@ -2358,6 +2296,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 08 2013 Justin M. Forbes +- Linux v3.11.4 + * Tue Oct 08 2013 Josh Boyer - Quiet irq remapping stack trace (rhbz 982153) - Use RCU safe kfree for conntrack (rhbz 1015989) diff --git a/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch b/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch index bba16ee6b..671ee98db 100644 --- a/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch +++ b/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch @@ -1,7 +1,7 @@ -From 9ecce5d19bce6d423342cee4348c3a44ed9edc02 Mon Sep 17 00:00:00 2001 +From 95ee62083cb6453e056562d91f597552021e6ae7 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 11 Sep 2013 14:58:36 +0000 -Subject: [PATCH] net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit +Subject: net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit Alan Chester reported an issue with IPv6 on SCTP that IPsec traffic is not being encrypted, whereas on IPv4 it is. Setting up an AH + ESP transport @@ -90,14 +90,11 @@ Cc: Hannes Frederic Sowa Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- - net/sctp/ipv6.c | 41 ++++++++++++----------------------------- - 1 file changed, 12 insertions(+), 29 deletions(-) - diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c -index 391a245..cc86f2c 100644 +index da613ce..4f52e2c 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c -@@ -210,45 +210,23 @@ out: +@@ -204,44 +204,23 @@ out: in6_dev_put(idev); } @@ -131,10 +128,9 @@ index 391a245..cc86f2c 100644 - } + struct flowi6 *fl6 = &transport->fl.u.ip6; - SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", - __func__, skb, skb->len, -- &fl6.saddr, &fl6.daddr); -+ &fl6->saddr, &fl6->daddr); + pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, +- skb->len, &fl6.saddr, &fl6.daddr); ++ skb->len, &fl6->saddr, &fl6->daddr); - SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); + IP6_ECN_flow_xmit(sk, fl6->flowlabel); @@ -144,11 +140,12 @@ index 391a245..cc86f2c 100644 - return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); + SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); ++ + return ip6_xmit(sk, skb, fl6, np->opt, np->tclass); } /* Returns the dst cache entry for the given source and destination ip -@@ -261,10 +239,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, +@@ -254,10 +233,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, struct dst_entry *dst = NULL; struct flowi6 *fl6 = &fl->u.ip6; struct sctp_bind_addr *bp; @@ -161,8 +158,8 @@ index 391a245..cc86f2c 100644 __u8 matchlen = 0; __u8 bmatchlen; sctp_scope_t scope; -@@ -287,7 +267,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); +@@ -281,7 +262,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + pr_debug("src=%pI6 - ", &fl6->saddr); } - dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); @@ -171,7 +168,7 @@ index 391a245..cc86f2c 100644 if (!asoc || saddr) goto out; -@@ -339,10 +320,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, +@@ -333,10 +315,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, } } rcu_read_unlock(); @@ -185,6 +182,5 @@ index 391a245..cc86f2c 100644 } out: --- -1.8.3.1 - +-- +cgit v0.9.2 From 20a0130a427715bcccba0b1e7f2fa7d2b786b9d0 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 8 Oct 2013 09:28:27 -0500 Subject: [PATCH 432/492] Add missing 3.11 patches from F19 --- ...00pci-Use-PCI-MSIs-whenever-possible.patch | 59 ++++++++++++++ bonding-driver-promisc.patch | 73 +++++++++++++++++ kernel.spec | 35 ++++++++ nowatchdog-on-virt.patch | 67 ++++++++++++++++ ...ke-periodic-RTC-update-more-reliable.patch | 44 ++++++++++ rt2800-add-support-for-rf3070.patch | 80 +++++++++++++++++++ ...alid-value-passed-to-pci_unmap_sigle.patch | 61 ++++++++++++++ 7 files changed, 419 insertions(+) create mode 100644 Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch create mode 100644 bonding-driver-promisc.patch create mode 100644 nowatchdog-on-virt.patch create mode 100644 ntp-Make-periodic-RTC-update-more-reliable.patch create mode 100644 rt2800-add-support-for-rf3070.patch create mode 100644 skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch diff --git a/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch b/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch new file mode 100644 index 000000000..4e48620ec --- /dev/null +++ b/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch @@ -0,0 +1,59 @@ +This reverts commit 9483f40d8d01918b399b4e24d0c1111db0afffeb. + +Some devices stop to connect with above commit, see: +https://bugzilla.kernel.org/show_bug.cgi?id=61621 + +Since there is no clear benefit of having MSI enabled, just revert +change to fix the problem. + +Cc: stable@vger.kernel.org # 3.11+ +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2x00pci.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c +index 76d95de..dc49e52 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -105,13 +105,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) + goto exit_release_regions; + } + +- pci_enable_msi(pci_dev); +- + hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); + if (!hw) { + rt2x00_probe_err("Failed to allocate hardware\n"); + retval = -ENOMEM; +- goto exit_disable_msi; ++ goto exit_release_regions; + } + + pci_set_drvdata(pci_dev, hw); +@@ -152,9 +150,6 @@ exit_free_reg: + exit_free_device: + ieee80211_free_hw(hw); + +-exit_disable_msi: +- pci_disable_msi(pci_dev); +- + exit_release_regions: + pci_release_regions(pci_dev); + +@@ -179,8 +174,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) + rt2x00pci_free_reg(rt2x00dev); + ieee80211_free_hw(hw); + +- pci_disable_msi(pci_dev); +- + /* + * Free the PCI device data. + */ +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/bonding-driver-promisc.patch b/bonding-driver-promisc.patch new file mode 100644 index 000000000..38315c906 --- /dev/null +++ b/bonding-driver-promisc.patch @@ -0,0 +1,73 @@ +commit 5a0068deb611109c5ba77358be533f763f395ee4 +Author: Neil Horman +Date: Fri Sep 27 12:22:15 2013 -0400 + + bonding: Fix broken promiscuity reference counting issue + + Recently grabbed this report: + https://bugzilla.redhat.com/show_bug.cgi?id=1005567 + + Of an issue in which the bonding driver, with an attached vlan encountered the + following errors when bond0 was taken down and back up: + + dummy1: promiscuity touches roof, set promiscuity failed. promiscuity feature of + device might be broken. + + The error occurs because, during __bond_release_one, if we release our last + slave, we take on a random mac address and issue a NETDEV_CHANGEADDR + notification. With an attached vlan, the vlan may see that the vlan and bond + mac address were in sync, but no longer are. This triggers a call to dev_uc_add + and dev_set_rx_mode, which enables IFF_PROMISC on the bond device. Then, when + we complete __bond_release_one, we use the current state of the bond flags to + determine if we should decrement the promiscuity of the releasing slave. But + since the bond changed promiscuity state during the release operation, we + incorrectly decrement the slave promisc count when it wasn't in promiscuous mode + to begin with, causing the above error + + Fix is pretty simple, just cache the bonding flags at the start of the function + and use those when determining the need to set promiscuity. + + This is also needed for the ALLMULTI flag + + CC: Jay Vosburgh + CC: Andy Gospodarek + CC: Mark Wu + CC: "David S. Miller" + Reported-by: Mark Wu + + Signed-off-by: David S. Miller + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 55bbb8b..e883bfe 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1724,6 +1724,7 @@ static int __bond_release_one(struct net_device *bond_dev, + struct bonding *bond = netdev_priv(bond_dev); + struct slave *slave, *oldcurrent; + struct sockaddr addr; ++ int old_flags = bond_dev->flags; + netdev_features_t old_features = bond_dev->features; + + /* slave is not a slave or master is not master of this slave */ +@@ -1855,12 +1856,18 @@ static int __bond_release_one(struct net_device *bond_dev, + * bond_change_active_slave(..., NULL) + */ + if (!USES_PRIMARY(bond->params.mode)) { +- /* unset promiscuity level from slave */ +- if (bond_dev->flags & IFF_PROMISC) ++ /* unset promiscuity level from slave ++ * NOTE: The NETDEV_CHANGEADDR call above may change the value ++ * of the IFF_PROMISC flag in the bond_dev, but we need the ++ * value of that flag before that change, as that was the value ++ * when this slave was attached, so we cache at the start of the ++ * function and use it here. Same goes for ALLMULTI below ++ */ ++ if (old_flags & IFF_PROMISC) + dev_set_promiscuity(slave_dev, -1); + + /* unset allmulti level from slave */ +- if (bond_dev->flags & IFF_ALLMULTI) ++ if (old_flags & IFF_ALLMULTI) + dev_set_allmulti(slave_dev, -1); + + bond_hw_addr_flush(bond_dev, slave_dev); diff --git a/kernel.spec b/kernel.spec index 10da03400..4bc5fd3d0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -698,6 +698,7 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch +Patch15000: nowatchdog-on-virt.patch Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -747,10 +748,25 @@ Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch #rhbz 971893 Patch25106: bonding-driver-alb-learning.patch +#rhbz 985522 +Patch25107: ntp-Make-periodic-RTC-update-more-reliable.patch + +#rhbz 1010431 +Patch25108: Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch + +#rhbz 1008323 +Patch25120: skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch + #rhbz 902012 Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch +#rhbz 974072 +Patch25117: rt2800-add-support-for-rf3070.patch + +#rhbz 1005567 +Patch25118: bonding-driver-promisc.patch + #CVE-2013-4387 rhbz 1011927 1015166 Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch @@ -1406,6 +1422,9 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch lis3-improve-handling-of-null-rate.patch +# Disable watchdog on virtual machines. +ApplyPatch nowatchdog-on-virt.patch + #ApplyPatch 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch #ApplyPatch 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch @@ -1439,13 +1458,28 @@ ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch #CVE-2013-4345 rhbz 1007690 1009136 ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch +#rhbz 985522 +ApplyPatch ntp-Make-periodic-RTC-update-more-reliable.patch + +#rhbz 1010431 +ApplyPatch Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch + #rhbz 971893 ApplyPatch bonding-driver-alb-learning.patch +#rhbz 1008323 +ApplyPatch skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch + #rhbz 902012 ApplyPatch elevator-Fix-a-race-in-elevator-switching-and-md.patch ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch +#rhbz 974072 +ApplyPatch rt2800-add-support-for-rf3070.patch + +#rhbz 1005567 +ApplyPatch bonding-driver-promisc.patch + #CVE-2013-4387 rhbz 1011927 1015166 ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch @@ -2298,6 +2332,7 @@ fi %changelog * Tue Oct 08 2013 Justin M. Forbes - Linux v3.11.4 +- Add missing 3.11 patches from F19 * Tue Oct 08 2013 Josh Boyer - Quiet irq remapping stack trace (rhbz 982153) diff --git a/nowatchdog-on-virt.patch b/nowatchdog-on-virt.patch new file mode 100644 index 000000000..87ab11a0f --- /dev/null +++ b/nowatchdog-on-virt.patch @@ -0,0 +1,67 @@ +Disable watchdog on virtual machines. + +For various reasons, VMs seem to trigger the soft lockup detector a lot, +in cases where it's just not possible for a lockup to occur. +(Example: https://bugzilla.redhat.com/show_bug.cgi?id=971139) + +In some cases it seems that the host just never scheduled the app running +the VM for a very long time (Could be the host was under heavy load). + +Just disable the detector on VMs. + +Signed-off-by: Dave Jones + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 1241d8c..b2dc4e4 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -96,6 +97,32 @@ static int __init nosoftlockup_setup(char *str) + __setup("nosoftlockup", nosoftlockup_setup); + /* */ + ++static int disable_watchdog(const struct dmi_system_id *d) ++{ ++ printk(KERN_INFO "watchdog: disabled (inside virtual machine)\n"); ++ watchdog_user_enabled = 0; ++ return 0; ++} ++ ++static const struct dmi_system_id watchdog_virt_dmi_table[] = { ++ { ++ .callback = disable_watchdog, ++ .ident = "VMware", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "VMware, Inc."), ++ }, ++ }, ++ { ++ .callback = disable_watchdog, ++ .ident = "Bochs", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Bochs Bochs"), ++ }, ++ }, ++ {} ++}; ++ ++ + /* + * Hard-lockup warnings should be triggered after just a few seconds. Soft- + * lockups can have false positives under extreme conditions. So we generally +@@ -551,6 +578,8 @@ int proc_dowatchdog(struct ctl_table *table, int write, + + void __init lockup_detector_init(void) + { ++ dmi_check_system(watchdog_virt_dmi_table); ++ + set_sample_period(); + + #ifdef CONFIG_NO_HZ_FULL diff --git a/ntp-Make-periodic-RTC-update-more-reliable.patch b/ntp-Make-periodic-RTC-update-more-reliable.patch new file mode 100644 index 000000000..59179e719 --- /dev/null +++ b/ntp-Make-periodic-RTC-update-more-reliable.patch @@ -0,0 +1,44 @@ +From a97ad0c4b447a132a322cedc3a5f7fa4cab4b304 Mon Sep 17 00:00:00 2001 +From: Miroslav Lichvar +Date: Thu, 1 Aug 2013 19:31:35 +0200 +Subject: [PATCH] ntp: Make periodic RTC update more reliable + +The current code requires that the scheduled update of the RTC happens +in the closest tick to the half of the second. This seems to be +difficult to achieve reliably. The scheduled work may be missing the +target time by a tick or two and be constantly rescheduled every second. + +Relax the limit to 10 ticks. As a typical RTC drifts in the 11-minute +update interval by several milliseconds, this shouldn't affect the +overall accuracy of the RTC much. + +Signed-off-by: Miroslav Lichvar +Signed-off-by: John Stultz +--- + kernel/time/ntp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index 8f5b3b9..ab1fa7c 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -475,6 +475,7 @@ static void sync_cmos_clock(struct work_struct *work) + * called as close as possible to 500 ms before the new second starts. + * This code is run on a timer. If the clock is set, that timer + * may not expire at the correct time. Thus, we adjust... ++ * We want the clock to be within a couple of ticks from the target. + */ + if (!ntp_synced()) { + /* +@@ -485,7 +486,7 @@ static void sync_cmos_clock(struct work_struct *work) + } + + getnstimeofday(&now); +- if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) { ++ if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) { + struct timespec adjust = now; + + fail = -ENODEV; +-- +1.7.9.5 + diff --git a/rt2800-add-support-for-rf3070.patch b/rt2800-add-support-for-rf3070.patch new file mode 100644 index 000000000..24c16cb9c --- /dev/null +++ b/rt2800-add-support-for-rf3070.patch @@ -0,0 +1,80 @@ +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index d78c495..2132830 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -65,6 +65,7 @@ + #define RF3021 0x0007 + #define RF3022 0x0008 + #define RF3052 0x0009 ++#define RF3070 0x3070 + #define RF2853 0x000a + #define RF3320 0x000b + #define RF3322 0x000c +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 1b41c8e..2958265 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -2597,6 +2597,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + case RF3322: + rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); + break; ++ case RF3070: + case RF5360: + case RF5370: + case RF5372: +@@ -2611,7 +2612,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); + } + +- if (rt2x00_rf(rt2x00dev, RF3290) || ++ if (rt2x00_rf(rt2x00dev, RF3070) || ++ rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || + rt2x00_rf(rt2x00dev, RF5360) || + rt2x00_rf(rt2x00dev, RF5370) || +@@ -3219,6 +3221,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + break; ++ case RF3070: + case RF3290: + case RF5360: + case RF5370: +@@ -5731,6 +5734,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + case RF3021: + case RF3022: + case RF3052: ++ case RF3070: + case RF3290: + case RF3320: + case RF3322: +@@ -6186,6 +6190,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + rt2x00_rf(rt2x00dev, RF2020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022) || ++ rt2x00_rf(rt2x00dev, RF3070) || + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3320) || + rt2x00_rf(rt2x00dev, RF3322) || +@@ -6219,10 +6224,11 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + /* + * Initialize HT information. + */ +- if (!rt2x00_rf(rt2x00dev, RF2020)) ++ if (!rt2x00_rf(rt2x00dev, RF2020)) { + spec->ht.ht_supported = true; +- else ++ } else { + spec->ht.ht_supported = false; ++ } + + spec->ht.cap = + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | +@@ -6290,6 +6296,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3022: + case RF3320: + case RF3052: ++ case RF3070: + case RF3290: + case RF5360: + case RF5370: diff --git a/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch b/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch new file mode 100644 index 000000000..908e0c751 --- /dev/null +++ b/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch @@ -0,0 +1,61 @@ +From 3361dc9538832a2a9150a8c722374ca844bf8dc8 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 20 Sep 2013 17:53:22 +0000 +Subject: skge: fix invalid value passed to pci_unmap_sigle + +In my patch c194992cbe71c20bb3623a566af8d11b0bfaa721 ("skge: fix +broken driver") I didn't fix the skge bug correctly. The value of the +new mapping (not old) was passed to pci_unmap_single. + +If we enable CONFIG_DMA_API_DEBUG, it results in this warning: +WARNING: CPU: 0 PID: 0 at lib/dma-debug.c:986 check_sync+0x4c4/0x580() +skge 0000:02:07.0: DMA-API: device driver tries to sync DMA memory it has +not allocated [device address=0x000000023a0096c0] [size=1536 bytes] + +This patch makes the skge driver pass the correct value to +pci_unmap_single and fixes the warning. It copies the old descriptor to +on-stack variable "ee" and unmaps it if mapping of the new descriptor +succeeded. + +This patch should be backported to 3.11-stable. + +Signed-off-by: Mikulas Patocka +Reported-by: Francois Romieu +Tested-by: Mikulas Patocka +Signed-off-by: David S. Miller +--- +diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c +index 1a9c4f6..ecc7f7b 100644 +--- a/drivers/net/ethernet/marvell/skge.c ++++ b/drivers/net/ethernet/marvell/skge.c +@@ -3086,13 +3086,16 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, + PCI_DMA_FROMDEVICE); + skge_rx_reuse(e, skge->rx_buf_size); + } else { ++ struct skge_element ee; + struct sk_buff *nskb; + + nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size); + if (!nskb) + goto resubmit; + +- skb = e->skb; ++ ee = *e; ++ ++ skb = ee.skb; + prefetch(skb->data); + + if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) { +@@ -3101,8 +3104,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, + } + + pci_unmap_single(skge->hw->pdev, +- dma_unmap_addr(e, mapaddr), +- dma_unmap_len(e, maplen), ++ dma_unmap_addr(&ee, mapaddr), ++ dma_unmap_len(&ee, maplen), + PCI_DMA_FROMDEVICE); + } + +-- +cgit v0.9.2 From 6d371ddaa702d7c5a63777d0a0029b5e46547398 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Oct 2013 11:56:16 -0400 Subject: [PATCH 433/492] Add patch to fix nouveau crash (rhbz 1015920) --- drm-nouveau-bios-init-stub-opcode-0xaa.patch | 109 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 118 insertions(+) create mode 100644 drm-nouveau-bios-init-stub-opcode-0xaa.patch diff --git a/drm-nouveau-bios-init-stub-opcode-0xaa.patch b/drm-nouveau-bios-init-stub-opcode-0xaa.patch new file mode 100644 index 000000000..2daa6ed1d --- /dev/null +++ b/drm-nouveau-bios-init-stub-opcode-0xaa.patch @@ -0,0 +1,109 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.76.11.131 with SMTP id q3csp149379oab; + Mon, 7 Oct 2013 23:45:24 -0700 (PDT) +X-Received: by 10.68.185.36 with SMTP id ez4mr69490pbc.144.1381214724506; + Mon, 07 Oct 2013 23:45:24 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id rz6si25872020pab.249.1969.12.31.16.00.00; + Mon, 07 Oct 2013 23:45:24 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com; + dmarc=fail (p=NONE dis=NONE) header.from=gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754014Ab3JHGow (ORCPT + 60 others); + Tue, 8 Oct 2013 02:44:52 -0400 +Received: from mail-pa0-f42.google.com ([209.85.220.42]:35990 "EHLO + mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1753696Ab3JHGov (ORCPT + ); Tue, 8 Oct 2013 02:44:51 -0400 +Received: by mail-pa0-f42.google.com with SMTP id lj1so8433751pab.15 + for ; Mon, 07 Oct 2013 23:44:51 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=from:to:cc:subject:date:message-id; + bh=DRveULH9ZaYYXMJRsSw3WWLRMs5ifsnU9G+VUu1PKtk=; + b=oCDYfvF1KXEUN6PZU0jit8kMHSKTzIWcR078uMTxLpTjheGcoLWW0efoqsO4Dac3jp + +4dHm3NSdeqk4e+aCjnvZw7He+nMGmbWhrf1vx49XCOE4s+YvC/AgSI78pku8BQE/plZ + w8F+64e+wNze1FfRAxPPM/PoLdBiuBfvUL18htMmYi/rgq0VRkNk2UwbzvGk5AJE+vwL + esavQLjvCuJZTc7i2J9Us53dUcY4aQuYlESFvOUlbDnkkgm5Htrsnyd2Eq7k61/hr0MR + /nIFNBXuhIadU5bvf6jpMT+toIK+PA176Yt9eyEgdOAxNXdn5g15mO93/WEyXf7idBfk + JLZA== +X-Received: by 10.68.232.132 with SMTP id to4mr7840579pbc.141.1381214691006; + Mon, 07 Oct 2013 23:44:51 -0700 (PDT) +Received: from turiel.redhat.com (124-148-32-6.dyn.iinet.net.au. [124.148.32.6]) + by mx.google.com with ESMTPSA id j9sm44764711paj.18.1969.12.31.16.00.00 + (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); + Mon, 07 Oct 2013 23:44:50 -0700 (PDT) +From: Ben Skeggs +To: stable@vger.kernel.org +Cc: Ben Skeggs +Subject: [PATCH] drm/nouveau/bios/init: stub opcode 0xaa +Date: Tue, 8 Oct 2013 16:45:08 +1000 +Message-Id: <1381214708-2990-1-git-send-email-skeggsb@gmail.com> +X-Mailer: git-send-email 1.8.3.2 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +From: Ben Skeggs + +Seen on a large number of recent boards, when triggered results in +nouveau aborting the card cold boot, giving unpredictable results +(oopses in the reported cases) later. + +commit 5495e39fb3695182b9f2a72fe4169056cada37a1 upstream + +Signed-off-by: Ben Skeggs +--- + drivers/gpu/drm/nouveau/core/subdev/bios/init.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +index 0687e64..8f06cca 100644 +--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +@@ -579,8 +579,22 @@ static void + init_reserved(struct nvbios_init *init) + { + u8 opcode = nv_ro08(init->bios, init->offset); +- trace("RESERVED\t0x%02x\n", opcode); +- init->offset += 1; ++ u8 length, i; ++ ++ switch (opcode) { ++ case 0xaa: ++ length = 4; ++ break; ++ default: ++ length = 1; ++ break; ++ } ++ ++ trace("RESERVED 0x%02x\t", opcode); ++ for (i = 1; i < length; i++) ++ cont(" 0x%02x", nv_ro08(init->bios, init->offset + i)); ++ cont("\n"); ++ init->offset += length; + } + + /** +@@ -2135,6 +2149,7 @@ static struct nvbios_init_opcode { + [0x99] = { init_zm_auxch }, + [0x9a] = { init_i2c_long_if }, + [0xa9] = { init_gpio_ne }, ++ [0xaa] = { init_reserved }, + }; + + #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) +-- +1.8.3.2 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index 4bc5fd3d0..4faf673a7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -776,6 +776,9 @@ Patch25122: netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch #rhbz 982153 Patch25123: iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch +#rhbz 1015920 +Patch25124: drm-nouveau-bios-init-stub-opcode-0xaa.patch + # END OF PATCH DEFINITIONS %endif @@ -1489,6 +1492,9 @@ ApplyPatch netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch #rhbz 982153 ApplyPatch iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch +#rhbz 1015920 +ApplyPatch drm-nouveau-bios-init-stub-opcode-0xaa.patch + # END OF PATCH APPLICATIONS %endif @@ -2330,6 +2336,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 08 2013 Josh Boyer +- Add patch to fix nouveau crash (rhbz 1015920) + * Tue Oct 08 2013 Justin M. Forbes - Linux v3.11.4 - Add missing 3.11 patches from F19 From 7fc3fa05db3a150ce0313aee59fd0c455303d87c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 9 Oct 2013 09:01:38 -0400 Subject: [PATCH 434/492] Add patch to fix VFIO IOMMU crash (rhbz 998732) --- kernel.spec | 9 +++++ ...ed-interaction-of-VFIO_IOMMU_MAP_DMA.patch | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch diff --git a/kernel.spec b/kernel.spec index 4faf673a7..f5dc4bd66 100644 --- a/kernel.spec +++ b/kernel.spec @@ -779,6 +779,9 @@ Patch25123: iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch #rhbz 1015920 Patch25124: drm-nouveau-bios-init-stub-opcode-0xaa.patch +#rhbz 998732 +Patch25125: vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch + # END OF PATCH DEFINITIONS %endif @@ -1495,6 +1498,9 @@ ApplyPatch iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch #rhbz 1015920 ApplyPatch drm-nouveau-bios-init-stub-opcode-0xaa.patch +#rhbz 998732 +ApplyPatch vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch + # END OF PATCH APPLICATIONS %endif @@ -2336,6 +2342,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 09 2013 Josh Boyer +- Add patch to fix VFIO IOMMU crash (rhbz 998732) + * Tue Oct 08 2013 Josh Boyer - Add patch to fix nouveau crash (rhbz 1015920) diff --git a/vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch b/vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch new file mode 100644 index 000000000..0b5fa8a7a --- /dev/null +++ b/vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch @@ -0,0 +1,39 @@ +From: Julian Stecklina +Subject: [PATCH] vfio, iommu: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits + +The BUG_ON in drivers/iommu/intel-iommu.c:785 can be triggered from userspace via +VFIO by calling the VFIO_IOMMU_MAP_DMA ioctl on a vfio device with any address +beyond the addressing capabilities of the IOMMU. The problem is that the ioctl code +calls iommu_iova_to_phys before it calls iommu_map. iommu_map handles the case that +it gets addresses beyond the addressing capabilities of its IOMMU. +intel_iommu_iova_to_phys does not. + +This patch fixes iommu_iova_to_phys to return NULL for addresses beyond what the +IOMMU can handle. This in turn causes the ioctl call to fail in iommu_map and +(correctly) return EFAULT to the user with a helpful warning message in the kernel +log. + +Signed-off-by: Julian Stecklina +--- + drivers/iommu/intel-iommu.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index eec0d3e..61303db 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -782,7 +782,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, + int offset; + + BUG_ON(!domain->pgd); +- BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); ++ ++ if (addr_width < BITS_PER_LONG && pfn >> addr_width) ++ /* Address beyond IOMMU's addressing capabilities. */ ++ return NULL; ++ + parent = domain->pgd; + + while (level > 0) { +-- +1.8.3.1 From 9f379b4ef15096e3e581e2f47b6f6fc4435e7db7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 9 Oct 2013 10:28:35 -0400 Subject: [PATCH 435/492] Don't trigger a stack trace on crashing iwlwifi firmware (rhbz 896695) --- ...RN-on-host-commands-sent-when-firmwa.patch | 35 +++++++ ...ifi-don-t-WARN-on-bad-firmware-state.patch | 98 +++++++++++++++++++ kernel.spec | 9 ++ 3 files changed, 142 insertions(+) create mode 100644 0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch create mode 100644 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch diff --git a/0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch b/0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch new file mode 100644 index 000000000..241b7d750 --- /dev/null +++ b/0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch @@ -0,0 +1,35 @@ +From 8ca95995e64f5d270889badb3e449dca91106a2b Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Sun, 15 Sep 2013 11:37:17 +0300 +Subject: [PATCH] iwlwifi: don't WARN on host commands sent when firmware is dead + +This triggers automatic bug reports and add no valuable +information. Print a simple error instead and drop the +host command. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +--- + drivers/net/wireless/iwlwifi/iwl-trans.h | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h +index dd57a36..80b4750 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans.h +@@ -601,8 +601,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, + { + int ret; + +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (trans->state != IWL_TRANS_FW_ALIVE) { ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); ++ return -EIO; ++ } + + if (!(cmd->flags & CMD_ASYNC)) + lock_map_acquire_read(&trans->sync_cmd_lockdep_map); +-- +1.7.1 + diff --git a/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch b/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch new file mode 100644 index 000000000..499c34a63 --- /dev/null +++ b/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch @@ -0,0 +1,98 @@ +From 3efd689c41080b0d4a9cc263a51f2868e3d5a37b Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Wed, 9 Oct 2013 15:03:57 +0200 +Subject: [PATCH] iwlwifi: don't WARN on bad firmware state + +When we restart firmware is possible and hance firmware is marked as not +alive, we can still get calls from mac80211. Don't WARN on in this +situation as this triggers automatic bug reports with no valuable +information. + +This extend change from: + +commit 8ca95995e64f5d270889badb3e449dca91106a2b +Author: Emmanuel Grumbach +Date: Sun Sep 15 11:37:17 2013 +0300 + + iwlwifi: don't WARN on host commands sent when firmware is dead + +which remove WARN_ONCE from one place, but those warnings are also +triggered from other functions. + +Patch adds also unlikely() statement. + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-trans.h | 22 +++++++++++----------- + 1 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h +index 80b4750..c6bac7c 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans.h +@@ -601,7 +601,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, + { + int ret; + +- if (trans->state != IWL_TRANS_FW_ALIVE) { ++ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { + IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + return -EIO; + } +@@ -640,8 +640,8 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, + static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_device_cmd *dev_cmd, int queue) + { +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + + return trans->ops->tx(trans, skb, dev_cmd, queue); + } +@@ -649,16 +649,16 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, + static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, + int ssn, struct sk_buff_head *skbs) + { +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + + trans->ops->reclaim(trans, queue, ssn, skbs); + } + + static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) + { +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + + trans->ops->txq_disable(trans, queue); + } +@@ -669,8 +669,8 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, + { + might_sleep(); + +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + + trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, + frame_limit, ssn); +@@ -685,8 +685,8 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, + + static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) + { +- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, +- "%s bad state = %d", __func__, trans->state); ++ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) ++ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + + return trans->ops->wait_tx_queue_empty(trans); + } +-- +1.7.1 + diff --git a/kernel.spec b/kernel.spec index f5dc4bd66..76031f37e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -782,6 +782,10 @@ Patch25124: drm-nouveau-bios-init-stub-opcode-0xaa.patch #rhbz 998732 Patch25125: vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch +#rhbz 896695 +Patch25126: 0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch +Patch25127: 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch + # END OF PATCH DEFINITIONS %endif @@ -1501,6 +1505,10 @@ ApplyPatch drm-nouveau-bios-init-stub-opcode-0xaa.patch #rhbz 998732 ApplyPatch vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch +#rhbz 896695 +ApplyPatch 0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch +ApplyPatch 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch + # END OF PATCH APPLICATIONS %endif @@ -2343,6 +2351,7 @@ fi # || || %changelog * Wed Oct 09 2013 Josh Boyer +- Don't trigger a stack trace on crashing iwlwifi firmware (rhbz 896695) - Add patch to fix VFIO IOMMU crash (rhbz 998732) * Tue Oct 08 2013 Josh Boyer From 8ca8f7ed8c532461e69363cdba1aa17fb8c88388 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 9 Oct 2013 16:53:47 -0500 Subject: [PATCH 436/492] Ooops, sources --- sources | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources b/sources index 77727a57c..85810a7b6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -4f25cd5bec5f8d5a7d935b3f2ccb8481 linux-3.10.tar.xz -3c2ce4933f210fef16664dfa16028de1 patch-3.10.14.xz +fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz +5147e7f82600452c5438f8309c07eccd patch-3.11.4.xz From 58a132eb1698e304f5e539c5e96e462f65a24c3d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 10 Oct 2013 08:53:35 -0400 Subject: [PATCH 437/492] Fix large order allocation in dm mq policy (rhbz 993744) --- ...fix-large-scale-table-allocation-bug.patch | 31 +++++++++++++++++++ kernel.spec | 9 ++++++ 2 files changed, 40 insertions(+) create mode 100644 dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch diff --git a/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch b/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch new file mode 100644 index 000000000..71234c1a7 --- /dev/null +++ b/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch @@ -0,0 +1,31 @@ +diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c +index cab6dd2..ec79c8f 100644 +--- a/drivers/md/dm-cache-policy-mq.c ++++ b/drivers/md/dm-cache-policy-mq.c +@@ -868,7 +868,7 @@ static void mq_destroy(struct dm_cache_policy *p) + struct mq_policy *mq = to_mq_policy(p); + + free_bitset(mq->allocation_bitset); +- kfree(mq->table); ++ vfree(mq->table); + free_entries(mq); + kfree(mq); + } +@@ -1189,7 +1189,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, + + mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16); + mq->hash_bits = ffs(mq->nr_buckets) - 1; +- mq->table = kzalloc(sizeof(*mq->table) * mq->nr_buckets, GFP_KERNEL); ++ mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets); + if (!mq->table) + goto bad_alloc_table; + +@@ -1200,7 +1200,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, + return &mq->policy; + + bad_alloc_bitset: +- kfree(mq->table); ++ vfree(mq->table); + bad_alloc_table: + free_entries(mq); + bad_cache_alloc: diff --git a/kernel.spec b/kernel.spec index 76031f37e..859f67fa7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,6 +786,9 @@ Patch25125: vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch Patch25126: 0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch Patch25127: 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch +#rhbz 993744 +Patch25128: dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch + # END OF PATCH DEFINITIONS %endif @@ -1509,6 +1512,9 @@ ApplyPatch vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch ApplyPatch 0001-iwlwifi-don-t-WARN-on-host-commands-sent-when-firmwa.patch ApplyPatch 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch +#rhbz 993744 +ApplyPatch dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch + # END OF PATCH APPLICATIONS %endif @@ -2350,6 +2356,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 10 2013 Josh Boyer +- Fix large order allocation in dm mq policy (rhbz 993744) + * Wed Oct 09 2013 Josh Boyer - Don't trigger a stack trace on crashing iwlwifi firmware (rhbz 896695) - Add patch to fix VFIO IOMMU crash (rhbz 998732) From ea640b1f003fa8b57cf5223c282e4f34d2df4def Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 10 Oct 2013 08:29:44 -0500 Subject: [PATCH 438/492] Fix linux-firmware requirement --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 859f67fa7..8df9a8a11 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -483,7 +483,7 @@ Provides: kernel-tegra\ Provides: kernel-tegra-uname-r = %{KVERREL}%{?1:.%{1}}\ Requires(pre): %{kernel_prereq}\ Requires(pre): %{initrd_prereq}\ -Requires(pre): linux-firmware >= 20130724-29.git31f6b30\ +Requires(pre): linux-firmware >= 20130724-0.3.git31f6b30\ Requires(post): /sbin/new-kernel-pkg\ Requires(preun): /sbin/new-kernel-pkg\ Conflicts: %{kernel_dot_org_conflicts}\ @@ -2356,6 +2356,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 10 2013 Justin M. Forbes - 3.11.4-101 +- Fix linux-firmware requirement + * Thu Oct 10 2013 Josh Boyer - Fix large order allocation in dm mq policy (rhbz 993744) From 8b0a7026d86b74720fbb63793f2c6f21fd60069a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 10 Oct 2013 09:45:17 -0400 Subject: [PATCH 439/492] USB OHCI accept very late isochronous URBs (in 3.11.4) (rhbz 975158) --- kernel.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel.spec b/kernel.spec index 8df9a8a11..2eb644f82 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2360,6 +2360,7 @@ fi - Fix linux-firmware requirement * Thu Oct 10 2013 Josh Boyer +- USB OHCI accept very late isochronous URBs (in 3.11.4) (rhbz 975158) - Fix large order allocation in dm mq policy (rhbz 993744) * Wed Oct 09 2013 Josh Boyer From bc253d7d2ed5507e7776959803789f61db6503ee Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 11 Oct 2013 08:53:10 -0400 Subject: [PATCH 440/492] Fix segfault in cpupower set (rhbz 1000439) --- ...fault-due-to-incorrect-getopt_long-a.patch | 40 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 49 insertions(+) create mode 100644 cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch diff --git a/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch b/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch new file mode 100644 index 000000000..dcc6b84b6 --- /dev/null +++ b/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch @@ -0,0 +1,40 @@ +From cb8e390d258b7f8073afafcbb163976e27346e9d Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 11 Oct 2013 08:37:53 -0400 +Subject: [PATCH] cpupower: Fix segfault due to incorrect getopt_long arugments + +If a user calls 'cpupower set --perf-bias 15', the process will end with a +SIGSEGV in libc because cpupower-set passes a NULL optarg to the atoi call. +This is because the getopt_long structure currently has all of the options +as having an optional_argument when they really have a required argument. +We change the structure to use required_argument to match the short options +and it resolves the issue. + +This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1000439 + +Cc: stable@vger.kernel.org +Signed-off-by: Josh Boyer +--- + tools/power/cpupower/utils/cpupower-set.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c +index dc4de37..bcf1d2f 100644 +--- a/tools/power/cpupower/utils/cpupower-set.c ++++ b/tools/power/cpupower/utils/cpupower-set.c +@@ -18,9 +18,9 @@ + #include "helpers/bitmask.h" + + static struct option set_opts[] = { +- { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, +- { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, +- { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, ++ { .name = "perf-bias", .has_arg = required_argument, .flag = NULL, .val = 'b'}, ++ { .name = "sched-mc", .has_arg = required_argument, .flag = NULL, .val = 'm'}, ++ { .name = "sched-smt", .has_arg = required_argument, .flag = NULL, .val = 's'}, + { }, + }; + +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 2eb644f82..c498d0723 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,6 +789,9 @@ Patch25127: 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch #rhbz 993744 Patch25128: dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch +#rhbz 1000439 +Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch + # END OF PATCH DEFINITIONS %endif @@ -1515,6 +1518,9 @@ ApplyPatch 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch #rhbz 993744 ApplyPatch dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch +#rhbz 1000439 +ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch + # END OF PATCH APPLICATIONS %endif @@ -2356,6 +2362,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 11 2013 Josh Boyer +- Fix segfault in cpupower set (rhbz 1000439) + * Thu Oct 10 2013 Justin M. Forbes - 3.11.4-101 - Fix linux-firmware requirement From 8acf10ede10ed85a4b5b555c1f4c901be0cf6d06 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 14 Oct 2013 08:03:00 -0500 Subject: [PATCH 441/492] Linux v3.11.5 --- bonding-driver-promisc.patch | 73 ------- cve-2013-2147-ciss-info-leak.patch | 27 --- drm-nouveau-bios-init-stub-opcode-0xaa.patch | 109 ---------- ...-following-an-UFO-enqueued-packet-ne.patch | 123 ------------ kernel.spec | 49 +---- ...ipsec-encryption-bug-in-sctp_v6_xmit.patch | 186 ------------------ ...alid-value-passed-to-pci_unmap_sigle.patch | 61 ------ sources | 2 +- ...orrectly-handle-error-in-tun_set_iff.patch | 57 ------ 9 files changed, 6 insertions(+), 681 deletions(-) delete mode 100644 bonding-driver-promisc.patch delete mode 100644 cve-2013-2147-ciss-info-leak.patch delete mode 100644 drm-nouveau-bios-init-stub-opcode-0xaa.patch delete mode 100644 ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch delete mode 100644 net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch delete mode 100644 skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch delete mode 100644 tuntap-correctly-handle-error-in-tun_set_iff.patch diff --git a/bonding-driver-promisc.patch b/bonding-driver-promisc.patch deleted file mode 100644 index 38315c906..000000000 --- a/bonding-driver-promisc.patch +++ /dev/null @@ -1,73 +0,0 @@ -commit 5a0068deb611109c5ba77358be533f763f395ee4 -Author: Neil Horman -Date: Fri Sep 27 12:22:15 2013 -0400 - - bonding: Fix broken promiscuity reference counting issue - - Recently grabbed this report: - https://bugzilla.redhat.com/show_bug.cgi?id=1005567 - - Of an issue in which the bonding driver, with an attached vlan encountered the - following errors when bond0 was taken down and back up: - - dummy1: promiscuity touches roof, set promiscuity failed. promiscuity feature of - device might be broken. - - The error occurs because, during __bond_release_one, if we release our last - slave, we take on a random mac address and issue a NETDEV_CHANGEADDR - notification. With an attached vlan, the vlan may see that the vlan and bond - mac address were in sync, but no longer are. This triggers a call to dev_uc_add - and dev_set_rx_mode, which enables IFF_PROMISC on the bond device. Then, when - we complete __bond_release_one, we use the current state of the bond flags to - determine if we should decrement the promiscuity of the releasing slave. But - since the bond changed promiscuity state during the release operation, we - incorrectly decrement the slave promisc count when it wasn't in promiscuous mode - to begin with, causing the above error - - Fix is pretty simple, just cache the bonding flags at the start of the function - and use those when determining the need to set promiscuity. - - This is also needed for the ALLMULTI flag - - CC: Jay Vosburgh - CC: Andy Gospodarek - CC: Mark Wu - CC: "David S. Miller" - Reported-by: Mark Wu - - Signed-off-by: David S. Miller - -diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c -index 55bbb8b..e883bfe 100644 ---- a/drivers/net/bonding/bond_main.c -+++ b/drivers/net/bonding/bond_main.c -@@ -1724,6 +1724,7 @@ static int __bond_release_one(struct net_device *bond_dev, - struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave, *oldcurrent; - struct sockaddr addr; -+ int old_flags = bond_dev->flags; - netdev_features_t old_features = bond_dev->features; - - /* slave is not a slave or master is not master of this slave */ -@@ -1855,12 +1856,18 @@ static int __bond_release_one(struct net_device *bond_dev, - * bond_change_active_slave(..., NULL) - */ - if (!USES_PRIMARY(bond->params.mode)) { -- /* unset promiscuity level from slave */ -- if (bond_dev->flags & IFF_PROMISC) -+ /* unset promiscuity level from slave -+ * NOTE: The NETDEV_CHANGEADDR call above may change the value -+ * of the IFF_PROMISC flag in the bond_dev, but we need the -+ * value of that flag before that change, as that was the value -+ * when this slave was attached, so we cache at the start of the -+ * function and use it here. Same goes for ALLMULTI below -+ */ -+ if (old_flags & IFF_PROMISC) - dev_set_promiscuity(slave_dev, -1); - - /* unset allmulti level from slave */ -- if (bond_dev->flags & IFF_ALLMULTI) -+ if (old_flags & IFF_ALLMULTI) - dev_set_allmulti(slave_dev, -1); - - bond_hw_addr_flush(bond_dev, slave_dev); diff --git a/cve-2013-2147-ciss-info-leak.patch b/cve-2013-2147-ciss-info-leak.patch deleted file mode 100644 index ee49d3bfb..000000000 --- a/cve-2013-2147-ciss-info-leak.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c -index 639d26b..2b94403 100644 ---- a/drivers/block/cpqarray.c -+++ b/drivers/block/cpqarray.c -@@ -1193,6 +1193,7 @@ out_passthru: - ida_pci_info_struct pciinfo; - - if (!arg) return -EINVAL; -+ memset(&pciinfo, 0, sizeof(pciinfo)); - pciinfo.bus = host->pci_dev->bus->number; - pciinfo.dev_fn = host->pci_dev->devfn; - pciinfo.board_id = host->board_id; - - diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index 6374dc1..34971aa 100644 ---- a/drivers/block/cciss.c -+++ b/drivers/block/cciss.c -@@ -1201,6 +1201,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, - int err; - u32 cp; - -+ memset(&arg64, 0, sizeof(arg64)); - err = 0; - err |= - copy_from_user(&arg64.LUN_info, &arg32->LUN_info, - - \ No newline at end of file diff --git a/drm-nouveau-bios-init-stub-opcode-0xaa.patch b/drm-nouveau-bios-init-stub-opcode-0xaa.patch deleted file mode 100644 index 2daa6ed1d..000000000 --- a/drm-nouveau-bios-init-stub-opcode-0xaa.patch +++ /dev/null @@ -1,109 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.76.11.131 with SMTP id q3csp149379oab; - Mon, 7 Oct 2013 23:45:24 -0700 (PDT) -X-Received: by 10.68.185.36 with SMTP id ez4mr69490pbc.144.1381214724506; - Mon, 07 Oct 2013 23:45:24 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id rz6si25872020pab.249.1969.12.31.16.00.00; - Mon, 07 Oct 2013 23:45:24 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; - spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; - dkim=neutral (bad format) header.i=@gmail.com; - dmarc=fail (p=NONE dis=NONE) header.from=gmail.com -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754014Ab3JHGow (ORCPT + 60 others); - Tue, 8 Oct 2013 02:44:52 -0400 -Received: from mail-pa0-f42.google.com ([209.85.220.42]:35990 "EHLO - mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1753696Ab3JHGov (ORCPT - ); Tue, 8 Oct 2013 02:44:51 -0400 -Received: by mail-pa0-f42.google.com with SMTP id lj1so8433751pab.15 - for ; Mon, 07 Oct 2013 23:44:51 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20120113; - h=from:to:cc:subject:date:message-id; - bh=DRveULH9ZaYYXMJRsSw3WWLRMs5ifsnU9G+VUu1PKtk=; - b=oCDYfvF1KXEUN6PZU0jit8kMHSKTzIWcR078uMTxLpTjheGcoLWW0efoqsO4Dac3jp - +4dHm3NSdeqk4e+aCjnvZw7He+nMGmbWhrf1vx49XCOE4s+YvC/AgSI78pku8BQE/plZ - w8F+64e+wNze1FfRAxPPM/PoLdBiuBfvUL18htMmYi/rgq0VRkNk2UwbzvGk5AJE+vwL - esavQLjvCuJZTc7i2J9Us53dUcY4aQuYlESFvOUlbDnkkgm5Htrsnyd2Eq7k61/hr0MR - /nIFNBXuhIadU5bvf6jpMT+toIK+PA176Yt9eyEgdOAxNXdn5g15mO93/WEyXf7idBfk - JLZA== -X-Received: by 10.68.232.132 with SMTP id to4mr7840579pbc.141.1381214691006; - Mon, 07 Oct 2013 23:44:51 -0700 (PDT) -Received: from turiel.redhat.com (124-148-32-6.dyn.iinet.net.au. [124.148.32.6]) - by mx.google.com with ESMTPSA id j9sm44764711paj.18.1969.12.31.16.00.00 - (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); - Mon, 07 Oct 2013 23:44:50 -0700 (PDT) -From: Ben Skeggs -To: stable@vger.kernel.org -Cc: Ben Skeggs -Subject: [PATCH] drm/nouveau/bios/init: stub opcode 0xaa -Date: Tue, 8 Oct 2013 16:45:08 +1000 -Message-Id: <1381214708-2990-1-git-send-email-skeggsb@gmail.com> -X-Mailer: git-send-email 1.8.3.2 -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -From: Ben Skeggs - -Seen on a large number of recent boards, when triggered results in -nouveau aborting the card cold boot, giving unpredictable results -(oopses in the reported cases) later. - -commit 5495e39fb3695182b9f2a72fe4169056cada37a1 upstream - -Signed-off-by: Ben Skeggs ---- - drivers/gpu/drm/nouveau/core/subdev/bios/init.c | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c -index 0687e64..8f06cca 100644 ---- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c -+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c -@@ -579,8 +579,22 @@ static void - init_reserved(struct nvbios_init *init) - { - u8 opcode = nv_ro08(init->bios, init->offset); -- trace("RESERVED\t0x%02x\n", opcode); -- init->offset += 1; -+ u8 length, i; -+ -+ switch (opcode) { -+ case 0xaa: -+ length = 4; -+ break; -+ default: -+ length = 1; -+ break; -+ } -+ -+ trace("RESERVED 0x%02x\t", opcode); -+ for (i = 1; i < length; i++) -+ cont(" 0x%02x", nv_ro08(init->bios, init->offset + i)); -+ cont("\n"); -+ init->offset += length; - } - - /** -@@ -2135,6 +2149,7 @@ static struct nvbios_init_opcode { - [0x99] = { init_zm_auxch }, - [0x9a] = { init_i2c_long_if }, - [0xa9] = { init_gpio_ne }, -+ [0xaa] = { init_reserved }, - }; - - #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) --- -1.8.3.2 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch b/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch deleted file mode 100644 index 9310e05a7..000000000 --- a/ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 2811ebac2521ceac84f2bdae402455baa6a7fb47 Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Sat, 21 Sep 2013 06:27:00 +0200 -Subject: [PATCH] ipv6: udp packets following an UFO enqueued packet need also - be handled by UFO - -In the following scenario the socket is corked: -If the first UDP packet is larger then the mtu we try to append it to the -write queue via ip6_ufo_append_data. A following packet, which is smaller -than the mtu would be appended to the already queued up gso-skb via -plain ip6_append_data. This causes random memory corruptions. - -In ip6_ufo_append_data we also have to be careful to not queue up the -same skb multiple times. So setup the gso frame only when no first skb -is available. - -This also fixes a shortcoming where we add the current packet's length to -cork->length but return early because of a packet > mtu with dontfrag set -(instead of sutracting it again). - -Found with trinity. - -Cc: YOSHIFUJI Hideaki -Signed-off-by: Hannes Frederic Sowa -Reported-by: Dmitry Vyukov -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_output.c | 53 +++++++++++++++++++++------------------------------ - 1 file changed, 22 insertions(+), 31 deletions(-) - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 3a692d5..a54c45c 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk, - * udp datagram - */ - if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { -+ struct frag_hdr fhdr; -+ - skb = sock_alloc_send_skb(sk, - hh_len + fragheaderlen + transhdrlen + 20, - (flags & MSG_DONTWAIT), &err); -@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, - skb->protocol = htons(ETH_P_IPV6); - skb->ip_summed = CHECKSUM_PARTIAL; - skb->csum = 0; -- } -- -- err = skb_append_datato_frags(sk,skb, getfrag, from, -- (length - transhdrlen)); -- if (!err) { -- struct frag_hdr fhdr; - - /* Specify the length of each IPv6 datagram fragment. - * It has to be a multiple of 8. -@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk, - ipv6_select_ident(&fhdr, rt); - skb_shinfo(skb)->ip6_frag_id = fhdr.identification; - __skb_queue_tail(&sk->sk_write_queue, skb); -- -- return 0; - } -- /* There is not enough support do UPD LSO, -- * so follow normal path -- */ -- kfree_skb(skb); - -- return err; -+ return skb_append_datato_frags(sk, skb, getfrag, from, -+ (length - transhdrlen)); - } - - static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, -@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, - * --yoshfuji - */ - -- cork->length += length; -- if (length > mtu) { -- int proto = sk->sk_protocol; -- if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ -- ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); -- return -EMSGSIZE; -- } -- -- if (proto == IPPROTO_UDP && -- (rt->dst.dev->features & NETIF_F_UFO)) { -+ if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || -+ sk->sk_protocol == IPPROTO_RAW)) { -+ ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); -+ return -EMSGSIZE; -+ } - -- err = ip6_ufo_append_data(sk, getfrag, from, length, -- hh_len, fragheaderlen, -- transhdrlen, mtu, flags, rt); -- if (err) -- goto error; -- return 0; -- } -+ skb = skb_peek_tail(&sk->sk_write_queue); -+ cork->length += length; -+ if (((length > mtu) || -+ (skb && skb_is_gso(skb))) && -+ (sk->sk_protocol == IPPROTO_UDP) && -+ (rt->dst.dev->features & NETIF_F_UFO)) { -+ err = ip6_ufo_append_data(sk, getfrag, from, length, -+ hh_len, fragheaderlen, -+ transhdrlen, mtu, flags, rt); -+ if (err) -+ goto error; -+ return 0; - } - -- if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) -+ if (!skb) - goto alloc_new_skb; - - while (length > 0) { --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index c498d0723..bdd8028e4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -726,9 +726,6 @@ Patch22247: ath9k_rx_dma_stop_check.patch #rhbz 927469 Patch25007: fix-child-thread-introspection.patch -#CVE-2013-2147 rhbz 971242 971249 -Patch25032: cve-2013-2147-ciss-info-leak.patch - #rhbz 977040 Patch25056: iwl3945-better-skb-management-in-rx-path.patch Patch25057: iwl4965-better-skb-management-in-rx-path.patch @@ -736,12 +733,6 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-4343 rhbz 1007733 1007741 -Patch25101: tuntap-correctly-handle-error-in-tun_set_iff.patch - -#CVE-2013-4350 rhbz 1007872 1007903 -Patch25102: net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch - #CVE-2013-4345 rhbz 1007690 1009136 Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch @@ -754,9 +745,6 @@ Patch25107: ntp-Make-periodic-RTC-update-more-reliable.patch #rhbz 1010431 Patch25108: Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch -#rhbz 1008323 -Patch25120: skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch - #rhbz 902012 Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch @@ -764,21 +752,12 @@ Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch #rhbz 974072 Patch25117: rt2800-add-support-for-rf3070.patch -#rhbz 1005567 -Patch25118: bonding-driver-promisc.patch - -#CVE-2013-4387 rhbz 1011927 1015166 -Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch - #rhbz 1015989 Patch25122: netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch #rhbz 982153 Patch25123: iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch -#rhbz 1015920 -Patch25124: drm-nouveau-bios-init-stub-opcode-0xaa.patch - #rhbz 998732 Patch25125: vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch @@ -1455,9 +1434,6 @@ ApplyPatch ath9k_rx_dma_stop_check.patch #rhbz 927469 ApplyPatch fix-child-thread-introspection.patch -#CVE-2013-2147 rhbz 971242 971249 -ApplyPatch cve-2013-2147-ciss-info-leak.patch - #rhbz 977040 ApplyPatch iwl3945-better-skb-management-in-rx-path.patch ApplyPatch iwl4965-better-skb-management-in-rx-path.patch @@ -1465,12 +1441,6 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-4343 rhbz 1007733 1007741 -ApplyPatch tuntap-correctly-handle-error-in-tun_set_iff.patch - -#CVE-2013-4350 rhbz 1007872 1007903 -ApplyPatch net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch - #CVE-2013-4345 rhbz 1007690 1009136 ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch @@ -1483,9 +1453,6 @@ ApplyPatch Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch #rhbz 971893 ApplyPatch bonding-driver-alb-learning.patch -#rhbz 1008323 -ApplyPatch skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch - #rhbz 902012 ApplyPatch elevator-Fix-a-race-in-elevator-switching-and-md.patch ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch @@ -1493,21 +1460,12 @@ ApplyPatch elevator-acquire-q-sysfs_lock-in-elevator_change.patch #rhbz 974072 ApplyPatch rt2800-add-support-for-rf3070.patch -#rhbz 1005567 -ApplyPatch bonding-driver-promisc.patch - -#CVE-2013-4387 rhbz 1011927 1015166 -ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch - #rhbz 1015989 ApplyPatch netfilter-nf_conntrack-use-RCU-safe-kfree-for-conntr.patch #rhbz 982153 ApplyPatch iommu-Remove-stack-trace-from-broken-irq-remapping-warning.patch -#rhbz 1015920 -ApplyPatch drm-nouveau-bios-init-stub-opcode-0xaa.patch - #rhbz 998732 ApplyPatch vfio-iommu-Fixed-interaction-of-VFIO_IOMMU_MAP_DMA.patch @@ -2362,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 14 2013 Justin M. Forbes - 3.11.5-100 +- Linux v3.11.5 + * Fri Oct 11 2013 Josh Boyer - Fix segfault in cpupower set (rhbz 1000439) diff --git a/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch b/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch deleted file mode 100644 index 671ee98db..000000000 --- a/net-sctp-fix-ipv6-ipsec-encryption-bug-in-sctp_v6_xmit.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 95ee62083cb6453e056562d91f597552021e6ae7 Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Wed, 11 Sep 2013 14:58:36 +0000 -Subject: net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit - -Alan Chester reported an issue with IPv6 on SCTP that IPsec traffic is not -being encrypted, whereas on IPv4 it is. Setting up an AH + ESP transport -does not seem to have the desired effect: - -SCTP + IPv4: - - 22:14:20.809645 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 116) - 192.168.0.2 > 192.168.0.5: AH(spi=0x00000042,sumlen=16,seq=0x1): ESP(spi=0x00000044,seq=0x1), length 72 - 22:14:20.813270 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 340) - 192.168.0.5 > 192.168.0.2: AH(spi=0x00000043,sumlen=16,seq=0x1): - -SCTP + IPv6: - - 22:31:19.215029 IP6 (class 0x02, hlim 64, next-header SCTP (132) payload length: 364) - fe80::222:15ff:fe87:7fc.3333 > fe80::92e6:baff:fe0d:5a54.36767: sctp - 1) [INIT ACK] [init tag: 747759530] [rwnd: 62464] [OS: 10] [MIS: 10] - -Moreover, Alan says: - - This problem was seen with both Racoon and Racoon2. Other people have seen - this with OpenSwan. When IPsec is configured to encrypt all upper layer - protocols the SCTP connection does not initialize. After using Wireshark to - follow packets, this is because the SCTP packet leaves Box A unencrypted and - Box B believes all upper layer protocols are to be encrypted so it drops - this packet, causing the SCTP connection to fail to initialize. When IPsec - is configured to encrypt just SCTP, the SCTP packets are observed unencrypted. - -In fact, using `socat sctp6-listen:3333 -` on one end and transferring "plaintext" -string on the other end, results in cleartext on the wire where SCTP eventually -does not report any errors, thus in the latter case that Alan reports, the -non-paranoid user might think he's communicating over an encrypted transport on -SCTP although he's not (tcpdump ... -X): - - ... - 0x0030: 5d70 8e1a 0003 001a 177d eb6c 0000 0000 ]p.......}.l.... - 0x0040: 0000 0000 706c 6169 6e74 6578 740a 0000 ....plaintext... - -Only in /proc/net/xfrm_stat we can see XfrmInTmplMismatch increasing on the -receiver side. Initial follow-up analysis from Alan's bug report was done by -Alexey Dobriyan. Also thanks to Vlad Yasevich for feedback on this. - -SCTP has its own implementation of sctp_v6_xmit() not calling inet6_csk_xmit(). -This has the implication that it probably never really got updated along with -changes in inet6_csk_xmit() and therefore does not seem to invoke xfrm handlers. - -SCTP's IPv4 xmit however, properly calls ip_queue_xmit() to do the work. Since -a call to inet6_csk_xmit() would solve this problem, but result in unecessary -route lookups, let us just use the cached flowi6 instead that we got through -sctp_v6_get_dst(). Since all SCTP packets are being sent through sctp_packet_transmit(), -we do the route lookup / flow caching in sctp_transport_route(), hold it in -tp->dst and skb_dst_set() right after that. If we would alter fl6->daddr in -sctp_v6_xmit() to np->opt->srcrt, we possibly could run into the same effect -of not having xfrm layer pick it up, hence, use fl6_update_dst() in sctp_v6_get_dst() -instead to get the correct source routed dst entry, which we assign to the skb. - -Also source address routing example from 625034113 ("sctp: fix sctp to work with -ipv6 source address routing") still works with this patch! Nevertheless, in RFC5095 -it is actually 'recommended' to not use that anyway due to traffic amplification [1]. -So it seems we're not supposed to do that anyway in sctp_v6_xmit(). Moreover, if -we overwrite the flow destination here, the lower IPv6 layer will be unable to -put the correct destination address into IP header, as routing header is added in -ipv6_push_nfrag_opts() but then probably with wrong final destination. Things aside, -result of this patch is that we do not have any XfrmInTmplMismatch increase plus on -the wire with this patch it now looks like: - -SCTP + IPv6: - - 08:17:47.074080 IP6 2620:52:0:102f:7a2b:cbff:fe27:1b0a > 2620:52:0:102f:213:72ff:fe32:7eba: - AH(spi=0x00005fb4,seq=0x1): ESP(spi=0x00005fb5,seq=0x1), length 72 - 08:17:47.074264 IP6 2620:52:0:102f:213:72ff:fe32:7eba > 2620:52:0:102f:7a2b:cbff:fe27:1b0a: - AH(spi=0x00003d54,seq=0x1): ESP(spi=0x00003d55,seq=0x1), length 296 - -This fixes Kernel Bugzilla 24412. This security issue seems to be present since -2.6.18 kernels. Lets just hope some big passive adversary in the wild didn't have -its fun with that. lksctp-tools IPv6 regression test suite passes as well with -this patch. - - [1] http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf - -Reported-by: Alan Chester -Reported-by: Alexey Dobriyan -Signed-off-by: Daniel Borkmann -Cc: Steffen Klassert -Cc: Hannes Frederic Sowa -Acked-by: Vlad Yasevich -Signed-off-by: David S. Miller ---- -diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c -index da613ce..4f52e2c 100644 ---- a/net/sctp/ipv6.c -+++ b/net/sctp/ipv6.c -@@ -204,44 +204,23 @@ out: - in6_dev_put(idev); - } - --/* Based on tcp_v6_xmit() in tcp_ipv6.c. */ - static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) - { - struct sock *sk = skb->sk; - struct ipv6_pinfo *np = inet6_sk(sk); -- struct flowi6 fl6; -- -- memset(&fl6, 0, sizeof(fl6)); -- -- fl6.flowi6_proto = sk->sk_protocol; -- -- /* Fill in the dest address from the route entry passed with the skb -- * and the source address from the transport. -- */ -- fl6.daddr = transport->ipaddr.v6.sin6_addr; -- fl6.saddr = transport->saddr.v6.sin6_addr; -- -- fl6.flowlabel = np->flow_label; -- IP6_ECN_flow_xmit(sk, fl6.flowlabel); -- if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL) -- fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id; -- else -- fl6.flowi6_oif = sk->sk_bound_dev_if; -- -- if (np->opt && np->opt->srcrt) { -- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -- fl6.daddr = *rt0->addr; -- } -+ struct flowi6 *fl6 = &transport->fl.u.ip6; - - pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, -- skb->len, &fl6.saddr, &fl6.daddr); -+ skb->len, &fl6->saddr, &fl6->daddr); - -- SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); -+ IP6_ECN_flow_xmit(sk, fl6->flowlabel); - - if (!(transport->param_flags & SPP_PMTUD_ENABLE)) - skb->local_df = 1; - -- return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); -+ SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); -+ -+ return ip6_xmit(sk, skb, fl6, np->opt, np->tclass); - } - - /* Returns the dst cache entry for the given source and destination ip -@@ -254,10 +233,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - struct dst_entry *dst = NULL; - struct flowi6 *fl6 = &fl->u.ip6; - struct sctp_bind_addr *bp; -+ struct ipv6_pinfo *np = inet6_sk(sk); - struct sctp_sockaddr_entry *laddr; - union sctp_addr *baddr = NULL; - union sctp_addr *daddr = &t->ipaddr; - union sctp_addr dst_saddr; -+ struct in6_addr *final_p, final; - __u8 matchlen = 0; - __u8 bmatchlen; - sctp_scope_t scope; -@@ -281,7 +262,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - pr_debug("src=%pI6 - ", &fl6->saddr); - } - -- dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); -+ final_p = fl6_update_dst(fl6, np->opt, &final); -+ dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); - if (!asoc || saddr) - goto out; - -@@ -333,10 +315,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - } - } - rcu_read_unlock(); -+ - if (baddr) { - fl6->saddr = baddr->v6.sin6_addr; - fl6->fl6_sport = baddr->v6.sin6_port; -- dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); -+ final_p = fl6_update_dst(fl6, np->opt, &final); -+ dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); - } - - out: --- -cgit v0.9.2 diff --git a/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch b/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch deleted file mode 100644 index 908e0c751..000000000 --- a/skge-fix-invalid-value-passed-to-pci_unmap_sigle.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 3361dc9538832a2a9150a8c722374ca844bf8dc8 Mon Sep 17 00:00:00 2001 -From: Mikulas Patocka -Date: Fri, 20 Sep 2013 17:53:22 +0000 -Subject: skge: fix invalid value passed to pci_unmap_sigle - -In my patch c194992cbe71c20bb3623a566af8d11b0bfaa721 ("skge: fix -broken driver") I didn't fix the skge bug correctly. The value of the -new mapping (not old) was passed to pci_unmap_single. - -If we enable CONFIG_DMA_API_DEBUG, it results in this warning: -WARNING: CPU: 0 PID: 0 at lib/dma-debug.c:986 check_sync+0x4c4/0x580() -skge 0000:02:07.0: DMA-API: device driver tries to sync DMA memory it has -not allocated [device address=0x000000023a0096c0] [size=1536 bytes] - -This patch makes the skge driver pass the correct value to -pci_unmap_single and fixes the warning. It copies the old descriptor to -on-stack variable "ee" and unmaps it if mapping of the new descriptor -succeeded. - -This patch should be backported to 3.11-stable. - -Signed-off-by: Mikulas Patocka -Reported-by: Francois Romieu -Tested-by: Mikulas Patocka -Signed-off-by: David S. Miller ---- -diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c -index 1a9c4f6..ecc7f7b 100644 ---- a/drivers/net/ethernet/marvell/skge.c -+++ b/drivers/net/ethernet/marvell/skge.c -@@ -3086,13 +3086,16 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, - PCI_DMA_FROMDEVICE); - skge_rx_reuse(e, skge->rx_buf_size); - } else { -+ struct skge_element ee; - struct sk_buff *nskb; - - nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size); - if (!nskb) - goto resubmit; - -- skb = e->skb; -+ ee = *e; -+ -+ skb = ee.skb; - prefetch(skb->data); - - if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) { -@@ -3101,8 +3104,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, - } - - pci_unmap_single(skge->hw->pdev, -- dma_unmap_addr(e, mapaddr), -- dma_unmap_len(e, maplen), -+ dma_unmap_addr(&ee, mapaddr), -+ dma_unmap_len(&ee, maplen), - PCI_DMA_FROMDEVICE); - } - --- -cgit v0.9.2 diff --git a/sources b/sources index 85810a7b6..ba90d655f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -5147e7f82600452c5438f8309c07eccd patch-3.11.4.xz +628876a432c0d4090013b383abac20e4 patch-3.11.5.xz diff --git a/tuntap-correctly-handle-error-in-tun_set_iff.patch b/tuntap-correctly-handle-error-in-tun_set_iff.patch deleted file mode 100644 index 563526765..000000000 --- a/tuntap-correctly-handle-error-in-tun_set_iff.patch +++ /dev/null @@ -1,57 +0,0 @@ -From dff4e504b2addc8053fc47712d44a21f733ef51b Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Wed, 11 Sep 2013 18:09:48 +0800 -Subject: [PATCH] tuntap: correctly handle error in tun_set_iff() - -Commit c8d68e6be1c3b242f1c598595830890b65cea64a -(tuntap: multiqueue support) only call free_netdev() on error in -tun_set_iff(). This causes several issues: - -- memory of tun security were leaked -- use after free since the flow gc timer was not deleted and the tfile - were not detached - -This patch solves the above issues. - -Reported-by: Wannes Rombouts -Cc: Michael S. Tsirkin -Signed-off-by: Jason Wang ---- - drivers/net/tun.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index 71af122..68b9aa3 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -1691,11 +1691,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) - INIT_LIST_HEAD(&tun->disabled); - err = tun_attach(tun, file); - if (err < 0) -- goto err_free_dev; -+ goto err_free_flow; - - err = register_netdevice(tun->dev); - if (err < 0) -- goto err_free_dev; -+ goto err_detach; - - if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || - device_create_file(&tun->dev->dev, &dev_attr_owner) || -@@ -1739,7 +1739,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) - strcpy(ifr->ifr_name, tun->dev->name); - return 0; - -- err_free_dev: -+err_detach: -+ tun_detach_all(dev); -+err_free_flow: -+ tun_flow_uninit(tun); -+ security_tun_dev_free_security(tun->security); -+err_free_dev: - free_netdev(dev); - return err; - } --- -1.8.3.1 - From 3b13d9541963344902db97d59aa461a97057597d Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 10 Jul 2013 10:33:31 -0400 Subject: [PATCH 442/492] Fix crash-driver.patch to properly use page_is_ram. --- crash-driver.patch | 17 +---------------- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/crash-driver.patch b/crash-driver.patch index 239f0f6a0..a7b7b72f9 100644 --- a/crash-driver.patch +++ b/crash-driver.patch @@ -131,7 +131,7 @@ new file mode 100644 index 0000000..dfcc006 --- /dev/null +++ b/arch/x86/include/asm/crash.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,73 @@ +#ifndef _ASM_I386_CRASH_H +#define _ASM_I386_CRASH_H + @@ -162,8 +162,6 @@ index 0000000..dfcc006 +#include +#include + -+extern int page_is_ram(unsigned long); -+ +static inline void * +map_virtual(u64 offset, struct page **pp) +{ @@ -207,19 +205,6 @@ index 0000000..dfcc006 +#endif /* __KERNEL__ */ + +#endif /* _ASM_I386_CRASH_H */ -diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c -index be1ef57..ac659f7 100644 ---- a/arch/x86/mm/ioremap.c -+++ b/arch/x86/mm/ioremap.c -@@ -24,6 +24,8 @@ - - #include "physaddr.h" - -+EXPORT_SYMBOL_GPL(page_is_ram); -+ - /* - * Fix up the linear direct mapping of the kernel to avoid cache attribute - * conflicts. diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 423fd56..e04a561 100644 --- a/drivers/char/Kconfig diff --git a/kernel.spec b/kernel.spec index bdd8028e4..2950b5a89 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2320,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Mon Oct 14 2013 Kyle McMartin +- Fix crash-driver.patch to properly use page_is_ram. + * Mon Oct 14 2013 Justin M. Forbes - 3.11.5-100 - Linux v3.11.5 From 6a04643da5ab6d50c29ba81d2a533d51b74cfbc1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 15 Oct 2013 11:50:58 -0400 Subject: [PATCH 443/492] Fix regression in radeon sound (rhbz 1010679) --- fix-radeon-sound.patch | 154 +++++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 163 insertions(+) create mode 100644 fix-radeon-sound.patch diff --git a/fix-radeon-sound.patch b/fix-radeon-sound.patch new file mode 100644 index 000000000..6e59256bb --- /dev/null +++ b/fix-radeon-sound.patch @@ -0,0 +1,154 @@ +From 062c2e4363451d49ef840232fe65e8bff0dde2a5 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 27 Sep 2013 18:09:54 -0400 +Subject: [PATCH 1/4] drm/radeon: use 64-bit math to calculate CTS values for + audio (v2) + +Avoid losing precision. See bug: +https://bugs.freedesktop.org/show_bug.cgi?id=69675 + +v2: fix math as per Anssi's comments. + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index b0fa600..49043a5 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -75,8 +75,15 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + */ + static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) + { +- if (*CTS == 0) +- *CTS = clock * N / (128 * freq) * 1000; ++ u64 n; ++ u32 d; ++ ++ if (*CTS == 0) { ++ n = (u64)clock * (u64)N * 1000ULL; ++ d = 128 * freq; ++ do_div(n, d); ++ *CTS = n; ++ } + DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", + N, *CTS, freq); + } +-- +1.8.3.1 + + +From e7d12c2f98ae1e68c7298e5028048d150fa553a1 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 27 Sep 2013 18:19:42 -0400 +Subject: [PATCH 2/4] drm/radeon: fix N/CTS clock matching for audio + +The drm code that calculates the 1001 clocks rounds up +rather than truncating. This allows the table to match +properly on those modes. + +See bug: +https://bugs.freedesktop.org/show_bug.cgi?id=69675 + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index 49043a5..567703f 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -57,15 +57,15 @@ enum r600_hdmi_iec_status_bits { + static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ +- { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ ++ { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ +- { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ ++ { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ +- { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ ++ { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ + { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ + }; +-- +1.8.3.1 + + +From ee0fec312a1c4e26f255955da942562cd8908a4b Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 27 Sep 2013 18:22:15 -0400 +Subject: [PATCH 3/4] drm/radeon: use hw generated CTS/N values for audio + +Use the hw generated values rather than calculating +them in the driver. There may be some older r6xx +asics where this doesn't work correctly. This remains +to be seen. + +See bug: +https://bugs.freedesktop.org/show_bug.cgi?id=69675 + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index 567703f..e2ae1c2 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -451,8 +451,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod + } + + WREG32(HDMI0_ACR_PACKET_CONTROL + offset, +- HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ +- HDMI0_ACR_SOURCE); /* select SW CTS value */ ++ HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND | /* send null packets when required */ +-- +1.8.3.1 + + +From b852c985010a77c850b7548d64bbb964ca462b02 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 10 Oct 2013 11:47:01 -0400 +Subject: [PATCH 4/4] drm/radeon: re-enable sw ACR support on pre-DCE4 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +HW ACR support may have issues on some older chips, so +use SW ACR for now until we've tested further. + +Signed-off-by: Alex Deucher +CC: Rafał Miłecki +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index e2ae1c2..5b72931 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -451,6 +451,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod + } + + WREG32(HDMI0_ACR_PACKET_CONTROL + offset, ++ HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ + HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 2950b5a89..264a0af8c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -771,6 +771,9 @@ Patch25128: dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch #rhbz 1000439 Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch +#rhbz 1010679 +Patch25130: fix-radeon-sound.patch + # END OF PATCH DEFINITIONS %endif @@ -1479,6 +1482,9 @@ ApplyPatch dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch #rhbz 1000439 ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch +#rhbz 1010679 +ApplyPatch fix-radeon-sound.patch + # END OF PATCH APPLICATIONS %endif @@ -2320,6 +2326,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 15 2013 Josh Boyer +- Fix regression in radeon sound (rhbz 1010679) + * Mon Oct 14 2013 Kyle McMartin - Fix crash-driver.patch to properly use page_is_ram. From be5fc1698aa1157a7deb05e7390ad9ce5fcac9db Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 16 Oct 2013 13:50:26 -0400 Subject: [PATCH 444/492] Fix btrfs balance/scrub issue (rhbz 1011714) --- ...ate-csums-properly-with-prealloc-ext.patch | 60 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 btrfs-relocate-csums-properly-with-prealloc-ext.patch diff --git a/btrfs-relocate-csums-properly-with-prealloc-ext.patch b/btrfs-relocate-csums-properly-with-prealloc-ext.patch new file mode 100644 index 000000000..e103f703a --- /dev/null +++ b/btrfs-relocate-csums-properly-with-prealloc-ext.patch @@ -0,0 +1,60 @@ +A user reported a problem where they were getting csum errors when running a +balance and running systemd's journal. This is because systemd is awesome and +fallocate()'s its log space and writes into it. Unfortunately we assume that +when we read in all the csums for an extent that they are sequential starting at +the bytenr we care about. This obviously isn't the case for prealloc extents, +where we could have written to the middle of the prealloc extent only, which +means the csum would be for the bytenr in the middle of our range and not the +front of our range. Fix this by offsetting the new bytenr we are logging to +based on the original bytenr the csum was for. With this patch I no longer see +the csum errors I was seeing. Thanks, + +Cc: stable@xxxxxxxxxxxxxxx +Reported-by: Chris Murphy +Signed-off-by: Josef Bacik +--- + fs/btrfs/relocation.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 5ca7ea9..b7afeaa 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -4472,6 +4472,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) + struct btrfs_root *root = BTRFS_I(inode)->root; + int ret; + u64 disk_bytenr; ++ u64 new_bytenr; + LIST_HEAD(list); + + ordered = btrfs_lookup_ordered_extent(inode, file_pos); +@@ -4483,13 +4484,24 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) + if (ret) + goto out; + +- disk_bytenr = ordered->start; + while (!list_empty(&list)) { + sums = list_entry(list.next, struct btrfs_ordered_sum, list); + list_del_init(&sums->list); + +- sums->bytenr = disk_bytenr; +- disk_bytenr += sums->len; ++ /* ++ * We need to offset the new_bytenr based on where the csum is. ++ * We need to do this because we will read in entire prealloc ++ * extents but we may have written to say the middle of the ++ * prealloc extent, so we need to make sure the csum goes with ++ * the right disk offset. ++ * ++ * We can do this because the data reloc inode refers strictly ++ * to the on disk bytes, so we don't have to worry about ++ * disk_len vs real len like with real inodes since it's all ++ * disk length. ++ */ ++ new_bytenr = ordered->start + (sums->bytenr - disk_bytenr); ++ sums->bytenr = new_bytenr; + + btrfs_add_ordered_sum(inode, ordered, sums); + } +-- +1.8.3.1 diff --git a/kernel.spec b/kernel.spec index 264a0af8c..1adc618ca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -774,6 +774,9 @@ Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch #rhbz 1010679 Patch25130: fix-radeon-sound.patch +#rhbz 1011714 +Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch + # END OF PATCH DEFINITIONS %endif @@ -1485,6 +1488,9 @@ ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch #rhbz 1010679 ApplyPatch fix-radeon-sound.patch +#rhbz 1011714 +ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch + # END OF PATCH APPLICATIONS %endif @@ -2326,6 +2332,9 @@ fi # ||----w | # || || %changelog +* Wed Oct 16 2013 Josh Boyer +- Fix btrfs balance/scrub issue (rhbz 1011714) + * Tue Oct 15 2013 Josh Boyer - Fix regression in radeon sound (rhbz 1010679) From 12c7ac7fb8a0a9aa28259fb2eb408ba853f3f079 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 17 Oct 2013 08:12:25 -0400 Subject: [PATCH 445/492] Fix rt2800usb polling timeouts and throughput issues (rhbz 984696) --- kernel.spec | 9 ++++ rt2800usb-slow-down-TX-status-polling.patch | 53 +++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 rt2800usb-slow-down-TX-status-polling.patch diff --git a/kernel.spec b/kernel.spec index 1adc618ca..b74c6d0a1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -777,6 +777,9 @@ Patch25130: fix-radeon-sound.patch #rhbz 1011714 Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch +#rhbz 984696 +Patch25132: rt2800usb-slow-down-TX-status-polling.patch + # END OF PATCH DEFINITIONS %endif @@ -1491,6 +1494,9 @@ ApplyPatch fix-radeon-sound.patch #rhbz 1011714 ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch +#rhbz 984696 +ApplyPatch rt2800usb-slow-down-TX-status-polling.patch + # END OF PATCH APPLICATIONS %endif @@ -2332,6 +2338,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 17 2013 Josh Boyer +- Fix rt2800usb polling timeouts and throughput issues (rhbz 984696) + * Wed Oct 16 2013 Josh Boyer - Fix btrfs balance/scrub issue (rhbz 1011714) diff --git a/rt2800usb-slow-down-TX-status-polling.patch b/rt2800usb-slow-down-TX-status-polling.patch new file mode 100644 index 000000000..a76f9b847 --- /dev/null +++ b/rt2800usb-slow-down-TX-status-polling.patch @@ -0,0 +1,53 @@ +Polling TX statuses too frequently has two negative effects. First is +randomly peek CPU usage, causing overall system functioning delays. +Second bad effect is that device is not able to fill TX statuses in +H/W register on some workloads and we get lot of timeouts like below: + +ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 +ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 +ieee80211 phy4: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping + +This not only cause flood of messages in dmesg, but also bad throughput, +since rate scaling algorithm can not work optimally. + +In the future, we should probably make polling interval be adjusted +automatically, but for now just increase values, this make mentioned +problems gone. + +Resolve: +https://bugzilla.kernel.org/show_bug.cgi?id=62781 + +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index 96677ce5..e095e61 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -176,8 +176,8 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + + if (rt2800usb_txstatus_pending(rt2x00dev)) { +- /* Read register after 250 us */ +- hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), ++ /* Read register after 1 ms */ ++ hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 1000000), + HRTIMER_MODE_REL); + return false; + } +@@ -202,8 +202,8 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) + if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) + return; + +- /* Read TX_STA_FIFO register after 500 us */ +- hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000), ++ /* Read TX_STA_FIFO register after 2 ms */ ++ hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 2000000), + HRTIMER_MODE_REL); + } + +-- +1.8.3.1 From d84051241bee3db9cd7adb02f9b2efe16cb28b79 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 17 Oct 2013 10:16:07 -0400 Subject: [PATCH 446/492] Add patch to fix BusLogic error (rhbz 1015558) --- fix-buslogic.patch | 121 +++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 128 insertions(+) create mode 100644 fix-buslogic.patch diff --git a/fix-buslogic.patch b/fix-buslogic.patch new file mode 100644 index 000000000..0862d00aa --- /dev/null +++ b/fix-buslogic.patch @@ -0,0 +1,121 @@ +This fixes an oops caused by buslogic driver when initializing a BusLogic +MultiMaster adapter. Initialization code used scope of a variable +incorrectly which created a NULL pointer. Oops message is below: + +BUG: unable to handle kernel NULL pointer dereference at 0000000c +IP: [] blogic_init_mm_probeinfo.isra.17+0x20a/0x583 +*pde = 00000000 +Oops: 002 [#1] PREEMPT SMP +Modules linked in: +CPU: 1 PID: 1 Comm: swapper/0 Not tainted 3.11.1.puz1 #1 +Hardware name: /Canterwood, BIOS 6.00 PG 05/16/2003 +task: f7050000 ti: f7054000 task.ti: f7054000 +EIP: 0060:[] EFLAGS: 00010246 CPU:1 +EIP is at blogic_init_mm_probeinfo.isra.17+0x20a/0x583 +EAX: 00000013 EBX: 00000000 ECX: 00000000 EDX: f8001000 +ESI: f71cb800 EDI: f7388000 EBP: 00007800 ESP: f7055c84 + DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 +CR0: 8005003b CR2: 0000000c CR3: 0154f000 CR4: 000007d0 +Stack: + 0000001c 00000000 c11a59f6 f7055c98 00008130 ffffffff ffffffff 00000000 + 00000003 00000000 00000000 00000000 00000013 f8001000 00000001 000003d0 + 00000000 00000000 00000000 c14e3f84 f78803c8 00000000 f738c000 000000e9 +Call Trace: + [] ? pci_get_subsys+0x33/0x38 + [] ? blogic_init_probeinfo_list+0x4b/0x19e + [] ? __alloc_pages_nodemask+0xe3/0x623 + [] ? __alloc_pages_nodemask+0xe3/0x623 + [] ? sysfs_link_sibling+0x61/0x8d + [] ? kmem_cache_alloc+0x8b/0xb5 + [] ? blogic_init+0xa1/0x10e8 + [] ? sysfs_add_one+0x10/0x9d + [] ? sysfs_addrm_finish+0x12/0x85 + [] ? sysfs_do_create_link_sd+0x9d/0x1b4 + [] ? blk_register_queue+0x69/0xb3 + [] ? sysfs_create_link+0x1a/0x2c + [] ? add_disk+0x1a1/0x3c7 + [] ? klist_next+0x60/0xc3 + [] ? scsi_dh_detach+0x68/0x68 + [] ? bus_for_each_dev+0x51/0x61 + [] ? do_one_initcall+0x22/0x12c + [] ? __proc_create+0x8c/0xba + [] ? blogic_setup+0x5f6/0x5f6 + [] ? repair_env_string+0xf/0x4d + [] ? do_early_param+0x71/0x71 + [] ? parse_args+0x21f/0x33d + [] ? kernel_init_freeable+0xdf/0x17d + [] ? do_early_param+0x71/0x71 + [] ? kernel_init+0x8/0xc0 + [] ? ret_from_kernel_thread+0x6/0x28 + [] ? ret_from_kernel_thread+0x1b/0x28 + [] ? rest_init+0x6c/0x6c +Code: 89 44 24 10 0f b6 44 24 3d 89 44 24 0c c7 44 24 08 00 00 00 00 c7 44 24 04 38 62 46 c1 c7 04 24 02 00 00 00 e8 78 13 d2 ff 31 db <89> 6b 0c b0 20 89 ea ee + c7 44 24 08 04 00 00 00 8d 44 24 4c 89 +EIP: [] blogic_init_mm_probeinfo.isra.17+0x20a/0x583 SS:ESP 0068:f7055c84 +CR2: 000000000000000c +---[ end trace 17f45f5196d40487 ]--- +Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000009 + +Signed-off-by: Khalid Aziz +Cc: # 3.11.x +Cc: Khalid Aziz +Reported-by: Pierre Uszynski +Tested-by: Pierre Uszynski +--- + drivers/scsi/BusLogic.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c +index feab3a5..757eb07 100644 +--- a/drivers/scsi/BusLogic.c ++++ b/drivers/scsi/BusLogic.c +@@ -696,7 +696,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) + while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, + PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, + pci_device)) != NULL) { +- struct blogic_adapter *adapter = adapter; ++ struct blogic_adapter *host_adapter = adapter; + struct blogic_adapter_info adapter_info; + enum blogic_isa_ioport mod_ioaddr_req; + unsigned char bus; +@@ -744,9 +744,9 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) + known and enabled, note that the particular Standard ISA I/O + Address should not be probed. + */ +- adapter->io_addr = io_addr; +- blogic_intreset(adapter); +- if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, ++ host_adapter->io_addr = io_addr; ++ blogic_intreset(host_adapter); ++ if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, + &adapter_info, sizeof(adapter_info)) == + sizeof(adapter_info)) { + if (adapter_info.isa_port < 6) +@@ -762,7 +762,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) + I/O Address assigned at system initialization. + */ + mod_ioaddr_req = BLOGIC_IO_DISABLE; +- blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, ++ blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, + sizeof(mod_ioaddr_req), NULL, 0); + /* + For the first MultiMaster Host Adapter enumerated, +@@ -779,12 +779,12 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) + + fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45; + fetch_localram.count = sizeof(autoscsi_byte45); +- blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, ++ blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM, + &fetch_localram, sizeof(fetch_localram), + &autoscsi_byte45, + sizeof(autoscsi_byte45)); +- blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id, +- sizeof(id)); ++ blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0, ++ &id, sizeof(id)); + if (id.fw_ver_digit1 == '5') + force_scan_order = + autoscsi_byte45.force_scan_order; +-- +1.7.10.4 + diff --git a/kernel.spec b/kernel.spec index b74c6d0a1..a7f66baef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -780,6 +780,9 @@ Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch #rhbz 984696 Patch25132: rt2800usb-slow-down-TX-status-polling.patch +#rhbz 1015558 +Patch25133: fix-buslogic.patch + # END OF PATCH DEFINITIONS %endif @@ -1497,6 +1500,9 @@ ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch #rhbz 984696 ApplyPatch rt2800usb-slow-down-TX-status-polling.patch +#rhbz 1015558 +ApplyPatch fix-buslogic.patch + # END OF PATCH APPLICATIONS %endif @@ -2339,6 +2345,7 @@ fi # || || %changelog * Thu Oct 17 2013 Josh Boyer +- Add patch to fix BusLogic error (rhbz 1015558) - Fix rt2800usb polling timeouts and throughput issues (rhbz 984696) * Wed Oct 16 2013 Josh Boyer From e097dcad4d0c6e33513ea2a2b77b7579ce997eb1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 18 Oct 2013 17:13:57 -0500 Subject: [PATCH 447/492] Linux v3.11.6 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index a7f66baef..59552a840 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2344,6 +2344,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 18 2013 Justin M. Forbes - 3.11.6-100 +- Linux v3.11.6 + * Thu Oct 17 2013 Josh Boyer - Add patch to fix BusLogic error (rhbz 1015558) - Fix rt2800usb polling timeouts and throughput issues (rhbz 984696) diff --git a/sources b/sources index ba90d655f..91571dae8 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -628876a432c0d4090013b383abac20e4 patch-3.11.5.xz +c44ebb225fe9956b636b79ab6b61aa42 patch-3.11.6.xz From 10ef192fcaa2b1a1b5ea8897a5b50fd4586bfd99 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 22 Oct 2013 10:24:30 -0400 Subject: [PATCH 448/492] Add patch to fix warning in tcp_fastretrans_alert (rhbz 989251) --- kernel.spec | 9 ++ ...ncorrect-ca_state-in-tail-loss-probe.patch | 107 ++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch diff --git a/kernel.spec b/kernel.spec index 59552a840..85a06767e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -783,6 +783,9 @@ Patch25132: rt2800usb-slow-down-TX-status-polling.patch #rhbz 1015558 Patch25133: fix-buslogic.patch +#rhbz 989251 +Patch25134: tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch + # END OF PATCH DEFINITIONS %endif @@ -1503,6 +1506,9 @@ ApplyPatch rt2800usb-slow-down-TX-status-polling.patch #rhbz 1015558 ApplyPatch fix-buslogic.patch +#rhbz 989251 +ApplyPatch tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch + # END OF PATCH APPLICATIONS %endif @@ -2344,6 +2350,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 22 2013 Josh Boyer +- Add patch to fix warning in tcp_fastretrans_alert (rhbz 989251) + * Fri Oct 18 2013 Justin M. Forbes - 3.11.6-100 - Linux v3.11.6 diff --git a/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch b/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch new file mode 100644 index 000000000..1a1264ffa --- /dev/null +++ b/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch @@ -0,0 +1,107 @@ +Path: news.gmane.org!not-for-mail +From: Yuchung Cheng +Newsgroups: gmane.linux.network +Subject: [PATCH net] tcp: fix incorrect ca_state in tail loss probe +Date: Sat, 12 Oct 2013 10:16:27 -0700 +Lines: 34 +Approved: news@gmane.org +Message-ID: <1381598187-9681-1-git-send-email-ycheng@google.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: ger.gmane.org 1381598242 29686 80.91.229.3 (12 Oct 2013 17:17:22 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Sat, 12 Oct 2013 17:17:22 +0000 (UTC) +Cc: netdev@vger.kernel.org, michael@sterretts.net, + jwboyer@fedoraproject.org, sesse@google.com, dormando@rydia.net, + Yuchung Cheng +To: davem@davemloft.net, ncardwell@google.com, nanditad@google.com +Original-X-From: netdev-owner@vger.kernel.org Sat Oct 12 19:17:23 2013 +Return-path: +Envelope-to: linux-netdev-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1VV2od-0004tp-02 + for linux-netdev-2@plane.gmane.org; Sat, 12 Oct 2013 19:17:23 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753183Ab3JLRRU (ORCPT ); + Sat, 12 Oct 2013 13:17:20 -0400 +Original-Received: from mail-pb0-f74.google.com ([209.85.160.74]:35839 "EHLO + mail-pb0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1752493Ab3JLRRS (ORCPT + ); Sat, 12 Oct 2013 13:17:18 -0400 +Original-Received: by mail-pb0-f74.google.com with SMTP id rq2so543459pbb.1 + for ; Sat, 12 Oct 2013 10:17:18 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20120113; + h=from:to:cc:subject:date:message-id; + bh=YSBIMZEgVuqyP2cau1199a1sz5d28JA7LPPsF6w9FYQ=; + b=cCkXgePT7f0kRy+VBGvs3DZSLhVn0z7O74B7OHYpdZkQBznhNZ2b6ZGbkDqaKJXyLT + GEsq/JXCgtwpC7aGSz9dPdAZU6kondKOAmfhh54u6f2+ymcZJ4zHpoA6mWuKJ4zlTF2w + 6tRhnT+/N5RkfIfYD/mcDx97X41kRT3NKJ6bsCoiNJIO2+6j8SrOi8C27InOkdIRY/AT + I1uu2bvai1CfrC5yQ6UfpKUg2jioFDOi7i5nSEon+JnWeJavHpO01JMHuar7ZeGnAKJg + kVLwyiRujU9Fz0CKIMPZihAngQu/0OgqORQIjygeqz+GPgtTxDGQP7IUNR/d+JOPVUse + XlSA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20130820; + h=x-gm-message-state:from:to:cc:subject:date:message-id; + bh=YSBIMZEgVuqyP2cau1199a1sz5d28JA7LPPsF6w9FYQ=; + b=d95i7RXY0ff5vnWvrGqxWfSvvAE8SC6YAaBn3ZqbARIZm5GgynIAB/WYnrIOqpqGV6 + 56jVM40bfzLrols1UZzyJWqPIgxee1zPrESh+WrSsDP2tTdYKl/zk13lbt/u7nOn9o3u + HrAo2aY4DtV3P0ABEq1lKdazmmPACTc6256QQ2nxtHs5n7s7P1ERkpX7NGNqNf1zDBSv + 60xeoswRpMkh0G5ZUgpPYsIbXws9F64n5ytq34O2UDZPv5oPEd8I7P34HpqWkNsLoEBs + XXTxs1SLc8TI3vdduhaQ+rmEvcE5vTaqjVCQAT2mMKTJJ9xIFueF5zExfI892PHAcJQ8 + jiaw== +X-Gm-Message-State: ALoCoQkeL+3MY64KlpZKI1BuYMU+yTQcYF1C+U5u+kPpqROoekUMzIaH45qERBARAi/0vgJ5YM1Cwm+43d66vZMn/WdHPurbMHfFn3PYqeZSAzOEeuSA2jGTSZUkpuH8YwFqiNhABtj93ahsBXrA6POrXb531UvuahU+rnFLTGNLxVHv/08PW3l5PbN8UaTNpUI1qcf6O6MarFcB+fZLYPb339v4EIrLxg== +X-Received: by 10.66.5.226 with SMTP id v2mr8825633pav.22.1381598238410; + Sat, 12 Oct 2013 10:17:18 -0700 (PDT) +Original-Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) + by gmr-mx.google.com with ESMTPS id a24si3247317yhl.1.1969.12.31.16.00.00 + (version=TLSv1.1 cipher=AES128-SHA bits=128/128); + Sat, 12 Oct 2013 10:17:18 -0700 (PDT) +Original-Received: from blast2.mtv.corp.google.com (blast2.mtv.corp.google.com [172.17.132.164]) + by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 2F2B45A41A0; + Sat, 12 Oct 2013 10:17:18 -0700 (PDT) +Original-Received: by blast2.mtv.corp.google.com (Postfix, from userid 5463) + id C6A85220C26; Sat, 12 Oct 2013 10:17:17 -0700 (PDT) +X-Mailer: git-send-email 1.8.4 +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:286793 +Archived-At: + +On receiving an ACK that covers the loss probe sequence, TLP +immediately sets the congestion state to Open, even though some packets +are not recovered and retransmisssion are on the way. The later ACks +may trigger a WARN_ON check in step D of tcp_fastretrans_alert(), e.g., +https://bugzilla.redhat.com/show_bug.cgi?id=989251 + +The fix is to follow the similar procedure in recovery by calling +tcp_try_keep_open(). The sender switches to Open state if no packets +are retransmissted. Otherwise it goes to Disorder and let subsequent +ACKs move the state to Recovery or Open. + +Reported-By: Michael Sterrett +Tested-By: Dormando +Signed-off-by: Yuchung Cheng +--- + net/ipv4/tcp_input.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 113dc5f..53974c7 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3291,7 +3291,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) + tcp_init_cwnd_reduction(sk, true); + tcp_set_ca_state(sk, TCP_CA_CWR); + tcp_end_cwnd_reduction(sk); +- tcp_set_ca_state(sk, TCP_CA_Open); ++ tcp_try_keep_open(sk); + NET_INC_STATS_BH(sock_net(sk), + LINUX_MIB_TCPLOSSPROBERECOVERY); + } +-- +1.8.4 + From 24372f67d80cac93d3fa4fbafe295376cc60e257 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 25 Oct 2013 12:43:16 -0400 Subject: [PATCH 449/492] Add touchpad support for Dell XT2 (rhbz 1023413) --- alps-Support-for-Dell-XT2-model.patch | 25 +++++++++++++++++++++++++ kernel.spec | 9 +++++++++ 2 files changed, 34 insertions(+) create mode 100644 alps-Support-for-Dell-XT2-model.patch diff --git a/alps-Support-for-Dell-XT2-model.patch b/alps-Support-for-Dell-XT2-model.patch new file mode 100644 index 000000000..453a6983a --- /dev/null +++ b/alps-Support-for-Dell-XT2-model.patch @@ -0,0 +1,25 @@ +From 7673be51f16e978a438bca8ac1bf9e939b7ed7a6 Mon Sep 17 00:00:00 2001 +From: Yunkang Tang +Date: Thu, 24 Oct 2013 13:39:08 +0800 +Subject: [PATCH] Support for Dell XT2 model + +Signed-off-by: Yunkang Tang +--- + drivers/input/mouse/alps.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index ca7a26f..24b3626 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -103,6 +103,7 @@ static const struct alps_model_info alps_model_data[] = { + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ + { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, ++ { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_DUALPOINT }, /* Dell XT2 */ + { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ +-- +1.8.1.2 + diff --git a/kernel.spec b/kernel.spec index 85a06767e..23389a51b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,6 +786,9 @@ Patch25133: fix-buslogic.patch #rhbz 989251 Patch25134: tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch +#rhbz 1023413 +Patch25135: alps-Support-for-Dell-XT2-model.patch + # END OF PATCH DEFINITIONS %endif @@ -1509,6 +1512,9 @@ ApplyPatch fix-buslogic.patch #rhbz 989251 ApplyPatch tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch +#rhbz 1023413 +ApplyPatch alps-Support-for-Dell-XT2-model.patch + # END OF PATCH APPLICATIONS %endif @@ -2350,6 +2356,9 @@ fi # ||----w | # || || %changelog +* Fri Oct 25 2013 Josh Boyer +- Add touchpad support for Dell XT2 (rhbz 1023413) + * Tue Oct 22 2013 Josh Boyer - Add patch to fix warning in tcp_fastretrans_alert (rhbz 989251) From d80bca6ba46730377c755874a9b91bcade76f27d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 25 Oct 2013 12:57:09 -0400 Subject: [PATCH 450/492] CVE-2013-XXXX net: memory corruption with UDP_CORK and UFO (rhbz 1023477 1023495) --- kernel.spec | 13 +- net_311.mbox | 3794 +++++++++++++++++ ...ncorrect-ca_state-in-tail-loss-probe.patch | 107 - 3 files changed, 3801 insertions(+), 113 deletions(-) create mode 100644 net_311.mbox delete mode 100644 tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch diff --git a/kernel.spec b/kernel.spec index 23389a51b..2b0a14d9f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -783,12 +783,12 @@ Patch25132: rt2800usb-slow-down-TX-status-polling.patch #rhbz 1015558 Patch25133: fix-buslogic.patch -#rhbz 989251 -Patch25134: tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch - #rhbz 1023413 Patch25135: alps-Support-for-Dell-XT2-model.patch +#CVE-2013-XXXX rhbz 1023477 1023495 +Patch25136: net_311.mbox + # END OF PATCH DEFINITIONS %endif @@ -1509,12 +1509,12 @@ ApplyPatch rt2800usb-slow-down-TX-status-polling.patch #rhbz 1015558 ApplyPatch fix-buslogic.patch -#rhbz 989251 -ApplyPatch tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch - #rhbz 1023413 ApplyPatch alps-Support-for-Dell-XT2-model.patch +#CVE-2013-XXXX rhbz 1023477 1023495 +ApplyPatch net_311.mbox + # END OF PATCH APPLICATIONS %endif @@ -2357,6 +2357,7 @@ fi # || || %changelog * Fri Oct 25 2013 Josh Boyer +- CVE-2013-XXXX net: memory corruption with UDP_CORK and UFO (rhbz 1023477 1023495) - Add touchpad support for Dell XT2 (rhbz 1023413) * Tue Oct 22 2013 Josh Boyer diff --git a/net_311.mbox b/net_311.mbox new file mode 100644 index 000000000..d420777dd --- /dev/null +++ b/net_311.mbox @@ -0,0 +1,3794 @@ +From 5444e381f5784d32d741864312909d2a6afe428e Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 27 Aug 2013 05:46:32 -0700 +Subject: [PATCH 01/47] tcp: TSO packets automatic sizing + +[ Upstream commits 6d36824e730f247b602c90e8715a792003e3c5a7, + 02cf4ebd82ff0ac7254b88e466820a290ed8289a, and parts of + 7eec4174ff29cd42f2acfae8112f51c228545d40 ] + +After hearing many people over past years complaining against TSO being +bursty or even buggy, we are proud to present automatic sizing of TSO +packets. + +One part of the problem is that tcp_tso_should_defer() uses an heuristic +relying on upcoming ACKS instead of a timer, but more generally, having +big TSO packets makes little sense for low rates, as it tends to create +micro bursts on the network, and general consensus is to reduce the +buffering amount. + +This patch introduces a per socket sk_pacing_rate, that approximates +the current sending rate, and allows us to size the TSO packets so +that we try to send one packet every ms. + +This field could be set by other transports. + +Patch has no impact for high speed flows, where having large TSO packets +makes sense to reach line rate. + +For other flows, this helps better packet scheduling and ACK clocking. + +This patch increases performance of TCP flows in lossy environments. + +A new sysctl (tcp_min_tso_segs) is added, to specify the +minimal size of a TSO packet (default being 2). + +A follow-up patch will provide a new packet scheduler (FQ), using +sk_pacing_rate as an input to perform optional per flow pacing. + +This explains why we chose to set sk_pacing_rate to twice the current +rate, allowing 'slow start' ramp up. + +sk_pacing_rate = 2 * cwnd * mss / srtt + +v2: Neal Cardwell reported a suspect deferring of last two segments on +initial write of 10 MSS, I had to change tcp_tso_should_defer() to take +into account tp->xmit_size_goal_segs + +Signed-off-by: Eric Dumazet +Cc: Neal Cardwell +Cc: Yuchung Cheng +Cc: Van Jacobson +Cc: Tom Herbert +Acked-by: Yuchung Cheng +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + Documentation/networking/ip-sysctl.txt | 9 +++++++++ + include/net/sock.h | 2 ++ + include/net/tcp.h | 1 + + net/core/sock.c | 1 + + net/ipv4/sysctl_net_ipv4.c | 10 ++++++++++ + net/ipv4/tcp.c | 28 +++++++++++++++++++++++----- + net/ipv4/tcp_input.c | 34 +++++++++++++++++++++++++++++++++- + net/ipv4/tcp_output.c | 2 +- + 8 files changed, 80 insertions(+), 7 deletions(-) + +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt +index 1074290..b522883 100644 +--- a/Documentation/networking/ip-sysctl.txt ++++ b/Documentation/networking/ip-sysctl.txt +@@ -478,6 +478,15 @@ tcp_syn_retries - INTEGER + tcp_timestamps - BOOLEAN + Enable timestamps as defined in RFC1323. + ++tcp_min_tso_segs - INTEGER ++ Minimal number of segments per TSO frame. ++ Since linux-3.12, TCP does an automatic sizing of TSO frames, ++ depending on flow rate, instead of filling 64Kbytes packets. ++ For specific usages, it's possible to force TCP to build big ++ TSO frames. Note that TCP stack might split too big TSO packets ++ if available window is too small. ++ Default: 2 ++ + tcp_tso_win_divisor - INTEGER + This allows control over what percentage of the congestion window + can be consumed by a single TSO frame. +diff --git a/include/net/sock.h b/include/net/sock.h +index 31d5cfb..04e148f 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -232,6 +232,7 @@ struct cg_proto; + * @sk_napi_id: id of the last napi context to receive data for sk + * @sk_ll_usec: usecs to busypoll when there is no data + * @sk_allocation: allocation mode ++ * @sk_pacing_rate: Pacing rate (if supported by transport/packet scheduler) + * @sk_sndbuf: size of send buffer in bytes + * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, + * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings +@@ -361,6 +362,7 @@ struct sock { + kmemcheck_bitfield_end(flags); + int sk_wmem_queued; + gfp_t sk_allocation; ++ u32 sk_pacing_rate; /* bytes per second */ + netdev_features_t sk_route_caps; + netdev_features_t sk_route_nocaps; + int sk_gso_type; +diff --git a/include/net/tcp.h b/include/net/tcp.h +index d198005..46cb8a4 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -284,6 +284,7 @@ extern int sysctl_tcp_thin_dupack; + extern int sysctl_tcp_early_retrans; + extern int sysctl_tcp_limit_output_bytes; + extern int sysctl_tcp_challenge_ack_limit; ++extern int sysctl_tcp_min_tso_segs; + + extern atomic_long_t tcp_memory_allocated; + extern struct percpu_counter tcp_sockets_allocated; +diff --git a/net/core/sock.c b/net/core/sock.c +index 2c097c5..8729d91 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2297,6 +2297,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) + sk->sk_ll_usec = sysctl_net_busy_read; + #endif + ++ sk->sk_pacing_rate = ~0U; + /* + * Before updating sk_refcnt, we must commit prior changes to memory + * (Documentation/RCU/rculist_nulls.txt for details) +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 610e324..6900b8b 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -29,6 +29,7 @@ + static int zero; + static int one = 1; + static int four = 4; ++static int gso_max_segs = GSO_MAX_SEGS; + static int tcp_retr1_max = 255; + static int ip_local_port_range_min[] = { 1, 1 }; + static int ip_local_port_range_max[] = { 65535, 65535 }; +@@ -754,6 +755,15 @@ static struct ctl_table ipv4_table[] = { + .extra2 = &four, + }, + { ++ .procname = "tcp_min_tso_segs", ++ .data = &sysctl_tcp_min_tso_segs, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &gso_max_segs, ++ }, ++ { + .procname = "udp_mem", + .data = &sysctl_udp_mem, + .maxlen = sizeof(sysctl_udp_mem), +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 95544e4..ec586e5 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -283,6 +283,8 @@ + + int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; + ++int sysctl_tcp_min_tso_segs __read_mostly = 2; ++ + struct percpu_counter tcp_orphan_count; + EXPORT_SYMBOL_GPL(tcp_orphan_count); + +@@ -789,12 +791,28 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, + xmit_size_goal = mss_now; + + if (large_allowed && sk_can_gso(sk)) { +- xmit_size_goal = ((sk->sk_gso_max_size - 1) - +- inet_csk(sk)->icsk_af_ops->net_header_len - +- inet_csk(sk)->icsk_ext_hdr_len - +- tp->tcp_header_len); ++ u32 gso_size, hlen; ++ ++ /* Maybe we should/could use sk->sk_prot->max_header here ? */ ++ hlen = inet_csk(sk)->icsk_af_ops->net_header_len + ++ inet_csk(sk)->icsk_ext_hdr_len + ++ tp->tcp_header_len; ++ ++ /* Goal is to send at least one packet per ms, ++ * not one big TSO packet every 100 ms. ++ * This preserves ACK clocking and is consistent ++ * with tcp_tso_should_defer() heuristic. ++ */ ++ gso_size = sk->sk_pacing_rate / (2 * MSEC_PER_SEC); ++ gso_size = max_t(u32, gso_size, ++ sysctl_tcp_min_tso_segs * mss_now); ++ ++ xmit_size_goal = min_t(u32, gso_size, ++ sk->sk_gso_max_size - 1 - hlen); + +- /* TSQ : try to have two TSO segments in flight */ ++ /* TSQ : try to have at least two segments in flight ++ * (one in NIC TX ring, another in Qdisc) ++ */ + xmit_size_goal = min_t(u32, xmit_size_goal, + sysctl_tcp_limit_output_bytes >> 1); + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 3ca2139..2f0e94b 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -688,6 +688,34 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) + } + } + ++/* Set the sk_pacing_rate to allow proper sizing of TSO packets. ++ * Note: TCP stack does not yet implement pacing. ++ * FQ packet scheduler can be used to implement cheap but effective ++ * TCP pacing, to smooth the burst on large writes when packets ++ * in flight is significantly lower than cwnd (or rwin) ++ */ ++static void tcp_update_pacing_rate(struct sock *sk) ++{ ++ const struct tcp_sock *tp = tcp_sk(sk); ++ u64 rate; ++ ++ /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */ ++ rate = (u64)tp->mss_cache * 2 * (HZ << 3); ++ ++ rate *= max(tp->snd_cwnd, tp->packets_out); ++ ++ /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3), ++ * be conservative and assume srtt = 1 (125 us instead of 1.25 ms) ++ * We probably need usec resolution in the future. ++ * Note: This also takes care of possible srtt=0 case, ++ * when tcp_rtt_estimator() was not yet called. ++ */ ++ if (tp->srtt > 8 + 2) ++ do_div(rate, tp->srtt); ++ ++ sk->sk_pacing_rate = min_t(u64, rate, ~0U); ++} ++ + /* Calculate rto without backoff. This is the second half of Van Jacobson's + * routine referred to above. + */ +@@ -3269,7 +3297,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + u32 ack_seq = TCP_SKB_CB(skb)->seq; + u32 ack = TCP_SKB_CB(skb)->ack_seq; + bool is_dupack = false; +- u32 prior_in_flight; ++ u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt; + u32 prior_fackets; + int prior_packets = tp->packets_out; + const int prior_unsacked = tp->packets_out - tp->sacked_out; +@@ -3375,6 +3403,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + + if (icsk->icsk_pending == ICSK_TIME_RETRANS) + tcp_schedule_loss_probe(sk); ++ if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd) ++ tcp_update_pacing_rate(sk); + return 1; + + no_queue: +@@ -5671,6 +5701,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, + } else + tcp_init_metrics(sk); + ++ tcp_update_pacing_rate(sk); ++ + /* Prevent spurious tcp_cwnd_restart() on first data packet */ + tp->lsndtime = tcp_time_stamp; + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 170737a..7b263c3 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1628,7 +1628,7 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) + + /* If a full-sized TSO skb can be sent, do it. */ + if (limit >= min_t(unsigned int, sk->sk_gso_max_size, +- sk->sk_gso_max_segs * tp->mss_cache)) ++ tp->xmit_size_goal_segs * tp->mss_cache)) + goto send_now; + + /* Middle in queue won't get any more data, full sendable already? */ +-- +1.7.11.7 + + +From 1b6c7d9979e1db1d42bd0545452a9d204c019582 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 27 Sep 2013 03:28:54 -0700 +Subject: [PATCH 02/47] tcp: TSQ can use a dynamic limit + +[ Upstream commit c9eeec26e32e087359160406f96e0949b3cc6f10 ] + +When TCP Small Queues was added, we used a sysctl to limit amount of +packets queues on Qdisc/device queues for a given TCP flow. + +Problem is this limit is either too big for low rates, or too small +for high rates. + +Now TCP stack has rate estimation in sk->sk_pacing_rate, and TSO +auto sizing, it can better control number of packets in Qdisc/device +queues. + +New limit is two packets or at least 1 to 2 ms worth of packets. + +Low rates flows benefit from this patch by having even smaller +number of packets in queues, allowing for faster recovery, +better RTT estimations. + +High rates flows benefit from this patch by allowing more than 2 packets +in flight as we had reports this was a limiting factor to reach line +rate. [ In particular if TX completion is delayed because of coalescing +parameters ] + +Example for a single flow on 10Gbp link controlled by FQ/pacing + +14 packets in flight instead of 2 + +$ tc -s -d qd +qdisc fq 8001: dev eth0 root refcnt 32 limit 10000p flow_limit 100p +buckets 1024 quantum 3028 initial_quantum 15140 + Sent 1168459366606 bytes 771822841 pkt (dropped 0, overlimits 0 +requeues 6822476) + rate 9346Mbit 771713pps backlog 953820b 14p requeues 6822476 + 2047 flow, 2046 inactive, 1 throttled, delay 15673 ns + 2372 gc, 0 highprio, 0 retrans, 9739249 throttled, 0 flows_plimit + +Note that sk_pacing_rate is currently set to twice the actual rate, but +this might be refined in the future when a flow is in congestion +avoidance. + +Additional change : skb->destructor should be set to tcp_wfree(). + +A future patch (for linux 3.13+) might remove tcp_limit_output_bytes + +Signed-off-by: Eric Dumazet +Cc: Wei Liu +Cc: Cong Wang +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_output.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 7b263c3..fe897ed 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -892,8 +892,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, + + skb_orphan(skb); + skb->sk = sk; +- skb->destructor = (sysctl_tcp_limit_output_bytes > 0) ? +- tcp_wfree : sock_wfree; ++ skb->destructor = tcp_wfree; + atomic_add(skb->truesize, &sk->sk_wmem_alloc); + + /* Build TCP header and checksum it. */ +@@ -1837,7 +1836,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + while ((skb = tcp_send_head(sk))) { + unsigned int limit; + +- + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); + BUG_ON(!tso_segs); + +@@ -1866,13 +1864,20 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + break; + } + +- /* TSQ : sk_wmem_alloc accounts skb truesize, +- * including skb overhead. But thats OK. ++ /* TCP Small Queues : ++ * Control number of packets in qdisc/devices to two packets / or ~1 ms. ++ * This allows for : ++ * - better RTT estimation and ACK scheduling ++ * - faster recovery ++ * - high rates + */ +- if (atomic_read(&sk->sk_wmem_alloc) >= sysctl_tcp_limit_output_bytes) { ++ limit = max(skb->truesize, sk->sk_pacing_rate >> 10); ++ ++ if (atomic_read(&sk->sk_wmem_alloc) > limit) { + set_bit(TSQ_THROTTLED, &tp->tsq_flags); + break; + } ++ + limit = mss_now; + if (tso_segs > 1 && !tcp_urg_mode(tp)) + limit = tcp_mss_split_point(sk, skb, mss_now, +-- +1.7.11.7 + + +From 4f25abff83e2780265eaa17d437b7659ea543bd5 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 15 Oct 2013 11:54:30 -0700 +Subject: [PATCH 03/47] tcp: must unclone packets before mangling them + +[ Upstream commit c52e2421f7368fd36cbe330d2cf41b10452e39a9 ] + +TCP stack should make sure it owns skbs before mangling them. + +We had various crashes using bnx2x, and it turned out gso_size +was cleared right before bnx2x driver was populating TC descriptor +of the _previous_ packet send. TCP stack can sometime retransmit +packets that are still in Qdisc. + +Of course we could make bnx2x driver more robust (using +ACCESS_ONCE(shinfo->gso_size) for example), but the bug is TCP stack. + +We have identified two points where skb_unclone() was needed. + +This patch adds a WARN_ON_ONCE() to warn us if we missed another +fix of this kind. + +Kudos to Neal for finding the root cause of this bug. Its visible +using small MSS. + +Signed-off-by: Eric Dumazet +Signed-off-by: Neal Cardwell +Cc: Yuchung Cheng +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_output.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index fe897ed..28c0d6a 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -981,6 +981,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) + static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, + unsigned int mss_now) + { ++ /* Make sure we own this skb before messing gso_size/gso_segs */ ++ WARN_ON_ONCE(skb_cloned(skb)); ++ + if (skb->len <= mss_now || !sk_can_gso(sk) || + skb->ip_summed == CHECKSUM_NONE) { + /* Avoid the costly divide in the normal +@@ -1062,9 +1065,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, + if (nsize < 0) + nsize = 0; + +- if (skb_cloned(skb) && +- skb_is_nonlinear(skb) && +- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) ++ if (skb_unclone(skb, GFP_ATOMIC)) + return -ENOMEM; + + /* Get a new skb... force flag on. */ +@@ -2339,6 +2340,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) + int oldpcount = tcp_skb_pcount(skb); + + if (unlikely(oldpcount > 1)) { ++ if (skb_unclone(skb, GFP_ATOMIC)) ++ return -ENOMEM; + tcp_init_tso_segs(sk, skb, cur_mss); + tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); + } +-- +1.7.11.7 + + +From 8731e25f7527ca851045eb0715d998d1ac07aadb Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 4 Oct 2013 10:31:41 -0700 +Subject: [PATCH 04/47] tcp: do not forget FIN in tcp_shifted_skb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 5e8a402f831dbe7ee831340a91439e46f0d38acd ] + +Yuchung found following problem : + + There are bugs in the SACK processing code, merging part in + tcp_shift_skb_data(), that incorrectly resets or ignores the sacked + skbs FIN flag. When a receiver first SACK the FIN sequence, and later + throw away ofo queue (e.g., sack-reneging), the sender will stop + retransmitting the FIN flag, and hangs forever. + +Following packetdrill test can be used to reproduce the bug. + +$ cat sack-merge-bug.pkt +`sysctl -q net.ipv4.tcp_fack=0` + +// Establish a connection and send 10 MSS. +0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 ++.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 ++.000 bind(3, ..., ...) = 0 ++.000 listen(3, 1) = 0 + ++.050 < S 0:0(0) win 32792 ++.000 > S. 0:0(0) ack 1 ++.001 < . 1:1(0) ack 1 win 1024 ++.000 accept(3, ..., ...) = 4 + ++.100 write(4, ..., 12000) = 12000 ++.000 shutdown(4, SHUT_WR) = 0 ++.000 > . 1:10001(10000) ack 1 ++.050 < . 1:1(0) ack 2001 win 257 ++.000 > FP. 10001:12001(2000) ack 1 ++.050 < . 1:1(0) ack 2001 win 257 ++.050 < . 1:1(0) ack 2001 win 257 +// SACK reneg ++.050 < . 1:1(0) ack 12001 win 257 ++0 %{ print "unacked: ",tcpi_unacked }% ++5 %{ print "" }% + +First, a typo inverted left/right of one OR operation, then +code forgot to advance end_seq if the merged skb carried FIN. + +Bug was added in 2.6.29 by commit 832d11c5cd076ab +("tcp: Try to restore large SKBs while SACK processing") + +Signed-off-by: Eric Dumazet +Signed-off-by: Yuchung Cheng +Acked-by: Neal Cardwell +Cc: Ilpo Järvinen +Acked-by: Ilpo Järvinen +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_input.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 2f0e94b..61e2360 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -1279,7 +1279,10 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, + tp->lost_cnt_hint -= tcp_skb_pcount(prev); + } + +- TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags; ++ TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; ++ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) ++ TCP_SKB_CB(prev)->end_seq++; ++ + if (skb == tcp_highest_sack(sk)) + tcp_advance_highest_sack(sk, skb); + +-- +1.7.11.7 + + +From bfc0a00d669a4fa0835c417f01c50c18996d1e60 Mon Sep 17 00:00:00 2001 +From: Yuchung Cheng +Date: Sat, 12 Oct 2013 10:16:27 -0700 +Subject: [PATCH 05/47] tcp: fix incorrect ca_state in tail loss probe + +[ Upstream commit 031afe4990a7c9dbff41a3a742c44d3e740ea0a1 ] + +On receiving an ACK that covers the loss probe sequence, TLP +immediately sets the congestion state to Open, even though some packets +are not recovered and retransmisssion are on the way. The later ACks +may trigger a WARN_ON check in step D of tcp_fastretrans_alert(), e.g., +https://bugzilla.redhat.com/show_bug.cgi?id=989251 + +The fix is to follow the similar procedure in recovery by calling +tcp_try_keep_open(). The sender switches to Open state if no packets +are retransmissted. Otherwise it goes to Disorder and let subsequent +ACKs move the state to Recovery or Open. + +Reported-By: Michael Sterrett +Tested-By: Dormando +Signed-off-by: Yuchung Cheng +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_input.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 61e2360..723951a 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3284,7 +3284,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) + tcp_init_cwnd_reduction(sk, true); + tcp_set_ca_state(sk, TCP_CA_CWR); + tcp_end_cwnd_reduction(sk); +- tcp_set_ca_state(sk, TCP_CA_Open); ++ tcp_try_keep_open(sk); + NET_INC_STATS_BH(sock_net(sk), + LINUX_MIB_TCPLOSSPROBERECOVERY); + } +-- +1.7.11.7 + + +From 05c9fdfad860abd64136d8ccd88dbf84e40bd5f5 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 1 Oct 2013 21:04:11 -0700 +Subject: [PATCH 06/47] net: do not call sock_put() on TIMEWAIT sockets + +[ Upstream commit 80ad1d61e72d626e30ebe8529a0455e660ca4693 ] + +commit 3ab5aee7fe84 ("net: Convert TCP & DCCP hash tables to use RCU / +hlist_nulls") incorrectly used sock_put() on TIMEWAIT sockets. + +We should instead use inet_twsk_put() + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/inet_hashtables.c | 2 +- + net/ipv6/inet6_hashtables.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 7bd8983..96da9c7 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -287,7 +287,7 @@ begintw: + if (unlikely(!INET_TW_MATCH(sk, net, acookie, + saddr, daddr, ports, + dif))) { +- sock_put(sk); ++ inet_twsk_put(inet_twsk(sk)); + goto begintw; + } + goto out; +diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c +index 32b4a16..066640e 100644 +--- a/net/ipv6/inet6_hashtables.c ++++ b/net/ipv6/inet6_hashtables.c +@@ -116,7 +116,7 @@ begintw: + } + if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr, + ports, dif))) { +- sock_put(sk); ++ inet_twsk_put(inet_twsk(sk)); + goto begintw; + } + goto out; +-- +1.7.11.7 + + +From bc7fd34d31c17b0e4c100013e77277a2ed7e15cf Mon Sep 17 00:00:00 2001 +From: Matthias Schiffer +Date: Fri, 27 Sep 2013 18:03:39 +0200 +Subject: [PATCH 07/47] batman-adv: set up network coding packet handlers + during module init + +[ Upstream commit 6c519bad7b19a2c14a075b400edabaa630330123 ] + +batman-adv saves its table of packet handlers as a global state, so handlers +must be set up only once (and setting them up a second time will fail). + +The recently-added network coding support tries to set up its handler each time +a new softif is registered, which obviously fails when more that one softif is +used (and in consequence, the softif creation fails). + +Fix this by splitting up batadv_nc_init into batadv_nc_init (which is called +only once) and batadv_nc_mesh_init (which is called for each softif); in +addition batadv_nc_free is renamed to batadv_nc_mesh_free to keep naming +consistent. + +Signed-off-by: Matthias Schiffer +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +--- + net/batman-adv/main.c | 5 +++-- + net/batman-adv/network-coding.c | 28 ++++++++++++++++++---------- + net/batman-adv/network-coding.h | 14 ++++++++++---- + 3 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c +index 08125f3..c8e0671 100644 +--- a/net/batman-adv/main.c ++++ b/net/batman-adv/main.c +@@ -61,6 +61,7 @@ static int __init batadv_init(void) + batadv_recv_handler_init(); + + batadv_iv_init(); ++ batadv_nc_init(); + + batadv_event_workqueue = create_singlethread_workqueue("bat_events"); + +@@ -138,7 +139,7 @@ int batadv_mesh_init(struct net_device *soft_iface) + if (ret < 0) + goto err; + +- ret = batadv_nc_init(bat_priv); ++ ret = batadv_nc_mesh_init(bat_priv); + if (ret < 0) + goto err; + +@@ -163,7 +164,7 @@ void batadv_mesh_free(struct net_device *soft_iface) + batadv_vis_quit(bat_priv); + + batadv_gw_node_purge(bat_priv); +- batadv_nc_free(bat_priv); ++ batadv_nc_mesh_free(bat_priv); + batadv_dat_free(bat_priv); + batadv_bla_free(bat_priv); + +diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c +index a487d46..4ecc0b6 100644 +--- a/net/batman-adv/network-coding.c ++++ b/net/batman-adv/network-coding.c +@@ -35,6 +35,20 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, + struct batadv_hard_iface *recv_if); + + /** ++ * batadv_nc_init - one-time initialization for network coding ++ */ ++int __init batadv_nc_init(void) ++{ ++ int ret; ++ ++ /* Register our packet type */ ++ ret = batadv_recv_handler_register(BATADV_CODED, ++ batadv_nc_recv_coded_packet); ++ ++ return ret; ++} ++ ++/** + * batadv_nc_start_timer - initialise the nc periodic worker + * @bat_priv: the bat priv with all the soft interface information + */ +@@ -45,10 +59,10 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv) + } + + /** +- * batadv_nc_init - initialise coding hash table and start house keeping ++ * batadv_nc_mesh_init - initialise coding hash table and start house keeping + * @bat_priv: the bat priv with all the soft interface information + */ +-int batadv_nc_init(struct batadv_priv *bat_priv) ++int batadv_nc_mesh_init(struct batadv_priv *bat_priv) + { + bat_priv->nc.timestamp_fwd_flush = jiffies; + bat_priv->nc.timestamp_sniffed_purge = jiffies; +@@ -70,11 +84,6 @@ int batadv_nc_init(struct batadv_priv *bat_priv) + batadv_hash_set_lock_class(bat_priv->nc.coding_hash, + &batadv_nc_decoding_hash_lock_class_key); + +- /* Register our packet type */ +- if (batadv_recv_handler_register(BATADV_CODED, +- batadv_nc_recv_coded_packet) < 0) +- goto err; +- + INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); + batadv_nc_start_timer(bat_priv); + +@@ -1721,12 +1730,11 @@ free_nc_packet: + } + + /** +- * batadv_nc_free - clean up network coding memory ++ * batadv_nc_mesh_free - clean up network coding memory + * @bat_priv: the bat priv with all the soft interface information + */ +-void batadv_nc_free(struct batadv_priv *bat_priv) ++void batadv_nc_mesh_free(struct batadv_priv *bat_priv) + { +- batadv_recv_handler_unregister(BATADV_CODED); + cancel_delayed_work_sync(&bat_priv->nc.work); + + batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); +diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h +index 85a4ec8..ddfa618 100644 +--- a/net/batman-adv/network-coding.h ++++ b/net/batman-adv/network-coding.h +@@ -22,8 +22,9 @@ + + #ifdef CONFIG_BATMAN_ADV_NC + +-int batadv_nc_init(struct batadv_priv *bat_priv); +-void batadv_nc_free(struct batadv_priv *bat_priv); ++int batadv_nc_init(void); ++int batadv_nc_mesh_init(struct batadv_priv *bat_priv); ++void batadv_nc_mesh_free(struct batadv_priv *bat_priv); + void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig_node, + struct batadv_orig_node *orig_neigh_node, +@@ -46,12 +47,17 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); + + #else /* ifdef CONFIG_BATMAN_ADV_NC */ + +-static inline int batadv_nc_init(struct batadv_priv *bat_priv) ++static inline int batadv_nc_init(void) + { + return 0; + } + +-static inline void batadv_nc_free(struct batadv_priv *bat_priv) ++static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv) ++{ ++ return 0; ++} ++ ++static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) + { + return; + } +-- +1.7.11.7 + + +From 8be4005ed947924104df5850944a20b7f6570137 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fran=C3=A7ois=20Cachereul?= +Date: Wed, 2 Oct 2013 10:16:02 +0200 +Subject: [PATCH 08/47] l2tp: fix kernel panic when using IPv4-mapped IPv6 + addresses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit e18503f41f9b12132c95d7c31ca6ee5155e44e5c ] + +IPv4 mapped addresses cause kernel panic. +The patch juste check whether the IPv6 address is an IPv4 mapped +address. If so, use IPv4 API instead of IPv6. + +[ 940.026915] general protection fault: 0000 [#1] +[ 940.026915] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppox ppp_generic slhc loop psmouse +[ 940.026915] CPU: 0 PID: 3184 Comm: memcheck-amd64- Not tainted 3.11.0+ #1 +[ 940.026915] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 +[ 940.026915] task: ffff880007130e20 ti: ffff88000737e000 task.ti: ffff88000737e000 +[ 940.026915] RIP: 0010:[] [] ip6_xmit+0x276/0x326 +[ 940.026915] RSP: 0018:ffff88000737fd28 EFLAGS: 00010286 +[ 940.026915] RAX: c748521a75ceff48 RBX: ffff880000c30800 RCX: 0000000000000000 +[ 940.026915] RDX: ffff88000075cc4e RSI: 0000000000000028 RDI: ffff8800060e5a40 +[ 940.026915] RBP: ffff8800060e5a40 R08: 0000000000000000 R09: ffff88000075cc90 +[ 940.026915] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88000737fda0 +[ 940.026915] R13: 0000000000000000 R14: 0000000000002000 R15: ffff880005d3b580 +[ 940.026915] FS: 00007f163dc5e800(0000) GS:ffffffff81623000(0000) knlGS:0000000000000000 +[ 940.026915] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 940.026915] CR2: 00000004032dc940 CR3: 0000000005c25000 CR4: 00000000000006f0 +[ 940.026915] Stack: +[ 940.026915] ffff88000075cc4e ffffffff81694e90 ffff880000c30b38 0000000000000020 +[ 940.026915] 11000000523c4bac ffff88000737fdb4 0000000000000000 ffff880000c30800 +[ 940.026915] ffff880005d3b580 ffff880000c30b38 ffff8800060e5a40 0000000000000020 +[ 940.026915] Call Trace: +[ 940.026915] [] ? inet6_csk_xmit+0xa4/0xc4 +[ 940.026915] [] ? l2tp_xmit_skb+0x503/0x55a [l2tp_core] +[ 940.026915] [] ? pskb_expand_head+0x161/0x214 +[ 940.026915] [] ? pppol2tp_xmit+0xf2/0x143 [l2tp_ppp] +[ 940.026915] [] ? ppp_channel_push+0x36/0x8b [ppp_generic] +[ 940.026915] [] ? ppp_write+0xaf/0xc5 [ppp_generic] +[ 940.026915] [] ? vfs_write+0xa2/0x106 +[ 940.026915] [] ? SyS_write+0x56/0x8a +[ 940.026915] [] ? system_call_fastpath+0x16/0x1b +[ 940.026915] Code: 00 49 8b 8f d8 00 00 00 66 83 7c 11 02 00 74 60 49 +8b 47 58 48 83 e0 fe 48 8b 80 18 01 00 00 48 85 c0 74 13 48 8b 80 78 02 +00 00 <48> ff 40 28 41 8b 57 68 48 01 50 30 48 8b 54 24 08 49 c7 c1 51 +[ 940.026915] RIP [] ip6_xmit+0x276/0x326 +[ 940.026915] RSP +[ 940.057945] ---[ end trace be8aba9a61c8b7f3 ]--- +[ 940.058583] Kernel panic - not syncing: Fatal exception in interrupt + +Signed-off-by: François CACHEREUL +Signed-off-by: David S. Miller +--- + net/l2tp/l2tp_core.c | 27 +++++++++++++++++++++++---- + net/l2tp/l2tp_core.h | 3 +++ + 2 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index feae495..aedaa2c 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -496,6 +496,7 @@ out: + static inline int l2tp_verify_udp_checksum(struct sock *sk, + struct sk_buff *skb) + { ++ struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; + struct udphdr *uh = udp_hdr(skb); + u16 ulen = ntohs(uh->len); + __wsum psum; +@@ -504,7 +505,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, + return 0; + + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6) { ++ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { + if (!uh->check) { + LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); + return 1; +@@ -1128,7 +1129,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, + /* Queue the packet to IP for output */ + skb->local_df = 1; + #if IS_ENABLED(CONFIG_IPV6) +- if (skb->sk->sk_family == PF_INET6) ++ if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped) + error = inet6_csk_xmit(skb, NULL); + else + #endif +@@ -1255,7 +1256,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len + + /* Calculate UDP checksum if configured to do so */ + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6) ++ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) + l2tp_xmit_ipv6_csum(sk, skb, udp_len); + else + #endif +@@ -1704,6 +1705,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 + if (cfg != NULL) + tunnel->debug = cfg->debug; + ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == PF_INET6) { ++ struct ipv6_pinfo *np = inet6_sk(sk); ++ ++ if (ipv6_addr_v4mapped(&np->saddr) && ++ ipv6_addr_v4mapped(&np->daddr)) { ++ struct inet_sock *inet = inet_sk(sk); ++ ++ tunnel->v4mapped = true; ++ inet->inet_saddr = np->saddr.s6_addr32[3]; ++ inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3]; ++ inet->inet_daddr = np->daddr.s6_addr32[3]; ++ } else { ++ tunnel->v4mapped = false; ++ } ++ } ++#endif ++ + /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ + tunnel->encap = encap; + if (encap == L2TP_ENCAPTYPE_UDP) { +@@ -1712,7 +1731,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 + udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; + udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6) ++ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) + udpv6_encap_enable(); + else + #endif +diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h +index 66a559b..6f251cb 100644 +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -194,6 +194,9 @@ struct l2tp_tunnel { + struct sock *sock; /* Parent socket */ + int fd; /* Parent fd, if tunnel socket + * was created by userspace */ ++#if IS_ENABLED(CONFIG_IPV6) ++ bool v4mapped; ++#endif + + struct work_struct del_work; + +-- +1.7.11.7 + + +From 0ec2b01190b1a2ba020241ab89730bf7e7d77b9c Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 8 Oct 2013 15:44:26 -0400 +Subject: [PATCH 09/47] l2tp: Fix build warning with ipv6 disabled. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 8d8a51e26a6d415e1470759f2cf5f3ee3ee86196 ] + +net/l2tp/l2tp_core.c: In function ‘l2tp_verify_udp_checksum’: +net/l2tp/l2tp_core.c:499:22: warning: unused variable ‘tunnel’ [-Wunused-variable] + +Create a helper "l2tp_tunnel()" to facilitate this, and as a side +effect get rid of a bunch of unnecessary void pointer casts. + +Signed-off-by: David S. Miller +--- + net/l2tp/l2tp_core.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index aedaa2c..b076e83 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -115,6 +115,11 @@ struct l2tp_net { + static void l2tp_session_set_header_len(struct l2tp_session *session, int version); + static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); + ++static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) ++{ ++ return sk->sk_user_data; ++} ++ + static inline struct l2tp_net *l2tp_pernet(struct net *net) + { + BUG_ON(!net); +@@ -496,7 +501,6 @@ out: + static inline int l2tp_verify_udp_checksum(struct sock *sk, + struct sk_buff *skb) + { +- struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; + struct udphdr *uh = udp_hdr(skb); + u16 ulen = ntohs(uh->len); + __wsum psum; +@@ -505,7 +509,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, + return 0; + + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { ++ if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) { + if (!uh->check) { + LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); + return 1; +@@ -1305,10 +1309,9 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb); + */ + static void l2tp_tunnel_destruct(struct sock *sk) + { +- struct l2tp_tunnel *tunnel; ++ struct l2tp_tunnel *tunnel = l2tp_tunnel(sk); + struct l2tp_net *pn; + +- tunnel = sk->sk_user_data; + if (tunnel == NULL) + goto end; + +@@ -1676,7 +1679,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 + } + + /* Check if this socket has already been prepped */ +- tunnel = (struct l2tp_tunnel *)sk->sk_user_data; ++ tunnel = l2tp_tunnel(sk); + if (tunnel != NULL) { + /* This socket has already been prepped */ + err = -EBUSY; +-- +1.7.11.7 + + +From 35e64a9e465a85ffacd373439c1caa757e407656 Mon Sep 17 00:00:00 2001 +From: Sebastian Hesselbarth +Date: Wed, 2 Oct 2013 12:57:20 +0200 +Subject: [PATCH 10/47] net: mv643xx_eth: update statistics timer from timer + context only + +[ Upstream commit 041b4ddb84989f06ff1df0ca869b950f1ee3cb1c ] + +Each port driver installs a periodic timer to update port statistics +by calling mib_counters_update. As mib_counters_update is also called +from non-timer context, we should not reschedule the timer there but +rather move it to timer-only context. + +Signed-off-by: Sebastian Hesselbarth +Acked-by: Jason Cooper +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mv643xx_eth.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index c35db73..51c138b 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -1131,15 +1131,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) + p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); + p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); + spin_unlock_bh(&mp->mib_counters_lock); +- +- mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); + } + + static void mib_counters_timer_wrapper(unsigned long _mp) + { + struct mv643xx_eth_private *mp = (void *)_mp; +- + mib_counters_update(mp); ++ mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); + } + + +-- +1.7.11.7 + + +From b6b20d9c54b23ba35c5807e45ff7d9579503bffa Mon Sep 17 00:00:00 2001 +From: Sebastian Hesselbarth +Date: Wed, 2 Oct 2013 12:57:21 +0200 +Subject: [PATCH 11/47] net: mv643xx_eth: fix orphaned statistics timer crash + +[ Upstream commit f564412c935111c583b787bcc18157377b208e2e ] + +The periodic statistics timer gets started at port _probe() time, but +is stopped on _stop() only. In a modular environment, this can cause +the timer to access already deallocated memory, if the module is unloaded +without starting the eth device. To fix this, we add the timer right +before the port is started, instead of at _probe() time. + +Signed-off-by: Sebastian Hesselbarth +Acked-by: Jason Cooper +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index 51c138b..39334d4 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -2235,6 +2235,7 @@ static int mv643xx_eth_open(struct net_device *dev) + mp->int_mask |= INT_TX_END_0 << i; + } + ++ add_timer(&mp->mib_counters_timer); + port_start(mp); + + wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); +@@ -2914,7 +2915,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) + mp->mib_counters_timer.data = (unsigned long)mp; + mp->mib_counters_timer.function = mib_counters_timer_wrapper; + mp->mib_counters_timer.expires = jiffies + 30 * HZ; +- add_timer(&mp->mib_counters_timer); + + spin_lock_init(&mp->mib_counters_lock); + +-- +1.7.11.7 + + +From b8baf1c21a214c1b836eef390c9d6e153293fef9 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Thu, 3 Oct 2013 00:27:20 +0300 +Subject: [PATCH 12/47] net: heap overflow in __audit_sockaddr() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 1661bf364ae9c506bc8795fef70d1532931be1e8 ] + +We need to cap ->msg_namelen or it leads to a buffer overflow when we +to the memcpy() in __audit_sockaddr(). It requires CAP_AUDIT_CONTROL to +exploit this bug. + +The call tree is: +___sys_recvmsg() + move_addr_to_user() + audit_sockaddr() + __audit_sockaddr() + +Reported-by: Jüri Aedla +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +--- + net/compat.c | 2 ++ + net/socket.c | 24 ++++++++++++++++++++---- + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/compat.c b/net/compat.c +index f0a1ba6..8903258 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) + __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; ++ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) ++ return -EINVAL; + kmsg->msg_name = compat_ptr(tmp1); + kmsg->msg_iov = compat_ptr(tmp2); + kmsg->msg_control = compat_ptr(tmp3); +diff --git a/net/socket.c b/net/socket.c +index b2d7c62..4b94643 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1973,6 +1973,16 @@ struct used_address { + unsigned int name_len; + }; + ++static int copy_msghdr_from_user(struct msghdr *kmsg, ++ struct msghdr __user *umsg) ++{ ++ if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) ++ return -EFAULT; ++ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) ++ return -EINVAL; ++ return 0; ++} ++ + static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + struct msghdr *msg_sys, unsigned int flags, + struct used_address *used_address) +@@ -1991,8 +2001,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + if (MSG_CMSG_COMPAT & flags) { + if (get_compat_msghdr(msg_sys, msg_compat)) + return -EFAULT; +- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) +- return -EFAULT; ++ } else { ++ err = copy_msghdr_from_user(msg_sys, msg); ++ if (err) ++ return err; ++ } + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +@@ -2200,8 +2213,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + if (MSG_CMSG_COMPAT & flags) { + if (get_compat_msghdr(msg_sys, msg_compat)) + return -EFAULT; +- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) +- return -EFAULT; ++ } else { ++ err = copy_msghdr_from_user(msg_sys, msg); ++ if (err) ++ return err; ++ } + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +-- +1.7.11.7 + + +From 6e24497ef79e18f5b1ddce66712d55093a6cf3e9 Mon Sep 17 00:00:00 2001 +From: Willem de Bruijn +Date: Tue, 22 Oct 2013 10:59:18 -0400 +Subject: [PATCH 13/47] sit: amend "allow to use rtnl ops on fb tunnel" + +Amend backport to 3.11.y of + + [ Upstream commit 205983c43700ac3a81e7625273a3fa83cd2759b5 ] + +The discussion thread in the upstream commit mentions that in +backports to stable-* branches, the line + + - unregister_netdevice_queue(sitn->fb_tunnel_dev, &list); + +must be omitted if that branch does not have commit 5e6700b3bf98 +("sit: add support of x-netns"). This line has correctly been omitted +in the backport to 3.10, which indeed does not have that commit. + +It was also removed in the backport to 3.11.y, which does have that +commit. + +This causes the following steps to hit a BUG at net/core/dev.c:5039: + + `modprobe sit; rmmod sit` + +The bug demonstrates that it causes a device to be unregistered twice. +The simple fix is to apply the one line in the upstream commit that +was dropped in the backport to 3.11 (3783100374653e2e7fbdf68c710f5). +This brings the logic in line with upstream linux, net and net-next +branches. + +Signed-off-by: Willem de Bruijn +Acked-by: Nicolas Dichtel +Reviewed-by: Veaceslav Falico +--- + net/ipv6/sit.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 86f639b..a51ad07 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -1708,7 +1708,6 @@ static void __net_exit sit_exit_net(struct net *net) + + rtnl_lock(); + sit_destroy_tunnels(sitn, &list); +- unregister_netdevice_queue(sitn->fb_tunnel_dev, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); + } +-- +1.7.11.7 + + +From 6c7e3c3382670fe98debedf2ddaff8abf2944bb4 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Mon, 30 Sep 2013 22:03:06 +0200 +Subject: [PATCH 14/47] proc connector: fix info leaks + +[ Upstream commit e727ca82e0e9616ab4844301e6bae60ca7327682 ] + +Initialize event_data for all possible message types to prevent leaking +kernel stack contents to userland (up to 20 bytes). Also set the flags +member of the connector message to 0 to prevent leaking two more stack +bytes this way. + +Cc: stable@vger.kernel.org # v2.6.15+ +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + drivers/connector/cn_proc.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c +index 08ae128..c73fc2b 100644 +--- a/drivers/connector/cn_proc.c ++++ b/drivers/connector/cn_proc.c +@@ -65,6 +65,7 @@ void proc_fork_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -80,6 +81,7 @@ void proc_fork_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + /* If cn_netlink_send() failed, the data is not sent */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } +@@ -96,6 +98,7 @@ void proc_exec_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -106,6 +109,7 @@ void proc_exec_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -122,6 +126,7 @@ void proc_id_connector(struct task_struct *task, int which_id) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + ev->what = which_id; + ev->event_data.id.process_pid = task->pid; + ev->event_data.id.process_tgid = task->tgid; +@@ -145,6 +150,7 @@ void proc_id_connector(struct task_struct *task, int which_id) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -160,6 +166,7 @@ void proc_sid_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -170,6 +177,7 @@ void proc_sid_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -185,6 +193,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -203,6 +212,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -218,6 +228,7 @@ void proc_comm_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -229,6 +240,7 @@ void proc_comm_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -244,6 +256,7 @@ void proc_coredump_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -254,6 +267,7 @@ void proc_coredump_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -269,6 +283,7 @@ void proc_exit_connector(struct task_struct *task) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -281,6 +296,7 @@ void proc_exit_connector(struct task_struct *task) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +@@ -304,6 +320,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) + + msg = (struct cn_msg *)buffer; + ev = (struct proc_event *)msg->data; ++ memset(&ev->event_data, 0, sizeof(ev->event_data)); + msg->seq = rcvd_seq; + ktime_get_ts(&ts); /* get high res monotonic timestamp */ + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); +@@ -313,6 +330,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = rcvd_ack + 1; + msg->len = sizeof(*ev); ++ msg->flags = 0; /* not used */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + } + +-- +1.7.11.7 + + +From f3d398e2465b3b74987a3a2fc42ea3e8c83d2166 Mon Sep 17 00:00:00 2001 +From: Jiri Benc +Date: Fri, 4 Oct 2013 17:04:48 +0200 +Subject: [PATCH 15/47] ipv4: fix ineffective source address selection + +[ Upstream commit 0a7e22609067ff524fc7bbd45c6951dd08561667 ] + +When sending out multicast messages, the source address in inet->mc_addr is +ignored and rewritten by an autoselected one. This is caused by a typo in +commit 813b3b5db831 ("ipv4: Use caller's on-stack flowi as-is in output +route lookups"). + +Signed-off-by: Jiri Benc +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index a9a54a2..2de16d9 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2074,7 +2074,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) + RT_SCOPE_LINK); + goto make_route; + } +- if (fl4->saddr) { ++ if (!fl4->saddr) { + if (ipv4_is_multicast(fl4->daddr)) + fl4->saddr = inet_select_addr(dev_out, 0, + fl4->flowi4_scope); +-- +1.7.11.7 + + +From 8fd516716afeb4631cf790a2be7ca30d0a664b01 Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Sat, 5 Oct 2013 21:25:17 +0200 +Subject: [PATCH 16/47] can: dev: fix nlmsg size calculation in can_get_size() + +[ Upstream commit fe119a05f8ca481623a8d02efcc984332e612528 ] + +This patch fixes the calculation of the nlmsg size, by adding the missing +nla_total_size(). + +Signed-off-by: Marc Kleine-Budde +Signed-off-by: David S. Miller +--- + drivers/net/can/dev.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index f9cba41..1870c47 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -705,14 +705,14 @@ static size_t can_get_size(const struct net_device *dev) + size_t size; + + size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ +- size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ ++ size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ +- size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ +- size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ ++ size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */ ++ size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */ + if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ +- size += sizeof(struct can_berr_counter); ++ size += nla_total_size(sizeof(struct can_berr_counter)); + if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ +- size += sizeof(struct can_bittiming_const); ++ size += nla_total_size(sizeof(struct can_bittiming_const)); + + return size; + } +-- +1.7.11.7 + + +From 1b3231ca7e26084580145c904dd10a60cac35c63 Mon Sep 17 00:00:00 2001 +From: Fabio Estevam +Date: Sat, 5 Oct 2013 17:56:59 -0300 +Subject: [PATCH 17/47] net: secure_seq: Fix warning when CONFIG_IPV6 and + CONFIG_INET are not selected + +[ Upstream commit cb03db9d0e964568407fb08ea46cc2b6b7f67587 ] + +net_secret() is only used when CONFIG_IPV6 or CONFIG_INET are selected. + +Building a defconfig with both of these symbols unselected (Using the ARM +at91sam9rl_defconfig, for example) leads to the following build warning: + +$ make at91sam9rl_defconfig +# +# configuration written to .config +# + +$ make net/core/secure_seq.o +scripts/kconfig/conf --silentoldconfig Kconfig + CHK include/config/kernel.release + CHK include/generated/uapi/linux/version.h + CHK include/generated/utsrelease.h +make[1]: `include/generated/mach-types.h' is up to date. + CALL scripts/checksyscalls.sh + CC net/core/secure_seq.o +net/core/secure_seq.c:17:13: warning: 'net_secret_init' defined but not used [-Wunused-function] + +Fix this warning by protecting the definition of net_secret() with these +symbols. + +Reported-by: Olof Johansson +Signed-off-by: Fabio Estevam +Signed-off-by: David S. Miller +--- + net/core/secure_seq.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c +index 3f1ec15..8d9d05e 100644 +--- a/net/core/secure_seq.c ++++ b/net/core/secure_seq.c +@@ -10,6 +10,7 @@ + + #include + ++#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) + #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) + + static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; +@@ -29,6 +30,7 @@ static void net_secret_init(void) + cmpxchg(&net_secret[--i], 0, tmp); + } + } ++#endif + + #ifdef CONFIG_INET + static u32 seq_scale(u32 seq) +-- +1.7.11.7 + + +From 538680b534f30fe6531099f87267bb676c935351 Mon Sep 17 00:00:00 2001 +From: Paul Durrant +Date: Tue, 8 Oct 2013 14:56:44 +0100 +Subject: [PATCH 18/47] xen-netback: Don't destroy the netdev until the vif is + shut down + +[ upstream commit id: 279f438e36c0a70b23b86d2090aeec50155034a9 ] + +Without this patch, if a frontend cycles through states Closing +and Closed (which Windows frontends need to do) then the netdev +will be destroyed and requires re-invocation of hotplug scripts +to restore state before the frontend can move to Connected. Thus +when udev is not in use the backend gets stuck in InitWait. + +With this patch, the netdev is left alone whilst the backend is +still online and is only de-registered and freed just prior to +destroying the vif (which is also nicely symmetrical with the +netdev allocation and registration being done during probe) so +no re-invocation of hotplug scripts is required. + +Signed-off-by: Paul Durrant +Cc: David Vrabel +Cc: Wei Liu +Cc: Ian Campbell +--- + drivers/net/xen-netback/common.h | 1 + + drivers/net/xen-netback/interface.c | 23 +++++++++-------------- + drivers/net/xen-netback/xenbus.c | 17 ++++++++++++----- + 3 files changed, 22 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h +index 8a4d77e..4d9a5e7 100644 +--- a/drivers/net/xen-netback/common.h ++++ b/drivers/net/xen-netback/common.h +@@ -120,6 +120,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, + unsigned long rx_ring_ref, unsigned int tx_evtchn, + unsigned int rx_evtchn); + void xenvif_disconnect(struct xenvif *vif); ++void xenvif_free(struct xenvif *vif); + + void xenvif_get(struct xenvif *vif); + void xenvif_put(struct xenvif *vif); +diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c +index 087d2db..73336c1 100644 +--- a/drivers/net/xen-netback/interface.c ++++ b/drivers/net/xen-netback/interface.c +@@ -326,6 +326,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, + } + + netdev_dbg(dev, "Successfully created xenvif\n"); ++ ++ __module_get(THIS_MODULE); ++ + return vif; + } + +@@ -413,12 +416,6 @@ void xenvif_carrier_off(struct xenvif *vif) + + void xenvif_disconnect(struct xenvif *vif) + { +- /* Disconnect funtion might get called by generic framework +- * even before vif connects, so we need to check if we really +- * need to do a module_put. +- */ +- int need_module_put = 0; +- + if (netif_carrier_ok(vif->dev)) + xenvif_carrier_off(vif); + +@@ -432,18 +429,16 @@ void xenvif_disconnect(struct xenvif *vif) + unbind_from_irqhandler(vif->tx_irq, vif); + unbind_from_irqhandler(vif->rx_irq, vif); + } +- /* vif->irq is valid, we had a module_get in +- * xenvif_connect. +- */ +- need_module_put = 1; + } + +- unregister_netdev(vif->dev); +- + xen_netbk_unmap_frontend_rings(vif); ++} ++ ++void xenvif_free(struct xenvif *vif) ++{ ++ unregister_netdev(vif->dev); + + free_netdev(vif->dev); + +- if (need_module_put) +- module_put(THIS_MODULE); ++ module_put(THIS_MODULE); + } +diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c +index 1fe48fe3..a53782e 100644 +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -42,7 +42,7 @@ static int netback_remove(struct xenbus_device *dev) + if (be->vif) { + kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); +- xenvif_disconnect(be->vif); ++ xenvif_free(be->vif); + be->vif = NULL; + } + kfree(be); +@@ -213,9 +213,18 @@ static void disconnect_backend(struct xenbus_device *dev) + { + struct backend_info *be = dev_get_drvdata(&dev->dev); + ++ if (be->vif) ++ xenvif_disconnect(be->vif); ++} ++ ++static void destroy_backend(struct xenbus_device *dev) ++{ ++ struct backend_info *be = dev_get_drvdata(&dev->dev); ++ + if (be->vif) { ++ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); +- xenvif_disconnect(be->vif); ++ xenvif_free(be->vif); + be->vif = NULL; + } + } +@@ -246,14 +255,11 @@ static void frontend_changed(struct xenbus_device *dev, + case XenbusStateConnected: + if (dev->state == XenbusStateConnected) + break; +- backend_create_xenvif(be); + if (be->vif) + connect(be); + break; + + case XenbusStateClosing: +- if (be->vif) +- kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + disconnect_backend(dev); + xenbus_switch_state(dev, XenbusStateClosing); + break; +@@ -262,6 +268,7 @@ static void frontend_changed(struct xenbus_device *dev, + xenbus_switch_state(dev, XenbusStateClosed); + if (xenbus_dev_is_online(dev)) + break; ++ destroy_backend(dev); + /* fall through if not online */ + case XenbusStateUnknown: + device_unregister(&dev->dev); +-- +1.7.11.7 + + +From 29bb21656d747e62d55b9e1929b23eadcd6be324 Mon Sep 17 00:00:00 2001 +From: Amir Vadai +Date: Mon, 7 Oct 2013 13:38:12 +0200 +Subject: [PATCH 19/47] net/mlx4_en: Rename name of mlx4_en_rx_alloc members + +[ Upstream commit 70fbe0794393829d9acd686428d87c27b6f6984b ] + +Add page prefix to page related members: @size and @offset into +@page_size and @page_offset + +CC: Eric Dumazet +Signed-off-by: Amir Vadai +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlx4/en_rx.c | 40 ++++++++++++++++------------ + drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 4 +-- + 2 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +index dec455c..066fc27 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +@@ -70,14 +70,15 @@ static int mlx4_alloc_pages(struct mlx4_en_priv *priv, + put_page(page); + return -ENOMEM; + } +- page_alloc->size = PAGE_SIZE << order; ++ page_alloc->page_size = PAGE_SIZE << order; + page_alloc->page = page; + page_alloc->dma = dma; +- page_alloc->offset = frag_info->frag_align; ++ page_alloc->page_offset = frag_info->frag_align; + /* Not doing get_page() for each frag is a big win + * on asymetric workloads. + */ +- atomic_set(&page->_count, page_alloc->size / frag_info->frag_stride); ++ atomic_set(&page->_count, ++ page_alloc->page_size / frag_info->frag_stride); + return 0; + } + +@@ -96,16 +97,19 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv, + for (i = 0; i < priv->num_frags; i++) { + frag_info = &priv->frag_info[i]; + page_alloc[i] = ring_alloc[i]; +- page_alloc[i].offset += frag_info->frag_stride; +- if (page_alloc[i].offset + frag_info->frag_stride <= ring_alloc[i].size) ++ page_alloc[i].page_offset += frag_info->frag_stride; ++ ++ if (page_alloc[i].page_offset + frag_info->frag_stride <= ++ ring_alloc[i].page_size) + continue; ++ + if (mlx4_alloc_pages(priv, &page_alloc[i], frag_info, gfp)) + goto out; + } + + for (i = 0; i < priv->num_frags; i++) { + frags[i] = ring_alloc[i]; +- dma = ring_alloc[i].dma + ring_alloc[i].offset; ++ dma = ring_alloc[i].dma + ring_alloc[i].page_offset; + ring_alloc[i] = page_alloc[i]; + rx_desc->data[i].addr = cpu_to_be64(dma); + } +@@ -117,7 +121,7 @@ out: + frag_info = &priv->frag_info[i]; + if (page_alloc[i].page != ring_alloc[i].page) { + dma_unmap_page(priv->ddev, page_alloc[i].dma, +- page_alloc[i].size, PCI_DMA_FROMDEVICE); ++ page_alloc[i].page_size, PCI_DMA_FROMDEVICE); + page = page_alloc[i].page; + atomic_set(&page->_count, 1); + put_page(page); +@@ -132,9 +136,10 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, + { + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; + +- if (frags[i].offset + frag_info->frag_stride > frags[i].size) +- dma_unmap_page(priv->ddev, frags[i].dma, frags[i].size, +- PCI_DMA_FROMDEVICE); ++ if (frags[i].page_offset + frag_info->frag_stride > ++ frags[i].page_size) ++ dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, ++ PCI_DMA_FROMDEVICE); + + if (frags[i].page) + put_page(frags[i].page); +@@ -161,7 +166,7 @@ out: + + page_alloc = &ring->page_alloc[i]; + dma_unmap_page(priv->ddev, page_alloc->dma, +- page_alloc->size, PCI_DMA_FROMDEVICE); ++ page_alloc->page_size, PCI_DMA_FROMDEVICE); + page = page_alloc->page; + atomic_set(&page->_count, 1); + put_page(page); +@@ -184,10 +189,11 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, + i, page_count(page_alloc->page)); + + dma_unmap_page(priv->ddev, page_alloc->dma, +- page_alloc->size, PCI_DMA_FROMDEVICE); +- while (page_alloc->offset + frag_info->frag_stride < page_alloc->size) { ++ page_alloc->page_size, PCI_DMA_FROMDEVICE); ++ while (page_alloc->page_offset + frag_info->frag_stride < ++ page_alloc->page_size) { + put_page(page_alloc->page); +- page_alloc->offset += frag_info->frag_stride; ++ page_alloc->page_offset += frag_info->frag_stride; + } + page_alloc->page = NULL; + } +@@ -478,7 +484,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, + /* Save page reference in skb */ + __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); + skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size); +- skb_frags_rx[nr].page_offset = frags[nr].offset; ++ skb_frags_rx[nr].page_offset = frags[nr].page_offset; + skb->truesize += frag_info->frag_stride; + frags[nr].page = NULL; + } +@@ -517,7 +523,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, + + /* Get pointer to first fragment so we could copy the headers into the + * (linear part of the) skb */ +- va = page_address(frags[0].page) + frags[0].offset; ++ va = page_address(frags[0].page) + frags[0].page_offset; + + if (length <= SMALL_PACKET_SIZE) { + /* We are copying all relevant data to the skb - temporarily +@@ -645,7 +651,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud + dma_sync_single_for_cpu(priv->ddev, dma, sizeof(*ethh), + DMA_FROM_DEVICE); + ethh = (struct ethhdr *)(page_address(frags[0].page) + +- frags[0].offset); ++ frags[0].page_offset); + + if (is_multicast_ether_addr(ethh->h_dest)) { + struct mlx4_mac_entry *entry; +diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +index 5e0aa56..bf06e36 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h ++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +@@ -237,8 +237,8 @@ struct mlx4_en_tx_desc { + struct mlx4_en_rx_alloc { + struct page *page; + dma_addr_t dma; +- u32 offset; +- u32 size; ++ u32 page_offset; ++ u32 page_size; + }; + + struct mlx4_en_tx_ring { +-- +1.7.11.7 + + +From 4bd2cc99115d31513bfe3c2bd7bcfe67fc081ae8 Mon Sep 17 00:00:00 2001 +From: Amir Vadai +Date: Mon, 7 Oct 2013 13:38:13 +0200 +Subject: [PATCH 20/47] net/mlx4_en: Fix pages never dma unmapped on rx + +[ Upstream commit 021f1107ffdae7a82af6c53f4c52654062e365c6 ] + +This patch fixes a bug introduced by commit 51151a16 (mlx4: allow +order-0 memory allocations in RX path). + +dma_unmap_page never reached because condition to detect last fragment +in page is wrong. offset+frag_stride can't be greater than size, need to +make sure no additional frag will fit in page => compare offset + +frag_stride + next_frag_size instead. +next_frag_size is the same as the current one, since page is shared only +with frags of the same size. + +CC: Eric Dumazet +Signed-off-by: Amir Vadai +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +index 066fc27..afe2efa 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +@@ -135,9 +135,10 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, + int i) + { + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; ++ u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride; + +- if (frags[i].page_offset + frag_info->frag_stride > +- frags[i].page_size) ++ ++ if (next_frag_end > frags[i].page_size) + dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, + PCI_DMA_FROMDEVICE); + +-- +1.7.11.7 + + +From af64f33fff313187ca01ddb7db09b537a89208dd Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Mon, 7 Oct 2013 23:19:58 +0200 +Subject: [PATCH 21/47] net: vlan: fix nlmsg size calculation in + vlan_get_size() + +[ Upstream commit c33a39c575068c2ea9bffb22fd6de2df19c74b89 ] + +This patch fixes the calculation of the nlmsg size, by adding the missing +nla_total_size(). + +Cc: Patrick McHardy +Signed-off-by: Marc Kleine-Budde +Signed-off-by: David S. Miller +--- + net/8021q/vlan_netlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c +index 3091297..c7e634a 100644 +--- a/net/8021q/vlan_netlink.c ++++ b/net/8021q/vlan_netlink.c +@@ -171,7 +171,7 @@ static size_t vlan_get_size(const struct net_device *dev) + + return nla_total_size(2) + /* IFLA_VLAN_PROTOCOL */ + nla_total_size(2) + /* IFLA_VLAN_ID */ +- sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */ ++ nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */ + vlan_qos_map_size(vlan->nr_ingress_mappings) + + vlan_qos_map_size(vlan->nr_egress_mappings); + } +-- +1.7.11.7 + + +From 74869292aeb07213144e34b0e21e23f7e3c9f61f Mon Sep 17 00:00:00 2001 +From: Vlad Yasevich +Date: Thu, 10 Oct 2013 15:57:59 -0400 +Subject: [PATCH 22/47] bridge: update mdb expiration timer upon reports. + +[ Upstream commit f144febd93d5ee534fdf23505ab091b2b9088edc ] + +commit 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b + bridge: only expire the mdb entry when query is received +changed the mdb expiration timer to be armed only when QUERY is +received. Howerver, this causes issues in an environment where +the multicast server socket comes and goes very fast while a client +is trying to send traffic to it. + +The root cause is a race where a sequence of LEAVE followed by REPORT +messages can race against QUERY messages generated in response to LEAVE. +The QUERY ends up starting the expiration timer, and that timer can +potentially expire after the new REPORT message has been received signaling +the new join operation. This leads to a significant drop in multicast +traffic and possible complete stall. + +The solution is to have REPORT messages update the expiration timer +on entries that already exist. + +CC: Cong Wang +CC: Herbert Xu +CC: Stephen Hemminger +Signed-off-by: Vlad Yasevich +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- + net/bridge/br_multicast.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index bbcb435..0e3fea7 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -610,6 +610,9 @@ rehash: + break; + + default: ++ /* If we have an existing entry, update it's expire timer */ ++ mod_timer(&mp->timer, ++ jiffies + br->multicast_membership_interval); + goto out; + } + +@@ -679,8 +682,12 @@ static int br_multicast_add_group(struct net_bridge *br, + for (pp = &mp->ports; + (p = mlock_dereference(*pp, br)) != NULL; + pp = &p->next) { +- if (p->port == port) ++ if (p->port == port) { ++ /* We already have a portgroup, update the timer. */ ++ mod_timer(&p->timer, ++ jiffies + br->multicast_membership_interval); + goto out; ++ } + if ((unsigned long)p->port < (unsigned long)port) + break; + } +-- +1.7.11.7 + + +From d9f02cfe59400677feea276d4b27981f6d91825a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Linus=20L=C3=BCssing?= +Date: Sun, 20 Oct 2013 00:58:57 +0200 +Subject: [PATCH 23/47] Revert "bridge: only expire the mdb entry when query + is received" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 454594f3b93a49ef568cd190c5af31376b105a7b ] + +While this commit was a good attempt to fix issues occuring when no +multicast querier is present, this commit still has two more issues: + +1) There are cases where mdb entries do not expire even if there is a +querier present. The bridge will unnecessarily continue flooding +multicast packets on the according ports. + +2) Never removing an mdb entry could be exploited for a Denial of +Service by an attacker on the local link, slowly, but steadily eating up +all memory. + +Actually, this commit became obsolete with +"bridge: disable snooping if there is no querier" (b00589af3b) +which included fixes for a few more cases. + +Therefore reverting the following commits (the commit stated in the +commit message plus three of its follow up fixes): + +==================== +Revert "bridge: update mdb expiration timer upon reports." +This reverts commit f144febd93d5ee534fdf23505ab091b2b9088edc. +Revert "bridge: do not call setup_timer() multiple times" +This reverts commit 1faabf2aab1fdaa1ace4e8c829d1b9cf7bfec2f1. +Revert "bridge: fix some kernel warning in multicast timer" +This reverts commit c7e8e8a8f7a70b343ca1e0f90a31e35ab2d16de1. +Revert "bridge: only expire the mdb entry when query is received" +This reverts commit 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b. +==================== + +CC: Cong Wang +Signed-off-by: Linus Lüssing +Reviewed-by: Vlad Yasevich +Signed-off-by: David S. Miller +--- + net/bridge/br_mdb.c | 2 +- + net/bridge/br_multicast.c | 47 +++++++++++++++++++++++++++-------------------- + net/bridge/br_private.h | 1 - + 3 files changed, 28 insertions(+), 22 deletions(-) + +diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c +index 6319c43..de3a0e7 100644 +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -451,7 +451,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) + call_rcu_bh(&p->rcu, br_multicast_free_pg); + err = 0; + +- if (!mp->ports && !mp->mglist && mp->timer_armed && ++ if (!mp->ports && !mp->mglist && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + break; +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 0e3fea7..fbad619 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -271,7 +271,7 @@ static void br_multicast_del_pg(struct net_bridge *br, + del_timer(&p->timer); + call_rcu_bh(&p->rcu, br_multicast_free_pg); + +- if (!mp->ports && !mp->mglist && mp->timer_armed && ++ if (!mp->ports && !mp->mglist && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + +@@ -610,9 +610,6 @@ rehash: + break; + + default: +- /* If we have an existing entry, update it's expire timer */ +- mod_timer(&mp->timer, +- jiffies + br->multicast_membership_interval); + goto out; + } + +@@ -622,7 +619,6 @@ rehash: + + mp->br = br; + mp->addr = *group; +- + setup_timer(&mp->timer, br_multicast_group_expired, + (unsigned long)mp); + +@@ -662,6 +658,7 @@ static int br_multicast_add_group(struct net_bridge *br, + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *p; + struct net_bridge_port_group __rcu **pp; ++ unsigned long now = jiffies; + int err; + + spin_lock(&br->multicast_lock); +@@ -676,18 +673,15 @@ static int br_multicast_add_group(struct net_bridge *br, + + if (!port) { + mp->mglist = true; ++ mod_timer(&mp->timer, now + br->multicast_membership_interval); + goto out; + } + + for (pp = &mp->ports; + (p = mlock_dereference(*pp, br)) != NULL; + pp = &p->next) { +- if (p->port == port) { +- /* We already have a portgroup, update the timer. */ +- mod_timer(&p->timer, +- jiffies + br->multicast_membership_interval); +- goto out; +- } ++ if (p->port == port) ++ goto found; + if ((unsigned long)p->port < (unsigned long)port) + break; + } +@@ -698,6 +692,8 @@ static int br_multicast_add_group(struct net_bridge *br, + rcu_assign_pointer(*pp, p); + br_mdb_notify(br->dev, port, group, RTM_NEWMDB); + ++found: ++ mod_timer(&p->timer, now + br->multicast_membership_interval); + out: + err = 0; + +@@ -1197,9 +1193,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + +- mod_timer(&mp->timer, now + br->multicast_membership_interval); +- mp->timer_armed = true; +- + max_delay *= br->multicast_last_member_count; + + if (mp->mglist && +@@ -1276,9 +1269,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, + if (!mp) + goto out; + +- mod_timer(&mp->timer, now + br->multicast_membership_interval); +- mp->timer_armed = true; +- + max_delay *= br->multicast_last_member_count; + if (mp->mglist && + (timer_pending(&mp->timer) ? +@@ -1364,7 +1354,7 @@ static void br_multicast_leave_group(struct net_bridge *br, + call_rcu_bh(&p->rcu, br_multicast_free_pg); + br_mdb_notify(br->dev, port, group, RTM_DELMDB); + +- if (!mp->ports && !mp->mglist && mp->timer_armed && ++ if (!mp->ports && !mp->mglist && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + } +@@ -1376,12 +1366,30 @@ static void br_multicast_leave_group(struct net_bridge *br, + br->multicast_last_member_interval; + + if (!port) { +- if (mp->mglist && mp->timer_armed && ++ if (mp->mglist && + (timer_pending(&mp->timer) ? + time_after(mp->timer.expires, time) : + try_to_del_timer_sync(&mp->timer) >= 0)) { + mod_timer(&mp->timer, time); + } ++ ++ goto out; ++ } ++ ++ for (p = mlock_dereference(mp->ports, br); ++ p != NULL; ++ p = mlock_dereference(p->next, br)) { ++ if (p->port != port) ++ continue; ++ ++ if (!hlist_unhashed(&p->mglist) && ++ (timer_pending(&p->timer) ? ++ time_after(p->timer.expires, time) : ++ try_to_del_timer_sync(&p->timer) >= 0)) { ++ mod_timer(&p->timer, time); ++ } ++ ++ break; + } + out: + spin_unlock(&br->multicast_lock); +@@ -1798,7 +1806,6 @@ void br_multicast_stop(struct net_bridge *br) + hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], + hlist[ver]) { + del_timer(&mp->timer); +- mp->timer_armed = false; + call_rcu_bh(&mp->rcu, br_multicast_free_group); + } + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index cde1eb1..aa05bd8 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -126,7 +126,6 @@ struct net_bridge_mdb_entry + struct timer_list timer; + struct br_ip addr; + bool mglist; +- bool timer_armed; + }; + + struct net_bridge_mdb_htable +-- +1.7.11.7 + + +From 40420baad983147cd23e6de95c958c96b96be727 Mon Sep 17 00:00:00 2001 +From: Christophe Gouault +Date: Tue, 8 Oct 2013 17:21:22 +0200 +Subject: [PATCH 24/47] vti: get rid of nf mark rule in prerouting + +[ Upstream commit 7263a5187f9e9de45fcb51349cf0e031142c19a1 ] + +This patch fixes and improves the use of vti interfaces (while +lightly changing the way of configuring them). + +Currently: + +- it is necessary to identify and mark inbound IPsec + packets destined to each vti interface, via netfilter rules in + the mangle table at prerouting hook. + +- the vti module cannot retrieve the right tunnel in input since + commit b9959fd3: vti tunnels all have an i_key, but the tunnel lookup + is done with flag TUNNEL_NO_KEY, so there no chance to retrieve them. + +- the i_key is used by the outbound processing as a mark to lookup + for the right SP and SA bundle. + +This patch uses the o_key to store the vti mark (instead of i_key) and +enables: + +- to avoid the need for previously marking the inbound skbuffs via a + netfilter rule. +- to properly retrieve the right tunnel in input, only based on the IPsec + packet outer addresses. +- to properly perform an inbound policy check (using the tunnel o_key + as a mark). +- to properly perform an outbound SPD and SAD lookup (using the tunnel + o_key as a mark). +- to keep the current mark of the skbuff. The skbuff mark is neither + used nor changed by the vti interface. Only the vti interface o_key + is used. + +SAs have a wildcard mark. +SPs have a mark equal to the vti interface o_key. + +The vti interface must be created as follows (i_key = 0, o_key = mark): + + ip link add vti1 mode vti local 1.1.1.1 remote 2.2.2.2 okey 1 + +The SPs attached to vti1 must be created as follows (mark = vti1 o_key): + + ip xfrm policy add dir out mark 1 tmpl src 1.1.1.1 dst 2.2.2.2 \ + proto esp mode tunnel + ip xfrm policy add dir in mark 1 tmpl src 2.2.2.2 dst 1.1.1.1 \ + proto esp mode tunnel + +The SAs are created with the default wildcard mark. There is no +distinction between global vs. vti SAs. Just their addresses will +possibly link them to a vti interface: + + ip xfrm state add src 1.1.1.1 dst 2.2.2.2 proto esp spi 1000 mode tunnel \ + enc "cbc(aes)" "azertyuiopqsdfgh" + + ip xfrm state add src 2.2.2.2 dst 1.1.1.1 proto esp spi 2000 mode tunnel \ + enc "cbc(aes)" "sqbdhgqsdjqjsdfh" + +To avoid matching "global" (not vti) SPs in vti interfaces, global SPs +should no use the default wildcard mark, but explicitly match mark 0. + +To avoid a double SPD lookup in input and output (in global and vti SPDs), +the NOPOLICY and NOXFRM options should be set on the vti interfaces: + + echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_policy + echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_xfrm + +The outgoing traffic is steered to vti1 by a route via the vti interface: + + ip route add 192.168.0.0/16 dev vti1 + +The incoming IPsec traffic is steered to vti1 because its outer addresses +match the vti1 tunnel configuration. + +Signed-off-by: Christophe Gouault +Signed-off-by: David S. Miller +--- + net/ipv4/ip_vti.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index 17cc0ff..0656041 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -285,8 +285,17 @@ static int vti_rcv(struct sk_buff *skb) + tunnel = vti_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); + if (tunnel != NULL) { + struct pcpu_tstats *tstats; ++ u32 oldmark = skb->mark; ++ int ret; + +- if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) ++ ++ /* temporarily mark the skb with the tunnel o_key, to ++ * only match policies with this mark. ++ */ ++ skb->mark = be32_to_cpu(tunnel->parms.o_key); ++ ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb); ++ skb->mark = oldmark; ++ if (!ret) + return -1; + + tstats = this_cpu_ptr(tunnel->dev->tstats); +@@ -295,7 +304,6 @@ static int vti_rcv(struct sk_buff *skb) + tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); + +- skb->mark = 0; + secpath_reset(skb); + skb->dev = tunnel->dev; + return 1; +@@ -327,7 +335,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) + + memset(&fl4, 0, sizeof(fl4)); + flowi4_init_output(&fl4, tunnel->parms.link, +- be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos), ++ be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos), + RT_SCOPE_UNIVERSE, + IPPROTO_IPIP, 0, + dst, tiph->saddr, 0, 0); +-- +1.7.11.7 + + +From d74d8a563ec79425464d7a8aeaa1796724fea7bc Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 10 Oct 2013 06:30:09 -0700 +Subject: [PATCH 25/47] l2tp: must disable bh before calling l2tp_xmit_skb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 455cc32bf128e114455d11ad919321ab89a2c312 ] + +François Cachereul made a very nice bug report and suspected +the bh_lock_sock() / bh_unlok_sock() pair used in l2tp_xmit_skb() from +process context was not good. + +This problem was added by commit 6af88da14ee284aaad6e4326da09a89191ab6165 +("l2tp: Fix locking in l2tp_core.c"). + +l2tp_eth_dev_xmit() runs from BH context, so we must disable BH +from other l2tp_xmit_skb() users. + +[ 452.060011] BUG: soft lockup - CPU#1 stuck for 23s! [accel-pppd:6662] +[ 452.061757] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppoe pppox +ppp_generic slhc ipv6 ext3 mbcache jbd virtio_balloon xfs exportfs dm_mod +virtio_blk ata_generic virtio_net floppy ata_piix libata virtio_pci virtio_ring virtio [last unloaded: scsi_wait_scan] +[ 452.064012] CPU 1 +[ 452.080015] BUG: soft lockup - CPU#2 stuck for 23s! [accel-pppd:6643] +[ 452.080015] CPU 2 +[ 452.080015] +[ 452.080015] Pid: 6643, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs +[ 452.080015] RIP: 0010:[] [] do_raw_spin_lock+0x17/0x1f +[ 452.080015] RSP: 0018:ffff88007125fc18 EFLAGS: 00000293 +[ 452.080015] RAX: 000000000000aba9 RBX: ffffffff811d0703 RCX: 0000000000000000 +[ 452.080015] RDX: 00000000000000ab RSI: ffff8800711f6896 RDI: ffff8800745c8110 +[ 452.080015] RBP: ffff88007125fc18 R08: 0000000000000020 R09: 0000000000000000 +[ 452.080015] R10: 0000000000000000 R11: 0000000000000280 R12: 0000000000000286 +[ 452.080015] R13: 0000000000000020 R14: 0000000000000240 R15: 0000000000000000 +[ 452.080015] FS: 00007fdc0cc24700(0000) GS:ffff8800b6f00000(0000) knlGS:0000000000000000 +[ 452.080015] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 452.080015] CR2: 00007fdb054899b8 CR3: 0000000074404000 CR4: 00000000000006a0 +[ 452.080015] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 452.080015] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +[ 452.080015] Process accel-pppd (pid: 6643, threadinfo ffff88007125e000, task ffff8800b27e6dd0) +[ 452.080015] Stack: +[ 452.080015] ffff88007125fc28 ffffffff81256559 ffff88007125fc98 ffffffffa01b2bd1 +[ 452.080015] ffff88007125fc58 000000000000000c 00000000029490d0 0000009c71dbe25e +[ 452.080015] 000000000000005c 000000080000000e 0000000000000000 ffff880071170600 +[ 452.080015] Call Trace: +[ 452.080015] [] _raw_spin_lock+0xe/0x10 +[ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] +[ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] +[ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 +[ 452.080015] [] sock_sendmsg+0xa1/0xb6 +[ 452.080015] [] ? __schedule+0x5c1/0x616 +[ 452.080015] [] ? __dequeue_signal+0xb7/0x10c +[ 452.080015] [] ? fget_light+0x75/0x89 +[ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 +[ 452.080015] [] sys_sendto+0x10c/0x13b +[ 452.080015] [] system_call_fastpath+0x16/0x1b +[ 452.080015] Code: 81 48 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 <8a> 07 eb f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 +[ 452.080015] Call Trace: +[ 452.080015] [] _raw_spin_lock+0xe/0x10 +[ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] +[ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] +[ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 +[ 452.080015] [] sock_sendmsg+0xa1/0xb6 +[ 452.080015] [] ? __schedule+0x5c1/0x616 +[ 452.080015] [] ? __dequeue_signal+0xb7/0x10c +[ 452.080015] [] ? fget_light+0x75/0x89 +[ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 +[ 452.080015] [] sys_sendto+0x10c/0x13b +[ 452.080015] [] system_call_fastpath+0x16/0x1b +[ 452.064012] +[ 452.064012] Pid: 6662, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs +[ 452.064012] RIP: 0010:[] [] do_raw_spin_lock+0x19/0x1f +[ 452.064012] RSP: 0018:ffff8800b6e83ba0 EFLAGS: 00000297 +[ 452.064012] RAX: 000000000000aaa9 RBX: ffff8800b6e83b40 RCX: 0000000000000002 +[ 452.064012] RDX: 00000000000000aa RSI: 000000000000000a RDI: ffff8800745c8110 +[ 452.064012] RBP: ffff8800b6e83ba0 R08: 000000000000c802 R09: 000000000000001c +[ 452.064012] R10: ffff880071096c4e R11: 0000000000000006 R12: ffff8800b6e83b18 +[ 452.064012] R13: ffffffff8125d51e R14: ffff8800b6e83ba0 R15: ffff880072a589c0 +[ 452.064012] FS: 00007fdc0b81e700(0000) GS:ffff8800b6e80000(0000) knlGS:0000000000000000 +[ 452.064012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 452.064012] CR2: 0000000000625208 CR3: 0000000074404000 CR4: 00000000000006a0 +[ 452.064012] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 452.064012] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +[ 452.064012] Process accel-pppd (pid: 6662, threadinfo ffff88007129a000, task ffff8800744f7410) +[ 452.064012] Stack: +[ 452.064012] ffff8800b6e83bb0 ffffffff81256559 ffff8800b6e83bc0 ffffffff8121c64a +[ 452.064012] ffff8800b6e83bf0 ffffffff8121ec7a ffff880072a589c0 ffff880071096c62 +[ 452.064012] 0000000000000011 ffffffff81430024 ffff8800b6e83c80 ffffffff8121f276 +[ 452.064012] Call Trace: +[ 452.064012] +[ 452.064012] [] _raw_spin_lock+0xe/0x10 +[ 452.064012] [] spin_lock+0x9/0xb +[ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 +[ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae +[ 452.064012] [] ? raw_rcv+0xe9/0xf0 +[ 452.064012] [] udp_rcv+0x1a/0x1c +[ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 +[ 452.064012] [] ip_local_deliver+0x53/0x84 +[ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 +[ 452.064012] [] ip_rcv+0x210/0x269 +[ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb +[ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 +[ 452.064012] [] netif_receive_skb+0x57/0x5e +[ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b +[ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] +[ 452.064012] [] net_rx_action+0x73/0x184 +[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] +[ 452.064012] [] __do_softirq+0xc3/0x1a8 +[ 452.064012] [] ? ack_APIC_irq+0x10/0x12 +[ 452.064012] [] ? _raw_spin_lock+0xe/0x10 +[ 452.064012] [] call_softirq+0x1c/0x26 +[ 452.064012] [] do_softirq+0x45/0x82 +[ 452.064012] [] irq_exit+0x42/0x9c +[ 452.064012] [] do_IRQ+0x8e/0xa5 +[ 452.064012] [] common_interrupt+0x6e/0x6e +[ 452.064012] +[ 452.064012] [] ? kfree+0x8a/0xa3 +[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] +[ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] +[ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] +[ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 +[ 452.064012] [] sock_sendmsg+0xa1/0xb6 +[ 452.064012] [] ? __schedule+0x5c1/0x616 +[ 452.064012] [] ? __dequeue_signal+0xb7/0x10c +[ 452.064012] [] ? fget_light+0x75/0x89 +[ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 +[ 452.064012] [] sys_sendto+0x10c/0x13b +[ 452.064012] [] system_call_fastpath+0x16/0x1b +[ 452.064012] Code: 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 8a 07 f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 55 48 +[ 452.064012] Call Trace: +[ 452.064012] [] _raw_spin_lock+0xe/0x10 +[ 452.064012] [] spin_lock+0x9/0xb +[ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 +[ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae +[ 452.064012] [] ? raw_rcv+0xe9/0xf0 +[ 452.064012] [] udp_rcv+0x1a/0x1c +[ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 +[ 452.064012] [] ip_local_deliver+0x53/0x84 +[ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 +[ 452.064012] [] ip_rcv+0x210/0x269 +[ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb +[ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 +[ 452.064012] [] netif_receive_skb+0x57/0x5e +[ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b +[ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] +[ 452.064012] [] net_rx_action+0x73/0x184 +[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] +[ 452.064012] [] __do_softirq+0xc3/0x1a8 +[ 452.064012] [] ? ack_APIC_irq+0x10/0x12 +[ 452.064012] [] ? _raw_spin_lock+0xe/0x10 +[ 452.064012] [] call_softirq+0x1c/0x26 +[ 452.064012] [] do_softirq+0x45/0x82 +[ 452.064012] [] irq_exit+0x42/0x9c +[ 452.064012] [] do_IRQ+0x8e/0xa5 +[ 452.064012] [] common_interrupt+0x6e/0x6e +[ 452.064012] [] ? kfree+0x8a/0xa3 +[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] +[ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] +[ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] +[ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 +[ 452.064012] [] sock_sendmsg+0xa1/0xb6 +[ 452.064012] [] ? __schedule+0x5c1/0x616 +[ 452.064012] [] ? __dequeue_signal+0xb7/0x10c +[ 452.064012] [] ? fget_light+0x75/0x89 +[ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 +[ 452.064012] [] sys_sendto+0x10c/0x13b +[ 452.064012] [] system_call_fastpath+0x16/0x1b + +Reported-by: François Cachereul +Tested-by: François Cachereul +Signed-off-by: Eric Dumazet +Cc: James Chapman +Signed-off-by: David S. Miller +--- + net/l2tp/l2tp_ppp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 5ebee2d..8c46b27 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -353,7 +353,9 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh + goto error_put_sess_tun; + } + ++ local_bh_disable(); + l2tp_xmit_skb(session, skb, session->hdr_len); ++ local_bh_enable(); + + sock_put(ps->tunnel_sock); + sock_put(sk); +@@ -422,7 +424,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + skb->data[0] = ppph[0]; + skb->data[1] = ppph[1]; + ++ local_bh_disable(); + l2tp_xmit_skb(session, skb, session->hdr_len); ++ local_bh_enable(); + + sock_put(sk_tun); + sock_put(sk); +-- +1.7.11.7 + + +From 5bf1c228293765ff84e4121cf2f92395403b7e33 Mon Sep 17 00:00:00 2001 +From: stephen hemminger +Date: Sun, 6 Oct 2013 15:15:33 -0700 +Subject: [PATCH 26/47] netem: update backlog after drop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 638a52b801e40ed276ceb69b73579ad99365361a ] + +When packet is dropped from rb-tree netem the backlog statistic should +also be updated. + +Reported-by: Сергеев Сергей +Signed-off-by: Stephen Hemminger +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/sched/sch_netem.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c +index 82f6016..7dc79940 100644 +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -523,6 +523,7 @@ static unsigned int netem_drop(struct Qdisc *sch) + skb->next = NULL; + skb->prev = NULL; + len = qdisc_pkt_len(skb); ++ sch->qstats.backlog -= len; + kfree_skb(skb); + } + } +-- +1.7.11.7 + + +From ddc30868db0e31c0c2ab4691131a050f9136f3bf Mon Sep 17 00:00:00 2001 +From: stephen hemminger +Date: Sun, 6 Oct 2013 15:16:49 -0700 +Subject: [PATCH 27/47] netem: free skb's in tree on reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit ff704050f2fc0f3382b5a70bba56a51a3feca79d ] + +Netem can leak memory because packets get stored in red-black +tree and it is not cleared on reset. + +Reported by: Сергеев Сергей +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +--- + net/sched/sch_netem.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c +index 7dc79940..3626010 100644 +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -358,6 +358,21 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche + return PSCHED_NS2TICKS(ticks); + } + ++static void tfifo_reset(struct Qdisc *sch) ++{ ++ struct netem_sched_data *q = qdisc_priv(sch); ++ struct rb_node *p; ++ ++ while ((p = rb_first(&q->t_root))) { ++ struct sk_buff *skb = netem_rb_to_skb(p); ++ ++ rb_erase(p, &q->t_root); ++ skb->next = NULL; ++ skb->prev = NULL; ++ kfree_skb(skb); ++ } ++} ++ + static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) + { + struct netem_sched_data *q = qdisc_priv(sch); +@@ -613,6 +628,7 @@ static void netem_reset(struct Qdisc *sch) + struct netem_sched_data *q = qdisc_priv(sch); + + qdisc_reset_queue(sch); ++ tfifo_reset(sch); + if (q->qdisc) + qdisc_reset(q->qdisc); + qdisc_watchdog_cancel(&q->watchdog); +-- +1.7.11.7 + + +From c871c477136615360e283471acdb33df95d70470 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Fri, 11 Oct 2013 12:50:03 +0300 +Subject: [PATCH 28/47] farsync: fix info leak in ioctl + +[ Upstream commit 96b340406724d87e4621284ebac5e059d67b2194 ] + +The fst_get_iface() code fails to initialize the two padding bytes of +struct sync_serial_settings after the ->loopback member. Add an explicit +memset(0) before filling the structure to avoid the info leak. + +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +--- + drivers/net/wan/farsync.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c +index 3f0c4f2..bcfff0d 100644 +--- a/drivers/net/wan/farsync.c ++++ b/drivers/net/wan/farsync.c +@@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port, + } + + i = port->index; ++ memset(&sync, 0, sizeof(sync)); + sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed); + /* Lucky card and linux use same encoding here */ + sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == +-- +1.7.11.7 + + +From e69ccba66791d0edd0d596520de268369aaab610 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Mon, 30 Sep 2013 22:05:40 +0200 +Subject: [PATCH 29/47] unix_diag: fix info leak + +[ Upstream commit 6865d1e834be84ddd5808d93d5035b492346c64a ] + +When filling the netlink message we miss to wipe the pad field, +therefore leak one byte of heap memory to userland. Fix this by +setting pad to 0. + +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + net/unix/diag.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/unix/diag.c b/net/unix/diag.c +index d591091..86fa0f3 100644 +--- a/net/unix/diag.c ++++ b/net/unix/diag.c +@@ -124,6 +124,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r + rep->udiag_family = AF_UNIX; + rep->udiag_type = sk->sk_type; + rep->udiag_state = sk->sk_state; ++ rep->pad = 0; + rep->udiag_ino = sk_ino; + sock_diag_save_cookie(sk, rep->udiag_cookie); + +-- +1.7.11.7 + + +From 00fa721e6873ccbb36fc008558bb7d23e9e3c21f Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Mon, 30 Sep 2013 22:03:07 +0200 +Subject: [PATCH 30/47] connector: use nlmsg_len() to check message length + +[ Upstream commit 162b2bedc084d2d908a04c93383ba02348b648b0 ] + +The current code tests the length of the whole netlink message to be +at least as long to fit a cn_msg. This is wrong as nlmsg_len includes +the length of the netlink message header. Use nlmsg_len() instead to +fix this "off-by-NLMSG_HDRLEN" size check. + +Cc: stable@vger.kernel.org # v2.6.14+ +Signed-off-by: Mathias Krause +Signed-off-by: David S. Miller +--- + drivers/connector/connector.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c +index 6ecfa75..0daa11e 100644 +--- a/drivers/connector/connector.c ++++ b/drivers/connector/connector.c +@@ -157,17 +157,18 @@ static int cn_call_callback(struct sk_buff *skb) + static void cn_rx_skb(struct sk_buff *__skb) + { + struct nlmsghdr *nlh; +- int err; + struct sk_buff *skb; ++ int len, err; + + skb = skb_get(__skb); + + if (skb->len >= NLMSG_HDRLEN) { + nlh = nlmsg_hdr(skb); ++ len = nlmsg_len(nlh); + +- if (nlh->nlmsg_len < sizeof(struct cn_msg) || ++ if (len < (int)sizeof(struct cn_msg) || + skb->len < nlh->nlmsg_len || +- nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { ++ len > CONNECTOR_MAX_MSG_SIZE) { + kfree_skb(skb); + return; + } +-- +1.7.11.7 + + +From d99d51100021c9f8b335fc1931880618eaa448e3 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 12 Oct 2013 14:08:34 -0700 +Subject: [PATCH 31/47] bnx2x: record rx queue for LRO packets + +[ Upstream commit 60e66fee56b2256dcb1dc2ea1b2ddcb6e273857d ] + +RPS support is kind of broken on bnx2x, because only non LRO packets +get proper rx queue information. This triggers reorders, as it seems +bnx2x like to generate a non LRO packet for segment including TCP PUSH +flag : (this might be pure coincidence, but all the reorders I've +seen involve segments with a PUSH) + +11:13:34.335847 IP A > B: . 415808:447136(31328) ack 1 win 457 +11:13:34.335992 IP A > B: . 447136:448560(1424) ack 1 win 457 +11:13:34.336391 IP A > B: . 448560:479888(31328) ack 1 win 457 +11:13:34.336425 IP A > B: P 511216:512640(1424) ack 1 win 457 +11:13:34.336423 IP A > B: . 479888:511216(31328) ack 1 win 457 +11:13:34.336924 IP A > B: . 512640:543968(31328) ack 1 win 457 +11:13:34.336963 IP A > B: . 543968:575296(31328) ack 1 win 457 + +We must call skb_record_rx_queue() to properly give to RPS (and more +generally for TX queue selection on forward path) the receive queue +information. + +Similar fix is needed for skb_mark_napi_id(), but will be handled +in a separate patch to ease stable backports. + +Signed-off-by: Eric Dumazet +Cc: Willem de Bruijn +Cc: Eilon Greenstein +Acked-by: Dmitry Kravkov +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index 0cc2611..4b0877e 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -676,6 +676,7 @@ static void bnx2x_gro_receive(struct bnx2x *bp, struct bnx2x_fastpath *fp, + } + } + #endif ++ skb_record_rx_queue(skb, fp->rx_queue); + napi_gro_receive(&fp->napi, skb); + } + +-- +1.7.11.7 + + +From 3f1db36c01909701d0e34cd2413a1127e144bcc3 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Tue, 15 Oct 2013 11:18:58 +0800 +Subject: [PATCH 32/47] virtio-net: don't respond to cpu hotplug notifier if + we're not ready + +[ Upstream commit 3ab098df35f8b98b6553edc2e40234af512ba877 ] + +We're trying to re-configure the affinity unconditionally in cpu hotplug +callback. This may lead the issue during resuming from s3/s4 since + +- virt queues haven't been allocated at that time. +- it's unnecessary since thaw method will re-configure the affinity. + +Fix this issue by checking the config_enable and do nothing is we're not ready. + +The bug were introduced by commit 8de4b2f3ae90c8fc0f17eeaab87d5a951b66ee17 +(virtio-net: reset virtqueue affinity when doing cpu hotplug). + +Cc: Rusty Russell +Cc: Michael S. Tsirkin +Cc: Wanlong Gao +Acked-by: Michael S. Tsirkin +Reviewed-by: Wanlong Gao +Signed-off-by: Jason Wang +Signed-off-by: David S. Miller +--- + drivers/net/virtio_net.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 3d2a90a..43a71d9 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1094,6 +1094,11 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, + { + struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + ++ mutex_lock(&vi->config_lock); ++ ++ if (!vi->config_enable) ++ goto done; ++ + switch(action & ~CPU_TASKS_FROZEN) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: +@@ -1106,6 +1111,9 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, + default: + break; + } ++ ++done: ++ mutex_unlock(&vi->config_lock); + return NOTIFY_OK; + } + +-- +1.7.11.7 + + +From 24ef3b7cfd16ce5ac263deebfecb661d1c784670 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Tue, 15 Oct 2013 11:18:59 +0800 +Subject: [PATCH 33/47] virtio-net: refill only when device is up during + setting queues + +[ Upstream commit 35ed159bfd96a7547ec277ed8b550c7cbd9841b6 ] + +We used to schedule the refill work unconditionally after changing the +number of queues. This may lead an issue if the device is not +up. Since we only try to cancel the work in ndo_stop(), this may cause +the refill work still work after removing the device. Fix this by only +schedule the work when device is up. + +The bug were introduce by commit 9b9cd8024a2882e896c65222aa421d461354e3f2. +(virtio-net: fix the race between channels setting and refill) + +Cc: Rusty Russell +Cc: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: David S. Miller +--- + drivers/net/virtio_net.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 43a71d9..1d01534 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -916,7 +916,9 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) + return -EINVAL; + } else { + vi->curr_queue_pairs = queue_pairs; +- schedule_delayed_work(&vi->refill, 0); ++ /* virtnet_open() will refill when device is going to up. */ ++ if (dev->flags & IFF_UP) ++ schedule_delayed_work(&vi->refill, 0); + } + + return 0; +@@ -1714,7 +1716,9 @@ static int virtnet_restore(struct virtio_device *vdev) + vi->config_enable = true; + mutex_unlock(&vi->config_lock); + ++ rtnl_lock(); + virtnet_set_queues(vi, vi->curr_queue_pairs); ++ rtnl_unlock(); + + return 0; + } +-- +1.7.11.7 + + +From d616bd8bf902f82ea742462a29bf4080aaa8f497 Mon Sep 17 00:00:00 2001 +From: Vlad Yasevich +Date: Tue, 15 Oct 2013 14:57:45 -0400 +Subject: [PATCH 34/47] bridge: Correctly clamp MAX forward_delay when + enabling STP + +[ Upstream commit 4b6c7879d84ad06a2ac5b964808ed599187a188d ] + +Commit be4f154d5ef0ca147ab6bcd38857a774133f5450 + bridge: Clamp forward_delay when enabling STP +had a typo when attempting to clamp maximum forward delay. + +It is possible to set bridge_forward_delay to be higher then +permitted maximum when STP is off. When turning STP on, the +higher then allowed delay has to be clamed down to max value. + +CC: Herbert Xu +CC: Stephen Hemminger +Signed-off-by: Vlad Yasevich +Reviewed-by: Veaceslav Falico +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- + net/bridge/br_stp_if.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c +index 108084a..656a6f3 100644 +--- a/net/bridge/br_stp_if.c ++++ b/net/bridge/br_stp_if.c +@@ -134,7 +134,7 @@ static void br_stp_start(struct net_bridge *br) + + if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) + __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); +- else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY) ++ else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY) + __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); + + if (r == 0) { +-- +1.7.11.7 + + +From 803490b7c577add0b976aa08e4bbfdd95f505270 Mon Sep 17 00:00:00 2001 +From: Vlad Yasevich +Date: Tue, 15 Oct 2013 22:01:29 -0400 +Subject: [PATCH 35/47] net: dst: provide accessor function to dst->xfrm + +[ Upstream commit e87b3998d795123b4139bc3f25490dd236f68212 ] + +dst->xfrm is conditionally defined. Provide accessor funtion that +is always available. + +Signed-off-by: Vlad Yasevich +Acked-by: Neil Horman +Signed-off-by: David S. Miller +--- + include/net/dst.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 1f8fd10..e0c97f5 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -477,10 +477,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, + { + return dst_orig; + } ++ ++static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) ++{ ++ return NULL; ++} ++ + #else + extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); ++ ++/* skb attached with this dst needs transformation if dst->xfrm is valid */ ++static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) ++{ ++ return dst->xfrm; ++} + #endif + + #endif /* _NET_DST_H */ +-- +1.7.11.7 + + +From 371a65903ccb75fc71fd42b30a310a28c42e54a3 Mon Sep 17 00:00:00 2001 +From: Fan Du +Date: Tue, 15 Oct 2013 22:01:30 -0400 +Subject: [PATCH 36/47] sctp: Use software crc32 checksum when xfrm transform + will happen. + +[ Upstream commit 27127a82561a2a3ed955ce207048e1b066a80a2a ] + +igb/ixgbe have hardware sctp checksum support, when this feature is enabled +and also IPsec is armed to protect sctp traffic, ugly things happened as +xfrm_output checks CHECKSUM_PARTIAL to do checksum operation(sum every thing +up and pack the 16bits result in the checksum field). The result is fail +establishment of sctp communication. + +Cc: Neil Horman +Cc: Steffen Klassert +Signed-off-by: Fan Du +Signed-off-by: Vlad Yasevich +Acked-by: Neil Horman +Signed-off-by: David S. Miller +--- + net/sctp/output.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/output.c b/net/sctp/output.c +index a46d1eb..a06a9b6 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -542,7 +542,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) + * by CRC32-C as described in . + */ + if (!sctp_checksum_disable) { +- if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) { ++ if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || ++ (dst_xfrm(dst) != NULL)) { + __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); + + /* 3) Put the resultant value into the checksum field in the +-- +1.7.11.7 + + +From 9067790bb296fb5818894222d7e85407238e9843 Mon Sep 17 00:00:00 2001 +From: Vlad Yasevich +Date: Tue, 15 Oct 2013 22:01:31 -0400 +Subject: [PATCH 37/47] sctp: Perform software checksum if packet has to be + fragmented. + +[ Upstream commit d2dbbba77e95dff4b4f901fee236fef6d9552072 ] + +IP/IPv6 fragmentation knows how to compute only TCP/UDP checksum. +This causes problems if SCTP packets has to be fragmented and +ipsummed has been set to PARTIAL due to checksum offload support. +This condition can happen when retransmitting after MTU discover, +or when INIT or other control chunks are larger then MTU. +Check for the rare fragmentation condition in SCTP and use software +checksum calculation in this case. + +CC: Fan Du +Signed-off-by: Vlad Yasevich +Acked-by: Neil Horman +Signed-off-by: David S. Miller +--- + net/sctp/output.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/output.c b/net/sctp/output.c +index a06a9b6..013a07d 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -543,7 +543,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) + */ + if (!sctp_checksum_disable) { + if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || +- (dst_xfrm(dst) != NULL)) { ++ (dst_xfrm(dst) != NULL) || packet->ipfragok) { + __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); + + /* 3) Put the resultant value into the checksum field in the +-- +1.7.11.7 + + +From 22e825ed8144360271614511563166f37fef9f90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Wed, 16 Oct 2013 12:46:50 +0200 +Subject: [PATCH 38/47] wanxl: fix info leak in ioctl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 2b13d06c9584b4eb773f1e80bbaedab9a1c344e1 ] + +The wanxl_ioctl() code fails to initialize the two padding bytes of +struct sync_serial_settings after the ->loopback member. Add an explicit +memset(0) before filling the structure to avoid the info leak. + +Signed-off-by: Salva Peiró +Signed-off-by: David S. Miller +--- + drivers/net/wan/wanxl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 6a24a5a..4c0a697 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -355,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } ++ memset(&line, 0, sizeof(line)); + line.clock_type = get_status(port)->clocking; + line.clock_rate = 0; + line.loopback = 0; +-- +1.7.11.7 + + +From b16dd2cff7a4eb3881f43371d71ed242332877dc Mon Sep 17 00:00:00 2001 +From: Vasundhara Volam +Date: Thu, 17 Oct 2013 11:47:14 +0530 +Subject: [PATCH 39/47] be2net: pass if_id for v1 and V2 versions of TX_CREATE + cmd + +[ Upstream commit 0fb88d61bc60779dde88b0fc268da17eb81d0412 ] + +It is a required field for all TX_CREATE cmd versions > 0. +This fixes a driver initialization failure, caused by recent SH-R Firmwares +(versions > 10.0.639.0) failing the TX_CREATE cmd when if_id field is +not passed. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 8ec5d74..13ac104 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1150,7 +1150,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) + + if (lancer_chip(adapter)) { + req->hdr.version = 1; +- req->if_id = cpu_to_le16(adapter->if_handle); + } else if (BEx_chip(adapter)) { + if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) + req->hdr.version = 2; +@@ -1158,6 +1157,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) + req->hdr.version = 2; + } + ++ if (req->hdr.version > 0) ++ req->if_id = cpu_to_le16(adapter->if_handle); + req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); + req->ulp_num = BE_ULP1_NUM; + req->type = BE_ETH_TX_RING_TYPE_STANDARD; +-- +1.7.11.7 + + +From 9829aac8208e7a31e4e42e7d2e7e165593c05202 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Thu, 17 Oct 2013 22:51:31 +0200 +Subject: [PATCH 40/47] net: unix: inherit SOCK_PASS{CRED, SEC} flags from + socket to fix race + +[ Upstream commit 90c6bd34f884cd9cee21f1d152baf6c18bcac949 ] + +In the case of credentials passing in unix stream sockets (dgram +sockets seem not affected), we get a rather sparse race after +commit 16e5726 ("af_unix: dont send SCM_CREDENTIALS by default"). + +We have a stream server on receiver side that requests credential +passing from senders (e.g. nc -U). Since we need to set SO_PASSCRED +on each spawned/accepted socket on server side to 1 first (as it's +not inherited), it can happen that in the time between accept() and +setsockopt() we get interrupted, the sender is being scheduled and +continues with passing data to our receiver. At that time SO_PASSCRED +is neither set on sender nor receiver side, hence in cmsg's +SCM_CREDENTIALS we get eventually pid:0, uid:65534, gid:65534 +(== overflow{u,g}id) instead of what we actually would like to see. + +On the sender side, here nc -U, the tests in maybe_add_creds() +invoked through unix_stream_sendmsg() would fail, as at that exact +time, as mentioned, the sender has neither SO_PASSCRED on his side +nor sees it on the server side, and we have a valid 'other' socket +in place. Thus, sender believes it would just look like a normal +connection, not needing/requesting SO_PASSCRED at that time. + +As reverting 16e5726 would not be an option due to the significant +performance regression reported when having creds always passed, +one way/trade-off to prevent that would be to set SO_PASSCRED on +the listener socket and allow inheriting these flags to the spawned +socket on server side in accept(). It seems also logical to do so +if we'd tell the listener socket to pass those flags onwards, and +would fix the race. + +Before, strace: + +recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], + msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, + cmsg_type=SCM_CREDENTIALS{pid=0, uid=65534, gid=65534}}, + msg_flags=0}, 0) = 5 + +After, strace: + +recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], + msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, + cmsg_type=SCM_CREDENTIALS{pid=11580, uid=1000, gid=1000}}, + msg_flags=0}, 0) = 5 + +Signed-off-by: Daniel Borkmann +Cc: Eric Dumazet +Cc: Eric W. Biederman +Signed-off-by: David S. Miller +--- + net/unix/af_unix.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index c4ce243..e64bbcf 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1246,6 +1246,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) + return 0; + } + ++static void unix_sock_inherit_flags(const struct socket *old, ++ struct socket *new) ++{ ++ if (test_bit(SOCK_PASSCRED, &old->flags)) ++ set_bit(SOCK_PASSCRED, &new->flags); ++ if (test_bit(SOCK_PASSSEC, &old->flags)) ++ set_bit(SOCK_PASSSEC, &new->flags); ++} ++ + static int unix_accept(struct socket *sock, struct socket *newsock, int flags) + { + struct sock *sk = sock->sk; +@@ -1280,6 +1289,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) + /* attach accepted sock to socket */ + unix_state_lock(tsk); + newsock->state = SS_CONNECTED; ++ unix_sock_inherit_flags(sock, newsock); + sock_graft(tsk, newsock); + unix_state_unlock(tsk); + return 0; +-- +1.7.11.7 + + +From 7b48750febb4c3387db39fd0b547936c53ba7364 Mon Sep 17 00:00:00 2001 +From: Seif Mazareeb +Date: Thu, 17 Oct 2013 20:33:21 -0700 +Subject: [PATCH 41/47] net: fix cipso packet validation when !NETLABEL + +[ Upstream commit f2e5ddcc0d12f9c4c7b254358ad245c9dddce13b ] + +When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop +forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel +crash in an SMP system, since the CPU executing this function will +stall /not respond to IPIs. + +This problem can be reproduced by running the IP Stack Integrity Checker +(http://isic.sourceforge.net) using the following command on a Linux machine +connected to DUT: + +"icmpsic -s rand -d -r 123456" +wait (1-2 min) + +Signed-off-by: Seif Mazareeb +Acked-by: Paul Moore +Signed-off-by: David S. Miller +--- + include/net/cipso_ipv4.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h +index a7a683e..a8c2ef6 100644 +--- a/include/net/cipso_ipv4.h ++++ b/include/net/cipso_ipv4.h +@@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, + unsigned char err_offset = 0; + u8 opt_len = opt[1]; + u8 opt_iter; ++ u8 tag_len; + + if (opt_len < 8) { + err_offset = 1; +@@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, + } + + for (opt_iter = 6; opt_iter < opt_len;) { +- if (opt[opt_iter + 1] > (opt_len - opt_iter)) { ++ tag_len = opt[opt_iter + 1]; ++ if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) { + err_offset = opt_iter + 1; + goto out; + } +- opt_iter += opt[opt_iter + 1]; ++ opt_iter += tag_len; + } + + out: +-- +1.7.11.7 + + +From 27e33640a8905b1aeefe9998242551caf24e84a6 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Tue, 22 Oct 2013 00:07:47 +0200 +Subject: [PATCH 42/47] inet: fix possible memory corruption with UDP_CORK and + UFO + +[ This is a simplified -stable version of a set of upstream commits. ] + +This is a replacement patch only for stable which does fix the problems +handled by the following two commits in -net: + +"ip_output: do skb ufo init for peeked non ufo skb as well" (e93b7d748be887cd7639b113ba7d7ef792a7efb9) +"ip6_output: do skb ufo init for peeked non ufo skb as well" (c547dbf55d5f8cf615ccc0e7265e98db27d3fb8b) + +Three frames are written on a corked udp socket for which the output +netdevice has UFO enabled. If the first and third frame are smaller than +the mtu and the second one is bigger, we enqueue the second frame with +skb_append_datato_frags without initializing the gso fields. This leads +to the third frame appended regulary and thus constructing an invalid skb. + +This fixes the problem by always using skb_append_datato_frags as soon +as the first frag got enqueued to the skb without marking the packet +as SKB_GSO_UDP. + +The problem with only two frames for ipv6 was fixed by "ipv6: udp +packets following an UFO enqueued packet need also be handled by UFO" +(2811ebac2521ceac84f2bdae402455baa6a7fb47). + +Cc: Jiri Pirko +Cc: Eric Dumazet +Cc: David Miller +Signed-off-by: Hannes Frederic Sowa +--- + include/linux/skbuff.h | 5 +++++ + net/ipv4/ip_output.c | 2 +- + net/ipv6/ip6_output.c | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 3b71a4e..6bd165b 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1316,6 +1316,11 @@ static inline int skb_pagelen(const struct sk_buff *skb) + return len + skb_headlen(skb); + } + ++static inline bool skb_has_frags(const struct sk_buff *skb) ++{ ++ return skb_shinfo(skb)->nr_frags; ++} ++ + /** + * __skb_fill_page_desc - initialise a paged fragment in an skb + * @skb: buffer containing fragment to be initialised +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index a04d872..7f4ab5d 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -836,7 +836,7 @@ static int __ip_append_data(struct sock *sk, + csummode = CHECKSUM_PARTIAL; + + cork->length += length; +- if (((length > mtu) || (skb && skb_is_gso(skb))) && ++ if (((length > mtu) || (skb && skb_has_frags(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { + err = ip_ufo_append_data(sk, queue, getfrag, from, length, +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 44df1c9..2e542d0 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1252,7 +1252,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + skb = skb_peek_tail(&sk->sk_write_queue); + cork->length += length; + if (((length > mtu) || +- (skb && skb_is_gso(skb))) && ++ (skb && skb_has_frags(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO)) { + err = ip6_ufo_append_data(sk, getfrag, from, length, +-- +1.7.11.7 + + +From 689f77d13532698739438b2288ec8eac2f667584 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Sun, 20 Oct 2013 15:43:03 +0300 +Subject: [PATCH 43/47] ipv6: always prefer rt6i_gateway if present + +[ Upstream commit 96dc809514fb2328605198a0602b67554d8cce7b ] + +In v3.9 6fd6ce2056de2709 ("ipv6: Do not depend on rt->n in +ip6_finish_output2()." changed the behaviour of ip6_finish_output2() +such that the recently introduced rt6_nexthop() is used +instead of an assigned neighbor. + +As rt6_nexthop() prefers rt6i_gateway only for gatewayed +routes this causes a problem for users like IPVS, xt_TEE and +RAW(hdrincl) if they want to use different address for routing +compared to the destination address. + +Another case is when redirect can create RTF_DYNAMIC +route without RTF_GATEWAY flag, we ignore the rt6i_gateway +in rt6_nexthop(). + +Fix the above problems by considering the rt6i_gateway if +present, so that traffic routed to address on local subnet is +not wrongly diverted to the destination address. + +Thanks to Simon Horman and Phil Oester for spotting the +problematic commit. + +Thanks to Hannes Frederic Sowa for his review and help in testing. + +Reported-by: Phil Oester +Reported-by: Mark Brooks +Signed-off-by: Julian Anastasov +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/ip6_route.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index f667248..0aaf0ec 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -198,7 +198,7 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) + + static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) + { +- if (rt->rt6i_flags & RTF_GATEWAY) ++ if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) + return &rt->rt6i_gateway; + return dest; + } +-- +1.7.11.7 + + +From 471dd605429d6645f990becd29c877740d3b32e7 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Sun, 20 Oct 2013 15:43:04 +0300 +Subject: [PATCH 44/47] ipv6: fill rt6i_gateway with nexthop address + +[ Upstream commit 550bab42f83308c9d6ab04a980cc4333cef1c8fa ] + +Make sure rt6i_gateway contains nexthop information in +all routes returned from lookup or when routes are directly +attached to skb for generated ICMP packets. + +The effect of this patch should be a faster version of +rt6_nexthop() and the consideration of local addresses as +nexthop. + +Signed-off-by: Julian Anastasov +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/ip6_route.h | 6 ++---- + net/ipv6/ip6_output.c | 4 ++-- + net/ipv6/route.c | 8 ++++++-- + 3 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index 0aaf0ec..c7b8860 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -196,11 +196,9 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) + skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); + } + +-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) ++static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt) + { +- if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) +- return &rt->rt6i_gateway; +- return dest; ++ return &rt->rt6i_gateway; + } + + #endif +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 2e542d0..5b25f85 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -130,7 +130,7 @@ static int ip6_finish_output2(struct sk_buff *skb) + } + + rcu_read_lock_bh(); +- nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); ++ nexthop = rt6_nexthop((struct rt6_info *)dst); + neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); + if (unlikely(!neigh)) + neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); +@@ -899,7 +899,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, + */ + rt = (struct rt6_info *) *dst; + rcu_read_lock_bh(); +- n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr)); ++ n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt)); + err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0; + rcu_read_unlock_bh(); + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 8d9a93ed..08e6c40 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -852,7 +852,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, + if (ort->rt6i_dst.plen != 128 && + ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) + rt->rt6i_flags |= RTF_ANYCAST; +- rt->rt6i_gateway = *daddr; + } + + rt->rt6i_flags |= RTF_CACHE; +@@ -1270,6 +1269,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, + rt->dst.flags |= DST_HOST; + rt->dst.output = ip6_output; + atomic_set(&rt->dst.__refcnt, 1); ++ rt->rt6i_gateway = fl6->daddr; + rt->rt6i_dst.addr = fl6->daddr; + rt->rt6i_dst.plen = 128; + rt->rt6i_idev = idev; +@@ -1824,7 +1824,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, + in6_dev_hold(rt->rt6i_idev); + rt->dst.lastuse = jiffies; + +- rt->rt6i_gateway = ort->rt6i_gateway; ++ if (ort->rt6i_flags & RTF_GATEWAY) ++ rt->rt6i_gateway = ort->rt6i_gateway; ++ else ++ rt->rt6i_gateway = *dest; + rt->rt6i_flags = ort->rt6i_flags; + if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == + (RTF_DEFAULT | RTF_ADDRCONF)) +@@ -2111,6 +2114,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, + else + rt->rt6i_flags |= RTF_LOCAL; + ++ rt->rt6i_gateway = *addr; + rt->rt6i_dst.addr = *addr; + rt->rt6i_dst.plen = 128; + rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); +-- +1.7.11.7 + + +From d01c3be45be54261f56ba63197d94e3d756befdf Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Sun, 20 Oct 2013 15:43:05 +0300 +Subject: [PATCH 45/47] netfilter: nf_conntrack: fix rt6i_gateway checks for + H.323 helper + +[ Upstream commit 56e42441ed54b092d6c7411138ce60d049e7c731 ] + +Now when rt6_nexthop() can return nexthop address we can use it +for proper nexthop comparison of directly connected destinations. +For more information refer to commit bbb5823cf742a7 +("netfilter: nf_conntrack: fix rt_gateway checks for H.323 helper"). + +Signed-off-by: Julian Anastasov +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/netfilter/nf_conntrack_h323_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c +index bdebd03..70866d1 100644 +--- a/net/netfilter/nf_conntrack_h323_main.c ++++ b/net/netfilter/nf_conntrack_h323_main.c +@@ -778,8 +778,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, + flowi6_to_flowi(&fl1), false)) { + if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, + flowi6_to_flowi(&fl2), false)) { +- if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, +- sizeof(rt1->rt6i_gateway)) && ++ if (ipv6_addr_equal(rt6_nexthop(rt1), ++ rt6_nexthop(rt2)) && + rt1->dst.dev == rt2->dst.dev) + ret = 1; + dst_release(&rt2->dst); +-- +1.7.11.7 + + +From 1d98ddb501bedeee62c916d3d6999109f0a22198 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Mon, 21 Oct 2013 06:17:15 +0200 +Subject: [PATCH 46/47] ipv6: probe routes asynchronous in rt6_probe + +[ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ] + +Routes need to be probed asynchronous otherwise the call stack gets +exhausted when the kernel attemps to deliver another skb inline, like +e.g. xt_TEE does, and we probe at the same time. + +We update neigh->updated still at once, otherwise we would send to +many probes. + +Cc: Julian Anastasov +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ipv6/route.c | 38 +++++++++++++++++++++++++++++++------- + 1 file changed, 31 insertions(+), 7 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 08e6c40..1e32d5c 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -477,6 +477,24 @@ out: + } + + #ifdef CONFIG_IPV6_ROUTER_PREF ++struct __rt6_probe_work { ++ struct work_struct work; ++ struct in6_addr target; ++ struct net_device *dev; ++}; ++ ++static void rt6_probe_deferred(struct work_struct *w) ++{ ++ struct in6_addr mcaddr; ++ struct __rt6_probe_work *work = ++ container_of(w, struct __rt6_probe_work, work); ++ ++ addrconf_addr_solict_mult(&work->target, &mcaddr); ++ ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL); ++ dev_put(work->dev); ++ kfree(w); ++} ++ + static void rt6_probe(struct rt6_info *rt) + { + struct neighbour *neigh; +@@ -500,17 +518,23 @@ static void rt6_probe(struct rt6_info *rt) + + if (!neigh || + time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { +- struct in6_addr mcaddr; +- struct in6_addr *target; ++ struct __rt6_probe_work *work; ++ ++ work = kmalloc(sizeof(*work), GFP_ATOMIC); + +- if (neigh) { ++ if (neigh && work) + neigh->updated = jiffies; ++ ++ if (neigh) + write_unlock(&neigh->lock); +- } + +- target = (struct in6_addr *)&rt->rt6i_gateway; +- addrconf_addr_solict_mult(target, &mcaddr); +- ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); ++ if (work) { ++ INIT_WORK(&work->work, rt6_probe_deferred); ++ work->target = rt->rt6i_gateway; ++ dev_hold(rt->dst.dev); ++ work->dev = rt->dst.dev; ++ schedule_work(&work->work); ++ } + } else { + out: + write_unlock(&neigh->lock); +-- +1.7.11.7 + + +From d7710f5e65b37ec3ac09dde758141e81fa47315d Mon Sep 17 00:00:00 2001 +From: Mariusz Ceier +Date: Mon, 21 Oct 2013 19:45:04 +0200 +Subject: [PATCH 47/47] davinci_emac.c: Fix IFF_ALLMULTI setup + +[ Upstream commit d69e0f7ea95fef8059251325a79c004bac01f018 ] + +When IFF_ALLMULTI flag is set on interface and IFF_PROMISC isn't, +emac_dev_mcast_set should only enable RX of multicasts and reset +MACHASH registers. + +It does this, but afterwards it either sets up multicast MACs +filtering or disables RX of multicasts and resets MACHASH registers +again, rendering IFF_ALLMULTI flag useless. + +This patch fixes emac_dev_mcast_set, so that multicast MACs filtering and +disabling of RX of multicasts are skipped when IFF_ALLMULTI flag is set. + +Tested with kernel 2.6.37. + +Signed-off-by: Mariusz Ceier +Acked-by: Mugunthan V N +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/ti/davinci_emac.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c +index 1a222bce..45c167f 100644 +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -876,8 +876,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) + netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { + mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); + emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); +- } +- if (!netdev_mc_empty(ndev)) { ++ } else if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; + + mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); +-- +1.7.11.7 + diff --git a/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch b/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch deleted file mode 100644 index 1a1264ffa..000000000 --- a/tcp-fix-incorrect-ca_state-in-tail-loss-probe.patch +++ /dev/null @@ -1,107 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Yuchung Cheng -Newsgroups: gmane.linux.network -Subject: [PATCH net] tcp: fix incorrect ca_state in tail loss probe -Date: Sat, 12 Oct 2013 10:16:27 -0700 -Lines: 34 -Approved: news@gmane.org -Message-ID: <1381598187-9681-1-git-send-email-ycheng@google.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: ger.gmane.org 1381598242 29686 80.91.229.3 (12 Oct 2013 17:17:22 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Sat, 12 Oct 2013 17:17:22 +0000 (UTC) -Cc: netdev@vger.kernel.org, michael@sterretts.net, - jwboyer@fedoraproject.org, sesse@google.com, dormando@rydia.net, - Yuchung Cheng -To: davem@davemloft.net, ncardwell@google.com, nanditad@google.com -Original-X-From: netdev-owner@vger.kernel.org Sat Oct 12 19:17:23 2013 -Return-path: -Envelope-to: linux-netdev-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1VV2od-0004tp-02 - for linux-netdev-2@plane.gmane.org; Sat, 12 Oct 2013 19:17:23 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753183Ab3JLRRU (ORCPT ); - Sat, 12 Oct 2013 13:17:20 -0400 -Original-Received: from mail-pb0-f74.google.com ([209.85.160.74]:35839 "EHLO - mail-pb0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1752493Ab3JLRRS (ORCPT - ); Sat, 12 Oct 2013 13:17:18 -0400 -Original-Received: by mail-pb0-f74.google.com with SMTP id rq2so543459pbb.1 - for ; Sat, 12 Oct 2013 10:17:18 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=from:to:cc:subject:date:message-id; - bh=YSBIMZEgVuqyP2cau1199a1sz5d28JA7LPPsF6w9FYQ=; - b=cCkXgePT7f0kRy+VBGvs3DZSLhVn0z7O74B7OHYpdZkQBznhNZ2b6ZGbkDqaKJXyLT - GEsq/JXCgtwpC7aGSz9dPdAZU6kondKOAmfhh54u6f2+ymcZJ4zHpoA6mWuKJ4zlTF2w - 6tRhnT+/N5RkfIfYD/mcDx97X41kRT3NKJ6bsCoiNJIO2+6j8SrOi8C27InOkdIRY/AT - I1uu2bvai1CfrC5yQ6UfpKUg2jioFDOi7i5nSEon+JnWeJavHpO01JMHuar7ZeGnAKJg - kVLwyiRujU9Fz0CKIMPZihAngQu/0OgqORQIjygeqz+GPgtTxDGQP7IUNR/d+JOPVUse - XlSA== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20130820; - h=x-gm-message-state:from:to:cc:subject:date:message-id; - bh=YSBIMZEgVuqyP2cau1199a1sz5d28JA7LPPsF6w9FYQ=; - b=d95i7RXY0ff5vnWvrGqxWfSvvAE8SC6YAaBn3ZqbARIZm5GgynIAB/WYnrIOqpqGV6 - 56jVM40bfzLrols1UZzyJWqPIgxee1zPrESh+WrSsDP2tTdYKl/zk13lbt/u7nOn9o3u - HrAo2aY4DtV3P0ABEq1lKdazmmPACTc6256QQ2nxtHs5n7s7P1ERkpX7NGNqNf1zDBSv - 60xeoswRpMkh0G5ZUgpPYsIbXws9F64n5ytq34O2UDZPv5oPEd8I7P34HpqWkNsLoEBs - XXTxs1SLc8TI3vdduhaQ+rmEvcE5vTaqjVCQAT2mMKTJJ9xIFueF5zExfI892PHAcJQ8 - jiaw== -X-Gm-Message-State: ALoCoQkeL+3MY64KlpZKI1BuYMU+yTQcYF1C+U5u+kPpqROoekUMzIaH45qERBARAi/0vgJ5YM1Cwm+43d66vZMn/WdHPurbMHfFn3PYqeZSAzOEeuSA2jGTSZUkpuH8YwFqiNhABtj93ahsBXrA6POrXb531UvuahU+rnFLTGNLxVHv/08PW3l5PbN8UaTNpUI1qcf6O6MarFcB+fZLYPb339v4EIrLxg== -X-Received: by 10.66.5.226 with SMTP id v2mr8825633pav.22.1381598238410; - Sat, 12 Oct 2013 10:17:18 -0700 (PDT) -Original-Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) - by gmr-mx.google.com with ESMTPS id a24si3247317yhl.1.1969.12.31.16.00.00 - (version=TLSv1.1 cipher=AES128-SHA bits=128/128); - Sat, 12 Oct 2013 10:17:18 -0700 (PDT) -Original-Received: from blast2.mtv.corp.google.com (blast2.mtv.corp.google.com [172.17.132.164]) - by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 2F2B45A41A0; - Sat, 12 Oct 2013 10:17:18 -0700 (PDT) -Original-Received: by blast2.mtv.corp.google.com (Postfix, from userid 5463) - id C6A85220C26; Sat, 12 Oct 2013 10:17:17 -0700 (PDT) -X-Mailer: git-send-email 1.8.4 -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:286793 -Archived-At: - -On receiving an ACK that covers the loss probe sequence, TLP -immediately sets the congestion state to Open, even though some packets -are not recovered and retransmisssion are on the way. The later ACks -may trigger a WARN_ON check in step D of tcp_fastretrans_alert(), e.g., -https://bugzilla.redhat.com/show_bug.cgi?id=989251 - -The fix is to follow the similar procedure in recovery by calling -tcp_try_keep_open(). The sender switches to Open state if no packets -are retransmissted. Otherwise it goes to Disorder and let subsequent -ACKs move the state to Recovery or Open. - -Reported-By: Michael Sterrett -Tested-By: Dormando -Signed-off-by: Yuchung Cheng ---- - net/ipv4/tcp_input.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 113dc5f..53974c7 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -3291,7 +3291,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) - tcp_init_cwnd_reduction(sk, true); - tcp_set_ca_state(sk, TCP_CA_CWR); - tcp_end_cwnd_reduction(sk); -- tcp_set_ca_state(sk, TCP_CA_Open); -+ tcp_try_keep_open(sk); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPLOSSPROBERECOVERY); - } --- -1.8.4 - From c8cb0727e03e05ef8947ba36304c9c796dffbee0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 25 Oct 2013 17:50:07 -0400 Subject: [PATCH 451/492] Fix CVE number --- kernel.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2b0a14d9f..9ebc5ec78 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,7 +786,7 @@ Patch25133: fix-buslogic.patch #rhbz 1023413 Patch25135: alps-Support-for-Dell-XT2-model.patch -#CVE-2013-XXXX rhbz 1023477 1023495 +#CVE-2013-4470 rhbz 1023477 1023495 Patch25136: net_311.mbox # END OF PATCH DEFINITIONS @@ -1512,7 +1512,7 @@ ApplyPatch fix-buslogic.patch #rhbz 1023413 ApplyPatch alps-Support-for-Dell-XT2-model.patch -#CVE-2013-XXXX rhbz 1023477 1023495 +#CVE-2013-4470 rhbz 1023477 1023495 ApplyPatch net_311.mbox # END OF PATCH APPLICATIONS @@ -2357,7 +2357,7 @@ fi # || || %changelog * Fri Oct 25 2013 Josh Boyer -- CVE-2013-XXXX net: memory corruption with UDP_CORK and UFO (rhbz 1023477 1023495) +- CVE-2013-4470 net: memory corruption with UDP_CORK and UFO (rhbz 1023477 1023495) - Add touchpad support for Dell XT2 (rhbz 1023413) * Tue Oct 22 2013 Josh Boyer From 56f4eb8f66696f3d2f6e4576e78ac46883e49e96 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Oct 2013 14:22:30 -0400 Subject: [PATCH 452/492] Fix plaintext auth regression in cifs (rhbz 1011621) --- ...auth-for-unencapsulated-auth-methods.patch | 39 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 48 insertions(+) create mode 100644 cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch diff --git a/cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch b/cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch new file mode 100644 index 000000000..51ce50f87 --- /dev/null +++ b/cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch @@ -0,0 +1,39 @@ +From dde2356c8466298bd77fa699e0ea296372eed47b Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Fri, 27 Sep 2013 17:35:42 +0000 +Subject: cifs: Allow LANMAN auth method for servers supporting unencapsulated authentication methods + +This allows users to use LANMAN authentication on servers which support +unencapsulated authentication. + +The patch fixes a regression where users using plaintext authentication +were no longer able to do so because of changed bought in by patch +3f618223dc0bdcbc8d510350e78ee2195ff93768 + +https://bugzilla.redhat.com/show_bug.cgi?id=1011621 + +Reported-by: Panos Kavalagios +Reviewed-by: Jeff Layton +Signed-off-by: Sachin Prabhu +Signed-off-by: Steve French +--- +(limited to 'fs/cifs') + +diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c +index 352358d..e87387d 100644 +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) + return NTLMv2; + if (global_secflags & CIFSSEC_MAY_NTLM) + return NTLM; +- /* Fallthrough */ + default: +- return Unspecified; ++ /* Fallthrough to attempt LANMAN authentication next */ ++ break; + } + case CIFS_NEGFLAVOR_LANMAN: + switch (requested) { +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 9ebc5ec78..81a40a196 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,6 +789,9 @@ Patch25135: alps-Support-for-Dell-XT2-model.patch #CVE-2013-4470 rhbz 1023477 1023495 Patch25136: net_311.mbox +#rhbz 1011621 +Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch + # END OF PATCH DEFINITIONS %endif @@ -1515,6 +1518,9 @@ ApplyPatch alps-Support-for-Dell-XT2-model.patch #CVE-2013-4470 rhbz 1023477 1023495 ApplyPatch net_311.mbox +#rhbz 1011621 +ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch + # END OF PATCH APPLICATIONS %endif @@ -2356,6 +2362,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 29 2013 Josh Boyer +- Fix plaintext auth regression in cifs (rhbz 1011621) + * Fri Oct 25 2013 Josh Boyer - CVE-2013-4470 net: memory corruption with UDP_CORK and UFO (rhbz 1023477 1023495) - Add touchpad support for Dell XT2 (rhbz 1023413) From 26d3ee3e40bb87bd531068dbbd8a76cdf346fff9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Nov 2013 08:14:33 -0400 Subject: [PATCH 453/492] Fix display regression on Dell XPS 13 machines (rhbz 995782) --- intel-3.12-stable-fixes.patch | 574 ++++++++++++++++++++++++++++++++++ kernel.spec | 9 + 2 files changed, 583 insertions(+) create mode 100644 intel-3.12-stable-fixes.patch diff --git a/intel-3.12-stable-fixes.patch b/intel-3.12-stable-fixes.patch new file mode 100644 index 000000000..35335423e --- /dev/null +++ b/intel-3.12-stable-fixes.patch @@ -0,0 +1,574 @@ +From 39bb622a9804de9fa51cae31f07104a19067483a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Mon, 21 Oct 2013 10:52:06 +0300 +Subject: [PATCH 1/5] drm/i915: Add support for pipe_bpp readout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On CTG+ read out the pipe bpp setting from hardware and fill it into +pipe config. Also check it appropriately. + +v2: Don't do the pipe_bpp extraction inside the PCH only code block on + ILK+. + Avoid the PIPECONF read as we already have read it for the + PIPECONF_EANBLE check. + +Note: This is already in drm-intel-next-queued as +commit 42571aefafb1d330ef84eb29418832f72e7dfb4c +Author: Ville Syrjälä +Date: Fri Sep 6 23:29:00 2013 +0300 + + drm/i915: Add support for pipe_bpp readout + +but is needed for the following bugfix. + +Signed-off-by: Ville Syrjälä +Reviewed-by: Jani Nikula +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_ddi.c | 17 +++++++++++++++++ + drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+) + +diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c +index b042ee5..83e413b 100644 +--- a/drivers/gpu/drm/i915/intel_ddi.c ++++ b/drivers/gpu/drm/i915/intel_ddi.c +@@ -1280,6 +1280,23 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, + flags |= DRM_MODE_FLAG_NVSYNC; + + pipe_config->adjusted_mode.flags |= flags; ++ ++ switch (temp & TRANS_DDI_BPC_MASK) { ++ case TRANS_DDI_BPC_6: ++ pipe_config->pipe_bpp = 18; ++ break; ++ case TRANS_DDI_BPC_8: ++ pipe_config->pipe_bpp = 24; ++ break; ++ case TRANS_DDI_BPC_10: ++ pipe_config->pipe_bpp = 30; ++ break; ++ case TRANS_DDI_BPC_12: ++ pipe_config->pipe_bpp = 36; ++ break; ++ default: ++ break; ++ } + } + + static void intel_ddi_destroy(struct drm_encoder *encoder) +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 90a7c17..4aaccd3 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -4943,6 +4943,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, + if (!(tmp & PIPECONF_ENABLE)) + return false; + ++ if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { ++ switch (tmp & PIPECONF_BPC_MASK) { ++ case PIPECONF_6BPC: ++ pipe_config->pipe_bpp = 18; ++ break; ++ case PIPECONF_8BPC: ++ pipe_config->pipe_bpp = 24; ++ break; ++ case PIPECONF_10BPC: ++ pipe_config->pipe_bpp = 30; ++ break; ++ default: ++ break; ++ } ++ } ++ + intel_get_pipe_timings(crtc, pipe_config); + + i9xx_get_pfit_config(crtc, pipe_config); +@@ -5821,6 +5837,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, + if (!(tmp & PIPECONF_ENABLE)) + return false; + ++ switch (tmp & PIPECONF_BPC_MASK) { ++ case PIPECONF_6BPC: ++ pipe_config->pipe_bpp = 18; ++ break; ++ case PIPECONF_8BPC: ++ pipe_config->pipe_bpp = 24; ++ break; ++ case PIPECONF_10BPC: ++ pipe_config->pipe_bpp = 30; ++ break; ++ case PIPECONF_12BPC: ++ pipe_config->pipe_bpp = 36; ++ break; ++ default: ++ break; ++ } ++ + if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { + struct intel_shared_dpll *pll; + +@@ -8147,6 +8180,9 @@ intel_pipe_config_compare(struct drm_device *dev, + PIPE_CONF_CHECK_X(dpll_hw_state.fp0); + PIPE_CONF_CHECK_X(dpll_hw_state.fp1); + ++ if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) ++ PIPE_CONF_CHECK_I(pipe_bpp); ++ + #undef PIPE_CONF_CHECK_X + #undef PIPE_CONF_CHECK_I + #undef PIPE_CONF_CHECK_FLAGS +-- +1.8.3.1 + + +From b59da942a708f7cf1c421a7cb666f98fd8172208 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Tue, 24 Sep 2013 14:24:05 +0300 +Subject: [PATCH 2/5] drm/i915: Add HSW CRT output readout support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Call intel_ddi_get_config() to get the pipe_bpp settings from +DDI. + +The sync polarity settings from DDI are irrelevant for CRT +output, so override them with data from the ADPA register. + +Note: This is already merged in drm-intel-next-queued as + +commit 6801c18c0a43386bb44712cbc028a7e05adb9f0d +Author: Ville Syrjälä +Date: Tue Sep 24 14:24:05 2013 +0300 + + drm/i915: Add HSW CRT output readout support + +but is required for the following edp bpp bugfix. + +v2: Extract intel_crt_get_flags() + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69691 +Tested-by: Qingshuai Tian +Signed-off-by: Ville Syrjälä +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_crt.c | 30 ++++++++++++++++++++++++++---- + drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- + drivers/gpu/drm/i915/intel_drv.h | 2 ++ + 3 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index 3acec8c..6aa6ebd 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -84,8 +84,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, + return true; + } + +-static void intel_crt_get_config(struct intel_encoder *encoder, +- struct intel_crtc_config *pipe_config) ++static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) + { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crt *crt = intel_encoder_to_crt(encoder); +@@ -103,7 +102,27 @@ static void intel_crt_get_config(struct intel_encoder *encoder, + else + flags |= DRM_MODE_FLAG_NVSYNC; + +- pipe_config->adjusted_mode.flags |= flags; ++ return flags; ++} ++ ++static void intel_crt_get_config(struct intel_encoder *encoder, ++ struct intel_crtc_config *pipe_config) ++{ ++ struct drm_device *dev = encoder->base.dev; ++ ++ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); ++} ++ ++static void hsw_crt_get_config(struct intel_encoder *encoder, ++ struct intel_crtc_config *pipe_config) ++{ ++ intel_ddi_get_config(encoder, pipe_config); ++ ++ pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | ++ DRM_MODE_FLAG_NHSYNC | ++ DRM_MODE_FLAG_PVSYNC | ++ DRM_MODE_FLAG_NVSYNC); ++ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); + } + + /* Note: The caller is required to filter out dpms modes not supported by the +@@ -802,7 +821,10 @@ void intel_crt_init(struct drm_device *dev) + crt->base.compute_config = intel_crt_compute_config; + crt->base.disable = intel_disable_crt; + crt->base.enable = intel_enable_crt; +- crt->base.get_config = intel_crt_get_config; ++ if (IS_HASWELL(dev)) ++ crt->base.get_config = hsw_crt_get_config; ++ else ++ crt->base.get_config = intel_crt_get_config; + if (I915_HAS_HOTPLUG(dev)) + crt->base.hpd_pin = HPD_CRT; + if (HAS_DDI(dev)) +diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c +index 83e413b..5a6368d 100644 +--- a/drivers/gpu/drm/i915/intel_ddi.c ++++ b/drivers/gpu/drm/i915/intel_ddi.c +@@ -1261,8 +1261,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) + intel_dp_check_link_status(intel_dp); + } + +-static void intel_ddi_get_config(struct intel_encoder *encoder, +- struct intel_crtc_config *pipe_config) ++void intel_ddi_get_config(struct intel_encoder *encoder, ++ struct intel_crtc_config *pipe_config) + { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index b7d6e09..ddf7e2f 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -816,6 +816,8 @@ extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); + extern bool + intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); + extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); ++extern void intel_ddi_get_config(struct intel_encoder *encoder, ++ struct intel_crtc_config *pipe_config); + + extern void intel_display_handle_reset(struct drm_device *dev); + extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, +-- +1.8.3.1 + + +From 92c64493f41092185230c552c277b42bf6113140 Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Mon, 21 Oct 2013 10:52:07 +0300 +Subject: [PATCH 3/5] drm/i915/dp: workaround BIOS eDP bpp clamping issue + +This isn't a real fix to the problem, but rather a stopgap measure while +trying to find a proper solution. + +There are several laptops out there that fail to light up the eDP panel +in UEFI boot mode. They seem to be mostly IVB machines, including but +apparently not limited to Dell XPS 13, Asus TX300, Asus UX31A, Asus +UX32VD, Acer Aspire S7. They seem to work in CSM or legacy boot. + +The difference between UEFI and CSM is that the BIOS provides a +different VBT to the kernel. The UEFI VBT typically specifies 18 bpp and +1.62 GHz link for eDP, while CSM VBT has 24 bpp and 2.7 GHz link. We end +up clamping to 18 bpp in UEFI mode, which we can fit in the 1.62 Ghz +link, and for reasons yet unknown fail to light up the panel. + +Dithering from 24 to 18 bpp itself seems to work; if we use 18 bpp with +2.7 GHz link, the eDP panel lights up. So essentially this is a link +speed issue, and *not* a bpp clamping issue. + +The bug raised its head since +commit 657445fe8660100ad174600ebfa61536392b7624 +Author: Daniel Vetter +Date: Sat May 4 10:09:18 2013 +0200 + + Revert "drm/i915: revert eDP bpp clamping code changes" + +which started clamping bpp *before* computing the link requirements, and +thus affecting the required bandwidth. Clamping after the computations +kept the link at 2.7 GHz. + +Even though the BIOS tells us to use 18 bpp through the VBT, it happily +boots up at 24 bpp and 2.7 GHz itself! Use this information to +selectively ignore the VBT provided value. + +We can't ignore the VBT eDP bpp altogether, as there are other laptops +that do require the clamping to be used due to EDID reporting higher bpp +than the panel can support. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59841 +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67950 +Tested-by: Ulf Winkelvos +Tested-by: jkp +CC: stable@vger.kernel.org +Signed-off-by: Jani Nikula +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 3aed1fe..07eb447 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -1371,6 +1371,26 @@ static void intel_dp_get_config(struct intel_encoder *encoder, + } + + pipe_config->adjusted_mode.flags |= flags; ++ ++ if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && ++ pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { ++ /* ++ * This is a big fat ugly hack. ++ * ++ * Some machines in UEFI boot mode provide us a VBT that has 18 ++ * bpp and 1.62 GHz link bandwidth for eDP, which for reasons ++ * unknown we fail to light up. Yet the same BIOS boots up with ++ * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as ++ * max, not what it tells us to use. ++ * ++ * Note: This will still be broken if the eDP panel is not lit ++ * up by the BIOS, and thus we can't get the mode at module ++ * load. ++ */ ++ DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", ++ pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); ++ dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; ++ } + } + + static void intel_disable_dp(struct intel_encoder *encoder) +-- +1.8.3.1 + + +From 1e5ec9a5628cfd23443a91f80dea2118efb21afd Mon Sep 17 00:00:00 2001 +From: Rob Pearce +Date: Sun, 27 Oct 2013 16:13:42 +0000 +Subject: [PATCH 4/5] drm/i915: No LVDS hardware on Intel D410PT and D425KT + +The Intel D410PT(LW) and D425KT Mini-ITX desktop boards both show up as +having LVDS but the hardware is not populated. This patch adds them to +the list of such systems. Patch is against 3.11.4 + +v2: Patch revised to match the D425KT exactly as the D425KTW does have +LVDS. According to Intel's documentation, the D410PTL and D410PLTW +don't. + +Signed-off-by: Rob Pearce +Cc: stable@vger.kernel.org +[danvet: Pimp commit message to my liking and add cc: stable.] +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_lvds.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index 61348ea..44533dd 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -696,6 +696,22 @@ static const struct dmi_system_id intel_no_lvds[] = { + }, + { + .callback = intel_no_lvds_dmi_callback, ++ .ident = "Intel D410PT", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), ++ DMI_MATCH(DMI_BOARD_NAME, "D410PT"), ++ }, ++ }, ++ { ++ .callback = intel_no_lvds_dmi_callback, ++ .ident = "Intel D425KT", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"), ++ }, ++ }, ++ { ++ .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D510MO", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), +-- +1.8.3.1 + + +From 239319357b4a2d085e5f5c27b46aab5f612c5036 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Tue, 29 Oct 2013 12:04:08 +0100 +Subject: [PATCH 5/5] drm/i915: Fix the PPT fdi lane bifurcate state handling + on ivb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Originally I've thought that this is leftover hw state dirt from the +BIOS. But after way too much helpless flailing around on my part I've +noticed that the actual bug is when we change the state of an already +active pipe. + +For example when we change the fdi lines from 2 to 3 without switching +off outputs in-between we'll never see the crucial on->off transition +in the ->modeset_global_resources hook the current logic relies on. + +Patch version 2 got this right by instead also checking whether the +pipe is indeed active. But that in turn broke things when pipes have +been turned off through dpms since the bifurcate enabling is done in +the ->crtc_mode_set callback. + +To address this issues discussed with Ville in the patch review move +the setting of the bifurcate bit into the ->crtc_enable hook. That way +we won't wreak havoc with this state when userspace puts all other +outputs into dpms off state. This also moves us forward with our +overall goal to unify the modeset and dpms on paths (which we need to +have to allow runtime pm in the dpms off state). + +Unfortunately this requires us to move the bifurcate helpers around a +bit. + +Also update the commit message, I've misanalyzed the bug rather badly. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70507 +Tested-by: Jan-Michael Brummer +Cc: stable@vger.kernel.org +Cc: Ville Syrjälä +Reviewed-by: Ville Syrjälä +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/intel_display.c | 95 ++++++++++++++++++------------------ + 1 file changed, 48 insertions(+), 47 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 4aaccd3..ad2a258 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -2251,9 +2251,10 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) + FDI_FE_ERRC_ENABLE); + } + +-static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc) ++static bool pipe_has_enabled_pch(struct intel_crtc *crtc) + { +- return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder; ++ return crtc->base.enabled && crtc->active && ++ crtc->config.has_pch_encoder; + } + + static void ivb_modeset_global_resources(struct drm_device *dev) +@@ -2901,6 +2902,48 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, + I915_READ(VSYNCSHIFT(cpu_transcoder))); + } + ++static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ uint32_t temp; ++ ++ temp = I915_READ(SOUTH_CHICKEN1); ++ if (temp & FDI_BC_BIFURCATION_SELECT) ++ return; ++ ++ WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); ++ WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); ++ ++ temp |= FDI_BC_BIFURCATION_SELECT; ++ DRM_DEBUG_KMS("enabling fdi C rx\n"); ++ I915_WRITE(SOUTH_CHICKEN1, temp); ++ POSTING_READ(SOUTH_CHICKEN1); ++} ++ ++static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) ++{ ++ struct drm_device *dev = intel_crtc->base.dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ ++ switch (intel_crtc->pipe) { ++ case PIPE_A: ++ break; ++ case PIPE_B: ++ if (intel_crtc->config.fdi_lanes > 2) ++ WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); ++ else ++ cpt_enable_fdi_bc_bifurcation(dev); ++ ++ break; ++ case PIPE_C: ++ cpt_enable_fdi_bc_bifurcation(dev); ++ ++ break; ++ default: ++ BUG(); ++ } ++} ++ + /* + * Enable PCH resources required for PCH ports: + * - PCH PLLs +@@ -2919,6 +2962,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) + + assert_pch_transcoder_disabled(dev_priv, pipe); + ++ if (IS_IVYBRIDGE(dev)) ++ ivybridge_update_fdi_bc_bifurcation(intel_crtc); ++ + /* Write the TU size bits before fdi link training, so that error + * detection works. */ + I915_WRITE(FDI_RX_TUSIZE1(pipe), +@@ -5512,48 +5558,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, + return true; + } + +-static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- uint32_t temp; +- +- temp = I915_READ(SOUTH_CHICKEN1); +- if (temp & FDI_BC_BIFURCATION_SELECT) +- return; +- +- WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); +- WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); +- +- temp |= FDI_BC_BIFURCATION_SELECT; +- DRM_DEBUG_KMS("enabling fdi C rx\n"); +- I915_WRITE(SOUTH_CHICKEN1, temp); +- POSTING_READ(SOUTH_CHICKEN1); +-} +- +-static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) +-{ +- struct drm_device *dev = intel_crtc->base.dev; +- struct drm_i915_private *dev_priv = dev->dev_private; +- +- switch (intel_crtc->pipe) { +- case PIPE_A: +- break; +- case PIPE_B: +- if (intel_crtc->config.fdi_lanes > 2) +- WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); +- else +- cpt_enable_fdi_bc_bifurcation(dev); +- +- break; +- case PIPE_C: +- cpt_enable_fdi_bc_bifurcation(dev); +- +- break; +- default: +- BUG(); +- } +-} +- + int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) + { + /* +@@ -5768,9 +5772,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + &intel_crtc->config.fdi_m_n); + } + +- if (IS_IVYBRIDGE(dev)) +- ivybridge_update_fdi_bc_bifurcation(intel_crtc); +- + ironlake_set_pipeconf(crtc); + + /* Set up the display plane register */ +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 81a40a196..72dd4062e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -792,6 +792,9 @@ Patch25136: net_311.mbox #rhbz 1011621 Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch +#rhbz 995782 +Patch25138: intel-3.12-stable-fixes.patch + # END OF PATCH DEFINITIONS %endif @@ -1521,6 +1524,9 @@ ApplyPatch net_311.mbox #rhbz 1011621 ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch +#rhbz 995782 +ApplyPatch intel-3.12-stable-fixes.patch + # END OF PATCH APPLICATIONS %endif @@ -2362,6 +2368,9 @@ fi # ||----w | # || || %changelog +* Thu Oct 31 2013 Josh Boyer +- Fix display regression on Dell XPS 13 machines (rhbz 995782) + * Tue Oct 29 2013 Josh Boyer - Fix plaintext auth regression in cifs (rhbz 1011621) From 65f14f4adcba1d3e04b7d3c8e4094cd9a6e86711 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Nov 2013 08:23:10 -0400 Subject: [PATCH 454/492] CVE-2013-4348 net: deadloop path in skb_flow_dissect (rhbz 1007939 1025647) --- kernel.spec | 9 ++ net-flow_dissector-fail-on-evil-iph-ihl.patch | 82 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 net-flow_dissector-fail-on-evil-iph-ihl.patch diff --git a/kernel.spec b/kernel.spec index 72dd4062e..5d4462849 100644 --- a/kernel.spec +++ b/kernel.spec @@ -795,6 +795,9 @@ Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch #rhbz 995782 Patch25138: intel-3.12-stable-fixes.patch +#CVE-2013-4348 rhbz 1007939 1025647 +Patch25139: net-flow_dissector-fail-on-evil-iph-ihl.patch + # END OF PATCH DEFINITIONS %endif @@ -1527,6 +1530,9 @@ ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch #rhbz 995782 ApplyPatch intel-3.12-stable-fixes.patch +#CVE-2013-4348 rhbz 1007939 1025647 +ApplyPatch net-flow_dissector-fail-on-evil-iph-ihl.patch + # END OF PATCH APPLICATIONS %endif @@ -2368,6 +2374,9 @@ fi # ||----w | # || || %changelog +* Fri Nov 01 2013 Josh Boyer +- CVE-2013-4348 net: deadloop path in skb_flow_dissect (rhbz 1007939 1025647) + * Thu Oct 31 2013 Josh Boyer - Fix display regression on Dell XPS 13 machines (rhbz 995782) diff --git a/net-flow_dissector-fail-on-evil-iph-ihl.patch b/net-flow_dissector-fail-on-evil-iph-ihl.patch new file mode 100644 index 000000000..aba3ea88b --- /dev/null +++ b/net-flow_dissector-fail-on-evil-iph-ihl.patch @@ -0,0 +1,82 @@ +Path: news.gmane.org!not-for-mail +From: Jason Wang +Newsgroups: gmane.linux.kernel,gmane.linux.network +Subject: [PATCH net] net: flow_dissector: fail on evil iph->ihl +Date: Fri, 1 Nov 2013 15:01:10 +0800 +Lines: 34 +Approved: news@gmane.org +Message-ID: <1383289270-18952-1-git-send-email-jasowang@redhat.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: ger.gmane.org 1383289296 18578 80.91.229.3 (1 Nov 2013 07:01:36 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Fri, 1 Nov 2013 07:01:36 +0000 (UTC) +Cc: Jason Wang , + Petr Matousek , + "Michael S. Tsirkin" , + Daniel Borkmann +To: davem@davemloft.net, edumazet@google.com, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-kernel-owner@vger.kernel.org Fri Nov 01 08:01:39 2013 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Vc8jh-00034h-9Y + for glk-linux-kernel-3@plane.gmane.org; Fri, 01 Nov 2013 08:01:37 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753899Ab3KAHB3 (ORCPT ); + Fri, 1 Nov 2013 03:01:29 -0400 +Original-Received: from mx1.redhat.com ([209.132.183.28]:8081 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752399Ab3KAHB1 (ORCPT ); + Fri, 1 Nov 2013 03:01:27 -0400 +Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rA171QgE005079 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Fri, 1 Nov 2013 03:01:26 -0400 +Original-Received: from jason-ThinkPad-T430s.nay.redhat.com (dhcp-66-71-71.eng.nay.redhat.com [10.66.71.71] (may be forged)) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id rA171Jpr015790; + Fri, 1 Nov 2013 03:01:20 -0400 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1588387 gmane.linux.network:289242 +Archived-At: + +We don't validate iph->ihl which may lead a dead loop if we meet a IPIP +skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl +is evil (less than 5). + +This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae +(rps: support IPIP encapsulation). + +Cc: Eric Dumazet +Cc: Petr Matousek +Cc: Michael S. Tsirkin +Cc: Daniel Borkmann +Signed-off-by: Jason Wang +--- +This patch is needed for stable. +--- + net/core/flow_dissector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index 8d7d0dd..143b6fd 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -40,7 +40,7 @@ again: + struct iphdr _iph; + ip: + iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); +- if (!iph) ++ if (!iph || iph->ihl < 5) + return false; + + if (ip_is_fragment(iph)) +-- +1.8.1.2 + From f1987ed1ac36a26138a73f75e9ffeba938db5372 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 2 Nov 2013 08:40:14 -0400 Subject: [PATCH 455/492] Revert blocking patches causing systemd to crash on resume (rhbz 1010603) --- ...rt-epoll-use-freezable-blocking-call.patch | 49 +++++++++++++++++ ...t-select-use-freezable-blocking-call.patch | 55 +++++++++++++++++++ kernel.spec | 13 ++++- 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 0001-Revert-epoll-use-freezable-blocking-call.patch create mode 100644 0001-Revert-select-use-freezable-blocking-call.patch diff --git a/0001-Revert-epoll-use-freezable-blocking-call.patch b/0001-Revert-epoll-use-freezable-blocking-call.patch new file mode 100644 index 000000000..eda58ee28 --- /dev/null +++ b/0001-Revert-epoll-use-freezable-blocking-call.patch @@ -0,0 +1,49 @@ +From c511851de162e8ec03d62e7d7feecbdf590d881d Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 29 Oct 2013 13:12:56 +0100 +Subject: [PATCH] Revert "epoll: use freezable blocking call" + +This reverts commit 1c441e921201 (epoll: use freezable blocking call) +which is reported to cause user space memory corruption to happen +after suspend to RAM. + +Since it appears to be extremely difficult to root cause this +problem, it is best to revert the offending commit and try to address +the original issue in a better way later. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=61781 +Reported-by: Natrio +Reported-by: Jeff Pohlmeyer +Bisected-by: Leo Wolf +Fixes: 1c441e921201 (epoll: use freezable blocking call) +Signed-off-by: Rafael J. Wysocki +Cc: 3.11+ # 3.11+ +--- + fs/eventpoll.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 473e09d..810c28f 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -1605,8 +1604,7 @@ fetch_events: + } + + spin_unlock_irqrestore(&ep->lock, flags); +- if (!freezable_schedule_hrtimeout_range(to, slack, +- HRTIMER_MODE_ABS)) ++ if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) + timed_out = 1; + + spin_lock_irqsave(&ep->lock, flags); +-- +1.8.3.1 + diff --git a/0001-Revert-select-use-freezable-blocking-call.patch b/0001-Revert-select-use-freezable-blocking-call.patch new file mode 100644 index 000000000..0ab5152a0 --- /dev/null +++ b/0001-Revert-select-use-freezable-blocking-call.patch @@ -0,0 +1,55 @@ +From 59612d187912750f416fbffe0c00bc0811c54ab5 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 29 Oct 2013 23:43:08 +0100 +Subject: [PATCH] Revert "select: use freezable blocking call" + +This reverts commit 9745cdb36da8 (select: use freezable blocking call) +that triggers problems during resume from suspend to RAM on Paul Bolle's +32-bit x86 machines. Paul says: + + Ever since I tried running (release candidates of) v3.11 on the two + working i686s I still have lying around I ran into issues on resuming + from suspend. Reverting 9745cdb36da8 (select: use freezable blocking + call) resolves those issues. + + Resuming from suspend on i686 on (release candidates of) v3.11 and + later triggers issues like: + + traps: systemd[1] general protection ip:b738e490 sp:bf882fc0 error:0 in libc-2.16.so[b731c000+1b0000] + + and + + traps: rtkit-daemon[552] general protection ip:804d6e5 sp:b6cb32f0 error:0 in rtkit-daemon[8048000+d000] + + Once I hit the systemd error I can only get out of the mess that the + system is at that point by power cycling it. + +Since we are reverting another freezer-related change causing similar +problems to happen, this one should be reverted as well. + +References: https://lkml.org/lkml/2013/10/29/583 +Reported-by: Paul Bolle +Fixes: 9745cdb36da8 (select: use freezable blocking call) +Signed-off-by: Rafael J. Wysocki +Cc: 3.11+ # 3.11+ +--- + fs/select.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/select.c b/fs/select.c +index 35d4adc7..dfd5cb1 100644 +--- a/fs/select.c ++++ b/fs/select.c +@@ -238,8 +238,7 @@ int poll_schedule_timeout(struct poll_wqueues *pwq, int state, + + set_current_state(state); + if (!pwq->triggered) +- rc = freezable_schedule_hrtimeout_range(expires, slack, +- HRTIMER_MODE_ABS); ++ rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS); + __set_current_state(TASK_RUNNING); + + /* +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 5d4462849..457c2bc86 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 100 +%global baserelease 101 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -798,6 +798,10 @@ Patch25138: intel-3.12-stable-fixes.patch #CVE-2013-4348 rhbz 1007939 1025647 Patch25139: net-flow_dissector-fail-on-evil-iph-ihl.patch +#rhbz 1010603 +Patch25140: 0001-Revert-epoll-use-freezable-blocking-call.patch +Patch25141: 0001-Revert-select-use-freezable-blocking-call.patch + # END OF PATCH DEFINITIONS %endif @@ -1533,6 +1537,10 @@ ApplyPatch intel-3.12-stable-fixes.patch #CVE-2013-4348 rhbz 1007939 1025647 ApplyPatch net-flow_dissector-fail-on-evil-iph-ihl.patch +#rhbz 1010603 +ApplyPatch 0001-Revert-epoll-use-freezable-blocking-call.patch +ApplyPatch 0001-Revert-select-use-freezable-blocking-call.patch + # END OF PATCH APPLICATIONS %endif @@ -2374,7 +2382,8 @@ fi # ||----w | # || || %changelog -* Fri Nov 01 2013 Josh Boyer +* Fri Nov 01 2013 Josh Boyer - 3.11.6-101 +- Revert blocking patches causing systemd to crash on resume (rhbz 1010603) - CVE-2013-4348 net: deadloop path in skb_flow_dissect (rhbz 1007939 1025647) * Thu Oct 31 2013 Josh Boyer From 697844d8519e6d9d54a699b070ebe4a658156747 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 4 Nov 2013 07:45:48 -0600 Subject: [PATCH 456/492] Linux v3.11.7 --- kernel.spec | 13 +- net_311.mbox | 3794 -------------------------------------------------- sources | 2 +- 3 files changed, 6 insertions(+), 3803 deletions(-) delete mode 100644 net_311.mbox diff --git a/kernel.spec b/kernel.spec index 457c2bc86..a00c5a2b0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 101 +%global baserelease 100 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -786,9 +786,6 @@ Patch25133: fix-buslogic.patch #rhbz 1023413 Patch25135: alps-Support-for-Dell-XT2-model.patch -#CVE-2013-4470 rhbz 1023477 1023495 -Patch25136: net_311.mbox - #rhbz 1011621 Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch @@ -1525,9 +1522,6 @@ ApplyPatch fix-buslogic.patch #rhbz 1023413 ApplyPatch alps-Support-for-Dell-XT2-model.patch -#CVE-2013-4470 rhbz 1023477 1023495 -ApplyPatch net_311.mbox - #rhbz 1011621 ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch @@ -2382,6 +2376,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 04 2013 Justin M. Forbes - 3.11.7-100 +- Linux v3.11.7 + * Fri Nov 01 2013 Josh Boyer - 3.11.6-101 - Revert blocking patches causing systemd to crash on resume (rhbz 1010603) - CVE-2013-4348 net: deadloop path in skb_flow_dissect (rhbz 1007939 1025647) diff --git a/net_311.mbox b/net_311.mbox deleted file mode 100644 index d420777dd..000000000 --- a/net_311.mbox +++ /dev/null @@ -1,3794 +0,0 @@ -From 5444e381f5784d32d741864312909d2a6afe428e Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Tue, 27 Aug 2013 05:46:32 -0700 -Subject: [PATCH 01/47] tcp: TSO packets automatic sizing - -[ Upstream commits 6d36824e730f247b602c90e8715a792003e3c5a7, - 02cf4ebd82ff0ac7254b88e466820a290ed8289a, and parts of - 7eec4174ff29cd42f2acfae8112f51c228545d40 ] - -After hearing many people over past years complaining against TSO being -bursty or even buggy, we are proud to present automatic sizing of TSO -packets. - -One part of the problem is that tcp_tso_should_defer() uses an heuristic -relying on upcoming ACKS instead of a timer, but more generally, having -big TSO packets makes little sense for low rates, as it tends to create -micro bursts on the network, and general consensus is to reduce the -buffering amount. - -This patch introduces a per socket sk_pacing_rate, that approximates -the current sending rate, and allows us to size the TSO packets so -that we try to send one packet every ms. - -This field could be set by other transports. - -Patch has no impact for high speed flows, where having large TSO packets -makes sense to reach line rate. - -For other flows, this helps better packet scheduling and ACK clocking. - -This patch increases performance of TCP flows in lossy environments. - -A new sysctl (tcp_min_tso_segs) is added, to specify the -minimal size of a TSO packet (default being 2). - -A follow-up patch will provide a new packet scheduler (FQ), using -sk_pacing_rate as an input to perform optional per flow pacing. - -This explains why we chose to set sk_pacing_rate to twice the current -rate, allowing 'slow start' ramp up. - -sk_pacing_rate = 2 * cwnd * mss / srtt - -v2: Neal Cardwell reported a suspect deferring of last two segments on -initial write of 10 MSS, I had to change tcp_tso_should_defer() to take -into account tp->xmit_size_goal_segs - -Signed-off-by: Eric Dumazet -Cc: Neal Cardwell -Cc: Yuchung Cheng -Cc: Van Jacobson -Cc: Tom Herbert -Acked-by: Yuchung Cheng -Acked-by: Neal Cardwell -Signed-off-by: David S. Miller ---- - Documentation/networking/ip-sysctl.txt | 9 +++++++++ - include/net/sock.h | 2 ++ - include/net/tcp.h | 1 + - net/core/sock.c | 1 + - net/ipv4/sysctl_net_ipv4.c | 10 ++++++++++ - net/ipv4/tcp.c | 28 +++++++++++++++++++++++----- - net/ipv4/tcp_input.c | 34 +++++++++++++++++++++++++++++++++- - net/ipv4/tcp_output.c | 2 +- - 8 files changed, 80 insertions(+), 7 deletions(-) - -diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt -index 1074290..b522883 100644 ---- a/Documentation/networking/ip-sysctl.txt -+++ b/Documentation/networking/ip-sysctl.txt -@@ -478,6 +478,15 @@ tcp_syn_retries - INTEGER - tcp_timestamps - BOOLEAN - Enable timestamps as defined in RFC1323. - -+tcp_min_tso_segs - INTEGER -+ Minimal number of segments per TSO frame. -+ Since linux-3.12, TCP does an automatic sizing of TSO frames, -+ depending on flow rate, instead of filling 64Kbytes packets. -+ For specific usages, it's possible to force TCP to build big -+ TSO frames. Note that TCP stack might split too big TSO packets -+ if available window is too small. -+ Default: 2 -+ - tcp_tso_win_divisor - INTEGER - This allows control over what percentage of the congestion window - can be consumed by a single TSO frame. -diff --git a/include/net/sock.h b/include/net/sock.h -index 31d5cfb..04e148f 100644 ---- a/include/net/sock.h -+++ b/include/net/sock.h -@@ -232,6 +232,7 @@ struct cg_proto; - * @sk_napi_id: id of the last napi context to receive data for sk - * @sk_ll_usec: usecs to busypoll when there is no data - * @sk_allocation: allocation mode -+ * @sk_pacing_rate: Pacing rate (if supported by transport/packet scheduler) - * @sk_sndbuf: size of send buffer in bytes - * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, - * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings -@@ -361,6 +362,7 @@ struct sock { - kmemcheck_bitfield_end(flags); - int sk_wmem_queued; - gfp_t sk_allocation; -+ u32 sk_pacing_rate; /* bytes per second */ - netdev_features_t sk_route_caps; - netdev_features_t sk_route_nocaps; - int sk_gso_type; -diff --git a/include/net/tcp.h b/include/net/tcp.h -index d198005..46cb8a4 100644 ---- a/include/net/tcp.h -+++ b/include/net/tcp.h -@@ -284,6 +284,7 @@ extern int sysctl_tcp_thin_dupack; - extern int sysctl_tcp_early_retrans; - extern int sysctl_tcp_limit_output_bytes; - extern int sysctl_tcp_challenge_ack_limit; -+extern int sysctl_tcp_min_tso_segs; - - extern atomic_long_t tcp_memory_allocated; - extern struct percpu_counter tcp_sockets_allocated; -diff --git a/net/core/sock.c b/net/core/sock.c -index 2c097c5..8729d91 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -2297,6 +2297,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) - sk->sk_ll_usec = sysctl_net_busy_read; - #endif - -+ sk->sk_pacing_rate = ~0U; - /* - * Before updating sk_refcnt, we must commit prior changes to memory - * (Documentation/RCU/rculist_nulls.txt for details) -diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c -index 610e324..6900b8b 100644 ---- a/net/ipv4/sysctl_net_ipv4.c -+++ b/net/ipv4/sysctl_net_ipv4.c -@@ -29,6 +29,7 @@ - static int zero; - static int one = 1; - static int four = 4; -+static int gso_max_segs = GSO_MAX_SEGS; - static int tcp_retr1_max = 255; - static int ip_local_port_range_min[] = { 1, 1 }; - static int ip_local_port_range_max[] = { 65535, 65535 }; -@@ -754,6 +755,15 @@ static struct ctl_table ipv4_table[] = { - .extra2 = &four, - }, - { -+ .procname = "tcp_min_tso_segs", -+ .data = &sysctl_tcp_min_tso_segs, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_minmax, -+ .extra1 = &zero, -+ .extra2 = &gso_max_segs, -+ }, -+ { - .procname = "udp_mem", - .data = &sysctl_udp_mem, - .maxlen = sizeof(sysctl_udp_mem), -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 95544e4..ec586e5 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -283,6 +283,8 @@ - - int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; - -+int sysctl_tcp_min_tso_segs __read_mostly = 2; -+ - struct percpu_counter tcp_orphan_count; - EXPORT_SYMBOL_GPL(tcp_orphan_count); - -@@ -789,12 +791,28 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, - xmit_size_goal = mss_now; - - if (large_allowed && sk_can_gso(sk)) { -- xmit_size_goal = ((sk->sk_gso_max_size - 1) - -- inet_csk(sk)->icsk_af_ops->net_header_len - -- inet_csk(sk)->icsk_ext_hdr_len - -- tp->tcp_header_len); -+ u32 gso_size, hlen; -+ -+ /* Maybe we should/could use sk->sk_prot->max_header here ? */ -+ hlen = inet_csk(sk)->icsk_af_ops->net_header_len + -+ inet_csk(sk)->icsk_ext_hdr_len + -+ tp->tcp_header_len; -+ -+ /* Goal is to send at least one packet per ms, -+ * not one big TSO packet every 100 ms. -+ * This preserves ACK clocking and is consistent -+ * with tcp_tso_should_defer() heuristic. -+ */ -+ gso_size = sk->sk_pacing_rate / (2 * MSEC_PER_SEC); -+ gso_size = max_t(u32, gso_size, -+ sysctl_tcp_min_tso_segs * mss_now); -+ -+ xmit_size_goal = min_t(u32, gso_size, -+ sk->sk_gso_max_size - 1 - hlen); - -- /* TSQ : try to have two TSO segments in flight */ -+ /* TSQ : try to have at least two segments in flight -+ * (one in NIC TX ring, another in Qdisc) -+ */ - xmit_size_goal = min_t(u32, xmit_size_goal, - sysctl_tcp_limit_output_bytes >> 1); - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 3ca2139..2f0e94b 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -688,6 +688,34 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) - } - } - -+/* Set the sk_pacing_rate to allow proper sizing of TSO packets. -+ * Note: TCP stack does not yet implement pacing. -+ * FQ packet scheduler can be used to implement cheap but effective -+ * TCP pacing, to smooth the burst on large writes when packets -+ * in flight is significantly lower than cwnd (or rwin) -+ */ -+static void tcp_update_pacing_rate(struct sock *sk) -+{ -+ const struct tcp_sock *tp = tcp_sk(sk); -+ u64 rate; -+ -+ /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */ -+ rate = (u64)tp->mss_cache * 2 * (HZ << 3); -+ -+ rate *= max(tp->snd_cwnd, tp->packets_out); -+ -+ /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3), -+ * be conservative and assume srtt = 1 (125 us instead of 1.25 ms) -+ * We probably need usec resolution in the future. -+ * Note: This also takes care of possible srtt=0 case, -+ * when tcp_rtt_estimator() was not yet called. -+ */ -+ if (tp->srtt > 8 + 2) -+ do_div(rate, tp->srtt); -+ -+ sk->sk_pacing_rate = min_t(u64, rate, ~0U); -+} -+ - /* Calculate rto without backoff. This is the second half of Van Jacobson's - * routine referred to above. - */ -@@ -3269,7 +3297,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) - u32 ack_seq = TCP_SKB_CB(skb)->seq; - u32 ack = TCP_SKB_CB(skb)->ack_seq; - bool is_dupack = false; -- u32 prior_in_flight; -+ u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt; - u32 prior_fackets; - int prior_packets = tp->packets_out; - const int prior_unsacked = tp->packets_out - tp->sacked_out; -@@ -3375,6 +3403,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) - - if (icsk->icsk_pending == ICSK_TIME_RETRANS) - tcp_schedule_loss_probe(sk); -+ if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd) -+ tcp_update_pacing_rate(sk); - return 1; - - no_queue: -@@ -5671,6 +5701,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - } else - tcp_init_metrics(sk); - -+ tcp_update_pacing_rate(sk); -+ - /* Prevent spurious tcp_cwnd_restart() on first data packet */ - tp->lsndtime = tcp_time_stamp; - -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 170737a..7b263c3 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -1628,7 +1628,7 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) - - /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= min_t(unsigned int, sk->sk_gso_max_size, -- sk->sk_gso_max_segs * tp->mss_cache)) -+ tp->xmit_size_goal_segs * tp->mss_cache)) - goto send_now; - - /* Middle in queue won't get any more data, full sendable already? */ --- -1.7.11.7 - - -From 1b6c7d9979e1db1d42bd0545452a9d204c019582 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Fri, 27 Sep 2013 03:28:54 -0700 -Subject: [PATCH 02/47] tcp: TSQ can use a dynamic limit - -[ Upstream commit c9eeec26e32e087359160406f96e0949b3cc6f10 ] - -When TCP Small Queues was added, we used a sysctl to limit amount of -packets queues on Qdisc/device queues for a given TCP flow. - -Problem is this limit is either too big for low rates, or too small -for high rates. - -Now TCP stack has rate estimation in sk->sk_pacing_rate, and TSO -auto sizing, it can better control number of packets in Qdisc/device -queues. - -New limit is two packets or at least 1 to 2 ms worth of packets. - -Low rates flows benefit from this patch by having even smaller -number of packets in queues, allowing for faster recovery, -better RTT estimations. - -High rates flows benefit from this patch by allowing more than 2 packets -in flight as we had reports this was a limiting factor to reach line -rate. [ In particular if TX completion is delayed because of coalescing -parameters ] - -Example for a single flow on 10Gbp link controlled by FQ/pacing - -14 packets in flight instead of 2 - -$ tc -s -d qd -qdisc fq 8001: dev eth0 root refcnt 32 limit 10000p flow_limit 100p -buckets 1024 quantum 3028 initial_quantum 15140 - Sent 1168459366606 bytes 771822841 pkt (dropped 0, overlimits 0 -requeues 6822476) - rate 9346Mbit 771713pps backlog 953820b 14p requeues 6822476 - 2047 flow, 2046 inactive, 1 throttled, delay 15673 ns - 2372 gc, 0 highprio, 0 retrans, 9739249 throttled, 0 flows_plimit - -Note that sk_pacing_rate is currently set to twice the actual rate, but -this might be refined in the future when a flow is in congestion -avoidance. - -Additional change : skb->destructor should be set to tcp_wfree(). - -A future patch (for linux 3.13+) might remove tcp_limit_output_bytes - -Signed-off-by: Eric Dumazet -Cc: Wei Liu -Cc: Cong Wang -Cc: Yuchung Cheng -Cc: Neal Cardwell -Acked-by: Neal Cardwell -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_output.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 7b263c3..fe897ed 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -892,8 +892,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, - - skb_orphan(skb); - skb->sk = sk; -- skb->destructor = (sysctl_tcp_limit_output_bytes > 0) ? -- tcp_wfree : sock_wfree; -+ skb->destructor = tcp_wfree; - atomic_add(skb->truesize, &sk->sk_wmem_alloc); - - /* Build TCP header and checksum it. */ -@@ -1837,7 +1836,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, - while ((skb = tcp_send_head(sk))) { - unsigned int limit; - -- - tso_segs = tcp_init_tso_segs(sk, skb, mss_now); - BUG_ON(!tso_segs); - -@@ -1866,13 +1864,20 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, - break; - } - -- /* TSQ : sk_wmem_alloc accounts skb truesize, -- * including skb overhead. But thats OK. -+ /* TCP Small Queues : -+ * Control number of packets in qdisc/devices to two packets / or ~1 ms. -+ * This allows for : -+ * - better RTT estimation and ACK scheduling -+ * - faster recovery -+ * - high rates - */ -- if (atomic_read(&sk->sk_wmem_alloc) >= sysctl_tcp_limit_output_bytes) { -+ limit = max(skb->truesize, sk->sk_pacing_rate >> 10); -+ -+ if (atomic_read(&sk->sk_wmem_alloc) > limit) { - set_bit(TSQ_THROTTLED, &tp->tsq_flags); - break; - } -+ - limit = mss_now; - if (tso_segs > 1 && !tcp_urg_mode(tp)) - limit = tcp_mss_split_point(sk, skb, mss_now, --- -1.7.11.7 - - -From 4f25abff83e2780265eaa17d437b7659ea543bd5 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Tue, 15 Oct 2013 11:54:30 -0700 -Subject: [PATCH 03/47] tcp: must unclone packets before mangling them - -[ Upstream commit c52e2421f7368fd36cbe330d2cf41b10452e39a9 ] - -TCP stack should make sure it owns skbs before mangling them. - -We had various crashes using bnx2x, and it turned out gso_size -was cleared right before bnx2x driver was populating TC descriptor -of the _previous_ packet send. TCP stack can sometime retransmit -packets that are still in Qdisc. - -Of course we could make bnx2x driver more robust (using -ACCESS_ONCE(shinfo->gso_size) for example), but the bug is TCP stack. - -We have identified two points where skb_unclone() was needed. - -This patch adds a WARN_ON_ONCE() to warn us if we missed another -fix of this kind. - -Kudos to Neal for finding the root cause of this bug. Its visible -using small MSS. - -Signed-off-by: Eric Dumazet -Signed-off-by: Neal Cardwell -Cc: Yuchung Cheng -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_output.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index fe897ed..28c0d6a 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -981,6 +981,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) - static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, - unsigned int mss_now) - { -+ /* Make sure we own this skb before messing gso_size/gso_segs */ -+ WARN_ON_ONCE(skb_cloned(skb)); -+ - if (skb->len <= mss_now || !sk_can_gso(sk) || - skb->ip_summed == CHECKSUM_NONE) { - /* Avoid the costly divide in the normal -@@ -1062,9 +1065,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, - if (nsize < 0) - nsize = 0; - -- if (skb_cloned(skb) && -- skb_is_nonlinear(skb) && -- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) -+ if (skb_unclone(skb, GFP_ATOMIC)) - return -ENOMEM; - - /* Get a new skb... force flag on. */ -@@ -2339,6 +2340,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) - int oldpcount = tcp_skb_pcount(skb); - - if (unlikely(oldpcount > 1)) { -+ if (skb_unclone(skb, GFP_ATOMIC)) -+ return -ENOMEM; - tcp_init_tso_segs(sk, skb, cur_mss); - tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); - } --- -1.7.11.7 - - -From 8731e25f7527ca851045eb0715d998d1ac07aadb Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Fri, 4 Oct 2013 10:31:41 -0700 -Subject: [PATCH 04/47] tcp: do not forget FIN in tcp_shifted_skb() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 5e8a402f831dbe7ee831340a91439e46f0d38acd ] - -Yuchung found following problem : - - There are bugs in the SACK processing code, merging part in - tcp_shift_skb_data(), that incorrectly resets or ignores the sacked - skbs FIN flag. When a receiver first SACK the FIN sequence, and later - throw away ofo queue (e.g., sack-reneging), the sender will stop - retransmitting the FIN flag, and hangs forever. - -Following packetdrill test can be used to reproduce the bug. - -$ cat sack-merge-bug.pkt -`sysctl -q net.ipv4.tcp_fack=0` - -// Establish a connection and send 10 MSS. -0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 -+.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 -+.000 bind(3, ..., ...) = 0 -+.000 listen(3, 1) = 0 - -+.050 < S 0:0(0) win 32792 -+.000 > S. 0:0(0) ack 1 -+.001 < . 1:1(0) ack 1 win 1024 -+.000 accept(3, ..., ...) = 4 - -+.100 write(4, ..., 12000) = 12000 -+.000 shutdown(4, SHUT_WR) = 0 -+.000 > . 1:10001(10000) ack 1 -+.050 < . 1:1(0) ack 2001 win 257 -+.000 > FP. 10001:12001(2000) ack 1 -+.050 < . 1:1(0) ack 2001 win 257 -+.050 < . 1:1(0) ack 2001 win 257 -// SACK reneg -+.050 < . 1:1(0) ack 12001 win 257 -+0 %{ print "unacked: ",tcpi_unacked }% -+5 %{ print "" }% - -First, a typo inverted left/right of one OR operation, then -code forgot to advance end_seq if the merged skb carried FIN. - -Bug was added in 2.6.29 by commit 832d11c5cd076ab -("tcp: Try to restore large SKBs while SACK processing") - -Signed-off-by: Eric Dumazet -Signed-off-by: Yuchung Cheng -Acked-by: Neal Cardwell -Cc: Ilpo Järvinen -Acked-by: Ilpo Järvinen -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_input.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 2f0e94b..61e2360 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -1279,7 +1279,10 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, - tp->lost_cnt_hint -= tcp_skb_pcount(prev); - } - -- TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags; -+ TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; -+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) -+ TCP_SKB_CB(prev)->end_seq++; -+ - if (skb == tcp_highest_sack(sk)) - tcp_advance_highest_sack(sk, skb); - --- -1.7.11.7 - - -From bfc0a00d669a4fa0835c417f01c50c18996d1e60 Mon Sep 17 00:00:00 2001 -From: Yuchung Cheng -Date: Sat, 12 Oct 2013 10:16:27 -0700 -Subject: [PATCH 05/47] tcp: fix incorrect ca_state in tail loss probe - -[ Upstream commit 031afe4990a7c9dbff41a3a742c44d3e740ea0a1 ] - -On receiving an ACK that covers the loss probe sequence, TLP -immediately sets the congestion state to Open, even though some packets -are not recovered and retransmisssion are on the way. The later ACks -may trigger a WARN_ON check in step D of tcp_fastretrans_alert(), e.g., -https://bugzilla.redhat.com/show_bug.cgi?id=989251 - -The fix is to follow the similar procedure in recovery by calling -tcp_try_keep_open(). The sender switches to Open state if no packets -are retransmissted. Otherwise it goes to Disorder and let subsequent -ACKs move the state to Recovery or Open. - -Reported-By: Michael Sterrett -Tested-By: Dormando -Signed-off-by: Yuchung Cheng -Acked-by: Neal Cardwell -Signed-off-by: David S. Miller ---- - net/ipv4/tcp_input.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 61e2360..723951a 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -3284,7 +3284,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) - tcp_init_cwnd_reduction(sk, true); - tcp_set_ca_state(sk, TCP_CA_CWR); - tcp_end_cwnd_reduction(sk); -- tcp_set_ca_state(sk, TCP_CA_Open); -+ tcp_try_keep_open(sk); - NET_INC_STATS_BH(sock_net(sk), - LINUX_MIB_TCPLOSSPROBERECOVERY); - } --- -1.7.11.7 - - -From 05c9fdfad860abd64136d8ccd88dbf84e40bd5f5 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Tue, 1 Oct 2013 21:04:11 -0700 -Subject: [PATCH 06/47] net: do not call sock_put() on TIMEWAIT sockets - -[ Upstream commit 80ad1d61e72d626e30ebe8529a0455e660ca4693 ] - -commit 3ab5aee7fe84 ("net: Convert TCP & DCCP hash tables to use RCU / -hlist_nulls") incorrectly used sock_put() on TIMEWAIT sockets. - -We should instead use inet_twsk_put() - -Signed-off-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv4/inet_hashtables.c | 2 +- - net/ipv6/inet6_hashtables.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c -index 7bd8983..96da9c7 100644 ---- a/net/ipv4/inet_hashtables.c -+++ b/net/ipv4/inet_hashtables.c -@@ -287,7 +287,7 @@ begintw: - if (unlikely(!INET_TW_MATCH(sk, net, acookie, - saddr, daddr, ports, - dif))) { -- sock_put(sk); -+ inet_twsk_put(inet_twsk(sk)); - goto begintw; - } - goto out; -diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c -index 32b4a16..066640e 100644 ---- a/net/ipv6/inet6_hashtables.c -+++ b/net/ipv6/inet6_hashtables.c -@@ -116,7 +116,7 @@ begintw: - } - if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr, - ports, dif))) { -- sock_put(sk); -+ inet_twsk_put(inet_twsk(sk)); - goto begintw; - } - goto out; --- -1.7.11.7 - - -From bc7fd34d31c17b0e4c100013e77277a2ed7e15cf Mon Sep 17 00:00:00 2001 -From: Matthias Schiffer -Date: Fri, 27 Sep 2013 18:03:39 +0200 -Subject: [PATCH 07/47] batman-adv: set up network coding packet handlers - during module init - -[ Upstream commit 6c519bad7b19a2c14a075b400edabaa630330123 ] - -batman-adv saves its table of packet handlers as a global state, so handlers -must be set up only once (and setting them up a second time will fail). - -The recently-added network coding support tries to set up its handler each time -a new softif is registered, which obviously fails when more that one softif is -used (and in consequence, the softif creation fails). - -Fix this by splitting up batadv_nc_init into batadv_nc_init (which is called -only once) and batadv_nc_mesh_init (which is called for each softif); in -addition batadv_nc_free is renamed to batadv_nc_mesh_free to keep naming -consistent. - -Signed-off-by: Matthias Schiffer -Signed-off-by: Marek Lindner -Signed-off-by: Antonio Quartulli ---- - net/batman-adv/main.c | 5 +++-- - net/batman-adv/network-coding.c | 28 ++++++++++++++++++---------- - net/batman-adv/network-coding.h | 14 ++++++++++---- - 3 files changed, 31 insertions(+), 16 deletions(-) - -diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c -index 08125f3..c8e0671 100644 ---- a/net/batman-adv/main.c -+++ b/net/batman-adv/main.c -@@ -61,6 +61,7 @@ static int __init batadv_init(void) - batadv_recv_handler_init(); - - batadv_iv_init(); -+ batadv_nc_init(); - - batadv_event_workqueue = create_singlethread_workqueue("bat_events"); - -@@ -138,7 +139,7 @@ int batadv_mesh_init(struct net_device *soft_iface) - if (ret < 0) - goto err; - -- ret = batadv_nc_init(bat_priv); -+ ret = batadv_nc_mesh_init(bat_priv); - if (ret < 0) - goto err; - -@@ -163,7 +164,7 @@ void batadv_mesh_free(struct net_device *soft_iface) - batadv_vis_quit(bat_priv); - - batadv_gw_node_purge(bat_priv); -- batadv_nc_free(bat_priv); -+ batadv_nc_mesh_free(bat_priv); - batadv_dat_free(bat_priv); - batadv_bla_free(bat_priv); - -diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c -index a487d46..4ecc0b6 100644 ---- a/net/batman-adv/network-coding.c -+++ b/net/batman-adv/network-coding.c -@@ -35,6 +35,20 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, - struct batadv_hard_iface *recv_if); - - /** -+ * batadv_nc_init - one-time initialization for network coding -+ */ -+int __init batadv_nc_init(void) -+{ -+ int ret; -+ -+ /* Register our packet type */ -+ ret = batadv_recv_handler_register(BATADV_CODED, -+ batadv_nc_recv_coded_packet); -+ -+ return ret; -+} -+ -+/** - * batadv_nc_start_timer - initialise the nc periodic worker - * @bat_priv: the bat priv with all the soft interface information - */ -@@ -45,10 +59,10 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv) - } - - /** -- * batadv_nc_init - initialise coding hash table and start house keeping -+ * batadv_nc_mesh_init - initialise coding hash table and start house keeping - * @bat_priv: the bat priv with all the soft interface information - */ --int batadv_nc_init(struct batadv_priv *bat_priv) -+int batadv_nc_mesh_init(struct batadv_priv *bat_priv) - { - bat_priv->nc.timestamp_fwd_flush = jiffies; - bat_priv->nc.timestamp_sniffed_purge = jiffies; -@@ -70,11 +84,6 @@ int batadv_nc_init(struct batadv_priv *bat_priv) - batadv_hash_set_lock_class(bat_priv->nc.coding_hash, - &batadv_nc_decoding_hash_lock_class_key); - -- /* Register our packet type */ -- if (batadv_recv_handler_register(BATADV_CODED, -- batadv_nc_recv_coded_packet) < 0) -- goto err; -- - INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); - batadv_nc_start_timer(bat_priv); - -@@ -1721,12 +1730,11 @@ free_nc_packet: - } - - /** -- * batadv_nc_free - clean up network coding memory -+ * batadv_nc_mesh_free - clean up network coding memory - * @bat_priv: the bat priv with all the soft interface information - */ --void batadv_nc_free(struct batadv_priv *bat_priv) -+void batadv_nc_mesh_free(struct batadv_priv *bat_priv) - { -- batadv_recv_handler_unregister(BATADV_CODED); - cancel_delayed_work_sync(&bat_priv->nc.work); - - batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); -diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h -index 85a4ec8..ddfa618 100644 ---- a/net/batman-adv/network-coding.h -+++ b/net/batman-adv/network-coding.h -@@ -22,8 +22,9 @@ - - #ifdef CONFIG_BATMAN_ADV_NC - --int batadv_nc_init(struct batadv_priv *bat_priv); --void batadv_nc_free(struct batadv_priv *bat_priv); -+int batadv_nc_init(void); -+int batadv_nc_mesh_init(struct batadv_priv *bat_priv); -+void batadv_nc_mesh_free(struct batadv_priv *bat_priv); - void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, - struct batadv_orig_node *orig_node, - struct batadv_orig_node *orig_neigh_node, -@@ -46,12 +47,17 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); - - #else /* ifdef CONFIG_BATMAN_ADV_NC */ - --static inline int batadv_nc_init(struct batadv_priv *bat_priv) -+static inline int batadv_nc_init(void) - { - return 0; - } - --static inline void batadv_nc_free(struct batadv_priv *bat_priv) -+static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv) -+{ -+ return 0; -+} -+ -+static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) - { - return; - } --- -1.7.11.7 - - -From 8be4005ed947924104df5850944a20b7f6570137 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fran=C3=A7ois=20Cachereul?= -Date: Wed, 2 Oct 2013 10:16:02 +0200 -Subject: [PATCH 08/47] l2tp: fix kernel panic when using IPv4-mapped IPv6 - addresses -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit e18503f41f9b12132c95d7c31ca6ee5155e44e5c ] - -IPv4 mapped addresses cause kernel panic. -The patch juste check whether the IPv6 address is an IPv4 mapped -address. If so, use IPv4 API instead of IPv6. - -[ 940.026915] general protection fault: 0000 [#1] -[ 940.026915] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppox ppp_generic slhc loop psmouse -[ 940.026915] CPU: 0 PID: 3184 Comm: memcheck-amd64- Not tainted 3.11.0+ #1 -[ 940.026915] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 -[ 940.026915] task: ffff880007130e20 ti: ffff88000737e000 task.ti: ffff88000737e000 -[ 940.026915] RIP: 0010:[] [] ip6_xmit+0x276/0x326 -[ 940.026915] RSP: 0018:ffff88000737fd28 EFLAGS: 00010286 -[ 940.026915] RAX: c748521a75ceff48 RBX: ffff880000c30800 RCX: 0000000000000000 -[ 940.026915] RDX: ffff88000075cc4e RSI: 0000000000000028 RDI: ffff8800060e5a40 -[ 940.026915] RBP: ffff8800060e5a40 R08: 0000000000000000 R09: ffff88000075cc90 -[ 940.026915] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88000737fda0 -[ 940.026915] R13: 0000000000000000 R14: 0000000000002000 R15: ffff880005d3b580 -[ 940.026915] FS: 00007f163dc5e800(0000) GS:ffffffff81623000(0000) knlGS:0000000000000000 -[ 940.026915] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 940.026915] CR2: 00000004032dc940 CR3: 0000000005c25000 CR4: 00000000000006f0 -[ 940.026915] Stack: -[ 940.026915] ffff88000075cc4e ffffffff81694e90 ffff880000c30b38 0000000000000020 -[ 940.026915] 11000000523c4bac ffff88000737fdb4 0000000000000000 ffff880000c30800 -[ 940.026915] ffff880005d3b580 ffff880000c30b38 ffff8800060e5a40 0000000000000020 -[ 940.026915] Call Trace: -[ 940.026915] [] ? inet6_csk_xmit+0xa4/0xc4 -[ 940.026915] [] ? l2tp_xmit_skb+0x503/0x55a [l2tp_core] -[ 940.026915] [] ? pskb_expand_head+0x161/0x214 -[ 940.026915] [] ? pppol2tp_xmit+0xf2/0x143 [l2tp_ppp] -[ 940.026915] [] ? ppp_channel_push+0x36/0x8b [ppp_generic] -[ 940.026915] [] ? ppp_write+0xaf/0xc5 [ppp_generic] -[ 940.026915] [] ? vfs_write+0xa2/0x106 -[ 940.026915] [] ? SyS_write+0x56/0x8a -[ 940.026915] [] ? system_call_fastpath+0x16/0x1b -[ 940.026915] Code: 00 49 8b 8f d8 00 00 00 66 83 7c 11 02 00 74 60 49 -8b 47 58 48 83 e0 fe 48 8b 80 18 01 00 00 48 85 c0 74 13 48 8b 80 78 02 -00 00 <48> ff 40 28 41 8b 57 68 48 01 50 30 48 8b 54 24 08 49 c7 c1 51 -[ 940.026915] RIP [] ip6_xmit+0x276/0x326 -[ 940.026915] RSP -[ 940.057945] ---[ end trace be8aba9a61c8b7f3 ]--- -[ 940.058583] Kernel panic - not syncing: Fatal exception in interrupt - -Signed-off-by: François CACHEREUL -Signed-off-by: David S. Miller ---- - net/l2tp/l2tp_core.c | 27 +++++++++++++++++++++++---- - net/l2tp/l2tp_core.h | 3 +++ - 2 files changed, 26 insertions(+), 4 deletions(-) - -diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c -index feae495..aedaa2c 100644 ---- a/net/l2tp/l2tp_core.c -+++ b/net/l2tp/l2tp_core.c -@@ -496,6 +496,7 @@ out: - static inline int l2tp_verify_udp_checksum(struct sock *sk, - struct sk_buff *skb) - { -+ struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; - struct udphdr *uh = udp_hdr(skb); - u16 ulen = ntohs(uh->len); - __wsum psum; -@@ -504,7 +505,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, - return 0; - - #if IS_ENABLED(CONFIG_IPV6) -- if (sk->sk_family == PF_INET6) { -+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { - if (!uh->check) { - LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); - return 1; -@@ -1128,7 +1129,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, - /* Queue the packet to IP for output */ - skb->local_df = 1; - #if IS_ENABLED(CONFIG_IPV6) -- if (skb->sk->sk_family == PF_INET6) -+ if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped) - error = inet6_csk_xmit(skb, NULL); - else - #endif -@@ -1255,7 +1256,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len - - /* Calculate UDP checksum if configured to do so */ - #if IS_ENABLED(CONFIG_IPV6) -- if (sk->sk_family == PF_INET6) -+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) - l2tp_xmit_ipv6_csum(sk, skb, udp_len); - else - #endif -@@ -1704,6 +1705,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 - if (cfg != NULL) - tunnel->debug = cfg->debug; - -+#if IS_ENABLED(CONFIG_IPV6) -+ if (sk->sk_family == PF_INET6) { -+ struct ipv6_pinfo *np = inet6_sk(sk); -+ -+ if (ipv6_addr_v4mapped(&np->saddr) && -+ ipv6_addr_v4mapped(&np->daddr)) { -+ struct inet_sock *inet = inet_sk(sk); -+ -+ tunnel->v4mapped = true; -+ inet->inet_saddr = np->saddr.s6_addr32[3]; -+ inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3]; -+ inet->inet_daddr = np->daddr.s6_addr32[3]; -+ } else { -+ tunnel->v4mapped = false; -+ } -+ } -+#endif -+ - /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ - tunnel->encap = encap; - if (encap == L2TP_ENCAPTYPE_UDP) { -@@ -1712,7 +1731,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 - udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; - udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; - #if IS_ENABLED(CONFIG_IPV6) -- if (sk->sk_family == PF_INET6) -+ if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) - udpv6_encap_enable(); - else - #endif -diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h -index 66a559b..6f251cb 100644 ---- a/net/l2tp/l2tp_core.h -+++ b/net/l2tp/l2tp_core.h -@@ -194,6 +194,9 @@ struct l2tp_tunnel { - struct sock *sock; /* Parent socket */ - int fd; /* Parent fd, if tunnel socket - * was created by userspace */ -+#if IS_ENABLED(CONFIG_IPV6) -+ bool v4mapped; -+#endif - - struct work_struct del_work; - --- -1.7.11.7 - - -From 0ec2b01190b1a2ba020241ab89730bf7e7d77b9c Mon Sep 17 00:00:00 2001 -From: "David S. Miller" -Date: Tue, 8 Oct 2013 15:44:26 -0400 -Subject: [PATCH 09/47] l2tp: Fix build warning with ipv6 disabled. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 8d8a51e26a6d415e1470759f2cf5f3ee3ee86196 ] - -net/l2tp/l2tp_core.c: In function ‘l2tp_verify_udp_checksum’: -net/l2tp/l2tp_core.c:499:22: warning: unused variable ‘tunnel’ [-Wunused-variable] - -Create a helper "l2tp_tunnel()" to facilitate this, and as a side -effect get rid of a bunch of unnecessary void pointer casts. - -Signed-off-by: David S. Miller ---- - net/l2tp/l2tp_core.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c -index aedaa2c..b076e83 100644 ---- a/net/l2tp/l2tp_core.c -+++ b/net/l2tp/l2tp_core.c -@@ -115,6 +115,11 @@ struct l2tp_net { - static void l2tp_session_set_header_len(struct l2tp_session *session, int version); - static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); - -+static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) -+{ -+ return sk->sk_user_data; -+} -+ - static inline struct l2tp_net *l2tp_pernet(struct net *net) - { - BUG_ON(!net); -@@ -496,7 +501,6 @@ out: - static inline int l2tp_verify_udp_checksum(struct sock *sk, - struct sk_buff *skb) - { -- struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; - struct udphdr *uh = udp_hdr(skb); - u16 ulen = ntohs(uh->len); - __wsum psum; -@@ -505,7 +509,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, - return 0; - - #if IS_ENABLED(CONFIG_IPV6) -- if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { -+ if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) { - if (!uh->check) { - LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); - return 1; -@@ -1305,10 +1309,9 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb); - */ - static void l2tp_tunnel_destruct(struct sock *sk) - { -- struct l2tp_tunnel *tunnel; -+ struct l2tp_tunnel *tunnel = l2tp_tunnel(sk); - struct l2tp_net *pn; - -- tunnel = sk->sk_user_data; - if (tunnel == NULL) - goto end; - -@@ -1676,7 +1679,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 - } - - /* Check if this socket has already been prepped */ -- tunnel = (struct l2tp_tunnel *)sk->sk_user_data; -+ tunnel = l2tp_tunnel(sk); - if (tunnel != NULL) { - /* This socket has already been prepped */ - err = -EBUSY; --- -1.7.11.7 - - -From 35e64a9e465a85ffacd373439c1caa757e407656 Mon Sep 17 00:00:00 2001 -From: Sebastian Hesselbarth -Date: Wed, 2 Oct 2013 12:57:20 +0200 -Subject: [PATCH 10/47] net: mv643xx_eth: update statistics timer from timer - context only - -[ Upstream commit 041b4ddb84989f06ff1df0ca869b950f1ee3cb1c ] - -Each port driver installs a periodic timer to update port statistics -by calling mib_counters_update. As mib_counters_update is also called -from non-timer context, we should not reschedule the timer there but -rather move it to timer-only context. - -Signed-off-by: Sebastian Hesselbarth -Acked-by: Jason Cooper -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mv643xx_eth.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c -index c35db73..51c138b 100644 ---- a/drivers/net/ethernet/marvell/mv643xx_eth.c -+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c -@@ -1131,15 +1131,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) - p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); - p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); - spin_unlock_bh(&mp->mib_counters_lock); -- -- mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); - } - - static void mib_counters_timer_wrapper(unsigned long _mp) - { - struct mv643xx_eth_private *mp = (void *)_mp; -- - mib_counters_update(mp); -+ mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); - } - - --- -1.7.11.7 - - -From b6b20d9c54b23ba35c5807e45ff7d9579503bffa Mon Sep 17 00:00:00 2001 -From: Sebastian Hesselbarth -Date: Wed, 2 Oct 2013 12:57:21 +0200 -Subject: [PATCH 11/47] net: mv643xx_eth: fix orphaned statistics timer crash - -[ Upstream commit f564412c935111c583b787bcc18157377b208e2e ] - -The periodic statistics timer gets started at port _probe() time, but -is stopped on _stop() only. In a modular environment, this can cause -the timer to access already deallocated memory, if the module is unloaded -without starting the eth device. To fix this, we add the timer right -before the port is started, instead of at _probe() time. - -Signed-off-by: Sebastian Hesselbarth -Acked-by: Jason Cooper -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c -index 51c138b..39334d4 100644 ---- a/drivers/net/ethernet/marvell/mv643xx_eth.c -+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c -@@ -2235,6 +2235,7 @@ static int mv643xx_eth_open(struct net_device *dev) - mp->int_mask |= INT_TX_END_0 << i; - } - -+ add_timer(&mp->mib_counters_timer); - port_start(mp); - - wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); -@@ -2914,7 +2915,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) - mp->mib_counters_timer.data = (unsigned long)mp; - mp->mib_counters_timer.function = mib_counters_timer_wrapper; - mp->mib_counters_timer.expires = jiffies + 30 * HZ; -- add_timer(&mp->mib_counters_timer); - - spin_lock_init(&mp->mib_counters_lock); - --- -1.7.11.7 - - -From b8baf1c21a214c1b836eef390c9d6e153293fef9 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 3 Oct 2013 00:27:20 +0300 -Subject: [PATCH 12/47] net: heap overflow in __audit_sockaddr() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 1661bf364ae9c506bc8795fef70d1532931be1e8 ] - -We need to cap ->msg_namelen or it leads to a buffer overflow when we -to the memcpy() in __audit_sockaddr(). It requires CAP_AUDIT_CONTROL to -exploit this bug. - -The call tree is: -___sys_recvmsg() - move_addr_to_user() - audit_sockaddr() - __audit_sockaddr() - -Reported-by: Jüri Aedla -Signed-off-by: Dan Carpenter -Signed-off-by: David S. Miller ---- - net/compat.c | 2 ++ - net/socket.c | 24 ++++++++++++++++++++---- - 2 files changed, 22 insertions(+), 4 deletions(-) - -diff --git a/net/compat.c b/net/compat.c -index f0a1ba6..8903258 100644 ---- a/net/compat.c -+++ b/net/compat.c -@@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) - __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || - __get_user(kmsg->msg_flags, &umsg->msg_flags)) - return -EFAULT; -+ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) -+ return -EINVAL; - kmsg->msg_name = compat_ptr(tmp1); - kmsg->msg_iov = compat_ptr(tmp2); - kmsg->msg_control = compat_ptr(tmp3); -diff --git a/net/socket.c b/net/socket.c -index b2d7c62..4b94643 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -1973,6 +1973,16 @@ struct used_address { - unsigned int name_len; - }; - -+static int copy_msghdr_from_user(struct msghdr *kmsg, -+ struct msghdr __user *umsg) -+{ -+ if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) -+ return -EFAULT; -+ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) -+ return -EINVAL; -+ return 0; -+} -+ - static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, - struct msghdr *msg_sys, unsigned int flags, - struct used_address *used_address) -@@ -1991,8 +2001,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, - if (MSG_CMSG_COMPAT & flags) { - if (get_compat_msghdr(msg_sys, msg_compat)) - return -EFAULT; -- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) -- return -EFAULT; -+ } else { -+ err = copy_msghdr_from_user(msg_sys, msg); -+ if (err) -+ return err; -+ } - - if (msg_sys->msg_iovlen > UIO_FASTIOV) { - err = -EMSGSIZE; -@@ -2200,8 +2213,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, - if (MSG_CMSG_COMPAT & flags) { - if (get_compat_msghdr(msg_sys, msg_compat)) - return -EFAULT; -- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) -- return -EFAULT; -+ } else { -+ err = copy_msghdr_from_user(msg_sys, msg); -+ if (err) -+ return err; -+ } - - if (msg_sys->msg_iovlen > UIO_FASTIOV) { - err = -EMSGSIZE; --- -1.7.11.7 - - -From 6e24497ef79e18f5b1ddce66712d55093a6cf3e9 Mon Sep 17 00:00:00 2001 -From: Willem de Bruijn -Date: Tue, 22 Oct 2013 10:59:18 -0400 -Subject: [PATCH 13/47] sit: amend "allow to use rtnl ops on fb tunnel" - -Amend backport to 3.11.y of - - [ Upstream commit 205983c43700ac3a81e7625273a3fa83cd2759b5 ] - -The discussion thread in the upstream commit mentions that in -backports to stable-* branches, the line - - - unregister_netdevice_queue(sitn->fb_tunnel_dev, &list); - -must be omitted if that branch does not have commit 5e6700b3bf98 -("sit: add support of x-netns"). This line has correctly been omitted -in the backport to 3.10, which indeed does not have that commit. - -It was also removed in the backport to 3.11.y, which does have that -commit. - -This causes the following steps to hit a BUG at net/core/dev.c:5039: - - `modprobe sit; rmmod sit` - -The bug demonstrates that it causes a device to be unregistered twice. -The simple fix is to apply the one line in the upstream commit that -was dropped in the backport to 3.11 (3783100374653e2e7fbdf68c710f5). -This brings the logic in line with upstream linux, net and net-next -branches. - -Signed-off-by: Willem de Bruijn -Acked-by: Nicolas Dichtel -Reviewed-by: Veaceslav Falico ---- - net/ipv6/sit.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c -index 86f639b..a51ad07 100644 ---- a/net/ipv6/sit.c -+++ b/net/ipv6/sit.c -@@ -1708,7 +1708,6 @@ static void __net_exit sit_exit_net(struct net *net) - - rtnl_lock(); - sit_destroy_tunnels(sitn, &list); -- unregister_netdevice_queue(sitn->fb_tunnel_dev, &list); - unregister_netdevice_many(&list); - rtnl_unlock(); - } --- -1.7.11.7 - - -From 6c7e3c3382670fe98debedf2ddaff8abf2944bb4 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Mon, 30 Sep 2013 22:03:06 +0200 -Subject: [PATCH 14/47] proc connector: fix info leaks - -[ Upstream commit e727ca82e0e9616ab4844301e6bae60ca7327682 ] - -Initialize event_data for all possible message types to prevent leaking -kernel stack contents to userland (up to 20 bytes). Also set the flags -member of the connector message to 0 to prevent leaking two more stack -bytes this way. - -Cc: stable@vger.kernel.org # v2.6.15+ -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - drivers/connector/cn_proc.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c -index 08ae128..c73fc2b 100644 ---- a/drivers/connector/cn_proc.c -+++ b/drivers/connector/cn_proc.c -@@ -65,6 +65,7 @@ void proc_fork_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -80,6 +81,7 @@ void proc_fork_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - /* If cn_netlink_send() failed, the data is not sent */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } -@@ -96,6 +98,7 @@ void proc_exec_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -106,6 +109,7 @@ void proc_exec_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -122,6 +126,7 @@ void proc_id_connector(struct task_struct *task, int which_id) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - ev->what = which_id; - ev->event_data.id.process_pid = task->pid; - ev->event_data.id.process_tgid = task->tgid; -@@ -145,6 +150,7 @@ void proc_id_connector(struct task_struct *task, int which_id) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -160,6 +166,7 @@ void proc_sid_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -170,6 +177,7 @@ void proc_sid_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -185,6 +193,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -203,6 +212,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -218,6 +228,7 @@ void proc_comm_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -229,6 +240,7 @@ void proc_comm_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -244,6 +256,7 @@ void proc_coredump_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -254,6 +267,7 @@ void proc_coredump_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -269,6 +283,7 @@ void proc_exit_connector(struct task_struct *task) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -281,6 +296,7 @@ void proc_exit_connector(struct task_struct *task) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - -@@ -304,6 +320,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; -+ memset(&ev->event_data, 0, sizeof(ev->event_data)); - msg->seq = rcvd_seq; - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); -@@ -313,6 +330,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = rcvd_ack + 1; - msg->len = sizeof(*ev); -+ msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); - } - --- -1.7.11.7 - - -From f3d398e2465b3b74987a3a2fc42ea3e8c83d2166 Mon Sep 17 00:00:00 2001 -From: Jiri Benc -Date: Fri, 4 Oct 2013 17:04:48 +0200 -Subject: [PATCH 15/47] ipv4: fix ineffective source address selection - -[ Upstream commit 0a7e22609067ff524fc7bbd45c6951dd08561667 ] - -When sending out multicast messages, the source address in inet->mc_addr is -ignored and rewritten by an autoselected one. This is caused by a typo in -commit 813b3b5db831 ("ipv4: Use caller's on-stack flowi as-is in output -route lookups"). - -Signed-off-by: Jiri Benc -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/ipv4/route.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index a9a54a2..2de16d9 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -2074,7 +2074,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) - RT_SCOPE_LINK); - goto make_route; - } -- if (fl4->saddr) { -+ if (!fl4->saddr) { - if (ipv4_is_multicast(fl4->daddr)) - fl4->saddr = inet_select_addr(dev_out, 0, - fl4->flowi4_scope); --- -1.7.11.7 - - -From 8fd516716afeb4631cf790a2be7ca30d0a664b01 Mon Sep 17 00:00:00 2001 -From: Marc Kleine-Budde -Date: Sat, 5 Oct 2013 21:25:17 +0200 -Subject: [PATCH 16/47] can: dev: fix nlmsg size calculation in can_get_size() - -[ Upstream commit fe119a05f8ca481623a8d02efcc984332e612528 ] - -This patch fixes the calculation of the nlmsg size, by adding the missing -nla_total_size(). - -Signed-off-by: Marc Kleine-Budde -Signed-off-by: David S. Miller ---- - drivers/net/can/dev.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c -index f9cba41..1870c47 100644 ---- a/drivers/net/can/dev.c -+++ b/drivers/net/can/dev.c -@@ -705,14 +705,14 @@ static size_t can_get_size(const struct net_device *dev) - size_t size; - - size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ -- size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ -+ size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */ - size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ -- size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ -- size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ -+ size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */ -+ size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */ - if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ -- size += sizeof(struct can_berr_counter); -+ size += nla_total_size(sizeof(struct can_berr_counter)); - if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ -- size += sizeof(struct can_bittiming_const); -+ size += nla_total_size(sizeof(struct can_bittiming_const)); - - return size; - } --- -1.7.11.7 - - -From 1b3231ca7e26084580145c904dd10a60cac35c63 Mon Sep 17 00:00:00 2001 -From: Fabio Estevam -Date: Sat, 5 Oct 2013 17:56:59 -0300 -Subject: [PATCH 17/47] net: secure_seq: Fix warning when CONFIG_IPV6 and - CONFIG_INET are not selected - -[ Upstream commit cb03db9d0e964568407fb08ea46cc2b6b7f67587 ] - -net_secret() is only used when CONFIG_IPV6 or CONFIG_INET are selected. - -Building a defconfig with both of these symbols unselected (Using the ARM -at91sam9rl_defconfig, for example) leads to the following build warning: - -$ make at91sam9rl_defconfig -# -# configuration written to .config -# - -$ make net/core/secure_seq.o -scripts/kconfig/conf --silentoldconfig Kconfig - CHK include/config/kernel.release - CHK include/generated/uapi/linux/version.h - CHK include/generated/utsrelease.h -make[1]: `include/generated/mach-types.h' is up to date. - CALL scripts/checksyscalls.sh - CC net/core/secure_seq.o -net/core/secure_seq.c:17:13: warning: 'net_secret_init' defined but not used [-Wunused-function] - -Fix this warning by protecting the definition of net_secret() with these -symbols. - -Reported-by: Olof Johansson -Signed-off-by: Fabio Estevam -Signed-off-by: David S. Miller ---- - net/core/secure_seq.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c -index 3f1ec15..8d9d05e 100644 ---- a/net/core/secure_seq.c -+++ b/net/core/secure_seq.c -@@ -10,6 +10,7 @@ - - #include - -+#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) - #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) - - static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; -@@ -29,6 +30,7 @@ static void net_secret_init(void) - cmpxchg(&net_secret[--i], 0, tmp); - } - } -+#endif - - #ifdef CONFIG_INET - static u32 seq_scale(u32 seq) --- -1.7.11.7 - - -From 538680b534f30fe6531099f87267bb676c935351 Mon Sep 17 00:00:00 2001 -From: Paul Durrant -Date: Tue, 8 Oct 2013 14:56:44 +0100 -Subject: [PATCH 18/47] xen-netback: Don't destroy the netdev until the vif is - shut down - -[ upstream commit id: 279f438e36c0a70b23b86d2090aeec50155034a9 ] - -Without this patch, if a frontend cycles through states Closing -and Closed (which Windows frontends need to do) then the netdev -will be destroyed and requires re-invocation of hotplug scripts -to restore state before the frontend can move to Connected. Thus -when udev is not in use the backend gets stuck in InitWait. - -With this patch, the netdev is left alone whilst the backend is -still online and is only de-registered and freed just prior to -destroying the vif (which is also nicely symmetrical with the -netdev allocation and registration being done during probe) so -no re-invocation of hotplug scripts is required. - -Signed-off-by: Paul Durrant -Cc: David Vrabel -Cc: Wei Liu -Cc: Ian Campbell ---- - drivers/net/xen-netback/common.h | 1 + - drivers/net/xen-netback/interface.c | 23 +++++++++-------------- - drivers/net/xen-netback/xenbus.c | 17 ++++++++++++----- - 3 files changed, 22 insertions(+), 19 deletions(-) - -diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h -index 8a4d77e..4d9a5e7 100644 ---- a/drivers/net/xen-netback/common.h -+++ b/drivers/net/xen-netback/common.h -@@ -120,6 +120,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, - unsigned long rx_ring_ref, unsigned int tx_evtchn, - unsigned int rx_evtchn); - void xenvif_disconnect(struct xenvif *vif); -+void xenvif_free(struct xenvif *vif); - - void xenvif_get(struct xenvif *vif); - void xenvif_put(struct xenvif *vif); -diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c -index 087d2db..73336c1 100644 ---- a/drivers/net/xen-netback/interface.c -+++ b/drivers/net/xen-netback/interface.c -@@ -326,6 +326,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, - } - - netdev_dbg(dev, "Successfully created xenvif\n"); -+ -+ __module_get(THIS_MODULE); -+ - return vif; - } - -@@ -413,12 +416,6 @@ void xenvif_carrier_off(struct xenvif *vif) - - void xenvif_disconnect(struct xenvif *vif) - { -- /* Disconnect funtion might get called by generic framework -- * even before vif connects, so we need to check if we really -- * need to do a module_put. -- */ -- int need_module_put = 0; -- - if (netif_carrier_ok(vif->dev)) - xenvif_carrier_off(vif); - -@@ -432,18 +429,16 @@ void xenvif_disconnect(struct xenvif *vif) - unbind_from_irqhandler(vif->tx_irq, vif); - unbind_from_irqhandler(vif->rx_irq, vif); - } -- /* vif->irq is valid, we had a module_get in -- * xenvif_connect. -- */ -- need_module_put = 1; - } - -- unregister_netdev(vif->dev); -- - xen_netbk_unmap_frontend_rings(vif); -+} -+ -+void xenvif_free(struct xenvif *vif) -+{ -+ unregister_netdev(vif->dev); - - free_netdev(vif->dev); - -- if (need_module_put) -- module_put(THIS_MODULE); -+ module_put(THIS_MODULE); - } -diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c -index 1fe48fe3..a53782e 100644 ---- a/drivers/net/xen-netback/xenbus.c -+++ b/drivers/net/xen-netback/xenbus.c -@@ -42,7 +42,7 @@ static int netback_remove(struct xenbus_device *dev) - if (be->vif) { - kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); - xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); -- xenvif_disconnect(be->vif); -+ xenvif_free(be->vif); - be->vif = NULL; - } - kfree(be); -@@ -213,9 +213,18 @@ static void disconnect_backend(struct xenbus_device *dev) - { - struct backend_info *be = dev_get_drvdata(&dev->dev); - -+ if (be->vif) -+ xenvif_disconnect(be->vif); -+} -+ -+static void destroy_backend(struct xenbus_device *dev) -+{ -+ struct backend_info *be = dev_get_drvdata(&dev->dev); -+ - if (be->vif) { -+ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); - xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); -- xenvif_disconnect(be->vif); -+ xenvif_free(be->vif); - be->vif = NULL; - } - } -@@ -246,14 +255,11 @@ static void frontend_changed(struct xenbus_device *dev, - case XenbusStateConnected: - if (dev->state == XenbusStateConnected) - break; -- backend_create_xenvif(be); - if (be->vif) - connect(be); - break; - - case XenbusStateClosing: -- if (be->vif) -- kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); - disconnect_backend(dev); - xenbus_switch_state(dev, XenbusStateClosing); - break; -@@ -262,6 +268,7 @@ static void frontend_changed(struct xenbus_device *dev, - xenbus_switch_state(dev, XenbusStateClosed); - if (xenbus_dev_is_online(dev)) - break; -+ destroy_backend(dev); - /* fall through if not online */ - case XenbusStateUnknown: - device_unregister(&dev->dev); --- -1.7.11.7 - - -From 29bb21656d747e62d55b9e1929b23eadcd6be324 Mon Sep 17 00:00:00 2001 -From: Amir Vadai -Date: Mon, 7 Oct 2013 13:38:12 +0200 -Subject: [PATCH 19/47] net/mlx4_en: Rename name of mlx4_en_rx_alloc members - -[ Upstream commit 70fbe0794393829d9acd686428d87c27b6f6984b ] - -Add page prefix to page related members: @size and @offset into -@page_size and @page_offset - -CC: Eric Dumazet -Signed-off-by: Amir Vadai -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mellanox/mlx4/en_rx.c | 40 ++++++++++++++++------------ - drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 4 +-- - 2 files changed, 25 insertions(+), 19 deletions(-) - -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c -index dec455c..066fc27 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c -@@ -70,14 +70,15 @@ static int mlx4_alloc_pages(struct mlx4_en_priv *priv, - put_page(page); - return -ENOMEM; - } -- page_alloc->size = PAGE_SIZE << order; -+ page_alloc->page_size = PAGE_SIZE << order; - page_alloc->page = page; - page_alloc->dma = dma; -- page_alloc->offset = frag_info->frag_align; -+ page_alloc->page_offset = frag_info->frag_align; - /* Not doing get_page() for each frag is a big win - * on asymetric workloads. - */ -- atomic_set(&page->_count, page_alloc->size / frag_info->frag_stride); -+ atomic_set(&page->_count, -+ page_alloc->page_size / frag_info->frag_stride); - return 0; - } - -@@ -96,16 +97,19 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv, - for (i = 0; i < priv->num_frags; i++) { - frag_info = &priv->frag_info[i]; - page_alloc[i] = ring_alloc[i]; -- page_alloc[i].offset += frag_info->frag_stride; -- if (page_alloc[i].offset + frag_info->frag_stride <= ring_alloc[i].size) -+ page_alloc[i].page_offset += frag_info->frag_stride; -+ -+ if (page_alloc[i].page_offset + frag_info->frag_stride <= -+ ring_alloc[i].page_size) - continue; -+ - if (mlx4_alloc_pages(priv, &page_alloc[i], frag_info, gfp)) - goto out; - } - - for (i = 0; i < priv->num_frags; i++) { - frags[i] = ring_alloc[i]; -- dma = ring_alloc[i].dma + ring_alloc[i].offset; -+ dma = ring_alloc[i].dma + ring_alloc[i].page_offset; - ring_alloc[i] = page_alloc[i]; - rx_desc->data[i].addr = cpu_to_be64(dma); - } -@@ -117,7 +121,7 @@ out: - frag_info = &priv->frag_info[i]; - if (page_alloc[i].page != ring_alloc[i].page) { - dma_unmap_page(priv->ddev, page_alloc[i].dma, -- page_alloc[i].size, PCI_DMA_FROMDEVICE); -+ page_alloc[i].page_size, PCI_DMA_FROMDEVICE); - page = page_alloc[i].page; - atomic_set(&page->_count, 1); - put_page(page); -@@ -132,9 +136,10 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, - { - const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; - -- if (frags[i].offset + frag_info->frag_stride > frags[i].size) -- dma_unmap_page(priv->ddev, frags[i].dma, frags[i].size, -- PCI_DMA_FROMDEVICE); -+ if (frags[i].page_offset + frag_info->frag_stride > -+ frags[i].page_size) -+ dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, -+ PCI_DMA_FROMDEVICE); - - if (frags[i].page) - put_page(frags[i].page); -@@ -161,7 +166,7 @@ out: - - page_alloc = &ring->page_alloc[i]; - dma_unmap_page(priv->ddev, page_alloc->dma, -- page_alloc->size, PCI_DMA_FROMDEVICE); -+ page_alloc->page_size, PCI_DMA_FROMDEVICE); - page = page_alloc->page; - atomic_set(&page->_count, 1); - put_page(page); -@@ -184,10 +189,11 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, - i, page_count(page_alloc->page)); - - dma_unmap_page(priv->ddev, page_alloc->dma, -- page_alloc->size, PCI_DMA_FROMDEVICE); -- while (page_alloc->offset + frag_info->frag_stride < page_alloc->size) { -+ page_alloc->page_size, PCI_DMA_FROMDEVICE); -+ while (page_alloc->page_offset + frag_info->frag_stride < -+ page_alloc->page_size) { - put_page(page_alloc->page); -- page_alloc->offset += frag_info->frag_stride; -+ page_alloc->page_offset += frag_info->frag_stride; - } - page_alloc->page = NULL; - } -@@ -478,7 +484,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, - /* Save page reference in skb */ - __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); - skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size); -- skb_frags_rx[nr].page_offset = frags[nr].offset; -+ skb_frags_rx[nr].page_offset = frags[nr].page_offset; - skb->truesize += frag_info->frag_stride; - frags[nr].page = NULL; - } -@@ -517,7 +523,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, - - /* Get pointer to first fragment so we could copy the headers into the - * (linear part of the) skb */ -- va = page_address(frags[0].page) + frags[0].offset; -+ va = page_address(frags[0].page) + frags[0].page_offset; - - if (length <= SMALL_PACKET_SIZE) { - /* We are copying all relevant data to the skb - temporarily -@@ -645,7 +651,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud - dma_sync_single_for_cpu(priv->ddev, dma, sizeof(*ethh), - DMA_FROM_DEVICE); - ethh = (struct ethhdr *)(page_address(frags[0].page) + -- frags[0].offset); -+ frags[0].page_offset); - - if (is_multicast_ether_addr(ethh->h_dest)) { - struct mlx4_mac_entry *entry; -diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -index 5e0aa56..bf06e36 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -@@ -237,8 +237,8 @@ struct mlx4_en_tx_desc { - struct mlx4_en_rx_alloc { - struct page *page; - dma_addr_t dma; -- u32 offset; -- u32 size; -+ u32 page_offset; -+ u32 page_size; - }; - - struct mlx4_en_tx_ring { --- -1.7.11.7 - - -From 4bd2cc99115d31513bfe3c2bd7bcfe67fc081ae8 Mon Sep 17 00:00:00 2001 -From: Amir Vadai -Date: Mon, 7 Oct 2013 13:38:13 +0200 -Subject: [PATCH 20/47] net/mlx4_en: Fix pages never dma unmapped on rx - -[ Upstream commit 021f1107ffdae7a82af6c53f4c52654062e365c6 ] - -This patch fixes a bug introduced by commit 51151a16 (mlx4: allow -order-0 memory allocations in RX path). - -dma_unmap_page never reached because condition to detect last fragment -in page is wrong. offset+frag_stride can't be greater than size, need to -make sure no additional frag will fit in page => compare offset + -frag_stride + next_frag_size instead. -next_frag_size is the same as the current one, since page is shared only -with frags of the same size. - -CC: Eric Dumazet -Signed-off-by: Amir Vadai -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c -index 066fc27..afe2efa 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c -@@ -135,9 +135,10 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, - int i) - { - const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; -+ u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride; - -- if (frags[i].page_offset + frag_info->frag_stride > -- frags[i].page_size) -+ -+ if (next_frag_end > frags[i].page_size) - dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, - PCI_DMA_FROMDEVICE); - --- -1.7.11.7 - - -From af64f33fff313187ca01ddb7db09b537a89208dd Mon Sep 17 00:00:00 2001 -From: Marc Kleine-Budde -Date: Mon, 7 Oct 2013 23:19:58 +0200 -Subject: [PATCH 21/47] net: vlan: fix nlmsg size calculation in - vlan_get_size() - -[ Upstream commit c33a39c575068c2ea9bffb22fd6de2df19c74b89 ] - -This patch fixes the calculation of the nlmsg size, by adding the missing -nla_total_size(). - -Cc: Patrick McHardy -Signed-off-by: Marc Kleine-Budde -Signed-off-by: David S. Miller ---- - net/8021q/vlan_netlink.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c -index 3091297..c7e634a 100644 ---- a/net/8021q/vlan_netlink.c -+++ b/net/8021q/vlan_netlink.c -@@ -171,7 +171,7 @@ static size_t vlan_get_size(const struct net_device *dev) - - return nla_total_size(2) + /* IFLA_VLAN_PROTOCOL */ - nla_total_size(2) + /* IFLA_VLAN_ID */ -- sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */ -+ nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */ - vlan_qos_map_size(vlan->nr_ingress_mappings) + - vlan_qos_map_size(vlan->nr_egress_mappings); - } --- -1.7.11.7 - - -From 74869292aeb07213144e34b0e21e23f7e3c9f61f Mon Sep 17 00:00:00 2001 -From: Vlad Yasevich -Date: Thu, 10 Oct 2013 15:57:59 -0400 -Subject: [PATCH 22/47] bridge: update mdb expiration timer upon reports. - -[ Upstream commit f144febd93d5ee534fdf23505ab091b2b9088edc ] - -commit 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b - bridge: only expire the mdb entry when query is received -changed the mdb expiration timer to be armed only when QUERY is -received. Howerver, this causes issues in an environment where -the multicast server socket comes and goes very fast while a client -is trying to send traffic to it. - -The root cause is a race where a sequence of LEAVE followed by REPORT -messages can race against QUERY messages generated in response to LEAVE. -The QUERY ends up starting the expiration timer, and that timer can -potentially expire after the new REPORT message has been received signaling -the new join operation. This leads to a significant drop in multicast -traffic and possible complete stall. - -The solution is to have REPORT messages update the expiration timer -on entries that already exist. - -CC: Cong Wang -CC: Herbert Xu -CC: Stephen Hemminger -Signed-off-by: Vlad Yasevich -Acked-by: Herbert Xu -Signed-off-by: David S. Miller ---- - net/bridge/br_multicast.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index bbcb435..0e3fea7 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -610,6 +610,9 @@ rehash: - break; - - default: -+ /* If we have an existing entry, update it's expire timer */ -+ mod_timer(&mp->timer, -+ jiffies + br->multicast_membership_interval); - goto out; - } - -@@ -679,8 +682,12 @@ static int br_multicast_add_group(struct net_bridge *br, - for (pp = &mp->ports; - (p = mlock_dereference(*pp, br)) != NULL; - pp = &p->next) { -- if (p->port == port) -+ if (p->port == port) { -+ /* We already have a portgroup, update the timer. */ -+ mod_timer(&p->timer, -+ jiffies + br->multicast_membership_interval); - goto out; -+ } - if ((unsigned long)p->port < (unsigned long)port) - break; - } --- -1.7.11.7 - - -From d9f02cfe59400677feea276d4b27981f6d91825a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Linus=20L=C3=BCssing?= -Date: Sun, 20 Oct 2013 00:58:57 +0200 -Subject: [PATCH 23/47] Revert "bridge: only expire the mdb entry when query - is received" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 454594f3b93a49ef568cd190c5af31376b105a7b ] - -While this commit was a good attempt to fix issues occuring when no -multicast querier is present, this commit still has two more issues: - -1) There are cases where mdb entries do not expire even if there is a -querier present. The bridge will unnecessarily continue flooding -multicast packets on the according ports. - -2) Never removing an mdb entry could be exploited for a Denial of -Service by an attacker on the local link, slowly, but steadily eating up -all memory. - -Actually, this commit became obsolete with -"bridge: disable snooping if there is no querier" (b00589af3b) -which included fixes for a few more cases. - -Therefore reverting the following commits (the commit stated in the -commit message plus three of its follow up fixes): - -==================== -Revert "bridge: update mdb expiration timer upon reports." -This reverts commit f144febd93d5ee534fdf23505ab091b2b9088edc. -Revert "bridge: do not call setup_timer() multiple times" -This reverts commit 1faabf2aab1fdaa1ace4e8c829d1b9cf7bfec2f1. -Revert "bridge: fix some kernel warning in multicast timer" -This reverts commit c7e8e8a8f7a70b343ca1e0f90a31e35ab2d16de1. -Revert "bridge: only expire the mdb entry when query is received" -This reverts commit 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b. -==================== - -CC: Cong Wang -Signed-off-by: Linus Lüssing -Reviewed-by: Vlad Yasevich -Signed-off-by: David S. Miller ---- - net/bridge/br_mdb.c | 2 +- - net/bridge/br_multicast.c | 47 +++++++++++++++++++++++++++-------------------- - net/bridge/br_private.h | 1 - - 3 files changed, 28 insertions(+), 22 deletions(-) - -diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c -index 6319c43..de3a0e7 100644 ---- a/net/bridge/br_mdb.c -+++ b/net/bridge/br_mdb.c -@@ -451,7 +451,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) - call_rcu_bh(&p->rcu, br_multicast_free_pg); - err = 0; - -- if (!mp->ports && !mp->mglist && mp->timer_armed && -+ if (!mp->ports && !mp->mglist && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - break; -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index 0e3fea7..fbad619 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -271,7 +271,7 @@ static void br_multicast_del_pg(struct net_bridge *br, - del_timer(&p->timer); - call_rcu_bh(&p->rcu, br_multicast_free_pg); - -- if (!mp->ports && !mp->mglist && mp->timer_armed && -+ if (!mp->ports && !mp->mglist && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - -@@ -610,9 +610,6 @@ rehash: - break; - - default: -- /* If we have an existing entry, update it's expire timer */ -- mod_timer(&mp->timer, -- jiffies + br->multicast_membership_interval); - goto out; - } - -@@ -622,7 +619,6 @@ rehash: - - mp->br = br; - mp->addr = *group; -- - setup_timer(&mp->timer, br_multicast_group_expired, - (unsigned long)mp); - -@@ -662,6 +658,7 @@ static int br_multicast_add_group(struct net_bridge *br, - struct net_bridge_mdb_entry *mp; - struct net_bridge_port_group *p; - struct net_bridge_port_group __rcu **pp; -+ unsigned long now = jiffies; - int err; - - spin_lock(&br->multicast_lock); -@@ -676,18 +673,15 @@ static int br_multicast_add_group(struct net_bridge *br, - - if (!port) { - mp->mglist = true; -+ mod_timer(&mp->timer, now + br->multicast_membership_interval); - goto out; - } - - for (pp = &mp->ports; - (p = mlock_dereference(*pp, br)) != NULL; - pp = &p->next) { -- if (p->port == port) { -- /* We already have a portgroup, update the timer. */ -- mod_timer(&p->timer, -- jiffies + br->multicast_membership_interval); -- goto out; -- } -+ if (p->port == port) -+ goto found; - if ((unsigned long)p->port < (unsigned long)port) - break; - } -@@ -698,6 +692,8 @@ static int br_multicast_add_group(struct net_bridge *br, - rcu_assign_pointer(*pp, p); - br_mdb_notify(br->dev, port, group, RTM_NEWMDB); - -+found: -+ mod_timer(&p->timer, now + br->multicast_membership_interval); - out: - err = 0; - -@@ -1197,9 +1193,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -- mod_timer(&mp->timer, now + br->multicast_membership_interval); -- mp->timer_armed = true; -- - max_delay *= br->multicast_last_member_count; - - if (mp->mglist && -@@ -1276,9 +1269,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, - if (!mp) - goto out; - -- mod_timer(&mp->timer, now + br->multicast_membership_interval); -- mp->timer_armed = true; -- - max_delay *= br->multicast_last_member_count; - if (mp->mglist && - (timer_pending(&mp->timer) ? -@@ -1364,7 +1354,7 @@ static void br_multicast_leave_group(struct net_bridge *br, - call_rcu_bh(&p->rcu, br_multicast_free_pg); - br_mdb_notify(br->dev, port, group, RTM_DELMDB); - -- if (!mp->ports && !mp->mglist && mp->timer_armed && -+ if (!mp->ports && !mp->mglist && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - } -@@ -1376,12 +1366,30 @@ static void br_multicast_leave_group(struct net_bridge *br, - br->multicast_last_member_interval; - - if (!port) { -- if (mp->mglist && mp->timer_armed && -+ if (mp->mglist && - (timer_pending(&mp->timer) ? - time_after(mp->timer.expires, time) : - try_to_del_timer_sync(&mp->timer) >= 0)) { - mod_timer(&mp->timer, time); - } -+ -+ goto out; -+ } -+ -+ for (p = mlock_dereference(mp->ports, br); -+ p != NULL; -+ p = mlock_dereference(p->next, br)) { -+ if (p->port != port) -+ continue; -+ -+ if (!hlist_unhashed(&p->mglist) && -+ (timer_pending(&p->timer) ? -+ time_after(p->timer.expires, time) : -+ try_to_del_timer_sync(&p->timer) >= 0)) { -+ mod_timer(&p->timer, time); -+ } -+ -+ break; - } - out: - spin_unlock(&br->multicast_lock); -@@ -1798,7 +1806,6 @@ void br_multicast_stop(struct net_bridge *br) - hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], - hlist[ver]) { - del_timer(&mp->timer); -- mp->timer_armed = false; - call_rcu_bh(&mp->rcu, br_multicast_free_group); - } - } -diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h -index cde1eb1..aa05bd8 100644 ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -126,7 +126,6 @@ struct net_bridge_mdb_entry - struct timer_list timer; - struct br_ip addr; - bool mglist; -- bool timer_armed; - }; - - struct net_bridge_mdb_htable --- -1.7.11.7 - - -From 40420baad983147cd23e6de95c958c96b96be727 Mon Sep 17 00:00:00 2001 -From: Christophe Gouault -Date: Tue, 8 Oct 2013 17:21:22 +0200 -Subject: [PATCH 24/47] vti: get rid of nf mark rule in prerouting - -[ Upstream commit 7263a5187f9e9de45fcb51349cf0e031142c19a1 ] - -This patch fixes and improves the use of vti interfaces (while -lightly changing the way of configuring them). - -Currently: - -- it is necessary to identify and mark inbound IPsec - packets destined to each vti interface, via netfilter rules in - the mangle table at prerouting hook. - -- the vti module cannot retrieve the right tunnel in input since - commit b9959fd3: vti tunnels all have an i_key, but the tunnel lookup - is done with flag TUNNEL_NO_KEY, so there no chance to retrieve them. - -- the i_key is used by the outbound processing as a mark to lookup - for the right SP and SA bundle. - -This patch uses the o_key to store the vti mark (instead of i_key) and -enables: - -- to avoid the need for previously marking the inbound skbuffs via a - netfilter rule. -- to properly retrieve the right tunnel in input, only based on the IPsec - packet outer addresses. -- to properly perform an inbound policy check (using the tunnel o_key - as a mark). -- to properly perform an outbound SPD and SAD lookup (using the tunnel - o_key as a mark). -- to keep the current mark of the skbuff. The skbuff mark is neither - used nor changed by the vti interface. Only the vti interface o_key - is used. - -SAs have a wildcard mark. -SPs have a mark equal to the vti interface o_key. - -The vti interface must be created as follows (i_key = 0, o_key = mark): - - ip link add vti1 mode vti local 1.1.1.1 remote 2.2.2.2 okey 1 - -The SPs attached to vti1 must be created as follows (mark = vti1 o_key): - - ip xfrm policy add dir out mark 1 tmpl src 1.1.1.1 dst 2.2.2.2 \ - proto esp mode tunnel - ip xfrm policy add dir in mark 1 tmpl src 2.2.2.2 dst 1.1.1.1 \ - proto esp mode tunnel - -The SAs are created with the default wildcard mark. There is no -distinction between global vs. vti SAs. Just their addresses will -possibly link them to a vti interface: - - ip xfrm state add src 1.1.1.1 dst 2.2.2.2 proto esp spi 1000 mode tunnel \ - enc "cbc(aes)" "azertyuiopqsdfgh" - - ip xfrm state add src 2.2.2.2 dst 1.1.1.1 proto esp spi 2000 mode tunnel \ - enc "cbc(aes)" "sqbdhgqsdjqjsdfh" - -To avoid matching "global" (not vti) SPs in vti interfaces, global SPs -should no use the default wildcard mark, but explicitly match mark 0. - -To avoid a double SPD lookup in input and output (in global and vti SPDs), -the NOPOLICY and NOXFRM options should be set on the vti interfaces: - - echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_policy - echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_xfrm - -The outgoing traffic is steered to vti1 by a route via the vti interface: - - ip route add 192.168.0.0/16 dev vti1 - -The incoming IPsec traffic is steered to vti1 because its outer addresses -match the vti1 tunnel configuration. - -Signed-off-by: Christophe Gouault -Signed-off-by: David S. Miller ---- - net/ipv4/ip_vti.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c -index 17cc0ff..0656041 100644 ---- a/net/ipv4/ip_vti.c -+++ b/net/ipv4/ip_vti.c -@@ -285,8 +285,17 @@ static int vti_rcv(struct sk_buff *skb) - tunnel = vti_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); - if (tunnel != NULL) { - struct pcpu_tstats *tstats; -+ u32 oldmark = skb->mark; -+ int ret; - -- if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) -+ -+ /* temporarily mark the skb with the tunnel o_key, to -+ * only match policies with this mark. -+ */ -+ skb->mark = be32_to_cpu(tunnel->parms.o_key); -+ ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb); -+ skb->mark = oldmark; -+ if (!ret) - return -1; - - tstats = this_cpu_ptr(tunnel->dev->tstats); -@@ -295,7 +304,6 @@ static int vti_rcv(struct sk_buff *skb) - tstats->rx_bytes += skb->len; - u64_stats_update_end(&tstats->syncp); - -- skb->mark = 0; - secpath_reset(skb); - skb->dev = tunnel->dev; - return 1; -@@ -327,7 +335,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) - - memset(&fl4, 0, sizeof(fl4)); - flowi4_init_output(&fl4, tunnel->parms.link, -- be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos), -+ be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos), - RT_SCOPE_UNIVERSE, - IPPROTO_IPIP, 0, - dst, tiph->saddr, 0, 0); --- -1.7.11.7 - - -From d74d8a563ec79425464d7a8aeaa1796724fea7bc Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Thu, 10 Oct 2013 06:30:09 -0700 -Subject: [PATCH 25/47] l2tp: must disable bh before calling l2tp_xmit_skb() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 455cc32bf128e114455d11ad919321ab89a2c312 ] - -François Cachereul made a very nice bug report and suspected -the bh_lock_sock() / bh_unlok_sock() pair used in l2tp_xmit_skb() from -process context was not good. - -This problem was added by commit 6af88da14ee284aaad6e4326da09a89191ab6165 -("l2tp: Fix locking in l2tp_core.c"). - -l2tp_eth_dev_xmit() runs from BH context, so we must disable BH -from other l2tp_xmit_skb() users. - -[ 452.060011] BUG: soft lockup - CPU#1 stuck for 23s! [accel-pppd:6662] -[ 452.061757] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppoe pppox -ppp_generic slhc ipv6 ext3 mbcache jbd virtio_balloon xfs exportfs dm_mod -virtio_blk ata_generic virtio_net floppy ata_piix libata virtio_pci virtio_ring virtio [last unloaded: scsi_wait_scan] -[ 452.064012] CPU 1 -[ 452.080015] BUG: soft lockup - CPU#2 stuck for 23s! [accel-pppd:6643] -[ 452.080015] CPU 2 -[ 452.080015] -[ 452.080015] Pid: 6643, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs -[ 452.080015] RIP: 0010:[] [] do_raw_spin_lock+0x17/0x1f -[ 452.080015] RSP: 0018:ffff88007125fc18 EFLAGS: 00000293 -[ 452.080015] RAX: 000000000000aba9 RBX: ffffffff811d0703 RCX: 0000000000000000 -[ 452.080015] RDX: 00000000000000ab RSI: ffff8800711f6896 RDI: ffff8800745c8110 -[ 452.080015] RBP: ffff88007125fc18 R08: 0000000000000020 R09: 0000000000000000 -[ 452.080015] R10: 0000000000000000 R11: 0000000000000280 R12: 0000000000000286 -[ 452.080015] R13: 0000000000000020 R14: 0000000000000240 R15: 0000000000000000 -[ 452.080015] FS: 00007fdc0cc24700(0000) GS:ffff8800b6f00000(0000) knlGS:0000000000000000 -[ 452.080015] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 452.080015] CR2: 00007fdb054899b8 CR3: 0000000074404000 CR4: 00000000000006a0 -[ 452.080015] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -[ 452.080015] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 -[ 452.080015] Process accel-pppd (pid: 6643, threadinfo ffff88007125e000, task ffff8800b27e6dd0) -[ 452.080015] Stack: -[ 452.080015] ffff88007125fc28 ffffffff81256559 ffff88007125fc98 ffffffffa01b2bd1 -[ 452.080015] ffff88007125fc58 000000000000000c 00000000029490d0 0000009c71dbe25e -[ 452.080015] 000000000000005c 000000080000000e 0000000000000000 ffff880071170600 -[ 452.080015] Call Trace: -[ 452.080015] [] _raw_spin_lock+0xe/0x10 -[ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] -[ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] -[ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 -[ 452.080015] [] sock_sendmsg+0xa1/0xb6 -[ 452.080015] [] ? __schedule+0x5c1/0x616 -[ 452.080015] [] ? __dequeue_signal+0xb7/0x10c -[ 452.080015] [] ? fget_light+0x75/0x89 -[ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 -[ 452.080015] [] sys_sendto+0x10c/0x13b -[ 452.080015] [] system_call_fastpath+0x16/0x1b -[ 452.080015] Code: 81 48 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 <8a> 07 eb f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 -[ 452.080015] Call Trace: -[ 452.080015] [] _raw_spin_lock+0xe/0x10 -[ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] -[ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] -[ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 -[ 452.080015] [] sock_sendmsg+0xa1/0xb6 -[ 452.080015] [] ? __schedule+0x5c1/0x616 -[ 452.080015] [] ? __dequeue_signal+0xb7/0x10c -[ 452.080015] [] ? fget_light+0x75/0x89 -[ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 -[ 452.080015] [] sys_sendto+0x10c/0x13b -[ 452.080015] [] system_call_fastpath+0x16/0x1b -[ 452.064012] -[ 452.064012] Pid: 6662, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs -[ 452.064012] RIP: 0010:[] [] do_raw_spin_lock+0x19/0x1f -[ 452.064012] RSP: 0018:ffff8800b6e83ba0 EFLAGS: 00000297 -[ 452.064012] RAX: 000000000000aaa9 RBX: ffff8800b6e83b40 RCX: 0000000000000002 -[ 452.064012] RDX: 00000000000000aa RSI: 000000000000000a RDI: ffff8800745c8110 -[ 452.064012] RBP: ffff8800b6e83ba0 R08: 000000000000c802 R09: 000000000000001c -[ 452.064012] R10: ffff880071096c4e R11: 0000000000000006 R12: ffff8800b6e83b18 -[ 452.064012] R13: ffffffff8125d51e R14: ffff8800b6e83ba0 R15: ffff880072a589c0 -[ 452.064012] FS: 00007fdc0b81e700(0000) GS:ffff8800b6e80000(0000) knlGS:0000000000000000 -[ 452.064012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 452.064012] CR2: 0000000000625208 CR3: 0000000074404000 CR4: 00000000000006a0 -[ 452.064012] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -[ 452.064012] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 -[ 452.064012] Process accel-pppd (pid: 6662, threadinfo ffff88007129a000, task ffff8800744f7410) -[ 452.064012] Stack: -[ 452.064012] ffff8800b6e83bb0 ffffffff81256559 ffff8800b6e83bc0 ffffffff8121c64a -[ 452.064012] ffff8800b6e83bf0 ffffffff8121ec7a ffff880072a589c0 ffff880071096c62 -[ 452.064012] 0000000000000011 ffffffff81430024 ffff8800b6e83c80 ffffffff8121f276 -[ 452.064012] Call Trace: -[ 452.064012] -[ 452.064012] [] _raw_spin_lock+0xe/0x10 -[ 452.064012] [] spin_lock+0x9/0xb -[ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 -[ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae -[ 452.064012] [] ? raw_rcv+0xe9/0xf0 -[ 452.064012] [] udp_rcv+0x1a/0x1c -[ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 -[ 452.064012] [] ip_local_deliver+0x53/0x84 -[ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 -[ 452.064012] [] ip_rcv+0x210/0x269 -[ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb -[ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 -[ 452.064012] [] netif_receive_skb+0x57/0x5e -[ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b -[ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] -[ 452.064012] [] net_rx_action+0x73/0x184 -[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] -[ 452.064012] [] __do_softirq+0xc3/0x1a8 -[ 452.064012] [] ? ack_APIC_irq+0x10/0x12 -[ 452.064012] [] ? _raw_spin_lock+0xe/0x10 -[ 452.064012] [] call_softirq+0x1c/0x26 -[ 452.064012] [] do_softirq+0x45/0x82 -[ 452.064012] [] irq_exit+0x42/0x9c -[ 452.064012] [] do_IRQ+0x8e/0xa5 -[ 452.064012] [] common_interrupt+0x6e/0x6e -[ 452.064012] -[ 452.064012] [] ? kfree+0x8a/0xa3 -[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] -[ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] -[ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] -[ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 -[ 452.064012] [] sock_sendmsg+0xa1/0xb6 -[ 452.064012] [] ? __schedule+0x5c1/0x616 -[ 452.064012] [] ? __dequeue_signal+0xb7/0x10c -[ 452.064012] [] ? fget_light+0x75/0x89 -[ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 -[ 452.064012] [] sys_sendto+0x10c/0x13b -[ 452.064012] [] system_call_fastpath+0x16/0x1b -[ 452.064012] Code: 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 8a 07 f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 55 48 -[ 452.064012] Call Trace: -[ 452.064012] [] _raw_spin_lock+0xe/0x10 -[ 452.064012] [] spin_lock+0x9/0xb -[ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 -[ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae -[ 452.064012] [] ? raw_rcv+0xe9/0xf0 -[ 452.064012] [] udp_rcv+0x1a/0x1c -[ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 -[ 452.064012] [] ip_local_deliver+0x53/0x84 -[ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 -[ 452.064012] [] ip_rcv+0x210/0x269 -[ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb -[ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 -[ 452.064012] [] netif_receive_skb+0x57/0x5e -[ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b -[ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] -[ 452.064012] [] net_rx_action+0x73/0x184 -[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] -[ 452.064012] [] __do_softirq+0xc3/0x1a8 -[ 452.064012] [] ? ack_APIC_irq+0x10/0x12 -[ 452.064012] [] ? _raw_spin_lock+0xe/0x10 -[ 452.064012] [] call_softirq+0x1c/0x26 -[ 452.064012] [] do_softirq+0x45/0x82 -[ 452.064012] [] irq_exit+0x42/0x9c -[ 452.064012] [] do_IRQ+0x8e/0xa5 -[ 452.064012] [] common_interrupt+0x6e/0x6e -[ 452.064012] [] ? kfree+0x8a/0xa3 -[ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] -[ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] -[ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] -[ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 -[ 452.064012] [] sock_sendmsg+0xa1/0xb6 -[ 452.064012] [] ? __schedule+0x5c1/0x616 -[ 452.064012] [] ? __dequeue_signal+0xb7/0x10c -[ 452.064012] [] ? fget_light+0x75/0x89 -[ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 -[ 452.064012] [] sys_sendto+0x10c/0x13b -[ 452.064012] [] system_call_fastpath+0x16/0x1b - -Reported-by: François Cachereul -Tested-by: François Cachereul -Signed-off-by: Eric Dumazet -Cc: James Chapman -Signed-off-by: David S. Miller ---- - net/l2tp/l2tp_ppp.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c -index 5ebee2d..8c46b27 100644 ---- a/net/l2tp/l2tp_ppp.c -+++ b/net/l2tp/l2tp_ppp.c -@@ -353,7 +353,9 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh - goto error_put_sess_tun; - } - -+ local_bh_disable(); - l2tp_xmit_skb(session, skb, session->hdr_len); -+ local_bh_enable(); - - sock_put(ps->tunnel_sock); - sock_put(sk); -@@ -422,7 +424,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) - skb->data[0] = ppph[0]; - skb->data[1] = ppph[1]; - -+ local_bh_disable(); - l2tp_xmit_skb(session, skb, session->hdr_len); -+ local_bh_enable(); - - sock_put(sk_tun); - sock_put(sk); --- -1.7.11.7 - - -From 5bf1c228293765ff84e4121cf2f92395403b7e33 Mon Sep 17 00:00:00 2001 -From: stephen hemminger -Date: Sun, 6 Oct 2013 15:15:33 -0700 -Subject: [PATCH 26/47] netem: update backlog after drop -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 638a52b801e40ed276ceb69b73579ad99365361a ] - -When packet is dropped from rb-tree netem the backlog statistic should -also be updated. - -Reported-by: Сергеев Сергей -Signed-off-by: Stephen Hemminger -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller ---- - net/sched/sch_netem.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c -index 82f6016..7dc79940 100644 ---- a/net/sched/sch_netem.c -+++ b/net/sched/sch_netem.c -@@ -523,6 +523,7 @@ static unsigned int netem_drop(struct Qdisc *sch) - skb->next = NULL; - skb->prev = NULL; - len = qdisc_pkt_len(skb); -+ sch->qstats.backlog -= len; - kfree_skb(skb); - } - } --- -1.7.11.7 - - -From ddc30868db0e31c0c2ab4691131a050f9136f3bf Mon Sep 17 00:00:00 2001 -From: stephen hemminger -Date: Sun, 6 Oct 2013 15:16:49 -0700 -Subject: [PATCH 27/47] netem: free skb's in tree on reset -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit ff704050f2fc0f3382b5a70bba56a51a3feca79d ] - -Netem can leak memory because packets get stored in red-black -tree and it is not cleared on reset. - -Reported by: Сергеев Сергей -Signed-off-by: Stephen Hemminger -Signed-off-by: David S. Miller ---- - net/sched/sch_netem.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c -index 7dc79940..3626010 100644 ---- a/net/sched/sch_netem.c -+++ b/net/sched/sch_netem.c -@@ -358,6 +358,21 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche - return PSCHED_NS2TICKS(ticks); - } - -+static void tfifo_reset(struct Qdisc *sch) -+{ -+ struct netem_sched_data *q = qdisc_priv(sch); -+ struct rb_node *p; -+ -+ while ((p = rb_first(&q->t_root))) { -+ struct sk_buff *skb = netem_rb_to_skb(p); -+ -+ rb_erase(p, &q->t_root); -+ skb->next = NULL; -+ skb->prev = NULL; -+ kfree_skb(skb); -+ } -+} -+ - static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) - { - struct netem_sched_data *q = qdisc_priv(sch); -@@ -613,6 +628,7 @@ static void netem_reset(struct Qdisc *sch) - struct netem_sched_data *q = qdisc_priv(sch); - - qdisc_reset_queue(sch); -+ tfifo_reset(sch); - if (q->qdisc) - qdisc_reset(q->qdisc); - qdisc_watchdog_cancel(&q->watchdog); --- -1.7.11.7 - - -From c871c477136615360e283471acdb33df95d70470 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Salva=20Peir=C3=B3?= -Date: Fri, 11 Oct 2013 12:50:03 +0300 -Subject: [PATCH 28/47] farsync: fix info leak in ioctl - -[ Upstream commit 96b340406724d87e4621284ebac5e059d67b2194 ] - -The fst_get_iface() code fails to initialize the two padding bytes of -struct sync_serial_settings after the ->loopback member. Add an explicit -memset(0) before filling the structure to avoid the info leak. - -Signed-off-by: Dan Carpenter -Signed-off-by: David S. Miller ---- - drivers/net/wan/farsync.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c -index 3f0c4f2..bcfff0d 100644 ---- a/drivers/net/wan/farsync.c -+++ b/drivers/net/wan/farsync.c -@@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port, - } - - i = port->index; -+ memset(&sync, 0, sizeof(sync)); - sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed); - /* Lucky card and linux use same encoding here */ - sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == --- -1.7.11.7 - - -From e69ccba66791d0edd0d596520de268369aaab610 Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Mon, 30 Sep 2013 22:05:40 +0200 -Subject: [PATCH 29/47] unix_diag: fix info leak - -[ Upstream commit 6865d1e834be84ddd5808d93d5035b492346c64a ] - -When filling the netlink message we miss to wipe the pad field, -therefore leak one byte of heap memory to userland. Fix this by -setting pad to 0. - -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - net/unix/diag.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/unix/diag.c b/net/unix/diag.c -index d591091..86fa0f3 100644 ---- a/net/unix/diag.c -+++ b/net/unix/diag.c -@@ -124,6 +124,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r - rep->udiag_family = AF_UNIX; - rep->udiag_type = sk->sk_type; - rep->udiag_state = sk->sk_state; -+ rep->pad = 0; - rep->udiag_ino = sk_ino; - sock_diag_save_cookie(sk, rep->udiag_cookie); - --- -1.7.11.7 - - -From 00fa721e6873ccbb36fc008558bb7d23e9e3c21f Mon Sep 17 00:00:00 2001 -From: Mathias Krause -Date: Mon, 30 Sep 2013 22:03:07 +0200 -Subject: [PATCH 30/47] connector: use nlmsg_len() to check message length - -[ Upstream commit 162b2bedc084d2d908a04c93383ba02348b648b0 ] - -The current code tests the length of the whole netlink message to be -at least as long to fit a cn_msg. This is wrong as nlmsg_len includes -the length of the netlink message header. Use nlmsg_len() instead to -fix this "off-by-NLMSG_HDRLEN" size check. - -Cc: stable@vger.kernel.org # v2.6.14+ -Signed-off-by: Mathias Krause -Signed-off-by: David S. Miller ---- - drivers/connector/connector.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c -index 6ecfa75..0daa11e 100644 ---- a/drivers/connector/connector.c -+++ b/drivers/connector/connector.c -@@ -157,17 +157,18 @@ static int cn_call_callback(struct sk_buff *skb) - static void cn_rx_skb(struct sk_buff *__skb) - { - struct nlmsghdr *nlh; -- int err; - struct sk_buff *skb; -+ int len, err; - - skb = skb_get(__skb); - - if (skb->len >= NLMSG_HDRLEN) { - nlh = nlmsg_hdr(skb); -+ len = nlmsg_len(nlh); - -- if (nlh->nlmsg_len < sizeof(struct cn_msg) || -+ if (len < (int)sizeof(struct cn_msg) || - skb->len < nlh->nlmsg_len || -- nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { -+ len > CONNECTOR_MAX_MSG_SIZE) { - kfree_skb(skb); - return; - } --- -1.7.11.7 - - -From d99d51100021c9f8b335fc1931880618eaa448e3 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Sat, 12 Oct 2013 14:08:34 -0700 -Subject: [PATCH 31/47] bnx2x: record rx queue for LRO packets - -[ Upstream commit 60e66fee56b2256dcb1dc2ea1b2ddcb6e273857d ] - -RPS support is kind of broken on bnx2x, because only non LRO packets -get proper rx queue information. This triggers reorders, as it seems -bnx2x like to generate a non LRO packet for segment including TCP PUSH -flag : (this might be pure coincidence, but all the reorders I've -seen involve segments with a PUSH) - -11:13:34.335847 IP A > B: . 415808:447136(31328) ack 1 win 457 -11:13:34.335992 IP A > B: . 447136:448560(1424) ack 1 win 457 -11:13:34.336391 IP A > B: . 448560:479888(31328) ack 1 win 457 -11:13:34.336425 IP A > B: P 511216:512640(1424) ack 1 win 457 -11:13:34.336423 IP A > B: . 479888:511216(31328) ack 1 win 457 -11:13:34.336924 IP A > B: . 512640:543968(31328) ack 1 win 457 -11:13:34.336963 IP A > B: . 543968:575296(31328) ack 1 win 457 - -We must call skb_record_rx_queue() to properly give to RPS (and more -generally for TX queue selection on forward path) the receive queue -information. - -Similar fix is needed for skb_mark_napi_id(), but will be handled -in a separate patch to ease stable backports. - -Signed-off-by: Eric Dumazet -Cc: Willem de Bruijn -Cc: Eilon Greenstein -Acked-by: Dmitry Kravkov -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -index 0cc2611..4b0877e 100644 ---- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -@@ -676,6 +676,7 @@ static void bnx2x_gro_receive(struct bnx2x *bp, struct bnx2x_fastpath *fp, - } - } - #endif -+ skb_record_rx_queue(skb, fp->rx_queue); - napi_gro_receive(&fp->napi, skb); - } - --- -1.7.11.7 - - -From 3f1db36c01909701d0e34cd2413a1127e144bcc3 Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Tue, 15 Oct 2013 11:18:58 +0800 -Subject: [PATCH 32/47] virtio-net: don't respond to cpu hotplug notifier if - we're not ready - -[ Upstream commit 3ab098df35f8b98b6553edc2e40234af512ba877 ] - -We're trying to re-configure the affinity unconditionally in cpu hotplug -callback. This may lead the issue during resuming from s3/s4 since - -- virt queues haven't been allocated at that time. -- it's unnecessary since thaw method will re-configure the affinity. - -Fix this issue by checking the config_enable and do nothing is we're not ready. - -The bug were introduced by commit 8de4b2f3ae90c8fc0f17eeaab87d5a951b66ee17 -(virtio-net: reset virtqueue affinity when doing cpu hotplug). - -Cc: Rusty Russell -Cc: Michael S. Tsirkin -Cc: Wanlong Gao -Acked-by: Michael S. Tsirkin -Reviewed-by: Wanlong Gao -Signed-off-by: Jason Wang -Signed-off-by: David S. Miller ---- - drivers/net/virtio_net.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c -index 3d2a90a..43a71d9 100644 ---- a/drivers/net/virtio_net.c -+++ b/drivers/net/virtio_net.c -@@ -1094,6 +1094,11 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, - { - struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); - -+ mutex_lock(&vi->config_lock); -+ -+ if (!vi->config_enable) -+ goto done; -+ - switch(action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: -@@ -1106,6 +1111,9 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, - default: - break; - } -+ -+done: -+ mutex_unlock(&vi->config_lock); - return NOTIFY_OK; - } - --- -1.7.11.7 - - -From 24ef3b7cfd16ce5ac263deebfecb661d1c784670 Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Tue, 15 Oct 2013 11:18:59 +0800 -Subject: [PATCH 33/47] virtio-net: refill only when device is up during - setting queues - -[ Upstream commit 35ed159bfd96a7547ec277ed8b550c7cbd9841b6 ] - -We used to schedule the refill work unconditionally after changing the -number of queues. This may lead an issue if the device is not -up. Since we only try to cancel the work in ndo_stop(), this may cause -the refill work still work after removing the device. Fix this by only -schedule the work when device is up. - -The bug were introduce by commit 9b9cd8024a2882e896c65222aa421d461354e3f2. -(virtio-net: fix the race between channels setting and refill) - -Cc: Rusty Russell -Cc: Michael S. Tsirkin -Signed-off-by: Jason Wang -Signed-off-by: David S. Miller ---- - drivers/net/virtio_net.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c -index 43a71d9..1d01534 100644 ---- a/drivers/net/virtio_net.c -+++ b/drivers/net/virtio_net.c -@@ -916,7 +916,9 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) - return -EINVAL; - } else { - vi->curr_queue_pairs = queue_pairs; -- schedule_delayed_work(&vi->refill, 0); -+ /* virtnet_open() will refill when device is going to up. */ -+ if (dev->flags & IFF_UP) -+ schedule_delayed_work(&vi->refill, 0); - } - - return 0; -@@ -1714,7 +1716,9 @@ static int virtnet_restore(struct virtio_device *vdev) - vi->config_enable = true; - mutex_unlock(&vi->config_lock); - -+ rtnl_lock(); - virtnet_set_queues(vi, vi->curr_queue_pairs); -+ rtnl_unlock(); - - return 0; - } --- -1.7.11.7 - - -From d616bd8bf902f82ea742462a29bf4080aaa8f497 Mon Sep 17 00:00:00 2001 -From: Vlad Yasevich -Date: Tue, 15 Oct 2013 14:57:45 -0400 -Subject: [PATCH 34/47] bridge: Correctly clamp MAX forward_delay when - enabling STP - -[ Upstream commit 4b6c7879d84ad06a2ac5b964808ed599187a188d ] - -Commit be4f154d5ef0ca147ab6bcd38857a774133f5450 - bridge: Clamp forward_delay when enabling STP -had a typo when attempting to clamp maximum forward delay. - -It is possible to set bridge_forward_delay to be higher then -permitted maximum when STP is off. When turning STP on, the -higher then allowed delay has to be clamed down to max value. - -CC: Herbert Xu -CC: Stephen Hemminger -Signed-off-by: Vlad Yasevich -Reviewed-by: Veaceslav Falico -Acked-by: Herbert Xu -Signed-off-by: David S. Miller ---- - net/bridge/br_stp_if.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c -index 108084a..656a6f3 100644 ---- a/net/bridge/br_stp_if.c -+++ b/net/bridge/br_stp_if.c -@@ -134,7 +134,7 @@ static void br_stp_start(struct net_bridge *br) - - if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) - __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); -- else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY) -+ else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY) - __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); - - if (r == 0) { --- -1.7.11.7 - - -From 803490b7c577add0b976aa08e4bbfdd95f505270 Mon Sep 17 00:00:00 2001 -From: Vlad Yasevich -Date: Tue, 15 Oct 2013 22:01:29 -0400 -Subject: [PATCH 35/47] net: dst: provide accessor function to dst->xfrm - -[ Upstream commit e87b3998d795123b4139bc3f25490dd236f68212 ] - -dst->xfrm is conditionally defined. Provide accessor funtion that -is always available. - -Signed-off-by: Vlad Yasevich -Acked-by: Neil Horman -Signed-off-by: David S. Miller ---- - include/net/dst.h | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/include/net/dst.h b/include/net/dst.h -index 1f8fd10..e0c97f5 100644 ---- a/include/net/dst.h -+++ b/include/net/dst.h -@@ -477,10 +477,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, - { - return dst_orig; - } -+ -+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) -+{ -+ return NULL; -+} -+ - #else - extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, - const struct flowi *fl, struct sock *sk, - int flags); -+ -+/* skb attached with this dst needs transformation if dst->xfrm is valid */ -+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) -+{ -+ return dst->xfrm; -+} - #endif - - #endif /* _NET_DST_H */ --- -1.7.11.7 - - -From 371a65903ccb75fc71fd42b30a310a28c42e54a3 Mon Sep 17 00:00:00 2001 -From: Fan Du -Date: Tue, 15 Oct 2013 22:01:30 -0400 -Subject: [PATCH 36/47] sctp: Use software crc32 checksum when xfrm transform - will happen. - -[ Upstream commit 27127a82561a2a3ed955ce207048e1b066a80a2a ] - -igb/ixgbe have hardware sctp checksum support, when this feature is enabled -and also IPsec is armed to protect sctp traffic, ugly things happened as -xfrm_output checks CHECKSUM_PARTIAL to do checksum operation(sum every thing -up and pack the 16bits result in the checksum field). The result is fail -establishment of sctp communication. - -Cc: Neil Horman -Cc: Steffen Klassert -Signed-off-by: Fan Du -Signed-off-by: Vlad Yasevich -Acked-by: Neil Horman -Signed-off-by: David S. Miller ---- - net/sctp/output.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/net/sctp/output.c b/net/sctp/output.c -index a46d1eb..a06a9b6 100644 ---- a/net/sctp/output.c -+++ b/net/sctp/output.c -@@ -542,7 +542,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) - * by CRC32-C as described in . - */ - if (!sctp_checksum_disable) { -- if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) { -+ if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || -+ (dst_xfrm(dst) != NULL)) { - __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); - - /* 3) Put the resultant value into the checksum field in the --- -1.7.11.7 - - -From 9067790bb296fb5818894222d7e85407238e9843 Mon Sep 17 00:00:00 2001 -From: Vlad Yasevich -Date: Tue, 15 Oct 2013 22:01:31 -0400 -Subject: [PATCH 37/47] sctp: Perform software checksum if packet has to be - fragmented. - -[ Upstream commit d2dbbba77e95dff4b4f901fee236fef6d9552072 ] - -IP/IPv6 fragmentation knows how to compute only TCP/UDP checksum. -This causes problems if SCTP packets has to be fragmented and -ipsummed has been set to PARTIAL due to checksum offload support. -This condition can happen when retransmitting after MTU discover, -or when INIT or other control chunks are larger then MTU. -Check for the rare fragmentation condition in SCTP and use software -checksum calculation in this case. - -CC: Fan Du -Signed-off-by: Vlad Yasevich -Acked-by: Neil Horman -Signed-off-by: David S. Miller ---- - net/sctp/output.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/sctp/output.c b/net/sctp/output.c -index a06a9b6..013a07d 100644 ---- a/net/sctp/output.c -+++ b/net/sctp/output.c -@@ -543,7 +543,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) - */ - if (!sctp_checksum_disable) { - if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || -- (dst_xfrm(dst) != NULL)) { -+ (dst_xfrm(dst) != NULL) || packet->ipfragok) { - __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); - - /* 3) Put the resultant value into the checksum field in the --- -1.7.11.7 - - -From 22e825ed8144360271614511563166f37fef9f90 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Salva=20Peir=C3=B3?= -Date: Wed, 16 Oct 2013 12:46:50 +0200 -Subject: [PATCH 38/47] wanxl: fix info leak in ioctl -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ Upstream commit 2b13d06c9584b4eb773f1e80bbaedab9a1c344e1 ] - -The wanxl_ioctl() code fails to initialize the two padding bytes of -struct sync_serial_settings after the ->loopback member. Add an explicit -memset(0) before filling the structure to avoid the info leak. - -Signed-off-by: Salva Peiró -Signed-off-by: David S. Miller ---- - drivers/net/wan/wanxl.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c -index 6a24a5a..4c0a697 100644 ---- a/drivers/net/wan/wanxl.c -+++ b/drivers/net/wan/wanxl.c -@@ -355,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } -+ memset(&line, 0, sizeof(line)); - line.clock_type = get_status(port)->clocking; - line.clock_rate = 0; - line.loopback = 0; --- -1.7.11.7 - - -From b16dd2cff7a4eb3881f43371d71ed242332877dc Mon Sep 17 00:00:00 2001 -From: Vasundhara Volam -Date: Thu, 17 Oct 2013 11:47:14 +0530 -Subject: [PATCH 39/47] be2net: pass if_id for v1 and V2 versions of TX_CREATE - cmd - -[ Upstream commit 0fb88d61bc60779dde88b0fc268da17eb81d0412 ] - -It is a required field for all TX_CREATE cmd versions > 0. -This fixes a driver initialization failure, caused by recent SH-R Firmwares -(versions > 10.0.639.0) failing the TX_CREATE cmd when if_id field is -not passed. - -Signed-off-by: Sathya Perla -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c -index 8ec5d74..13ac104 100644 ---- a/drivers/net/ethernet/emulex/benet/be_cmds.c -+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c -@@ -1150,7 +1150,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) - - if (lancer_chip(adapter)) { - req->hdr.version = 1; -- req->if_id = cpu_to_le16(adapter->if_handle); - } else if (BEx_chip(adapter)) { - if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) - req->hdr.version = 2; -@@ -1158,6 +1157,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) - req->hdr.version = 2; - } - -+ if (req->hdr.version > 0) -+ req->if_id = cpu_to_le16(adapter->if_handle); - req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); - req->ulp_num = BE_ULP1_NUM; - req->type = BE_ETH_TX_RING_TYPE_STANDARD; --- -1.7.11.7 - - -From 9829aac8208e7a31e4e42e7d2e7e165593c05202 Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Thu, 17 Oct 2013 22:51:31 +0200 -Subject: [PATCH 40/47] net: unix: inherit SOCK_PASS{CRED, SEC} flags from - socket to fix race - -[ Upstream commit 90c6bd34f884cd9cee21f1d152baf6c18bcac949 ] - -In the case of credentials passing in unix stream sockets (dgram -sockets seem not affected), we get a rather sparse race after -commit 16e5726 ("af_unix: dont send SCM_CREDENTIALS by default"). - -We have a stream server on receiver side that requests credential -passing from senders (e.g. nc -U). Since we need to set SO_PASSCRED -on each spawned/accepted socket on server side to 1 first (as it's -not inherited), it can happen that in the time between accept() and -setsockopt() we get interrupted, the sender is being scheduled and -continues with passing data to our receiver. At that time SO_PASSCRED -is neither set on sender nor receiver side, hence in cmsg's -SCM_CREDENTIALS we get eventually pid:0, uid:65534, gid:65534 -(== overflow{u,g}id) instead of what we actually would like to see. - -On the sender side, here nc -U, the tests in maybe_add_creds() -invoked through unix_stream_sendmsg() would fail, as at that exact -time, as mentioned, the sender has neither SO_PASSCRED on his side -nor sees it on the server side, and we have a valid 'other' socket -in place. Thus, sender believes it would just look like a normal -connection, not needing/requesting SO_PASSCRED at that time. - -As reverting 16e5726 would not be an option due to the significant -performance regression reported when having creds always passed, -one way/trade-off to prevent that would be to set SO_PASSCRED on -the listener socket and allow inheriting these flags to the spawned -socket on server side in accept(). It seems also logical to do so -if we'd tell the listener socket to pass those flags onwards, and -would fix the race. - -Before, strace: - -recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], - msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, - cmsg_type=SCM_CREDENTIALS{pid=0, uid=65534, gid=65534}}, - msg_flags=0}, 0) = 5 - -After, strace: - -recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], - msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, - cmsg_type=SCM_CREDENTIALS{pid=11580, uid=1000, gid=1000}}, - msg_flags=0}, 0) = 5 - -Signed-off-by: Daniel Borkmann -Cc: Eric Dumazet -Cc: Eric W. Biederman -Signed-off-by: David S. Miller ---- - net/unix/af_unix.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c -index c4ce243..e64bbcf 100644 ---- a/net/unix/af_unix.c -+++ b/net/unix/af_unix.c -@@ -1246,6 +1246,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) - return 0; - } - -+static void unix_sock_inherit_flags(const struct socket *old, -+ struct socket *new) -+{ -+ if (test_bit(SOCK_PASSCRED, &old->flags)) -+ set_bit(SOCK_PASSCRED, &new->flags); -+ if (test_bit(SOCK_PASSSEC, &old->flags)) -+ set_bit(SOCK_PASSSEC, &new->flags); -+} -+ - static int unix_accept(struct socket *sock, struct socket *newsock, int flags) - { - struct sock *sk = sock->sk; -@@ -1280,6 +1289,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) - /* attach accepted sock to socket */ - unix_state_lock(tsk); - newsock->state = SS_CONNECTED; -+ unix_sock_inherit_flags(sock, newsock); - sock_graft(tsk, newsock); - unix_state_unlock(tsk); - return 0; --- -1.7.11.7 - - -From 7b48750febb4c3387db39fd0b547936c53ba7364 Mon Sep 17 00:00:00 2001 -From: Seif Mazareeb -Date: Thu, 17 Oct 2013 20:33:21 -0700 -Subject: [PATCH 41/47] net: fix cipso packet validation when !NETLABEL - -[ Upstream commit f2e5ddcc0d12f9c4c7b254358ad245c9dddce13b ] - -When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop -forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel -crash in an SMP system, since the CPU executing this function will -stall /not respond to IPIs. - -This problem can be reproduced by running the IP Stack Integrity Checker -(http://isic.sourceforge.net) using the following command on a Linux machine -connected to DUT: - -"icmpsic -s rand -d -r 123456" -wait (1-2 min) - -Signed-off-by: Seif Mazareeb -Acked-by: Paul Moore -Signed-off-by: David S. Miller ---- - include/net/cipso_ipv4.h | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h -index a7a683e..a8c2ef6 100644 ---- a/include/net/cipso_ipv4.h -+++ b/include/net/cipso_ipv4.h -@@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, - unsigned char err_offset = 0; - u8 opt_len = opt[1]; - u8 opt_iter; -+ u8 tag_len; - - if (opt_len < 8) { - err_offset = 1; -@@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, - } - - for (opt_iter = 6; opt_iter < opt_len;) { -- if (opt[opt_iter + 1] > (opt_len - opt_iter)) { -+ tag_len = opt[opt_iter + 1]; -+ if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) { - err_offset = opt_iter + 1; - goto out; - } -- opt_iter += opt[opt_iter + 1]; -+ opt_iter += tag_len; - } - - out: --- -1.7.11.7 - - -From 27e33640a8905b1aeefe9998242551caf24e84a6 Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Tue, 22 Oct 2013 00:07:47 +0200 -Subject: [PATCH 42/47] inet: fix possible memory corruption with UDP_CORK and - UFO - -[ This is a simplified -stable version of a set of upstream commits. ] - -This is a replacement patch only for stable which does fix the problems -handled by the following two commits in -net: - -"ip_output: do skb ufo init for peeked non ufo skb as well" (e93b7d748be887cd7639b113ba7d7ef792a7efb9) -"ip6_output: do skb ufo init for peeked non ufo skb as well" (c547dbf55d5f8cf615ccc0e7265e98db27d3fb8b) - -Three frames are written on a corked udp socket for which the output -netdevice has UFO enabled. If the first and third frame are smaller than -the mtu and the second one is bigger, we enqueue the second frame with -skb_append_datato_frags without initializing the gso fields. This leads -to the third frame appended regulary and thus constructing an invalid skb. - -This fixes the problem by always using skb_append_datato_frags as soon -as the first frag got enqueued to the skb without marking the packet -as SKB_GSO_UDP. - -The problem with only two frames for ipv6 was fixed by "ipv6: udp -packets following an UFO enqueued packet need also be handled by UFO" -(2811ebac2521ceac84f2bdae402455baa6a7fb47). - -Cc: Jiri Pirko -Cc: Eric Dumazet -Cc: David Miller -Signed-off-by: Hannes Frederic Sowa ---- - include/linux/skbuff.h | 5 +++++ - net/ipv4/ip_output.c | 2 +- - net/ipv6/ip6_output.c | 2 +- - 3 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index 3b71a4e..6bd165b 100644 ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -1316,6 +1316,11 @@ static inline int skb_pagelen(const struct sk_buff *skb) - return len + skb_headlen(skb); - } - -+static inline bool skb_has_frags(const struct sk_buff *skb) -+{ -+ return skb_shinfo(skb)->nr_frags; -+} -+ - /** - * __skb_fill_page_desc - initialise a paged fragment in an skb - * @skb: buffer containing fragment to be initialised -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c -index a04d872..7f4ab5d 100644 ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c -@@ -836,7 +836,7 @@ static int __ip_append_data(struct sock *sk, - csummode = CHECKSUM_PARTIAL; - - cork->length += length; -- if (((length > mtu) || (skb && skb_is_gso(skb))) && -+ if (((length > mtu) || (skb && skb_has_frags(skb))) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { - err = ip_ufo_append_data(sk, queue, getfrag, from, length, -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 44df1c9..2e542d0 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1252,7 +1252,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, - skb = skb_peek_tail(&sk->sk_write_queue); - cork->length += length; - if (((length > mtu) || -- (skb && skb_is_gso(skb))) && -+ (skb && skb_has_frags(skb))) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO)) { - err = ip6_ufo_append_data(sk, getfrag, from, length, --- -1.7.11.7 - - -From 689f77d13532698739438b2288ec8eac2f667584 Mon Sep 17 00:00:00 2001 -From: Julian Anastasov -Date: Sun, 20 Oct 2013 15:43:03 +0300 -Subject: [PATCH 43/47] ipv6: always prefer rt6i_gateway if present - -[ Upstream commit 96dc809514fb2328605198a0602b67554d8cce7b ] - -In v3.9 6fd6ce2056de2709 ("ipv6: Do not depend on rt->n in -ip6_finish_output2()." changed the behaviour of ip6_finish_output2() -such that the recently introduced rt6_nexthop() is used -instead of an assigned neighbor. - -As rt6_nexthop() prefers rt6i_gateway only for gatewayed -routes this causes a problem for users like IPVS, xt_TEE and -RAW(hdrincl) if they want to use different address for routing -compared to the destination address. - -Another case is when redirect can create RTF_DYNAMIC -route without RTF_GATEWAY flag, we ignore the rt6i_gateway -in rt6_nexthop(). - -Fix the above problems by considering the rt6i_gateway if -present, so that traffic routed to address on local subnet is -not wrongly diverted to the destination address. - -Thanks to Simon Horman and Phil Oester for spotting the -problematic commit. - -Thanks to Hannes Frederic Sowa for his review and help in testing. - -Reported-by: Phil Oester -Reported-by: Mark Brooks -Signed-off-by: Julian Anastasov -Acked-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - include/net/ip6_route.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h -index f667248..0aaf0ec 100644 ---- a/include/net/ip6_route.h -+++ b/include/net/ip6_route.h -@@ -198,7 +198,7 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) - - static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) - { -- if (rt->rt6i_flags & RTF_GATEWAY) -+ if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) - return &rt->rt6i_gateway; - return dest; - } --- -1.7.11.7 - - -From 471dd605429d6645f990becd29c877740d3b32e7 Mon Sep 17 00:00:00 2001 -From: Julian Anastasov -Date: Sun, 20 Oct 2013 15:43:04 +0300 -Subject: [PATCH 44/47] ipv6: fill rt6i_gateway with nexthop address - -[ Upstream commit 550bab42f83308c9d6ab04a980cc4333cef1c8fa ] - -Make sure rt6i_gateway contains nexthop information in -all routes returned from lookup or when routes are directly -attached to skb for generated ICMP packets. - -The effect of this patch should be a faster version of -rt6_nexthop() and the consideration of local addresses as -nexthop. - -Signed-off-by: Julian Anastasov -Acked-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - include/net/ip6_route.h | 6 ++---- - net/ipv6/ip6_output.c | 4 ++-- - net/ipv6/route.c | 8 ++++++-- - 3 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h -index 0aaf0ec..c7b8860 100644 ---- a/include/net/ip6_route.h -+++ b/include/net/ip6_route.h -@@ -196,11 +196,9 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) - skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); - } - --static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) -+static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt) - { -- if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) -- return &rt->rt6i_gateway; -- return dest; -+ return &rt->rt6i_gateway; - } - - #endif -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 2e542d0..5b25f85 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -130,7 +130,7 @@ static int ip6_finish_output2(struct sk_buff *skb) - } - - rcu_read_lock_bh(); -- nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); -+ nexthop = rt6_nexthop((struct rt6_info *)dst); - neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); - if (unlikely(!neigh)) - neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); -@@ -899,7 +899,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, - */ - rt = (struct rt6_info *) *dst; - rcu_read_lock_bh(); -- n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr)); -+ n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt)); - err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0; - rcu_read_unlock_bh(); - -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 8d9a93ed..08e6c40 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -852,7 +852,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, - if (ort->rt6i_dst.plen != 128 && - ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) - rt->rt6i_flags |= RTF_ANYCAST; -- rt->rt6i_gateway = *daddr; - } - - rt->rt6i_flags |= RTF_CACHE; -@@ -1270,6 +1269,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, - rt->dst.flags |= DST_HOST; - rt->dst.output = ip6_output; - atomic_set(&rt->dst.__refcnt, 1); -+ rt->rt6i_gateway = fl6->daddr; - rt->rt6i_dst.addr = fl6->daddr; - rt->rt6i_dst.plen = 128; - rt->rt6i_idev = idev; -@@ -1824,7 +1824,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, - in6_dev_hold(rt->rt6i_idev); - rt->dst.lastuse = jiffies; - -- rt->rt6i_gateway = ort->rt6i_gateway; -+ if (ort->rt6i_flags & RTF_GATEWAY) -+ rt->rt6i_gateway = ort->rt6i_gateway; -+ else -+ rt->rt6i_gateway = *dest; - rt->rt6i_flags = ort->rt6i_flags; - if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == - (RTF_DEFAULT | RTF_ADDRCONF)) -@@ -2111,6 +2114,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, - else - rt->rt6i_flags |= RTF_LOCAL; - -+ rt->rt6i_gateway = *addr; - rt->rt6i_dst.addr = *addr; - rt->rt6i_dst.plen = 128; - rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); --- -1.7.11.7 - - -From d01c3be45be54261f56ba63197d94e3d756befdf Mon Sep 17 00:00:00 2001 -From: Julian Anastasov -Date: Sun, 20 Oct 2013 15:43:05 +0300 -Subject: [PATCH 45/47] netfilter: nf_conntrack: fix rt6i_gateway checks for - H.323 helper - -[ Upstream commit 56e42441ed54b092d6c7411138ce60d049e7c731 ] - -Now when rt6_nexthop() can return nexthop address we can use it -for proper nexthop comparison of directly connected destinations. -For more information refer to commit bbb5823cf742a7 -("netfilter: nf_conntrack: fix rt_gateway checks for H.323 helper"). - -Signed-off-by: Julian Anastasov -Acked-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - net/netfilter/nf_conntrack_h323_main.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c -index bdebd03..70866d1 100644 ---- a/net/netfilter/nf_conntrack_h323_main.c -+++ b/net/netfilter/nf_conntrack_h323_main.c -@@ -778,8 +778,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, - flowi6_to_flowi(&fl1), false)) { - if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, - flowi6_to_flowi(&fl2), false)) { -- if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, -- sizeof(rt1->rt6i_gateway)) && -+ if (ipv6_addr_equal(rt6_nexthop(rt1), -+ rt6_nexthop(rt2)) && - rt1->dst.dev == rt2->dst.dev) - ret = 1; - dst_release(&rt2->dst); --- -1.7.11.7 - - -From 1d98ddb501bedeee62c916d3d6999109f0a22198 Mon Sep 17 00:00:00 2001 -From: Hannes Frederic Sowa -Date: Mon, 21 Oct 2013 06:17:15 +0200 -Subject: [PATCH 46/47] ipv6: probe routes asynchronous in rt6_probe - -[ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ] - -Routes need to be probed asynchronous otherwise the call stack gets -exhausted when the kernel attemps to deliver another skb inline, like -e.g. xt_TEE does, and we probe at the same time. - -We update neigh->updated still at once, otherwise we would send to -many probes. - -Cc: Julian Anastasov -Signed-off-by: Hannes Frederic Sowa -Signed-off-by: David S. Miller ---- - net/ipv6/route.c | 38 +++++++++++++++++++++++++++++++------- - 1 file changed, 31 insertions(+), 7 deletions(-) - -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 08e6c40..1e32d5c 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -477,6 +477,24 @@ out: - } - - #ifdef CONFIG_IPV6_ROUTER_PREF -+struct __rt6_probe_work { -+ struct work_struct work; -+ struct in6_addr target; -+ struct net_device *dev; -+}; -+ -+static void rt6_probe_deferred(struct work_struct *w) -+{ -+ struct in6_addr mcaddr; -+ struct __rt6_probe_work *work = -+ container_of(w, struct __rt6_probe_work, work); -+ -+ addrconf_addr_solict_mult(&work->target, &mcaddr); -+ ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL); -+ dev_put(work->dev); -+ kfree(w); -+} -+ - static void rt6_probe(struct rt6_info *rt) - { - struct neighbour *neigh; -@@ -500,17 +518,23 @@ static void rt6_probe(struct rt6_info *rt) - - if (!neigh || - time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { -- struct in6_addr mcaddr; -- struct in6_addr *target; -+ struct __rt6_probe_work *work; -+ -+ work = kmalloc(sizeof(*work), GFP_ATOMIC); - -- if (neigh) { -+ if (neigh && work) - neigh->updated = jiffies; -+ -+ if (neigh) - write_unlock(&neigh->lock); -- } - -- target = (struct in6_addr *)&rt->rt6i_gateway; -- addrconf_addr_solict_mult(target, &mcaddr); -- ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); -+ if (work) { -+ INIT_WORK(&work->work, rt6_probe_deferred); -+ work->target = rt->rt6i_gateway; -+ dev_hold(rt->dst.dev); -+ work->dev = rt->dst.dev; -+ schedule_work(&work->work); -+ } - } else { - out: - write_unlock(&neigh->lock); --- -1.7.11.7 - - -From d7710f5e65b37ec3ac09dde758141e81fa47315d Mon Sep 17 00:00:00 2001 -From: Mariusz Ceier -Date: Mon, 21 Oct 2013 19:45:04 +0200 -Subject: [PATCH 47/47] davinci_emac.c: Fix IFF_ALLMULTI setup - -[ Upstream commit d69e0f7ea95fef8059251325a79c004bac01f018 ] - -When IFF_ALLMULTI flag is set on interface and IFF_PROMISC isn't, -emac_dev_mcast_set should only enable RX of multicasts and reset -MACHASH registers. - -It does this, but afterwards it either sets up multicast MACs -filtering or disables RX of multicasts and resets MACHASH registers -again, rendering IFF_ALLMULTI flag useless. - -This patch fixes emac_dev_mcast_set, so that multicast MACs filtering and -disabling of RX of multicasts are skipped when IFF_ALLMULTI flag is set. - -Tested with kernel 2.6.37. - -Signed-off-by: Mariusz Ceier -Acked-by: Mugunthan V N -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/ti/davinci_emac.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c -index 1a222bce..45c167f 100644 ---- a/drivers/net/ethernet/ti/davinci_emac.c -+++ b/drivers/net/ethernet/ti/davinci_emac.c -@@ -876,8 +876,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) - netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { - mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); - emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); -- } -- if (!netdev_mc_empty(ndev)) { -+ } else if (!netdev_mc_empty(ndev)) { - struct netdev_hw_addr *ha; - - mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); --- -1.7.11.7 - diff --git a/sources b/sources index 91571dae8..585450e45 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -c44ebb225fe9956b636b79ab6b61aa42 patch-3.11.6.xz +42361474ed56948d8f52e72958b2cdf0 patch-3.11.7.xz From 288eb79a53ec43ae2037de5c93b325f0c2af6c78 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Nov 2013 08:46:19 -0500 Subject: [PATCH 457/492] Add patch to fix iwlwifi queue settings backtrace (rhbz 1025769) --- ...dont-override-mac80211-queue-setting.patch | 98 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-dvm-dont-override-mac80211-queue-setting.patch diff --git a/iwlwifi-dvm-dont-override-mac80211-queue-setting.patch b/iwlwifi-dvm-dont-override-mac80211-queue-setting.patch new file mode 100644 index 000000000..ce5f00b0b --- /dev/null +++ b/iwlwifi-dvm-dont-override-mac80211-queue-setting.patch @@ -0,0 +1,98 @@ +From f6b129527ca15bae29ffb9417ddaa1c9d99ffc5d Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Tue, 15 Oct 2013 19:04:54 +0000 +Subject: iwlwifi: dvm: don't override mac80211's queue setting + +Since we set IEEE80211_HW_QUEUE_CONTROL, we can let +mac80211 do the queue assignement and don't need to +override its decisions. +While reassiging the same values is harmless of course, +it triggered a WARNING when iwlwifi and mac80211 came +to different conclusions. This happened when mac80211 set +IEEE80211_TX_CTL_SEND_AFTER_DTIM, but didn't route the +packet to the cab_queue because no stations were asleep. + +iwlwifi should not override mac80211's decicions for +offchannel packets and packets to be sent after DTIM, +but it should override mac80211's decision for AMPDUs +since we have a special queue for them. So for AMPDU, +we still override info->hw_queue by the AMPDU queue. + +This avoids: +------------[ cut here ]------------ +WARNING: CPU: 0 PID: 2531 at drivers/net/wireless/iwlwifi/dvm/tx.c:456 iwlagn_tx_skb+0x6c5/0x883() +Modules linked in: +CPU: 0 PID: 2531 Comm: hostapd Not tainted 3.12.0-rc5+ #1 +Hardware name: /D53427RKE, BIOS RKPPT10H.86A.0017.2013.0425.1251 04/25/2013 + 0000000000000000 0000000000000009 ffffffff8189aa62 0000000000000000 + ffffffff8105a4f2 ffff880058339a48 ffffffff815f8a04 0000000000000000 + ffff8800560097b0 0000000000000208 0000000000000000 ffff8800561a9e5e +Call Trace: + [] ? dump_stack+0x41/0x51 + [] ? warn_slowpath_common+0x78/0x90 + [] ? iwlagn_tx_skb+0x6c5/0x883 + [] ? iwlagn_tx_skb+0x6c5/0x883 + [] ? put_cred+0x15/0x15 + [] ? iwlagn_mac_tx+0x19/0x2f + [] ? __ieee80211_tx+0x226/0x29b + [] ? ieee80211_tx+0xa6/0xb5 + [] ? ieee80211_monitor_start_xmit+0x1e9/0x204 + [] ? dev_hard_start_xmit+0x271/0x3ec + [] ? sch_direct_xmit+0x66/0x164 + [] ? dev_queue_xmit+0x1e5/0x3c8 + [] ? packet_sendmsg+0xac5/0xb3d + [] ? sock_sendmsg+0x37/0x52 + [] ? __do_fault+0x338/0x36b + [] ? verify_iovec+0x44/0x94 + [] ? ___sys_sendmsg+0x1f1/0x283 + [] ? __inode_wait_for_writeback+0x67/0xae + [] ? __cache_free.isra.46+0x178/0x187 + [] ? kmem_cache_free+0x44/0x84 + [] ? dentry_kill+0x13d/0x149 + [] ? dput+0xe5/0xef + [] ? fget_light+0x2e/0x7c + [] ? __sys_sendmsg+0x39/0x57 + [] ? system_call_fastpath+0x16/0x1b +---[ end trace 1b3eb79359c1d1e6 ]--- + +Reported-by: Sander Eikelenboom +Reviewed-by: Johannes Berg +Signed-off-by: Johannes Berg +--- +diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c +index da442b8..1fef524 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -433,27 +433,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, + /* Copy MAC header from skb into command buffer */ + memcpy(tx_cmd->hdr, hdr, hdr_len); + ++ txq_id = info->hw_queue; ++ + if (is_agg) + txq_id = priv->tid_data[sta_id][tid].agg.txq_id; + else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + /* +- * Send this frame after DTIM -- there's a special queue +- * reserved for this for contexts that support AP mode. +- */ +- txq_id = ctx->mcast_queue; +- +- /* + * The microcode will clear the more data + * bit in the last frame it transmits. + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); +- } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) +- txq_id = IWL_AUX_QUEUE; +- else +- txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; ++ } + +- WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue); + WARN_ON_ONCE(is_agg && + priv->queue_to_mac80211[txq_id] != info->hw_queue); + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index a00c5a2b0..70e9ffc82 100644 --- a/kernel.spec +++ b/kernel.spec @@ -799,6 +799,9 @@ Patch25139: net-flow_dissector-fail-on-evil-iph-ihl.patch Patch25140: 0001-Revert-epoll-use-freezable-blocking-call.patch Patch25141: 0001-Revert-select-use-freezable-blocking-call.patch +#rhbz 1025769 +Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch + # END OF PATCH DEFINITIONS %endif @@ -1535,6 +1538,9 @@ ApplyPatch net-flow_dissector-fail-on-evil-iph-ihl.patch ApplyPatch 0001-Revert-epoll-use-freezable-blocking-call.patch ApplyPatch 0001-Revert-select-use-freezable-blocking-call.patch +#rhbz 1025769 +ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch + # END OF PATCH APPLICATIONS %endif @@ -2376,7 +2382,10 @@ fi # ||----w | # || || %changelog -* Mon Nov 04 2013 Justin M. Forbes - 3.11.7-100 +* Mon Nov 04 2013 Josh Boyer - 3.11.7-100 +- Add patch to fix iwlwifi queue settings backtrace (rhbz 1025769) + +* Mon Nov 04 2013 Justin M. Forbes - Linux v3.11.7 * Fri Nov 01 2013 Josh Boyer - 3.11.6-101 From f2fe333330fe139d91c033313b12b1ba83fe8042 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 9 Nov 2013 09:30:06 -0500 Subject: [PATCH 458/492] Add qxl backport fixes from Dave Airlie --- drm-qxl-backport-fixes-for-Fedora.patch | 226 ++++++++++++++++++++++++ kernel.spec | 7 + 2 files changed, 233 insertions(+) create mode 100644 drm-qxl-backport-fixes-for-Fedora.patch diff --git a/drm-qxl-backport-fixes-for-Fedora.patch b/drm-qxl-backport-fixes-for-Fedora.patch new file mode 100644 index 000000000..c46060d64 --- /dev/null +++ b/drm-qxl-backport-fixes-for-Fedora.patch @@ -0,0 +1,226 @@ +Bugzilla: N/A +Upstream-status: Queued for 3.13 + +From db8edc33193879f39c1b52521e20f4d6eb4e9858 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Fri, 08 Nov 2013 06:36:45 +0000 +Subject: drm/qxl: backport fixes for Fedora + +This pulls these changes from drm-next back into Fedora. + +drm/qxl: prefer the monitor config resolution (b080742393e2c1) +drm/qxl: remove unnecessary check (a40a60d912a101e8dfb08ee1) +drm/qxl: fix disabling extra monitors from client (5cab51cb3381157) +qxl: avoid an oops in the deferred io code. (cc87509d87696d7cd39) +drm/qxl: support 64bit surface bar (35541782dcc1e502) +qxl: add a connector property to denote hotplug should rescan modes. (4695b03970df37) + +Signed-off-by: Dave Airlie +--- +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index 835caba..1d975eb 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -110,7 +110,9 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev) + drm_helper_hpd_irq_event(qdev->ddev); + } + +-static int qxl_add_monitors_config_modes(struct drm_connector *connector) ++static int qxl_add_monitors_config_modes(struct drm_connector *connector, ++ unsigned *pwidth, ++ unsigned *pheight) + { + struct drm_device *dev = connector->dev; + struct qxl_device *qdev = dev->dev_private; +@@ -126,11 +128,15 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector) + mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false, + false); + mode->type |= DRM_MODE_TYPE_PREFERRED; ++ *pwidth = head->width; ++ *pheight = head->height; + drm_mode_probed_add(connector, mode); + return 1; + } + +-static int qxl_add_common_modes(struct drm_connector *connector) ++static int qxl_add_common_modes(struct drm_connector *connector, ++ unsigned pwidth, ++ unsigned pheight) + { + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode = NULL; +@@ -159,12 +165,9 @@ static int qxl_add_common_modes(struct drm_connector *connector) + }; + + for (i = 0; i < ARRAY_SIZE(common_modes); i++) { +- if (common_modes[i].w < 320 || common_modes[i].h < 200) +- continue; +- + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, + 60, false, false, false); +- if (common_modes[i].w == 1024 && common_modes[i].h == 768) ++ if (common_modes[i].w == pwidth && common_modes[i].h == pheight) + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + } +@@ -720,16 +723,18 @@ static int qxl_conn_get_modes(struct drm_connector *connector) + { + int ret = 0; + struct qxl_device *qdev = connector->dev->dev_private; ++ unsigned pwidth = 1024; ++ unsigned pheight = 768; + + DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config); + /* TODO: what should we do here? only show the configured modes for the + * device, or allow the full list, or both? */ + if (qdev->monitors_config && qdev->monitors_config->count) { +- ret = qxl_add_monitors_config_modes(connector); ++ ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight); + if (ret < 0) + return ret; + } +- ret += qxl_add_common_modes(connector); ++ ret += qxl_add_common_modes(connector, pwidth, pheight); + return ret; + } + +@@ -793,7 +798,10 @@ static enum drm_connector_status qxl_conn_detect( + qdev->client_monitors_config->count > output->index && + qxl_head_enabled(&qdev->client_monitors_config->heads[output->index])); + +- DRM_DEBUG("\n"); ++ DRM_DEBUG("#%d connected: %d\n", output->index, connected); ++ if (!connected) ++ qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0); ++ + return connected ? connector_status_connected + : connector_status_disconnected; + } +@@ -835,8 +843,21 @@ static const struct drm_encoder_funcs qxl_enc_funcs = { + .destroy = qxl_enc_destroy, + }; + ++static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev) ++{ ++ if (qdev->hotplug_mode_update_property) ++ return 0; ++ ++ qdev->hotplug_mode_update_property = ++ drm_property_create_range(qdev->ddev, DRM_MODE_PROP_IMMUTABLE, ++ "hotplug_mode_update", 0, 1); ++ ++ return 0; ++} ++ + static int qdev_output_init(struct drm_device *dev, int num_output) + { ++ struct qxl_device *qdev = dev->dev_private; + struct qxl_output *qxl_output; + struct drm_connector *connector; + struct drm_encoder *encoder; +@@ -863,6 +884,8 @@ static int qdev_output_init(struct drm_device *dev, int num_output) + drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs); + drm_connector_helper_add(connector, &qxl_connector_helper_funcs); + ++ drm_object_attach_property(&connector->base, ++ qdev->hotplug_mode_update_property, 0); + drm_sysfs_connector_add(connector); + return 0; + } +@@ -975,6 +998,9 @@ int qxl_modeset_init(struct qxl_device *qdev) + qdev->ddev->mode_config.max_height = 8192; + + qdev->ddev->mode_config.fb_base = qdev->vram_base; ++ ++ qxl_mode_create_hotplug_mode_update_property(qdev); ++ + for (i = 0 ; i < qxl_num_crtc; ++i) { + qdev_crtc_init(qdev->ddev, i); + qdev_output_init(qdev->ddev, i); +diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h +index 7e96f4f..18c599d 100644 +--- a/drivers/gpu/drm/qxl/qxl_drv.h ++++ b/drivers/gpu/drm/qxl/qxl_drv.h +@@ -323,6 +323,8 @@ struct qxl_device { + struct work_struct gc_work; + + struct work_struct fb_work; ++ ++ struct drm_property *hotplug_mode_update_property; + }; + + /* forward declaration for QXL_INFO_IO */ +diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c +index 88722f2..f437b30 100644 +--- a/drivers/gpu/drm/qxl/qxl_fb.c ++++ b/drivers/gpu/drm/qxl/qxl_fb.c +@@ -108,7 +108,7 @@ static void qxl_fb_dirty_flush(struct fb_info *info) + u32 x1, x2, y1, y2; + + /* TODO: hard coding 32 bpp */ +- int stride = qfbdev->qfb.base.pitches[0] * 4; ++ int stride = qfbdev->qfb.base.pitches[0]; + + x1 = qfbdev->dirty.x1; + x2 = qfbdev->dirty.x2; +diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c +index 9e8da9e..e0ddd5b 100644 +--- a/drivers/gpu/drm/qxl/qxl_kms.c ++++ b/drivers/gpu/drm/qxl/qxl_kms.c +@@ -120,7 +120,7 @@ int qxl_device_init(struct qxl_device *qdev, + struct pci_dev *pdev, + unsigned long flags) + { +- int r; ++ int r, sb; + + qdev->dev = &pdev->dev; + qdev->ddev = ddev; +@@ -136,21 +136,39 @@ int qxl_device_init(struct qxl_device *qdev, + qdev->rom_base = pci_resource_start(pdev, 2); + qdev->rom_size = pci_resource_len(pdev, 2); + qdev->vram_base = pci_resource_start(pdev, 0); +- qdev->surfaceram_base = pci_resource_start(pdev, 1); +- qdev->surfaceram_size = pci_resource_len(pdev, 1); + qdev->io_base = pci_resource_start(pdev, 3); + + qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0)); +- qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size); +- DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n", ++ ++ if (pci_resource_len(pdev, 4) > 0) { ++ /* 64bit surface bar present */ ++ sb = 4; ++ qdev->surfaceram_base = pci_resource_start(pdev, sb); ++ qdev->surfaceram_size = pci_resource_len(pdev, sb); ++ qdev->surface_mapping = ++ io_mapping_create_wc(qdev->surfaceram_base, ++ qdev->surfaceram_size); ++ } ++ if (qdev->surface_mapping == NULL) { ++ /* 64bit surface bar not present (or mapping failed) */ ++ sb = 1; ++ qdev->surfaceram_base = pci_resource_start(pdev, sb); ++ qdev->surfaceram_size = pci_resource_len(pdev, sb); ++ qdev->surface_mapping = ++ io_mapping_create_wc(qdev->surfaceram_base, ++ qdev->surfaceram_size); ++ } ++ ++ DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n", + (unsigned long long)qdev->vram_base, + (unsigned long long)pci_resource_end(pdev, 0), + (int)pci_resource_len(pdev, 0) / 1024 / 1024, + (int)pci_resource_len(pdev, 0) / 1024, + (unsigned long long)qdev->surfaceram_base, +- (unsigned long long)pci_resource_end(pdev, 1), ++ (unsigned long long)pci_resource_end(pdev, sb), + (int)qdev->surfaceram_size / 1024 / 1024, +- (int)qdev->surfaceram_size / 1024); ++ (int)qdev->surfaceram_size / 1024, ++ (sb == 4) ? "64bit" : "32bit"); + + qdev->rom = ioremap(qdev->rom_base, qdev->rom_size); + if (!qdev->rom) { +-- +cgit v0.9.0.2-2-gbebe diff --git a/kernel.spec b/kernel.spec index 70e9ffc82..0dcb1956d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,6 +802,8 @@ Patch25141: 0001-Revert-select-use-freezable-blocking-call.patch #rhbz 1025769 Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch +Patch25143: drm-qxl-backport-fixes-for-Fedora.patch + # END OF PATCH DEFINITIONS %endif @@ -1541,6 +1543,8 @@ ApplyPatch 0001-Revert-select-use-freezable-blocking-call.patch #rhbz 1025769 ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch +ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch + # END OF PATCH APPLICATIONS %endif @@ -2382,6 +2386,9 @@ fi # ||----w | # || || %changelog +* Sat Nov 09 2013 Josh Boyer +- Add qxl backport fixes from Dave Airlie + * Mon Nov 04 2013 Josh Boyer - 3.11.7-100 - Add patch to fix iwlwifi queue settings backtrace (rhbz 1025769) From 99f4e6a8b21c182fba9634b15f2afdd508b3b867 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 9 Nov 2013 09:38:53 -0500 Subject: [PATCH 459/492] Add patch from Daniel Stone to avoid high order allocations in evdev --- ...k-to-vmalloc-for-client-event-buffer.patch | 64 +++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 69 insertions(+) create mode 100644 Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch diff --git a/Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch b/Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch new file mode 100644 index 000000000..da1b92ed8 --- /dev/null +++ b/Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch @@ -0,0 +1,64 @@ +From 92eb77d0ffbaa71b501a0a8dabf09a351bf4267f Mon Sep 17 00:00:00 2001 +From: Daniel Stone +Date: Thu, 31 Oct 2013 07:25:34 +0000 +Subject: Input: evdev - fall back to vmalloc for client event buffer + +evdev always tries to allocate the event buffer for clients using +kzalloc rather than vmalloc, presumably to avoid mapping overhead where +possible. However, drivers like bcm5974, which claims support for +reporting 16 fingers simultaneously, can have an extraordinarily large +buffer. The resultant contiguous order-4 allocation attempt fails due +to fragmentation, and the device is thus unusable until reboot. + +Try kzalloc if we can to avoid the mapping overhead, but if that fails, +fall back to vzalloc. + +Signed-off-by: Daniel Stone +Signed-off-by: Dmitry Torokhov +--- +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index b6ded17..a06e125 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -18,6 +18,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -369,7 +371,11 @@ static int evdev_release(struct inode *inode, struct file *file) + mutex_unlock(&evdev->mutex); + + evdev_detach_client(evdev, client); +- kfree(client); ++ ++ if (is_vmalloc_addr(client)) ++ vfree(client); ++ else ++ kfree(client); + + evdev_close_device(evdev); + +@@ -389,12 +395,14 @@ static int evdev_open(struct inode *inode, struct file *file) + { + struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); + unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); ++ unsigned int size = sizeof(struct evdev_client) + ++ bufsize * sizeof(struct input_event); + struct evdev_client *client; + int error; + +- client = kzalloc(sizeof(struct evdev_client) + +- bufsize * sizeof(struct input_event), +- GFP_KERNEL); ++ client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); ++ if (!client) ++ client = vzalloc(size); + if (!client) + return -ENOMEM; + +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 0dcb1956d..eba97f365 100644 --- a/kernel.spec +++ b/kernel.spec @@ -804,6 +804,8 @@ Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch Patch25143: drm-qxl-backport-fixes-for-Fedora.patch +Patch25144: Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch + # END OF PATCH DEFINITIONS %endif @@ -1545,6 +1547,8 @@ ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch +ApplyPatch Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch + # END OF PATCH APPLICATIONS %endif @@ -2387,6 +2391,7 @@ fi # || || %changelog * Sat Nov 09 2013 Josh Boyer +- Add patch from Daniel Stone to avoid high order allocations in evdev - Add qxl backport fixes from Dave Airlie * Mon Nov 04 2013 Josh Boyer - 3.11.7-100 From 73a4ef0af14373b55cfea6843196315dc7c84533 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 13 Nov 2013 09:56:12 -0600 Subject: [PATCH 460/492] Linux v3.11.8 --- ...rt-epoll-use-freezable-blocking-call.patch | 49 -- ...t-select-use-freezable-blocking-call.patch | 55 -- ...00pci-Use-PCI-MSIs-whenever-possible.patch | 59 --- fix-buslogic.patch | 121 ----- intel-3.12-stable-fixes.patch | 488 ------------------ kernel.spec | 25 +- sources | 2 +- 7 files changed, 5 insertions(+), 794 deletions(-) delete mode 100644 0001-Revert-epoll-use-freezable-blocking-call.patch delete mode 100644 0001-Revert-select-use-freezable-blocking-call.patch delete mode 100644 Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch delete mode 100644 fix-buslogic.patch diff --git a/0001-Revert-epoll-use-freezable-blocking-call.patch b/0001-Revert-epoll-use-freezable-blocking-call.patch deleted file mode 100644 index eda58ee28..000000000 --- a/0001-Revert-epoll-use-freezable-blocking-call.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c511851de162e8ec03d62e7d7feecbdf590d881d Mon Sep 17 00:00:00 2001 -From: "Rafael J. Wysocki" -Date: Tue, 29 Oct 2013 13:12:56 +0100 -Subject: [PATCH] Revert "epoll: use freezable blocking call" - -This reverts commit 1c441e921201 (epoll: use freezable blocking call) -which is reported to cause user space memory corruption to happen -after suspend to RAM. - -Since it appears to be extremely difficult to root cause this -problem, it is best to revert the offending commit and try to address -the original issue in a better way later. - -References: https://bugzilla.kernel.org/show_bug.cgi?id=61781 -Reported-by: Natrio -Reported-by: Jeff Pohlmeyer -Bisected-by: Leo Wolf -Fixes: 1c441e921201 (epoll: use freezable blocking call) -Signed-off-by: Rafael J. Wysocki -Cc: 3.11+ # 3.11+ ---- - fs/eventpoll.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index 473e09d..810c28f 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -1605,8 +1604,7 @@ fetch_events: - } - - spin_unlock_irqrestore(&ep->lock, flags); -- if (!freezable_schedule_hrtimeout_range(to, slack, -- HRTIMER_MODE_ABS)) -+ if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) - timed_out = 1; - - spin_lock_irqsave(&ep->lock, flags); --- -1.8.3.1 - diff --git a/0001-Revert-select-use-freezable-blocking-call.patch b/0001-Revert-select-use-freezable-blocking-call.patch deleted file mode 100644 index 0ab5152a0..000000000 --- a/0001-Revert-select-use-freezable-blocking-call.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 59612d187912750f416fbffe0c00bc0811c54ab5 Mon Sep 17 00:00:00 2001 -From: "Rafael J. Wysocki" -Date: Tue, 29 Oct 2013 23:43:08 +0100 -Subject: [PATCH] Revert "select: use freezable blocking call" - -This reverts commit 9745cdb36da8 (select: use freezable blocking call) -that triggers problems during resume from suspend to RAM on Paul Bolle's -32-bit x86 machines. Paul says: - - Ever since I tried running (release candidates of) v3.11 on the two - working i686s I still have lying around I ran into issues on resuming - from suspend. Reverting 9745cdb36da8 (select: use freezable blocking - call) resolves those issues. - - Resuming from suspend on i686 on (release candidates of) v3.11 and - later triggers issues like: - - traps: systemd[1] general protection ip:b738e490 sp:bf882fc0 error:0 in libc-2.16.so[b731c000+1b0000] - - and - - traps: rtkit-daemon[552] general protection ip:804d6e5 sp:b6cb32f0 error:0 in rtkit-daemon[8048000+d000] - - Once I hit the systemd error I can only get out of the mess that the - system is at that point by power cycling it. - -Since we are reverting another freezer-related change causing similar -problems to happen, this one should be reverted as well. - -References: https://lkml.org/lkml/2013/10/29/583 -Reported-by: Paul Bolle -Fixes: 9745cdb36da8 (select: use freezable blocking call) -Signed-off-by: Rafael J. Wysocki -Cc: 3.11+ # 3.11+ ---- - fs/select.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/fs/select.c b/fs/select.c -index 35d4adc7..dfd5cb1 100644 ---- a/fs/select.c -+++ b/fs/select.c -@@ -238,8 +238,7 @@ int poll_schedule_timeout(struct poll_wqueues *pwq, int state, - - set_current_state(state); - if (!pwq->triggered) -- rc = freezable_schedule_hrtimeout_range(expires, slack, -- HRTIMER_MODE_ABS); -+ rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS); - __set_current_state(TASK_RUNNING); - - /* --- -1.8.3.1 - diff --git a/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch b/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch deleted file mode 100644 index 4e48620ec..000000000 --- a/Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch +++ /dev/null @@ -1,59 +0,0 @@ -This reverts commit 9483f40d8d01918b399b4e24d0c1111db0afffeb. - -Some devices stop to connect with above commit, see: -https://bugzilla.kernel.org/show_bug.cgi?id=61621 - -Since there is no clear benefit of having MSI enabled, just revert -change to fix the problem. - -Cc: stable@vger.kernel.org # 3.11+ -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rt2x00/rt2x00pci.c | 9 +-------- - 1 file changed, 1 insertion(+), 8 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c -index 76d95de..dc49e52 100644 ---- a/drivers/net/wireless/rt2x00/rt2x00pci.c -+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c -@@ -105,13 +105,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) - goto exit_release_regions; - } - -- pci_enable_msi(pci_dev); -- - hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); - if (!hw) { - rt2x00_probe_err("Failed to allocate hardware\n"); - retval = -ENOMEM; -- goto exit_disable_msi; -+ goto exit_release_regions; - } - - pci_set_drvdata(pci_dev, hw); -@@ -152,9 +150,6 @@ exit_free_reg: - exit_free_device: - ieee80211_free_hw(hw); - --exit_disable_msi: -- pci_disable_msi(pci_dev); -- - exit_release_regions: - pci_release_regions(pci_dev); - -@@ -179,8 +174,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) - rt2x00pci_free_reg(rt2x00dev); - ieee80211_free_hw(hw); - -- pci_disable_msi(pci_dev); -- - /* - * Free the PCI device data. - */ --- -1.8.3.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/fix-buslogic.patch b/fix-buslogic.patch deleted file mode 100644 index 0862d00aa..000000000 --- a/fix-buslogic.patch +++ /dev/null @@ -1,121 +0,0 @@ -This fixes an oops caused by buslogic driver when initializing a BusLogic -MultiMaster adapter. Initialization code used scope of a variable -incorrectly which created a NULL pointer. Oops message is below: - -BUG: unable to handle kernel NULL pointer dereference at 0000000c -IP: [] blogic_init_mm_probeinfo.isra.17+0x20a/0x583 -*pde = 00000000 -Oops: 002 [#1] PREEMPT SMP -Modules linked in: -CPU: 1 PID: 1 Comm: swapper/0 Not tainted 3.11.1.puz1 #1 -Hardware name: /Canterwood, BIOS 6.00 PG 05/16/2003 -task: f7050000 ti: f7054000 task.ti: f7054000 -EIP: 0060:[] EFLAGS: 00010246 CPU:1 -EIP is at blogic_init_mm_probeinfo.isra.17+0x20a/0x583 -EAX: 00000013 EBX: 00000000 ECX: 00000000 EDX: f8001000 -ESI: f71cb800 EDI: f7388000 EBP: 00007800 ESP: f7055c84 - DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 -CR0: 8005003b CR2: 0000000c CR3: 0154f000 CR4: 000007d0 -Stack: - 0000001c 00000000 c11a59f6 f7055c98 00008130 ffffffff ffffffff 00000000 - 00000003 00000000 00000000 00000000 00000013 f8001000 00000001 000003d0 - 00000000 00000000 00000000 c14e3f84 f78803c8 00000000 f738c000 000000e9 -Call Trace: - [] ? pci_get_subsys+0x33/0x38 - [] ? blogic_init_probeinfo_list+0x4b/0x19e - [] ? __alloc_pages_nodemask+0xe3/0x623 - [] ? __alloc_pages_nodemask+0xe3/0x623 - [] ? sysfs_link_sibling+0x61/0x8d - [] ? kmem_cache_alloc+0x8b/0xb5 - [] ? blogic_init+0xa1/0x10e8 - [] ? sysfs_add_one+0x10/0x9d - [] ? sysfs_addrm_finish+0x12/0x85 - [] ? sysfs_do_create_link_sd+0x9d/0x1b4 - [] ? blk_register_queue+0x69/0xb3 - [] ? sysfs_create_link+0x1a/0x2c - [] ? add_disk+0x1a1/0x3c7 - [] ? klist_next+0x60/0xc3 - [] ? scsi_dh_detach+0x68/0x68 - [] ? bus_for_each_dev+0x51/0x61 - [] ? do_one_initcall+0x22/0x12c - [] ? __proc_create+0x8c/0xba - [] ? blogic_setup+0x5f6/0x5f6 - [] ? repair_env_string+0xf/0x4d - [] ? do_early_param+0x71/0x71 - [] ? parse_args+0x21f/0x33d - [] ? kernel_init_freeable+0xdf/0x17d - [] ? do_early_param+0x71/0x71 - [] ? kernel_init+0x8/0xc0 - [] ? ret_from_kernel_thread+0x6/0x28 - [] ? ret_from_kernel_thread+0x1b/0x28 - [] ? rest_init+0x6c/0x6c -Code: 89 44 24 10 0f b6 44 24 3d 89 44 24 0c c7 44 24 08 00 00 00 00 c7 44 24 04 38 62 46 c1 c7 04 24 02 00 00 00 e8 78 13 d2 ff 31 db <89> 6b 0c b0 20 89 ea ee - c7 44 24 08 04 00 00 00 8d 44 24 4c 89 -EIP: [] blogic_init_mm_probeinfo.isra.17+0x20a/0x583 SS:ESP 0068:f7055c84 -CR2: 000000000000000c ----[ end trace 17f45f5196d40487 ]--- -Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000009 - -Signed-off-by: Khalid Aziz -Cc: # 3.11.x -Cc: Khalid Aziz -Reported-by: Pierre Uszynski -Tested-by: Pierre Uszynski ---- - drivers/scsi/BusLogic.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c -index feab3a5..757eb07 100644 ---- a/drivers/scsi/BusLogic.c -+++ b/drivers/scsi/BusLogic.c -@@ -696,7 +696,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) - while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, - pci_device)) != NULL) { -- struct blogic_adapter *adapter = adapter; -+ struct blogic_adapter *host_adapter = adapter; - struct blogic_adapter_info adapter_info; - enum blogic_isa_ioport mod_ioaddr_req; - unsigned char bus; -@@ -744,9 +744,9 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) - known and enabled, note that the particular Standard ISA I/O - Address should not be probed. - */ -- adapter->io_addr = io_addr; -- blogic_intreset(adapter); -- if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, -+ host_adapter->io_addr = io_addr; -+ blogic_intreset(host_adapter); -+ if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, - &adapter_info, sizeof(adapter_info)) == - sizeof(adapter_info)) { - if (adapter_info.isa_port < 6) -@@ -762,7 +762,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) - I/O Address assigned at system initialization. - */ - mod_ioaddr_req = BLOGIC_IO_DISABLE; -- blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, -+ blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, - sizeof(mod_ioaddr_req), NULL, 0); - /* - For the first MultiMaster Host Adapter enumerated, -@@ -779,12 +779,12 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) - - fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45; - fetch_localram.count = sizeof(autoscsi_byte45); -- blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, -+ blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM, - &fetch_localram, sizeof(fetch_localram), - &autoscsi_byte45, - sizeof(autoscsi_byte45)); -- blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id, -- sizeof(id)); -+ blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0, -+ &id, sizeof(id)); - if (id.fw_ver_digit1 == '5') - force_scan_order = - autoscsi_byte45.force_scan_order; --- -1.7.10.4 - diff --git a/intel-3.12-stable-fixes.patch b/intel-3.12-stable-fixes.patch index 35335423e..24a80dc0f 100644 --- a/intel-3.12-stable-fixes.patch +++ b/intel-3.12-stable-fixes.patch @@ -1,254 +1,3 @@ -From 39bb622a9804de9fa51cae31f07104a19067483a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= -Date: Mon, 21 Oct 2013 10:52:06 +0300 -Subject: [PATCH 1/5] drm/i915: Add support for pipe_bpp readout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On CTG+ read out the pipe bpp setting from hardware and fill it into -pipe config. Also check it appropriately. - -v2: Don't do the pipe_bpp extraction inside the PCH only code block on - ILK+. - Avoid the PIPECONF read as we already have read it for the - PIPECONF_EANBLE check. - -Note: This is already in drm-intel-next-queued as -commit 42571aefafb1d330ef84eb29418832f72e7dfb4c -Author: Ville Syrjälä -Date: Fri Sep 6 23:29:00 2013 +0300 - - drm/i915: Add support for pipe_bpp readout - -but is needed for the following bugfix. - -Signed-off-by: Ville Syrjälä -Reviewed-by: Jani Nikula -Cc: stable@vger.kernel.org -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_ddi.c | 17 +++++++++++++++++ - drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 53 insertions(+) - -diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c -index b042ee5..83e413b 100644 ---- a/drivers/gpu/drm/i915/intel_ddi.c -+++ b/drivers/gpu/drm/i915/intel_ddi.c -@@ -1280,6 +1280,23 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, - flags |= DRM_MODE_FLAG_NVSYNC; - - pipe_config->adjusted_mode.flags |= flags; -+ -+ switch (temp & TRANS_DDI_BPC_MASK) { -+ case TRANS_DDI_BPC_6: -+ pipe_config->pipe_bpp = 18; -+ break; -+ case TRANS_DDI_BPC_8: -+ pipe_config->pipe_bpp = 24; -+ break; -+ case TRANS_DDI_BPC_10: -+ pipe_config->pipe_bpp = 30; -+ break; -+ case TRANS_DDI_BPC_12: -+ pipe_config->pipe_bpp = 36; -+ break; -+ default: -+ break; -+ } - } - - static void intel_ddi_destroy(struct drm_encoder *encoder) -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 90a7c17..4aaccd3 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -4943,6 +4943,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, - if (!(tmp & PIPECONF_ENABLE)) - return false; - -+ if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { -+ switch (tmp & PIPECONF_BPC_MASK) { -+ case PIPECONF_6BPC: -+ pipe_config->pipe_bpp = 18; -+ break; -+ case PIPECONF_8BPC: -+ pipe_config->pipe_bpp = 24; -+ break; -+ case PIPECONF_10BPC: -+ pipe_config->pipe_bpp = 30; -+ break; -+ default: -+ break; -+ } -+ } -+ - intel_get_pipe_timings(crtc, pipe_config); - - i9xx_get_pfit_config(crtc, pipe_config); -@@ -5821,6 +5837,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, - if (!(tmp & PIPECONF_ENABLE)) - return false; - -+ switch (tmp & PIPECONF_BPC_MASK) { -+ case PIPECONF_6BPC: -+ pipe_config->pipe_bpp = 18; -+ break; -+ case PIPECONF_8BPC: -+ pipe_config->pipe_bpp = 24; -+ break; -+ case PIPECONF_10BPC: -+ pipe_config->pipe_bpp = 30; -+ break; -+ case PIPECONF_12BPC: -+ pipe_config->pipe_bpp = 36; -+ break; -+ default: -+ break; -+ } -+ - if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { - struct intel_shared_dpll *pll; - -@@ -8147,6 +8180,9 @@ intel_pipe_config_compare(struct drm_device *dev, - PIPE_CONF_CHECK_X(dpll_hw_state.fp0); - PIPE_CONF_CHECK_X(dpll_hw_state.fp1); - -+ if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) -+ PIPE_CONF_CHECK_I(pipe_bpp); -+ - #undef PIPE_CONF_CHECK_X - #undef PIPE_CONF_CHECK_I - #undef PIPE_CONF_CHECK_FLAGS --- -1.8.3.1 - - -From b59da942a708f7cf1c421a7cb666f98fd8172208 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= -Date: Tue, 24 Sep 2013 14:24:05 +0300 -Subject: [PATCH 2/5] drm/i915: Add HSW CRT output readout support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Call intel_ddi_get_config() to get the pipe_bpp settings from -DDI. - -The sync polarity settings from DDI are irrelevant for CRT -output, so override them with data from the ADPA register. - -Note: This is already merged in drm-intel-next-queued as - -commit 6801c18c0a43386bb44712cbc028a7e05adb9f0d -Author: Ville Syrjälä -Date: Tue Sep 24 14:24:05 2013 +0300 - - drm/i915: Add HSW CRT output readout support - -but is required for the following edp bpp bugfix. - -v2: Extract intel_crt_get_flags() - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69691 -Tested-by: Qingshuai Tian -Signed-off-by: Ville Syrjälä -Cc: stable@vger.kernel.org -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_crt.c | 30 ++++++++++++++++++++++++++---- - drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- - drivers/gpu/drm/i915/intel_drv.h | 2 ++ - 3 files changed, 30 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c -index 3acec8c..6aa6ebd 100644 ---- a/drivers/gpu/drm/i915/intel_crt.c -+++ b/drivers/gpu/drm/i915/intel_crt.c -@@ -84,8 +84,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, - return true; - } - --static void intel_crt_get_config(struct intel_encoder *encoder, -- struct intel_crtc_config *pipe_config) -+static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) - { - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crt *crt = intel_encoder_to_crt(encoder); -@@ -103,7 +102,27 @@ static void intel_crt_get_config(struct intel_encoder *encoder, - else - flags |= DRM_MODE_FLAG_NVSYNC; - -- pipe_config->adjusted_mode.flags |= flags; -+ return flags; -+} -+ -+static void intel_crt_get_config(struct intel_encoder *encoder, -+ struct intel_crtc_config *pipe_config) -+{ -+ struct drm_device *dev = encoder->base.dev; -+ -+ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); -+} -+ -+static void hsw_crt_get_config(struct intel_encoder *encoder, -+ struct intel_crtc_config *pipe_config) -+{ -+ intel_ddi_get_config(encoder, pipe_config); -+ -+ pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | -+ DRM_MODE_FLAG_NHSYNC | -+ DRM_MODE_FLAG_PVSYNC | -+ DRM_MODE_FLAG_NVSYNC); -+ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); - } - - /* Note: The caller is required to filter out dpms modes not supported by the -@@ -802,7 +821,10 @@ void intel_crt_init(struct drm_device *dev) - crt->base.compute_config = intel_crt_compute_config; - crt->base.disable = intel_disable_crt; - crt->base.enable = intel_enable_crt; -- crt->base.get_config = intel_crt_get_config; -+ if (IS_HASWELL(dev)) -+ crt->base.get_config = hsw_crt_get_config; -+ else -+ crt->base.get_config = intel_crt_get_config; - if (I915_HAS_HOTPLUG(dev)) - crt->base.hpd_pin = HPD_CRT; - if (HAS_DDI(dev)) -diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c -index 83e413b..5a6368d 100644 ---- a/drivers/gpu/drm/i915/intel_ddi.c -+++ b/drivers/gpu/drm/i915/intel_ddi.c -@@ -1261,8 +1261,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) - intel_dp_check_link_status(intel_dp); - } - --static void intel_ddi_get_config(struct intel_encoder *encoder, -- struct intel_crtc_config *pipe_config) -+void intel_ddi_get_config(struct intel_encoder *encoder, -+ struct intel_crtc_config *pipe_config) - { - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index b7d6e09..ddf7e2f 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -816,6 +816,8 @@ extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); - extern bool - intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); - extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); -+extern void intel_ddi_get_config(struct intel_encoder *encoder, -+ struct intel_crtc_config *pipe_config); - - extern void intel_display_handle_reset(struct drm_device *dev); - extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, --- -1.8.3.1 - - From 92c64493f41092185230c552c277b42bf6113140 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Oct 2013 10:52:07 +0300 @@ -335,240 +84,3 @@ index 3aed1fe..07eb447 100644 static void intel_disable_dp(struct intel_encoder *encoder) -- 1.8.3.1 - - -From 1e5ec9a5628cfd23443a91f80dea2118efb21afd Mon Sep 17 00:00:00 2001 -From: Rob Pearce -Date: Sun, 27 Oct 2013 16:13:42 +0000 -Subject: [PATCH 4/5] drm/i915: No LVDS hardware on Intel D410PT and D425KT - -The Intel D410PT(LW) and D425KT Mini-ITX desktop boards both show up as -having LVDS but the hardware is not populated. This patch adds them to -the list of such systems. Patch is against 3.11.4 - -v2: Patch revised to match the D425KT exactly as the D425KTW does have -LVDS. According to Intel's documentation, the D410PTL and D410PLTW -don't. - -Signed-off-by: Rob Pearce -Cc: stable@vger.kernel.org -[danvet: Pimp commit message to my liking and add cc: stable.] -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_lvds.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c -index 61348ea..44533dd 100644 ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -696,6 +696,22 @@ static const struct dmi_system_id intel_no_lvds[] = { - }, - { - .callback = intel_no_lvds_dmi_callback, -+ .ident = "Intel D410PT", -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), -+ DMI_MATCH(DMI_BOARD_NAME, "D410PT"), -+ }, -+ }, -+ { -+ .callback = intel_no_lvds_dmi_callback, -+ .ident = "Intel D425KT", -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"), -+ }, -+ }, -+ { -+ .callback = intel_no_lvds_dmi_callback, - .ident = "Intel D510MO", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), --- -1.8.3.1 - - -From 239319357b4a2d085e5f5c27b46aab5f612c5036 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Tue, 29 Oct 2013 12:04:08 +0100 -Subject: [PATCH 5/5] drm/i915: Fix the PPT fdi lane bifurcate state handling - on ivb -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Originally I've thought that this is leftover hw state dirt from the -BIOS. But after way too much helpless flailing around on my part I've -noticed that the actual bug is when we change the state of an already -active pipe. - -For example when we change the fdi lines from 2 to 3 without switching -off outputs in-between we'll never see the crucial on->off transition -in the ->modeset_global_resources hook the current logic relies on. - -Patch version 2 got this right by instead also checking whether the -pipe is indeed active. But that in turn broke things when pipes have -been turned off through dpms since the bifurcate enabling is done in -the ->crtc_mode_set callback. - -To address this issues discussed with Ville in the patch review move -the setting of the bifurcate bit into the ->crtc_enable hook. That way -we won't wreak havoc with this state when userspace puts all other -outputs into dpms off state. This also moves us forward with our -overall goal to unify the modeset and dpms on paths (which we need to -have to allow runtime pm in the dpms off state). - -Unfortunately this requires us to move the bifurcate helpers around a -bit. - -Also update the commit message, I've misanalyzed the bug rather badly. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70507 -Tested-by: Jan-Michael Brummer -Cc: stable@vger.kernel.org -Cc: Ville Syrjälä -Reviewed-by: Ville Syrjälä -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_display.c | 95 ++++++++++++++++++------------------ - 1 file changed, 48 insertions(+), 47 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 4aaccd3..ad2a258 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -2251,9 +2251,10 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) - FDI_FE_ERRC_ENABLE); - } - --static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc) -+static bool pipe_has_enabled_pch(struct intel_crtc *crtc) - { -- return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder; -+ return crtc->base.enabled && crtc->active && -+ crtc->config.has_pch_encoder; - } - - static void ivb_modeset_global_resources(struct drm_device *dev) -@@ -2901,6 +2902,48 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, - I915_READ(VSYNCSHIFT(cpu_transcoder))); - } - -+static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ uint32_t temp; -+ -+ temp = I915_READ(SOUTH_CHICKEN1); -+ if (temp & FDI_BC_BIFURCATION_SELECT) -+ return; -+ -+ WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); -+ WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); -+ -+ temp |= FDI_BC_BIFURCATION_SELECT; -+ DRM_DEBUG_KMS("enabling fdi C rx\n"); -+ I915_WRITE(SOUTH_CHICKEN1, temp); -+ POSTING_READ(SOUTH_CHICKEN1); -+} -+ -+static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) -+{ -+ struct drm_device *dev = intel_crtc->base.dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ -+ switch (intel_crtc->pipe) { -+ case PIPE_A: -+ break; -+ case PIPE_B: -+ if (intel_crtc->config.fdi_lanes > 2) -+ WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); -+ else -+ cpt_enable_fdi_bc_bifurcation(dev); -+ -+ break; -+ case PIPE_C: -+ cpt_enable_fdi_bc_bifurcation(dev); -+ -+ break; -+ default: -+ BUG(); -+ } -+} -+ - /* - * Enable PCH resources required for PCH ports: - * - PCH PLLs -@@ -2919,6 +2962,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) - - assert_pch_transcoder_disabled(dev_priv, pipe); - -+ if (IS_IVYBRIDGE(dev)) -+ ivybridge_update_fdi_bc_bifurcation(intel_crtc); -+ - /* Write the TU size bits before fdi link training, so that error - * detection works. */ - I915_WRITE(FDI_RX_TUSIZE1(pipe), -@@ -5512,48 +5558,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, - return true; - } - --static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- uint32_t temp; -- -- temp = I915_READ(SOUTH_CHICKEN1); -- if (temp & FDI_BC_BIFURCATION_SELECT) -- return; -- -- WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); -- WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); -- -- temp |= FDI_BC_BIFURCATION_SELECT; -- DRM_DEBUG_KMS("enabling fdi C rx\n"); -- I915_WRITE(SOUTH_CHICKEN1, temp); -- POSTING_READ(SOUTH_CHICKEN1); --} -- --static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) --{ -- struct drm_device *dev = intel_crtc->base.dev; -- struct drm_i915_private *dev_priv = dev->dev_private; -- -- switch (intel_crtc->pipe) { -- case PIPE_A: -- break; -- case PIPE_B: -- if (intel_crtc->config.fdi_lanes > 2) -- WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); -- else -- cpt_enable_fdi_bc_bifurcation(dev); -- -- break; -- case PIPE_C: -- cpt_enable_fdi_bc_bifurcation(dev); -- -- break; -- default: -- BUG(); -- } --} -- - int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) - { - /* -@@ -5768,9 +5772,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, - &intel_crtc->config.fdi_m_n); - } - -- if (IS_IVYBRIDGE(dev)) -- ivybridge_update_fdi_bc_bifurcation(intel_crtc); -- - ironlake_set_pipeconf(crtc); - - /* Set up the display plane register */ --- -1.8.3.1 - diff --git a/kernel.spec b/kernel.spec index eba97f365..bf2d4ec3b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -742,9 +742,6 @@ Patch25106: bonding-driver-alb-learning.patch #rhbz 985522 Patch25107: ntp-Make-periodic-RTC-update-more-reliable.patch -#rhbz 1010431 -Patch25108: Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch - #rhbz 902012 Patch25114: elevator-Fix-a-race-in-elevator-switching-and-md.patch Patch25115: elevator-acquire-q-sysfs_lock-in-elevator_change.patch @@ -780,9 +777,6 @@ Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch #rhbz 984696 Patch25132: rt2800usb-slow-down-TX-status-polling.patch -#rhbz 1015558 -Patch25133: fix-buslogic.patch - #rhbz 1023413 Patch25135: alps-Support-for-Dell-XT2-model.patch @@ -795,10 +789,6 @@ Patch25138: intel-3.12-stable-fixes.patch #CVE-2013-4348 rhbz 1007939 1025647 Patch25139: net-flow_dissector-fail-on-evil-iph-ihl.patch -#rhbz 1010603 -Patch25140: 0001-Revert-epoll-use-freezable-blocking-call.patch -Patch25141: 0001-Revert-select-use-freezable-blocking-call.patch - #rhbz 1025769 Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch @@ -1482,9 +1472,6 @@ ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch #rhbz 985522 ApplyPatch ntp-Make-periodic-RTC-update-more-reliable.patch -#rhbz 1010431 -ApplyPatch Revert-rt2x00pci-Use-PCI-MSIs-whenever-possible.patch - #rhbz 971893 ApplyPatch bonding-driver-alb-learning.patch @@ -1523,9 +1510,6 @@ ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch #rhbz 984696 ApplyPatch rt2800usb-slow-down-TX-status-polling.patch -#rhbz 1015558 -ApplyPatch fix-buslogic.patch - #rhbz 1023413 ApplyPatch alps-Support-for-Dell-XT2-model.patch @@ -1538,10 +1522,6 @@ ApplyPatch intel-3.12-stable-fixes.patch #CVE-2013-4348 rhbz 1007939 1025647 ApplyPatch net-flow_dissector-fail-on-evil-iph-ihl.patch -#rhbz 1010603 -ApplyPatch 0001-Revert-epoll-use-freezable-blocking-call.patch -ApplyPatch 0001-Revert-select-use-freezable-blocking-call.patch - #rhbz 1025769 ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch @@ -2390,6 +2370,9 @@ fi # ||----w | # || || %changelog +* Wed Nov 13 2013 Justin M. Forbes - 3.11.8-100 +- Linux v3.11.8 + * Sat Nov 09 2013 Josh Boyer - Add patch from Daniel Stone to avoid high order allocations in evdev - Add qxl backport fixes from Dave Airlie diff --git a/sources b/sources index 585450e45..4a8174344 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -42361474ed56948d8f52e72958b2cdf0 patch-3.11.7.xz +e6c14ecc86eab4cfaf498ba3c70b3f04 patch-3.11.8.xz From cd2a7b7da766ff7609b0b83897c91d50a1a36b40 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Nov 2013 14:32:25 -0500 Subject: [PATCH 461/492] CVE-2013-4563: net: large udp packet over IPv6 over UFO-enabled device with TBF qdisc panic (rhbz 1030015 1030017) --- ...oom-calculation-in-udp6_ufo_fragment.patch | 43 +++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 52 insertions(+) create mode 100644 ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch diff --git a/ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch b/ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch new file mode 100644 index 000000000..2b030387b --- /dev/null +++ b/ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch @@ -0,0 +1,43 @@ +Bugzilla: 1030015 1030017 +Upstream-status: 3.13 + +From aeb45260747b0a1bf4d374d5e65298cc254cb4f5 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Tue, 5 Nov 2013 02:41:27 +0100 +Subject: [PATCH] ipv6: fix headroom calculation in udp6_ufo_fragment + +Commit 1e2bd517c108816220f262d7954b697af03b5f9c ("udp6: Fix udp +fragmentation for tunnel traffic.") changed the calculation if +there is enough space to include a fragment header in the skb from a +skb->mac_header dervived one to skb_headroom. Because we already peeled +off the skb to transport_header this is wrong. Change this back to check +if we have enough room before the mac_header. + +This fixes a panic Saran Neti reported. He used the tbf scheduler which +skb_gso_segments the skb. The offsets get negative and we panic in memcpy +because the skb was erroneously not expanded at the head. + +Reported-by: Saran Neti +Cc: Pravin B Shelar +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ipv6/udp_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c +index 5d1b8d7..657914b 100644 +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -86,7 +86,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, + + /* Check if there is enough headroom to insert fragment header. */ + tnl_hlen = skb_tnl_header_len(skb); +- if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) { ++ if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) { + if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) + goto out; + } +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index bf2d4ec3b..ee80a9294 100644 --- a/kernel.spec +++ b/kernel.spec @@ -796,6 +796,9 @@ Patch25143: drm-qxl-backport-fixes-for-Fedora.patch Patch25144: Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch +#CVE-2013-4563 rhbz 1030015 1030017 +Patch25145: ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch + # END OF PATCH DEFINITIONS %endif @@ -1529,6 +1532,9 @@ ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch ApplyPatch Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch +#CVE-2013-4563 rhbz 1030015 1030017 +ApplyPatch ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch + # END OF PATCH APPLICATIONS %endif @@ -2370,6 +2376,9 @@ fi # ||----w | # || || %changelog +* Thu Nov 14 2013 Josh Boyer +- CVE-2013-4563: net: large udp packet over IPv6 over UFO-enabled device with TBF qdisc panic (rhbz 1030015 1030017) + * Wed Nov 13 2013 Justin M. Forbes - 3.11.8-100 - Linux v3.11.8 From 741d8741147ba7b2ae7243e9c91cd53c2ba3519b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 10:47:47 -0500 Subject: [PATCH 462/492] Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905) --- ...ent-outgoing-reassembled-skb-properl.patch | 39 ++ ...easm-skb-through-instead-of-original.patch | 499 ++++++++++++++++++ kernel.spec | 11 + 3 files changed, 549 insertions(+) create mode 100644 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch create mode 100644 0002-netfilter-push-reasm-skb-through-instead-of-original.patch diff --git a/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch b/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch new file mode 100644 index 000000000..a19217d12 --- /dev/null +++ b/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch @@ -0,0 +1,39 @@ +Bugzilla: 1015905 +Upstream-status: 3.13 (should hit stable) + +From 90e4e23d52fd04f228eed2c3d341136c50058b37 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Wed, 6 Nov 2013 17:52:19 +0100 +Subject: [PATCH 1/2] ip6_output: fragment outgoing reassembled skb properly + +If reassembled packet would fit into outdev MTU, it is not fragmented +according the original frag size and it is send as single big packet. + +The second case is if skb is gso. In that case fragmentation does not happen +according to the original frag size. + +This patch fixes these. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 5b25f85..f80f2fa 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -150,7 +150,8 @@ static int ip6_finish_output2(struct sk_buff *skb) + static int ip6_finish_output(struct sk_buff *skb) + { + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || +- dst_allfrag(skb_dst(skb))) ++ dst_allfrag(skb_dst(skb)) || ++ (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) + return ip6_fragment(skb, ip6_finish_output2); + else + return ip6_finish_output2(skb); +-- +1.8.3.1 + diff --git a/0002-netfilter-push-reasm-skb-through-instead-of-original.patch b/0002-netfilter-push-reasm-skb-through-instead-of-original.patch new file mode 100644 index 000000000..27fee5173 --- /dev/null +++ b/0002-netfilter-push-reasm-skb-through-instead-of-original.patch @@ -0,0 +1,499 @@ +Bugzilla: 1015905 +Upstream-status: 3.13 (should hit stable) + +From 5c0df04613dd39fba5d2a43eaf90a2dc1dcd8899 Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Wed, 6 Nov 2013 17:52:20 +0100 +Subject: [PATCH 2/2] netfilter: push reasm skb through instead of original + frag skbs + +Pushing original fragments through causes several problems. For example +for matching, frags may not be matched correctly. Take following +example: + + +On HOSTA do: +ip6tables -I INPUT -p icmpv6 -j DROP +ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT + +and on HOSTB you do: +ping6 HOSTA -s2000 (MTU is 1500) + +Incoming echo requests will be filtered out on HOSTA. This issue does +not occur with smaller packets than MTU (where fragmentation does not happen) + + +As was discussed previously, the only correct solution seems to be to use +reassembled skb instead of separete frags. Doing this has positive side +effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams +dances in ipvs and conntrack can be removed. + +Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c +entirely and use code in net/ipv6/reassembly.c instead. + +Signed-off-by: Jiri Pirko +Acked-by: Julian Anastasov +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller + +Conflicts: + include/net/netfilter/ipv6/nf_defrag_ipv6.h + net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c + net/ipv6/netfilter/nf_defrag_ipv6_hooks.c + net/netfilter/ipvs/ip_vs_core.c +--- + include/linux/skbuff.h | 32 --------------- + include/net/ip_vs.h | 32 +-------------- + include/net/netfilter/ipv6/nf_defrag_ipv6.h | 5 +-- + net/core/skbuff.c | 3 -- + net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 54 +------------------------ + net/ipv6/netfilter/nf_conntrack_reasm.c | 19 +-------- + net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 7 +++- + net/netfilter/ipvs/ip_vs_core.c | 55 +------------------------- + net/netfilter/ipvs/ip_vs_pe_sip.c | 8 +--- + 9 files changed, 13 insertions(+), 202 deletions(-) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 6bd165b..37b4517 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -333,11 +333,6 @@ typedef unsigned int sk_buff_data_t; + typedef unsigned char *sk_buff_data_t; + #endif + +-#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \ +- defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +-#define NET_SKBUFF_NF_DEFRAG_NEEDED 1 +-#endif +- + /** + * struct sk_buff - socket buffer + * @next: Next buffer in list +@@ -370,7 +365,6 @@ typedef unsigned char *sk_buff_data_t; + * @protocol: Packet protocol from driver + * @destructor: Destruct function + * @nfct: Associated connection, if any +- * @nfct_reasm: netfilter conntrack re-assembly pointer + * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c + * @skb_iif: ifindex of device we arrived on + * @tc_index: Traffic control index +@@ -459,9 +453,6 @@ struct sk_buff { + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + struct nf_conntrack *nfct; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- struct sk_buff *nfct_reasm; +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + struct nf_bridge_info *nf_bridge; + #endif +@@ -2603,18 +2594,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct) + atomic_inc(&nfct->use); + } + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +-static inline void nf_conntrack_get_reasm(struct sk_buff *skb) +-{ +- if (skb) +- atomic_inc(&skb->users); +-} +-static inline void nf_conntrack_put_reasm(struct sk_buff *skb) +-{ +- if (skb) +- kfree_skb(skb); +-} +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) + { +@@ -2633,10 +2612,6 @@ static inline void nf_reset(struct sk_buff *skb) + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(skb->nfct_reasm); +- skb->nfct_reasm = NULL; +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(skb->nf_bridge); + skb->nf_bridge = NULL; +@@ -2658,10 +2633,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) + nf_conntrack_get(src->nfct); + dst->nfctinfo = src->nfctinfo; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- dst->nfct_reasm = src->nfct_reasm; +- nf_conntrack_get_reasm(src->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + dst->nf_bridge = src->nf_bridge; + nf_bridge_get(src->nf_bridge); +@@ -2673,9 +2644,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_conntrack_put(dst->nfct); + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(dst->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(dst->nf_bridge); + #endif +diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h +index f0d70f0..ff21521 100644 +--- a/include/net/ip_vs.h ++++ b/include/net/ip_vs.h +@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size; + struct ip_vs_iphdr { + __u32 len; /* IPv4 simply where L4 starts + IPv6 where L4 Transport Header starts */ +- __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */ + __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ + __s16 protocol; + __s32 flags; +@@ -117,34 +116,12 @@ struct ip_vs_iphdr { + union nf_inet_addr daddr; + }; + +-/* Dependency to module: nf_defrag_ipv6 */ +-#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +-{ +- return skb->nfct_reasm; +-} +-static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, +- int len, void *buffer, +- const struct ip_vs_iphdr *ipvsh) +-{ +- if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb))) +- return skb_header_pointer(skb_nfct_reasm(skb), +- ipvsh->thoff_reasm, len, buffer); +- +- return skb_header_pointer(skb, offset, len, buffer); +-} +-#else +-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +-{ +- return NULL; +-} + static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, + int len, void *buffer, + const struct ip_vs_iphdr *ipvsh) + { + return skb_header_pointer(skb, offset, len, buffer); + } +-#endif + + static inline void + ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) +@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) + (struct ipv6hdr *)skb_network_header(skb); + iphdr->saddr.in6 = iph->saddr; + iphdr->daddr.in6 = iph->daddr; +- /* ipv6_find_hdr() updates len, flags, thoff_reasm */ +- iphdr->thoff_reasm = 0; ++ /* ipv6_find_hdr() updates len, flags */ + iphdr->len = 0; + iphdr->flags = 0; + iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, + &iphdr->fragoffs, + &iphdr->flags); +- /* get proto from re-assembled packet and it's offset */ +- if (skb_nfct_reasm(skb)) +- iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb), +- &iphdr->thoff_reasm, +- -1, NULL, NULL); +- + } else + #endif + { +diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h +index fd79c9a..17920d8 100644 +--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h ++++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h +@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void); + extern int nf_ct_frag6_init(void); + extern void nf_ct_frag6_cleanup(void); + extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); +-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, +- struct net_device *in, +- struct net_device *out, +- int (*okfn)(struct sk_buff *)); ++extern void nf_ct_frag6_consume_orig(struct sk_buff *skb); + + struct inet_frags_ctl; + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 2c3d0f5..a75022e 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -580,9 +580,6 @@ static void skb_release_head_state(struct sk_buff *skb) + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + nf_conntrack_put(skb->nfct); + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(skb->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(skb->nf_bridge); + #endif +diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +index c9b6a6e..97cd750 100644 +--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c ++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +@@ -172,63 +172,13 @@ out: + return nf_conntrack_confirm(skb); + } + +-static unsigned int __ipv6_conntrack_in(struct net *net, +- unsigned int hooknum, +- struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- struct sk_buff *reasm = skb->nfct_reasm; +- const struct nf_conn_help *help; +- struct nf_conn *ct; +- enum ip_conntrack_info ctinfo; +- +- /* This packet is fragmented and has reassembled packet. */ +- if (reasm) { +- /* Reassembled packet isn't parsed yet ? */ +- if (!reasm->nfct) { +- unsigned int ret; +- +- ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm); +- if (ret != NF_ACCEPT) +- return ret; +- } +- +- /* Conntrack helpers need the entire reassembled packet in the +- * POST_ROUTING hook. In case of unconfirmed connections NAT +- * might reassign a helper, so the entire packet is also +- * required. +- */ +- ct = nf_ct_get(reasm, &ctinfo); +- if (ct != NULL && !nf_ct_is_untracked(ct)) { +- help = nfct_help(ct); +- if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { +- nf_conntrack_get_reasm(reasm); +- NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, +- (struct net_device *)in, +- (struct net_device *)out, +- okfn, NF_IP6_PRI_CONNTRACK + 1); +- return NF_DROP_ERR(-ECANCELED); +- } +- } +- +- nf_conntrack_get(reasm->nfct); +- skb->nfct = reasm->nfct; +- skb->nfctinfo = reasm->nfctinfo; +- return NF_ACCEPT; +- } +- +- return nf_conntrack_in(net, PF_INET6, hooknum, skb); +-} +- + static unsigned int ipv6_conntrack_in(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) + { +- return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn); ++ return nf_conntrack_in(dev_net(in), PF_INET6, hooknum, skb); + } + + static unsigned int ipv6_conntrack_local(unsigned int hooknum, +@@ -242,7 +192,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, + net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); + return NF_ACCEPT; + } +- return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn); ++ return nf_conntrack_in(dev_net(out), PF_INET6, hooknum, skb); + } + + static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index dffdc1a..253566a 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -621,31 +621,16 @@ ret_orig: + return skb; + } + +-void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, +- struct net_device *in, struct net_device *out, +- int (*okfn)(struct sk_buff *)) ++void nf_ct_frag6_consume_orig(struct sk_buff *skb) + { + struct sk_buff *s, *s2; +- unsigned int ret = 0; + + for (s = NFCT_FRAG6_CB(skb)->orig; s;) { +- nf_conntrack_put_reasm(s->nfct_reasm); +- nf_conntrack_get_reasm(skb); +- s->nfct_reasm = skb; +- + s2 = s->next; + s->next = NULL; +- +- if (ret != -ECANCELED) +- ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, +- in, out, okfn, +- NF_IP6_PRI_CONNTRACK_DEFRAG + 1); +- else +- kfree_skb(s); +- ++ consume_skb(s); + s = s2; + } +- nf_conntrack_put_reasm(skb); + } + + static int nf_ct_net_init(struct net *net) +diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +index aacd121..581dd9e 100644 +--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c ++++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum, + if (reasm == skb) + return NF_ACCEPT; + +- nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, +- (struct net_device *)out, okfn); ++ nf_ct_frag6_consume_orig(reasm); ++ ++ NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, ++ (struct net_device *) in, (struct net_device *) out, ++ okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); + + return NF_STOLEN; + } +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 4f69e83..1517b50 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -1131,12 +1131,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) + ip_vs_fill_iph_skb(af, skb, &iph); + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (!iph.fragoffs && skb_nfct_reasm(skb)) { +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- /* Save fw mark for coming frags */ +- reasm->ipvs_property = 1; +- reasm->mark = skb->mark; +- } + if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { + int related; + int verdict = ip_vs_out_icmp_v6(skb, &related, +@@ -1606,12 +1600,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) + + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (!iph.fragoffs && skb_nfct_reasm(skb)) { +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- /* Save fw mark for coming frags. */ +- reasm->ipvs_property = 1; +- reasm->mark = skb->mark; +- } + if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { + int related; + int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum, +@@ -1663,9 +1651,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) + /* sorry, all this trouble for a no-hit :) */ + IP_VS_DBG_PKT(12, af, pp, skb, 0, + "ip_vs_in: packet continues traversal as normal"); +- if (iph.fragoffs && !skb_nfct_reasm(skb)) { ++ if (iph.fragoffs) { + /* Fragment that couldn't be mapped to a conn entry +- * and don't have any pointer to a reasm skb + * is missing module nf_defrag_ipv6 + */ + IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n"); +@@ -1748,38 +1735,6 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb, + #ifdef CONFIG_IP_VS_IPV6 + + /* +- * AF_INET6 fragment handling +- * Copy info from first fragment, to the rest of them. +- */ +-static unsigned int +-ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- struct net *net; +- +- /* Skip if not a "replay" from nf_ct_frag6_output or first fragment. +- * ipvs_property is set when checking first fragment +- * in ip_vs_in() and ip_vs_out(). +- */ +- if (reasm) +- IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property); +- if (!reasm || !reasm->ipvs_property) +- return NF_ACCEPT; +- +- net = skb_net(skb); +- if (!net_ipvs(net)->enable) +- return NF_ACCEPT; +- +- /* Copy stored fw mark, saved in ip_vs_{in,out} */ +- skb->mark = reasm->mark; +- +- return NF_ACCEPT; +-} +- +-/* + * AF_INET6 handler in NF_INET_LOCAL_IN chain + * Schedule and forward packets from remote clients + */ +@@ -1916,14 +1871,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { + .priority = 100, + }, + #ifdef CONFIG_IP_VS_IPV6 +- /* After mangle & nat fetch 2:nd fragment and following */ +- { +- .hook = ip_vs_preroute_frag6, +- .owner = THIS_MODULE, +- .pf = NFPROTO_IPV6, +- .hooknum = NF_INET_PRE_ROUTING, +- .priority = NF_IP6_PRI_NAT_DST + 1, +- }, + /* After packet filtering, change source only for VS/NAT */ + { + .hook = ip_vs_reply6, +diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c +index 9ef22bd..bed5f70 100644 +--- a/net/netfilter/ipvs/ip_vs_pe_sip.c ++++ b/net/netfilter/ipvs/ip_vs_pe_sip.c +@@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff, + static int + ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) + { +- struct sk_buff *reasm = skb_nfct_reasm(skb); + struct ip_vs_iphdr iph; + unsigned int dataoff, datalen, matchoff, matchlen; + const char *dptr; +@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) + /* todo: IPv6 fragments: + * I think this only should be done for the first fragment. /HS + */ +- if (reasm) { +- skb = reasm; +- dataoff = iph.thoff_reasm + sizeof(struct udphdr); +- } else +- dataoff = iph.len + sizeof(struct udphdr); ++ dataoff = iph.len + sizeof(struct udphdr); + + if (dataoff >= skb->len) + return -EINVAL; +- /* todo: Check if this will mess-up the reasm skb !!! /HS */ + retc = skb_linearize(skb); + if (retc < 0) + return retc; +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index ee80a9294..3dad6f8f7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -799,6 +799,10 @@ Patch25144: Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch #CVE-2013-4563 rhbz 1030015 1030017 Patch25145: ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch +#rhbz 1015905 +Patch25146: 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch +Patch25147: 0002-netfilter-push-reasm-skb-through-instead-of-original.patch + # END OF PATCH DEFINITIONS %endif @@ -1535,6 +1539,10 @@ ApplyPatch Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch #CVE-2013-4563 rhbz 1030015 1030017 ApplyPatch ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch +#rhbz 1015905 +ApplyPatch 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch +ApplyPatch 0002-netfilter-push-reasm-skb-through-instead-of-original.patch + # END OF PATCH APPLICATIONS %endif @@ -2376,6 +2384,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 18 2013 Josh Boyer +- Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905) + * Thu Nov 14 2013 Josh Boyer - CVE-2013-4563: net: large udp packet over IPv6 over UFO-enabled device with TBF qdisc panic (rhbz 1030015 1030017) From 961cc9375cfcef461d4c93bcc061b3c3c3e1309c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 10:55:44 -0500 Subject: [PATCH 463/492] Add patch to fix ALX phy issues after resume (rhbz 1011362) --- alx-Reset-phy-speed-after-resume.patch | 33 ++++++++++++++++++++++++++ kernel.spec | 7 ++++++ 2 files changed, 40 insertions(+) create mode 100644 alx-Reset-phy-speed-after-resume.patch diff --git a/alx-Reset-phy-speed-after-resume.patch b/alx-Reset-phy-speed-after-resume.patch new file mode 100644 index 000000000..3af169f78 --- /dev/null +++ b/alx-Reset-phy-speed-after-resume.patch @@ -0,0 +1,33 @@ +Bugzilla: 1011362 +Upstream-status: queued for 3.13 + +From b54629e226d196e802abdd30c5e34f2a47cddcf2 Mon Sep 17 00:00:00 2001 +From: hahnjo +Date: Tue, 12 Nov 2013 17:19:24 +0000 +Subject: alx: Reset phy speed after resume + +This fixes bug 62491 (https://bugzilla.kernel.org/show_bug.cgi?id=62491). +After resuming some users got the following error flooding the kernel log: +alx 0000:02:00.0: invalid PHY speed/duplex: 0xffff + +Signed-off-by: Jonas Hahnfeld +Signed-off-by: David S. Miller +--- +(limited to 'drivers/net/ethernet/atheros/alx') + +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index 5aa5e81..c3c4c26 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -1388,6 +1388,9 @@ static int alx_resume(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct alx_priv *alx = pci_get_drvdata(pdev); ++ struct alx_hw *hw = &alx->hw; ++ ++ alx_reset_phy(hw); + + if (!netif_running(alx->dev)) + return 0; +-- +cgit v0.9.2 diff --git a/kernel.spec b/kernel.spec index 3dad6f8f7..1123008d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -803,6 +803,9 @@ Patch25145: ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch Patch25146: 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch Patch25147: 0002-netfilter-push-reasm-skb-through-instead-of-original.patch +#rhbz 1011362 +Patch25148: alx-Reset-phy-speed-after-resume.patch + # END OF PATCH DEFINITIONS %endif @@ -1543,6 +1546,9 @@ ApplyPatch ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch ApplyPatch 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch ApplyPatch 0002-netfilter-push-reasm-skb-through-instead-of-original.patch +#rhbz 1011362 +ApplyPatch alx-Reset-phy-speed-after-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -2385,6 +2391,7 @@ fi # || || %changelog * Mon Nov 18 2013 Josh Boyer +- Add patch to fix ALX phy issues after resume (rhbz 1011362) - Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905) * Thu Nov 14 2013 Josh Boyer From f0c371f0381992a2565742946261bb841b2c8553 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 11:25:28 -0500 Subject: [PATCH 464/492] Add patches from Pierre Ossman to fix 24Hz/24p radeon audio (rhbz 1010679) --- drm-radeon-24hz-audio-fixes.patch | 170 ++++++++++++++++++++++++++++++ kernel.spec | 3 + 2 files changed, 173 insertions(+) create mode 100644 drm-radeon-24hz-audio-fixes.patch diff --git a/drm-radeon-24hz-audio-fixes.patch b/drm-radeon-24hz-audio-fixes.patch new file mode 100644 index 000000000..b2ecf9332 --- /dev/null +++ b/drm-radeon-24hz-audio-fixes.patch @@ -0,0 +1,170 @@ +From 908171aa738b5bbcc6241cec46f73fcd57dd00d4 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Wed, 6 Nov 2013 20:00:32 +0100 +Subject: [PATCH 1/2] drm/radeon/audio: correct ACR table + +The values were taken from the HDMI spec, but they assumed +exact x/1.001 clocks. Since we round the clocks, we also need +to calculate different N and CTS values. + +Note that the N for 25.2/1.001 MHz at 44.1 kHz audio is out of +spec. Hopefully this mode is rarely used and/or HDMI sinks +tolerate overly large values of N. + +bug: +https://bugs.freedesktop.org/show_bug.cgi?id=69675 + +Signed-off-by: Pierre Ossman +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index 4140fe8..e8ca095 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -57,15 +57,15 @@ enum r600_hdmi_iec_status_bits { + static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ +- { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ ++ { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ +- { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ ++ { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ +- { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ ++ { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ + { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ + }; +-- +1.8.3.1 + + +From 05e4776357fe7217e531cbaaa163e24f688d10ce Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Wed, 6 Nov 2013 20:09:08 +0100 +Subject: [PATCH 2/2] drm/radeon/audio: improve ACR calculation + +In order to have any realistic chance of calculating proper +ACR values, we need to be able to calculate both N and CTS, +not just CTS. We still aim for the ideal N as specified in +the HDMI spec though. + +bug: +https://bugs.freedesktop.org/show_bug.cgi?id=69675 + +Signed-off-by: Pierre Ossman +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/r600_hdmi.c | 68 ++++++++++++++++++++++++++------------ + 1 file changed, 46 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index e8ca095..92c6df7 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -24,6 +24,7 @@ + * Authors: Christian König + */ + #include ++#include + #include + #include + #include "radeon.h" +@@ -67,25 +68,47 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ + { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ +- { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ + }; + ++ + /* +- * calculate CTS value if it's not found in the table ++ * calculate CTS and N values if they are not found in the table + */ +-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) ++static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) + { +- u64 n; +- u32 d; +- +- if (*CTS == 0) { +- n = (u64)clock * (u64)N * 1000ULL; +- d = 128 * freq; +- do_div(n, d); +- *CTS = n; +- } +- DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", +- N, *CTS, freq); ++ int n, cts; ++ unsigned long div, mul; ++ ++ /* Safe, but overly large values */ ++ n = 128 * freq; ++ cts = clock * 1000; ++ ++ /* Smallest valid fraction */ ++ div = gcd(n, cts); ++ ++ n /= div; ++ cts /= div; ++ ++ /* ++ * The optimal N is 128*freq/1000. Calculate the closest larger ++ * value that doesn't truncate any bits. ++ */ ++ mul = ((128*freq/1000) + (n-1))/n; ++ ++ n *= mul; ++ cts *= mul; ++ ++ /* Check that we are in spec (not always possible) */ ++ if (n < (128*freq/1500)) ++ printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); ++ if (n > (128*freq/300)) ++ printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); ++ ++ *N = n; ++ *CTS = cts; ++ ++ DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", ++ *N, *CTS, freq); + } + + struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) +@@ -93,15 +116,16 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) + struct radeon_hdmi_acr res; + u8 i; + +- for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && +- r600_hdmi_predefined_acr[i].clock != 0; i++) +- ; +- res = r600_hdmi_predefined_acr[i]; ++ /* Precalculated values for common clocks */ ++ for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { ++ if (r600_hdmi_predefined_acr[i].clock == clock) ++ return r600_hdmi_predefined_acr[i]; ++ } + +- /* In case some CTS are missing */ +- r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); +- r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); +- r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); ++ /* And odd clocks get manually calculated */ ++ r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); ++ r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); ++ r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); + + return res; + } +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 1123008d4..fac3d5568 100644 --- a/kernel.spec +++ b/kernel.spec @@ -770,6 +770,7 @@ Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch #rhbz 1010679 Patch25130: fix-radeon-sound.patch +Patch25149: drm-radeon-24hz-audio-fixes.patch #rhbz 1011714 Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch @@ -1513,6 +1514,7 @@ ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch #rhbz 1010679 ApplyPatch fix-radeon-sound.patch +ApplyPatch drm-radeon-24hz-audio-fixes.patch #rhbz 1011714 ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch @@ -2391,6 +2393,7 @@ fi # || || %changelog * Mon Nov 18 2013 Josh Boyer +- Add patches from Pierre Ossman to fix 24Hz/24p radeon audio (rhbz 1010679) - Add patch to fix ALX phy issues after resume (rhbz 1011362) - Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905) From 2771222ebd3c1d7c79b25cea4825e667aa78d3b4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 11:37:26 -0500 Subject: [PATCH 465/492] Add patch to fix crash from slab when using md-raid mirrors (rhbz 1031086) --- kernel.spec | 7 ++ ...o-not-check-for-duplicate-slab-names.patch | 71 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 slab_common-Do-not-check-for-duplicate-slab-names.patch diff --git a/kernel.spec b/kernel.spec index fac3d5568..21239a937 100644 --- a/kernel.spec +++ b/kernel.spec @@ -807,6 +807,9 @@ Patch25147: 0002-netfilter-push-reasm-skb-through-instead-of-original.patch #rhbz 1011362 Patch25148: alx-Reset-phy-speed-after-resume.patch +#rhbz 1031086 +Patch25150: slab_common-Do-not-check-for-duplicate-slab-names.patch + # END OF PATCH DEFINITIONS %endif @@ -1551,6 +1554,9 @@ ApplyPatch 0002-netfilter-push-reasm-skb-through-instead-of-original.patch #rhbz 1011362 ApplyPatch alx-Reset-phy-speed-after-resume.patch +#rhbz 1031086 +ApplyPatch slab_common-Do-not-check-for-duplicate-slab-names.patch + # END OF PATCH APPLICATIONS %endif @@ -2393,6 +2399,7 @@ fi # || || %changelog * Mon Nov 18 2013 Josh Boyer +- Add patch to fix crash from slab when using md-raid mirrors (rhbz 1031086) - Add patches from Pierre Ossman to fix 24Hz/24p radeon audio (rhbz 1010679) - Add patch to fix ALX phy issues after resume (rhbz 1011362) - Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905) diff --git a/slab_common-Do-not-check-for-duplicate-slab-names.patch b/slab_common-Do-not-check-for-duplicate-slab-names.patch new file mode 100644 index 000000000..c99303cc0 --- /dev/null +++ b/slab_common-Do-not-check-for-duplicate-slab-names.patch @@ -0,0 +1,71 @@ +Bugzilla: 1031086 +Upstream-status: 3.12 + +From cd8fa0170867ce6e6e2d7edba1dc1a0b87485854 Mon Sep 17 00:00:00 2001 +From: Christoph Lameter +Date: Sat, 21 Sep 2013 21:56:34 +0000 +Subject: [PATCH] slab_common: Do not check for duplicate slab names + +SLUB can alias multiple slab kmem_create_requests to one slab cache to save +memory and increase the cache hotness. As a result the name of the slab can be +stale. Only check the name for duplicates if we are in debug mode where we do +not merge multiple caches. + +This fixes the following problem reported by Jonathan Brassow: + + The problem with kmem_cache* is this: + + *) Assume CONFIG_SLUB is set + 1) kmem_cache_create(name="foo-a") + - creates new kmem_cache structure + 2) kmem_cache_create(name="foo-b") + - If identical cache characteristics, it will be merged with the previously + created cache associated with "foo-a". The cache's refcount will be + incremented and an alias will be created via sysfs_slab_alias(). + 3) kmem_cache_destroy() + - Attempting to destroy cache associated with "foo-a", but instead the + refcount is simply decremented. I don't even think the sysfs aliases are + ever removed... + 4) kmem_cache_create(name="foo-a") + - This FAILS because kmem_cache_sanity_check colides with the existing + name ("foo-a") associated with the non-removed cache. + + This is a problem for RAID (specifically dm-raid) because the name used + for the kmem_cache_create is ("raid%d-%p", level, mddev). If the cache + persists for long enough, the memory address of an old mddev will be + reused for a new mddev - causing an identical formulation of the cache + name. Even though kmem_cache_destory had long ago been used to delete + the old cache, the merging of caches has cause the name and cache of that + old instance to be preserved and causes a colision (and thus failure) in + kmem_cache_create(). I see this regularly in my testing. + +Reported-by: Jonathan Brassow +Signed-off-by: Christoph Lameter +Signed-off-by: Pekka Enberg +--- + mm/slab_common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 538bade..d434771 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -55,6 +55,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + continue; + } + ++#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON) + /* + * For simplicity, we won't check this in the list of memcg + * caches. We have control over memcg naming, and if there +@@ -68,6 +69,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + s = NULL; + return -EINVAL; + } ++#endif + } + + WARN_ON(strchr(name, ' ')); /* It confuses parsers */ +-- +1.8.3.1 + From 9790654176eca1e5c8bd1e7b52c15caa734788f7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 11:39:30 -0500 Subject: [PATCH 466/492] Add bugzilla/upstream-status notes to 24hz audio patch --- drm-radeon-24hz-audio-fixes.patch | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drm-radeon-24hz-audio-fixes.patch b/drm-radeon-24hz-audio-fixes.patch index b2ecf9332..4fd8341ed 100644 --- a/drm-radeon-24hz-audio-fixes.patch +++ b/drm-radeon-24hz-audio-fixes.patch @@ -1,3 +1,6 @@ +Bugzilla: 1010679 +Upstream-status: 3.13 + From 908171aa738b5bbcc6241cec46f73fcd57dd00d4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 6 Nov 2013 20:00:32 +0100 From be089ee6cae01ff37525249972cba0623be26018 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Nov 2013 14:19:27 -0500 Subject: [PATCH 467/492] Add patch to fix rhel5.9 KVM guests (rhbz 967652) --- KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch | 53 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 60 insertions(+) create mode 100644 KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch diff --git a/KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch b/KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch new file mode 100644 index 000000000..65a48c349 --- /dev/null +++ b/KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch @@ -0,0 +1,53 @@ +Bugzilla: 967652 +Upstream-status: 3.13 (should hit stable) + +From daf727225b8abfdfe424716abac3d15a3ac5626a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 31 Oct 2013 23:05:24 +0100 +Subject: [PATCH] KVM: x86: fix emulation of "movzbl %bpl, %eax" + +When I was looking at RHEL5.9's failure to start with +unrestricted_guest=0/emulate_invalid_guest_state=1, I got it working with a +slightly older tree than kvm.git. I now debugged the remaining failure, +which was introduced by commit 660696d1 (KVM: X86 emulator: fix +source operand decoding for 8bit mov[zs]x instructions, 2013-04-24) +introduced a similar mis-emulation to the one in commit 8acb4207 (KVM: +fix sil/dil/bpl/spl in the mod/rm fields, 2013-05-30). The incorrect +decoding occurs in 8-bit movzx/movsx instructions whose 8-bit operand +is sil/dil/bpl/spl. + +Needless to say, "movzbl %bpl, %eax" does occur in RHEL5.9's decompression +prolog, just a handful of instructions before finally giving control to +the decompressed vmlinux and getting out of the invalid guest state. + +Because OpMem8 bypasses decode_modrm, the same handling of the REX prefix +must be applied to OpMem8. + +Reported-by: Michele Baldessari +Cc: stable@vger.kernel.org +Cc: Gleb Natapov +Signed-off-by: Paolo Bonzini +Signed-off-by: Gleb Natapov +--- + arch/x86/kvm/emulate.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 16c037e..282d28c 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4117,7 +4117,10 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, + case OpMem8: + ctxt->memop.bytes = 1; + if (ctxt->memop.type == OP_REG) { +- ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1); ++ int highbyte_regs = ctxt->rex_prefix == 0; ++ ++ ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, ++ highbyte_regs); + fetch_register_operand(&ctxt->memop); + } + goto mem_common; +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 21239a937..532c2f5dc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -810,6 +810,9 @@ Patch25148: alx-Reset-phy-speed-after-resume.patch #rhbz 1031086 Patch25150: slab_common-Do-not-check-for-duplicate-slab-names.patch +#rhbz 967652 +Patch25151: KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch + # END OF PATCH DEFINITIONS %endif @@ -1557,6 +1560,9 @@ ApplyPatch alx-Reset-phy-speed-after-resume.patch #rhbz 1031086 ApplyPatch slab_common-Do-not-check-for-duplicate-slab-names.patch +#rhbz 967652 +ApplyPatch KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch + # END OF PATCH APPLICATIONS %endif @@ -2399,6 +2405,7 @@ fi # || || %changelog * Mon Nov 18 2013 Josh Boyer +- Add patch to fix rhel5.9 KVM guests (rhbz 967652) - Add patch to fix crash from slab when using md-raid mirrors (rhbz 1031086) - Add patches from Pierre Ossman to fix 24Hz/24p radeon audio (rhbz 1010679) - Add patch to fix ALX phy issues after resume (rhbz 1011362) From 98d2c800fbb45444162c5af0308cb8a8e1cb6d46 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Nov 2013 16:00:22 -0500 Subject: [PATCH 468/492] Linux v3.11.9 --- intel-3.12-stable-fixes.patch | 86 ------------------- kernel.spec | 17 +--- net-flow_dissector-fail-on-evil-iph-ihl.patch | 82 ------------------ sources | 2 +- 4 files changed, 5 insertions(+), 182 deletions(-) delete mode 100644 intel-3.12-stable-fixes.patch delete mode 100644 net-flow_dissector-fail-on-evil-iph-ihl.patch diff --git a/intel-3.12-stable-fixes.patch b/intel-3.12-stable-fixes.patch deleted file mode 100644 index 24a80dc0f..000000000 --- a/intel-3.12-stable-fixes.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 92c64493f41092185230c552c277b42bf6113140 Mon Sep 17 00:00:00 2001 -From: Jani Nikula -Date: Mon, 21 Oct 2013 10:52:07 +0300 -Subject: [PATCH 3/5] drm/i915/dp: workaround BIOS eDP bpp clamping issue - -This isn't a real fix to the problem, but rather a stopgap measure while -trying to find a proper solution. - -There are several laptops out there that fail to light up the eDP panel -in UEFI boot mode. They seem to be mostly IVB machines, including but -apparently not limited to Dell XPS 13, Asus TX300, Asus UX31A, Asus -UX32VD, Acer Aspire S7. They seem to work in CSM or legacy boot. - -The difference between UEFI and CSM is that the BIOS provides a -different VBT to the kernel. The UEFI VBT typically specifies 18 bpp and -1.62 GHz link for eDP, while CSM VBT has 24 bpp and 2.7 GHz link. We end -up clamping to 18 bpp in UEFI mode, which we can fit in the 1.62 Ghz -link, and for reasons yet unknown fail to light up the panel. - -Dithering from 24 to 18 bpp itself seems to work; if we use 18 bpp with -2.7 GHz link, the eDP panel lights up. So essentially this is a link -speed issue, and *not* a bpp clamping issue. - -The bug raised its head since -commit 657445fe8660100ad174600ebfa61536392b7624 -Author: Daniel Vetter -Date: Sat May 4 10:09:18 2013 +0200 - - Revert "drm/i915: revert eDP bpp clamping code changes" - -which started clamping bpp *before* computing the link requirements, and -thus affecting the required bandwidth. Clamping after the computations -kept the link at 2.7 GHz. - -Even though the BIOS tells us to use 18 bpp through the VBT, it happily -boots up at 24 bpp and 2.7 GHz itself! Use this information to -selectively ignore the VBT provided value. - -We can't ignore the VBT eDP bpp altogether, as there are other laptops -that do require the clamping to be used due to EDID reporting higher bpp -than the panel can support. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59841 -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67950 -Tested-by: Ulf Winkelvos -Tested-by: jkp -CC: stable@vger.kernel.org -Signed-off-by: Jani Nikula -Signed-off-by: Daniel Vetter ---- - drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 3aed1fe..07eb447 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -1371,6 +1371,26 @@ static void intel_dp_get_config(struct intel_encoder *encoder, - } - - pipe_config->adjusted_mode.flags |= flags; -+ -+ if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && -+ pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { -+ /* -+ * This is a big fat ugly hack. -+ * -+ * Some machines in UEFI boot mode provide us a VBT that has 18 -+ * bpp and 1.62 GHz link bandwidth for eDP, which for reasons -+ * unknown we fail to light up. Yet the same BIOS boots up with -+ * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as -+ * max, not what it tells us to use. -+ * -+ * Note: This will still be broken if the eDP panel is not lit -+ * up by the BIOS, and thus we can't get the mode at module -+ * load. -+ */ -+ DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", -+ pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); -+ dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; -+ } - } - - static void intel_disable_dp(struct intel_encoder *encoder) --- -1.8.3.1 diff --git a/kernel.spec b/kernel.spec index 532c2f5dc..104dd57d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -784,12 +784,6 @@ Patch25135: alps-Support-for-Dell-XT2-model.patch #rhbz 1011621 Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch -#rhbz 995782 -Patch25138: intel-3.12-stable-fixes.patch - -#CVE-2013-4348 rhbz 1007939 1025647 -Patch25139: net-flow_dissector-fail-on-evil-iph-ihl.patch - #rhbz 1025769 Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch @@ -1534,12 +1528,6 @@ ApplyPatch alps-Support-for-Dell-XT2-model.patch #rhbz 1011621 ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch -#rhbz 995782 -ApplyPatch intel-3.12-stable-fixes.patch - -#CVE-2013-4348 rhbz 1007939 1025647 -ApplyPatch net-flow_dissector-fail-on-evil-iph-ihl.patch - #rhbz 1025769 ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch @@ -2404,6 +2392,9 @@ fi # ||----w | # || || %changelog +* Wed Nov 20 2013 Josh Boyer - 3.11.9-100 +- Linux v3.11.9 + * Mon Nov 18 2013 Josh Boyer - Add patch to fix rhel5.9 KVM guests (rhbz 967652) - Add patch to fix crash from slab when using md-raid mirrors (rhbz 1031086) diff --git a/net-flow_dissector-fail-on-evil-iph-ihl.patch b/net-flow_dissector-fail-on-evil-iph-ihl.patch deleted file mode 100644 index aba3ea88b..000000000 --- a/net-flow_dissector-fail-on-evil-iph-ihl.patch +++ /dev/null @@ -1,82 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Jason Wang -Newsgroups: gmane.linux.kernel,gmane.linux.network -Subject: [PATCH net] net: flow_dissector: fail on evil iph->ihl -Date: Fri, 1 Nov 2013 15:01:10 +0800 -Lines: 34 -Approved: news@gmane.org -Message-ID: <1383289270-18952-1-git-send-email-jasowang@redhat.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: ger.gmane.org 1383289296 18578 80.91.229.3 (1 Nov 2013 07:01:36 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Fri, 1 Nov 2013 07:01:36 +0000 (UTC) -Cc: Jason Wang , - Petr Matousek , - "Michael S. Tsirkin" , - Daniel Borkmann -To: davem@davemloft.net, edumazet@google.com, netdev@vger.kernel.org, - linux-kernel@vger.kernel.org -Original-X-From: linux-kernel-owner@vger.kernel.org Fri Nov 01 08:01:39 2013 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Vc8jh-00034h-9Y - for glk-linux-kernel-3@plane.gmane.org; Fri, 01 Nov 2013 08:01:37 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753899Ab3KAHB3 (ORCPT ); - Fri, 1 Nov 2013 03:01:29 -0400 -Original-Received: from mx1.redhat.com ([209.132.183.28]:8081 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1752399Ab3KAHB1 (ORCPT ); - Fri, 1 Nov 2013 03:01:27 -0400 -Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rA171QgE005079 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Fri, 1 Nov 2013 03:01:26 -0400 -Original-Received: from jason-ThinkPad-T430s.nay.redhat.com (dhcp-66-71-71.eng.nay.redhat.com [10.66.71.71] (may be forged)) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id rA171Jpr015790; - Fri, 1 Nov 2013 03:01:20 -0400 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1588387 gmane.linux.network:289242 -Archived-At: - -We don't validate iph->ihl which may lead a dead loop if we meet a IPIP -skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl -is evil (less than 5). - -This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae -(rps: support IPIP encapsulation). - -Cc: Eric Dumazet -Cc: Petr Matousek -Cc: Michael S. Tsirkin -Cc: Daniel Borkmann -Signed-off-by: Jason Wang ---- -This patch is needed for stable. ---- - net/core/flow_dissector.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c -index 8d7d0dd..143b6fd 100644 ---- a/net/core/flow_dissector.c -+++ b/net/core/flow_dissector.c -@@ -40,7 +40,7 @@ again: - struct iphdr _iph; - ip: - iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); -- if (!iph) -+ if (!iph || iph->ihl < 5) - return false; - - if (ip_is_fragment(iph)) --- -1.8.1.2 - diff --git a/sources b/sources index 4a8174344..391b9ff05 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -e6c14ecc86eab4cfaf498ba3c70b3f04 patch-3.11.8.xz +6cea7db9419cefdf4c3a4bcc89bf904b patch-3.11.9.xz From 7306d34d3c20eb59faa02636c27ac14e5825fba2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 22 Nov 2013 13:35:39 -0500 Subject: [PATCH 469/492] Add patches from Jeff Layton to fix 15sec NFS mount hang --- kernel.spec | 13 + ...check-gssd-running-before-krb5i-auth.patch | 46 ++++ ...new-dummy-pipe-for-gssd-to-hold-open.patch | 231 ++++++++++++++++++ ...ssd_running-with-more-reliable-check.patch | 132 ++++++++++ 4 files changed, 422 insertions(+) create mode 100644 nfs-check-gssd-running-before-krb5i-auth.patch create mode 100644 sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch create mode 100644 sunrpc-replace-gssd_running-with-more-reliable-check.patch diff --git a/kernel.spec b/kernel.spec index 104dd57d4..df82c5909 100644 --- a/kernel.spec +++ b/kernel.spec @@ -807,6 +807,11 @@ Patch25150: slab_common-Do-not-check-for-duplicate-slab-names.patch #rhbz 967652 Patch25151: KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch +# Fix 15sec NFS mount delay +Patch25152: sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch +Patch25153: sunrpc-replace-gssd_running-with-more-reliable-check.patch +Patch25154: nfs-check-gssd-running-before-krb5i-auth.patch + # END OF PATCH DEFINITIONS %endif @@ -1551,6 +1556,11 @@ ApplyPatch slab_common-Do-not-check-for-duplicate-slab-names.patch #rhbz 967652 ApplyPatch KVM-x86-fix-emulation-of-movzbl-bpl-eax.patch +# Fix 15sec NFS mount delay +ApplyPatch sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch +ApplyPatch sunrpc-replace-gssd_running-with-more-reliable-check.patch +ApplyPatch nfs-check-gssd-running-before-krb5i-auth.patch + # END OF PATCH APPLICATIONS %endif @@ -2392,6 +2402,9 @@ fi # ||----w | # || || %changelog +* Fri Nov 22 2013 Josh Boyer +- Add patches from Jeff Layton to fix 15sec NFS mount hang + * Wed Nov 20 2013 Josh Boyer - 3.11.9-100 - Linux v3.11.9 diff --git a/nfs-check-gssd-running-before-krb5i-auth.patch b/nfs-check-gssd-running-before-krb5i-auth.patch new file mode 100644 index 000000000..d26d51233 --- /dev/null +++ b/nfs-check-gssd-running-before-krb5i-auth.patch @@ -0,0 +1,46 @@ + +Currently, the client will attempt to use krb5i in the SETCLIENTID call +even if rpc.gssd isn't running. When that fails, it'll then fall back to +RPC_AUTH_UNIX. This introduced a delay when mounting if rpc.gssd isn't +running, and causes warning messages to pop up in the ring buffer. + +Check to see if rpc.gssd is running before even attempting to use krb5i +auth, and just silently skip trying to do so if it isn't. In the event +that the admin is actually trying to mount with krb5*, it will still +fail at a later stage of the mount attempt. + +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4client.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff -up linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c.orig linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c +--- linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c 2013-11-21 10:20:27.288286000 -0500 +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include "internal.h" + #include "callback.h" + #include "delegation.h" +@@ -206,7 +207,11 @@ struct nfs_client *nfs4_init_client(stru + if (clp->cl_minorversion != 0) + __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); + __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); +- error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); ++ ++ error = -EINVAL; ++ if (gssd_running(clp->cl_net)) ++ error = nfs_create_rpc_client(clp, timeparms, ++ RPC_AUTH_GSS_KRB5I); + if (error == -EINVAL) + error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); + if (error < 0) + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel \ No newline at end of file diff --git a/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch b/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch new file mode 100644 index 000000000..559477fc2 --- /dev/null +++ b/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch @@ -0,0 +1,231 @@ + +rpc.gssd will naturally hold open any pipe named */clnt*/gssd that shows +up under rpc_pipefs. That behavior gives us a reliable mechanism to tell +whether it's actually running or not. + +Create a new toplevel "gssd" directory in rpc_pipefs when it's mounted. +Under that directory create another directory called "clntXX", and then +within that a pipe called "gssd". + +We'll never send an upcall along that pipe, and any downcall written to +it will just return -EINVAL. + +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +--- + include/linux/sunrpc/rpc_pipe_fs.h | 3 +- + net/sunrpc/netns.h | 1 + + net/sunrpc/rpc_pipe.c | 93 ++++++++++++++++++++++++++++++++++- + net/sunrpc/sunrpc_syms.c | 8 +++- + 4 files changed, 100 insertions(+), 5 deletions(-) + +diff -up linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h +--- linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h 2013-11-21 10:11:17.893026000 -0500 +@@ -64,7 +64,8 @@ enum { + + extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb, + const unsigned char *dir_name); +-extern void rpc_pipefs_init_net(struct net *net); ++extern int rpc_pipefs_init_net(struct net *net); ++extern void rpc_pipefs_exit_net(struct net *net); + extern struct super_block *rpc_get_sb_net(const struct net *net); + extern void rpc_put_sb_net(const struct net *net); + +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h 2013-11-21 10:11:17.897029000 -0500 +@@ -14,6 +14,7 @@ struct sunrpc_net { + struct cache_detail *rsi_cache; + + struct super_block *pipefs_sb; ++ struct rpc_pipe *gssd_dummy; + struct mutex pipefs_sb_lock; + + struct list_head all_clients; +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c 2013-11-21 10:11:17.903026000 -0500 +@@ -38,7 +38,7 @@ + #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") + + static struct file_system_type rpc_pipe_fs_type; +- ++static const struct rpc_pipe_ops gssd_dummy_pipe_ops; + + static struct kmem_cache *rpc_inode_cachep __read_mostly; + +@@ -1019,6 +1019,7 @@ enum { + RPCAUTH_nfsd4_cb, + RPCAUTH_cache, + RPCAUTH_nfsd, ++ RPCAUTH_gssd, + RPCAUTH_RootEOF + }; + +@@ -1055,6 +1056,10 @@ static const struct rpc_filelist files[] + .name = "nfsd", + .mode = S_IFDIR | S_IRUGO | S_IXUGO, + }, ++ [RPCAUTH_gssd] = { ++ .name = "gssd", ++ .mode = S_IFDIR | S_IRUGO | S_IXUGO, ++ }, + }; + + /* +@@ -1068,13 +1073,25 @@ struct dentry *rpc_d_lookup_sb(const str + } + EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); + +-void rpc_pipefs_init_net(struct net *net) ++int rpc_pipefs_init_net(struct net *net) + { + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + ++ sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0); ++ if (IS_ERR(sn->gssd_dummy)) ++ return PTR_ERR(sn->gssd_dummy); ++ + mutex_init(&sn->pipefs_sb_lock); + sn->gssd_running = 1; + sn->pipe_version = -1; ++ return 0; ++} ++ ++void rpc_pipefs_exit_net(struct net *net) ++{ ++ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); ++ ++ rpc_destroy_pipe_data(sn->gssd_dummy); + } + + /* +@@ -1104,11 +1121,73 @@ void rpc_put_sb_net(const struct net *ne + } + EXPORT_SYMBOL_GPL(rpc_put_sb_net); + ++static const struct rpc_filelist gssd_dummy_clnt_dir[] = { ++ [0] = { ++ .name = "clntXX", ++ .mode = S_IFDIR | S_IRUGO | S_IXUGO, ++ }, ++}; ++ ++static ssize_t ++dummy_downcall(struct file *filp, const char __user *src, size_t len) ++{ ++ return -EINVAL; ++} ++ ++static const struct rpc_pipe_ops gssd_dummy_pipe_ops = { ++ .upcall = rpc_pipe_generic_upcall, ++ .downcall = dummy_downcall, ++}; ++ ++/** ++ * rpc_gssd_dummy_populate - create a dummy gssd pipe ++ * @root: root of the rpc_pipefs filesystem ++ * @pipe_data: pipe data created when netns is initialized ++ * ++ * Create a dummy set of directories and a pipe that gssd can hold open to ++ * indicate that it is up and running. ++ */ ++static struct dentry * ++rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data) ++{ ++ int ret = 0; ++ struct dentry *gssd_dentry; ++ struct dentry *clnt_dentry = NULL; ++ struct dentry *pipe_dentry = NULL; ++ struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name, ++ strlen(files[RPCAUTH_gssd].name)); ++ ++ /* We should never get this far if "gssd" doesn't exist */ ++ gssd_dentry = d_hash_and_lookup(root, &q); ++ if (!gssd_dentry) ++ return ERR_PTR(-ENOENT); ++ ++ ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL); ++ if (ret) { ++ pipe_dentry = ERR_PTR(ret); ++ goto out; ++ } ++ ++ q.name = gssd_dummy_clnt_dir[0].name; ++ q.len = strlen(gssd_dummy_clnt_dir[0].name); ++ clnt_dentry = d_hash_and_lookup(gssd_dentry, &q); ++ if (!clnt_dentry) { ++ pipe_dentry = ERR_PTR(-ENOENT); ++ goto out; ++ } ++ ++ pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data); ++out: ++ dput(clnt_dentry); ++ dput(gssd_dentry); ++ return pipe_dentry; ++} ++ + static int + rpc_fill_super(struct super_block *sb, void *data, int silent) + { + struct inode *inode; +- struct dentry *root; ++ struct dentry *root, *gssd_dentry; + struct net *net = data; + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + int err; +@@ -1126,6 +1205,13 @@ rpc_fill_super(struct super_block *sb, v + return -ENOMEM; + if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) + return -ENOMEM; ++ ++ gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy); ++ if (IS_ERR(gssd_dentry)) { ++ __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); ++ return PTR_ERR(gssd_dentry); ++ } ++ + dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", + net, NET_NAME(net)); + mutex_lock(&sn->pipefs_sb_lock); +@@ -1140,6 +1226,7 @@ rpc_fill_super(struct super_block *sb, v + return 0; + + err_depopulate: ++ dput(gssd_dentry); + blocking_notifier_call_chain(&rpc_pipefs_notifier_list, + RPC_PIPEFS_UMOUNT, + sb); +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c 2013-11-21 10:11:17.908026000 -0500 +@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(st + if (err) + goto err_unixgid; + +- rpc_pipefs_init_net(net); ++ err = rpc_pipefs_init_net(net); ++ if (err) ++ goto err_pipefs; ++ + INIT_LIST_HEAD(&sn->all_clients); + spin_lock_init(&sn->rpc_client_lock); + spin_lock_init(&sn->rpcb_clnt_lock); + return 0; + ++err_pipefs: ++ unix_gid_cache_destroy(net); + err_unixgid: + ip_map_cache_destroy(net); + err_ipmap: +@@ -60,6 +65,7 @@ err_proc: + + static __net_exit void sunrpc_exit_net(struct net *net) + { ++ rpc_pipefs_exit_net(net); + unix_gid_cache_destroy(net); + ip_map_cache_destroy(net); + rpc_proc_exit(net); + diff --git a/sunrpc-replace-gssd_running-with-more-reliable-check.patch b/sunrpc-replace-gssd_running-with-more-reliable-check.patch new file mode 100644 index 000000000..82dd0853e --- /dev/null +++ b/sunrpc-replace-gssd_running-with-more-reliable-check.patch @@ -0,0 +1,132 @@ + +Now that we have a more reliable method to tell if gssd is running, we +can replace the sn->gssd_running flag with a function that will query to +see if it's up and running. + +There's also no need to attempt an upcall that we know will fail, so +just return -EACCES if gssd isn't running. Finally, fix the warn_gss() +message not to claim that that the upcall timed out since we don't +necesarily perform one now when gssd isn't running, and remove the +extraneous newline from the message. + +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +--- + include/linux/sunrpc/rpc_pipe_fs.h | 2 ++ + net/sunrpc/auth_gss/auth_gss.c | 17 +++++++---------- + net/sunrpc/netns.h | 2 -- + net/sunrpc/rpc_pipe.c | 14 ++++++++++---- + 4 files changed, 19 insertions(+), 16 deletions(-) + +diff -up linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h +--- linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig 2013-11-21 10:11:17.893026000 -0500 ++++ linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h 2013-11-21 10:14:17.709348000 -0500 +@@ -94,5 +94,7 @@ extern int rpc_unlink(struct dentry *); + extern int register_rpc_pipefs(void); + extern void unregister_rpc_pipefs(void); + ++extern bool gssd_running(struct net *net); ++ + #endif + #endif +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/auth_gss/auth_gss.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/auth_gss/auth_gss.c +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/auth_gss/auth_gss.c.orig 2013-09-02 16:46:10.000000000 -0400 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/auth_gss/auth_gss.c 2013-11-21 10:18:33.681923000 -0500 +@@ -507,8 +507,7 @@ static void warn_gssd(void) + unsigned long now = jiffies; + + if (time_after(now, ratelimit)) { +- printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n" +- "Please check user daemon is running.\n"); ++ pr_warn("RPC: AUTH_GSS upcall failed. Please check user daemon is running.\n"); + ratelimit = now + 15*HZ; + } + } +@@ -571,7 +570,6 @@ gss_create_upcall(struct gss_auth *gss_a + struct rpc_pipe *pipe; + struct rpc_cred *cred = &gss_cred->gc_base; + struct gss_upcall_msg *gss_msg; +- unsigned long timeout; + DEFINE_WAIT(wait); + int err; + +@@ -579,17 +577,16 @@ gss_create_upcall(struct gss_auth *gss_a + __func__, from_kuid(&init_user_ns, cred->cr_uid)); + retry: + err = 0; +- /* Default timeout is 15s unless we know that gssd is not running */ +- timeout = 15 * HZ; +- if (!sn->gssd_running) +- timeout = HZ >> 2; ++ /* if gssd is down, just skip upcalling altogether */ ++ if (!gssd_running(net)) { ++ warn_gssd(); ++ return -EACCES; ++ } + gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); + if (PTR_ERR(gss_msg) == -EAGAIN) { + err = wait_event_interruptible_timeout(pipe_version_waitqueue, +- sn->pipe_version >= 0, timeout); ++ sn->pipe_version >= 0, 15 * HZ); + if (sn->pipe_version < 0) { +- if (err == 0) +- sn->gssd_running = 0; + warn_gssd(); + err = -EACCES; + } +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig 2013-11-21 10:11:17.897029000 -0500 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h 2013-11-21 10:14:17.722351000 -0500 +@@ -33,8 +33,6 @@ struct sunrpc_net { + int pipe_version; + atomic_t pipe_users; + struct proc_dir_entry *use_gssp_proc; +- +- unsigned int gssd_running; + }; + + extern int sunrpc_net_id; +diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c +--- linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig 2013-11-21 10:11:17.903026000 -0500 ++++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c 2013-11-21 10:14:17.727348000 -0500 +@@ -216,14 +216,11 @@ rpc_destroy_inode(struct inode *inode) + static int + rpc_pipe_open(struct inode *inode, struct file *filp) + { +- struct net *net = inode->i_sb->s_fs_info; +- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + struct rpc_pipe *pipe; + int first_open; + int res = -ENXIO; + + mutex_lock(&inode->i_mutex); +- sn->gssd_running = 1; + pipe = RPC_I(inode)->pipe; + if (pipe == NULL) + goto out; +@@ -1082,7 +1079,6 @@ int rpc_pipefs_init_net(struct net *net) + return PTR_ERR(sn->gssd_dummy); + + mutex_init(&sn->pipefs_sb_lock); +- sn->gssd_running = 1; + sn->pipe_version = -1; + return 0; + } +@@ -1236,6 +1232,16 @@ err_depopulate: + return err; + } + ++bool ++gssd_running(struct net *net) ++{ ++ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); ++ struct rpc_pipe *pipe = sn->gssd_dummy; ++ ++ return pipe->nreaders || pipe->nwriters; ++} ++EXPORT_SYMBOL_GPL(gssd_running); ++ + static struct dentry * + rpc_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + From c476786b43337b84a2af2879d86d7e6a39d53ed0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 22 Nov 2013 14:23:22 -0500 Subject: [PATCH 470/492] Add bugzilla and upstream-status fields to nfs patches --- nfs-check-gssd-running-before-krb5i-auth.patch | 4 +++- sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch | 2 ++ sunrpc-replace-gssd_running-with-more-reliable-check.patch | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/nfs-check-gssd-running-before-krb5i-auth.patch b/nfs-check-gssd-running-before-krb5i-auth.patch index d26d51233..be81fec76 100644 --- a/nfs-check-gssd-running-before-krb5i-auth.patch +++ b/nfs-check-gssd-running-before-krb5i-auth.patch @@ -1,3 +1,5 @@ +Bugzilla: N/A +Upstream-status: queued in NFS git tree (for 3.13/3.14?) Currently, the client will attempt to use krb5i in the SETCLIENTID call even if rpc.gssd isn't running. When that fails, it'll then fall back to @@ -43,4 +45,4 @@ diff -up linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c.orig linux-3.11.9-200. _______________________________________________ kernel mailing list kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel \ No newline at end of file +https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch b/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch index 559477fc2..805498a70 100644 --- a/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch +++ b/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch @@ -1,3 +1,5 @@ +Bugzilla: N/A +Upstream-status: queued in NFS git tree (for 3.13/3.14?) rpc.gssd will naturally hold open any pipe named */clnt*/gssd that shows up under rpc_pipefs. That behavior gives us a reliable mechanism to tell diff --git a/sunrpc-replace-gssd_running-with-more-reliable-check.patch b/sunrpc-replace-gssd_running-with-more-reliable-check.patch index 82dd0853e..f2ca18555 100644 --- a/sunrpc-replace-gssd_running-with-more-reliable-check.patch +++ b/sunrpc-replace-gssd_running-with-more-reliable-check.patch @@ -1,3 +1,5 @@ +Bugzilla: N/A +Upstream-status: queued in NFS git tree (for 3.13/3.14?) Now that we have a more reliable method to tell if gssd is running, we can replace the sn->gssd_running flag with a function that will query to From e76774d6396aae653788da5996830ad31227c344 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Nov 2013 08:21:51 -0500 Subject: [PATCH 471/492] CVE-2013-6378 libertas: potential oops in debugfs (rhbz 1033578 1034183) --- kernel.spec | 9 +++++ libertas-potential-oops-in-debugfs.patch | 50 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 libertas-potential-oops-in-debugfs.patch diff --git a/kernel.spec b/kernel.spec index df82c5909..1ad24440b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -812,6 +812,9 @@ Patch25152: sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch Patch25153: sunrpc-replace-gssd_running-with-more-reliable-check.patch Patch25154: nfs-check-gssd-running-before-krb5i-auth.patch +#CVE-2013-6378 rhbz 1033578 1034183 +Patch25155: libertas-potential-oops-in-debugfs.patch + # END OF PATCH DEFINITIONS %endif @@ -1561,6 +1564,9 @@ ApplyPatch sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch ApplyPatch sunrpc-replace-gssd_running-with-more-reliable-check.patch ApplyPatch nfs-check-gssd-running-before-krb5i-auth.patch +#CVE-2013-6378 rhbz 1033578 1034183 +ApplyPatch libertas-potential-oops-in-debugfs.patch + # END OF PATCH APPLICATIONS %endif @@ -2402,6 +2408,9 @@ fi # ||----w | # || || %changelog +* Mon Nov 25 2013 Josh Boyer +- CVE-2013-6378 libertas: potential oops in debugfs (rhbz 1033578 1034183) + * Fri Nov 22 2013 Josh Boyer - Add patches from Jeff Layton to fix 15sec NFS mount hang diff --git a/libertas-potential-oops-in-debugfs.patch b/libertas-potential-oops-in-debugfs.patch new file mode 100644 index 000000000..02e72d8f9 --- /dev/null +++ b/libertas-potential-oops-in-debugfs.patch @@ -0,0 +1,50 @@ +Bugzilla: 1034183 +Upstream-status: 3.13 + +From a497e47d4aec37aaf8f13509f3ef3d1f6a717d88 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 30 Oct 2013 20:12:51 +0300 +Subject: [PATCH] libertas: potential oops in debugfs + +If we do a zero size allocation then it will oops. Also we can't be +sure the user passes us a NUL terminated string so I've added a +terminator. + +This code can only be triggered by root. + +Reported-by: Nico Golde +Reported-by: Fabian Yamaguchi +Signed-off-by: Dan Carpenter +Acked-by: Dan Williams +Signed-off-by: John W. Linville +--- + drivers/net/wireless/libertas/debugfs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c +index 668dd27..cc6a0a5 100644 +--- a/drivers/net/wireless/libertas/debugfs.c ++++ b/drivers/net/wireless/libertas/debugfs.c +@@ -913,7 +913,10 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, + char *p2; + struct debug_data *d = f->private_data; + +- pdata = kmalloc(cnt, GFP_KERNEL); ++ if (cnt == 0) ++ return 0; ++ ++ pdata = kmalloc(cnt + 1, GFP_KERNEL); + if (pdata == NULL) + return 0; + +@@ -922,6 +925,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, + kfree(pdata); + return 0; + } ++ pdata[cnt] = '\0'; + + p0 = pdata; + for (i = 0; i < num_of_items; i++) { +-- +1.8.3.1 + From 457c7156db59d851bfe81b7b1c79f1129b90a603 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 25 Nov 2013 11:34:44 -0500 Subject: [PATCH 472/492] CVE-2013-6380 aacraid: invalid pointer dereference (rhbz 1033593 1034304) --- ...-prevent-invalid-pointer-dereference.patch | 42 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 49 insertions(+) create mode 100644 aacraid-prevent-invalid-pointer-dereference.patch diff --git a/aacraid-prevent-invalid-pointer-dereference.patch b/aacraid-prevent-invalid-pointer-dereference.patch new file mode 100644 index 000000000..f5517aba9 --- /dev/null +++ b/aacraid-prevent-invalid-pointer-dereference.patch @@ -0,0 +1,42 @@ +Bugzilla: 1033593 +Upstream-status: 3.13 + +From b4789b8e6be3151a955ade74872822f30e8cd914 Mon Sep 17 00:00:00 2001 +From: Mahesh Rajashekhara +Date: Thu, 31 Oct 2013 14:01:02 +0530 +Subject: [PATCH] aacraid: prevent invalid pointer dereference + +It appears that driver runs into a problem here if fibsize is too small +because we allocate user_srbcmd with fibsize size only but later we +access it until user_srbcmd->sg.count to copy it over to srbcmd. + +It is not correct to test (fibsize < sizeof(*user_srbcmd)) because this +structure already includes one sg element and this is not needed for +commands without data. So, we would recommend to add the following +(instead of test for fibsize == 0). + +Signed-off-by: Mahesh Rajashekhara +Reported-by: Nico Golde +Reported-by: Fabian Yamaguchi +Signed-off-by: Linus Torvalds +--- + drivers/scsi/aacraid/commctrl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c +index d85ac1a..fbcd48d 100644 +--- a/drivers/scsi/aacraid/commctrl.c ++++ b/drivers/scsi/aacraid/commctrl.c +@@ -511,7 +511,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) + goto cleanup; + } + +- if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) { ++ if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || ++ (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { + rcode = -EINVAL; + goto cleanup; + } +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 1ad24440b..ccb68ea99 100644 --- a/kernel.spec +++ b/kernel.spec @@ -815,6 +815,9 @@ Patch25154: nfs-check-gssd-running-before-krb5i-auth.patch #CVE-2013-6378 rhbz 1033578 1034183 Patch25155: libertas-potential-oops-in-debugfs.patch +#CVE-2013-6380 rhbz 1033593 1034304 +Patch25156: aacraid-prevent-invalid-pointer-dereference.patch + # END OF PATCH DEFINITIONS %endif @@ -1567,6 +1570,9 @@ ApplyPatch nfs-check-gssd-running-before-krb5i-auth.patch #CVE-2013-6378 rhbz 1033578 1034183 ApplyPatch libertas-potential-oops-in-debugfs.patch +#CVE-2013-6380 rhbz 1033593 1034304 +ApplyPatch aacraid-prevent-invalid-pointer-dereference.patch + # END OF PATCH APPLICATIONS %endif @@ -2409,6 +2415,7 @@ fi # || || %changelog * Mon Nov 25 2013 Josh Boyer +- CVE-2013-6380 aacraid: invalid pointer dereference (rhbz 1033593 1034304) - CVE-2013-6378 libertas: potential oops in debugfs (rhbz 1033578 1034183) * Fri Nov 22 2013 Josh Boyer From 56372cd7642f8c3cf9d7129adfe63fd069d27ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Tue, 26 Nov 2013 14:10:37 +0100 Subject: [PATCH 473/492] x86_64-generic - remove duplicate options --- config-x86_64-generic | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config-x86_64-generic b/config-x86_64-generic index 85f588bc1..b1bfed734 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -145,11 +145,6 @@ CONFIG_CHECKPOINT_RESTORE=y CONFIG_NTB=m CONFIG_NTB_NETDEV=m -CONFIG_SFC=m -CONFIG_SFC_MCDI_MON=y -CONFIG_SFC_SRIOV=y -CONFIG_SFC_PTP=y - # 10GigE # CONFIG_IP1000=m From 05b8b9945b5ae60fd947b3bc6dc852c755feac4e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Nov 2013 12:20:03 -0500 Subject: [PATCH 474/492] CVE-2013-6382 xfs: missing check for ZERO_SIZE_PTR (rhbz 1033603 1034670) --- kernel.spec | 9 ++ ...erflow-bug-in-xfs_attrlist_by_handle.patch | 149 ++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 xfs-underflow-bug-in-xfs_attrlist_by_handle.patch diff --git a/kernel.spec b/kernel.spec index ccb68ea99..4d51140b8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -818,6 +818,9 @@ Patch25155: libertas-potential-oops-in-debugfs.patch #CVE-2013-6380 rhbz 1033593 1034304 Patch25156: aacraid-prevent-invalid-pointer-dereference.patch +#CVE-2013-6382 rhbz 1033603 1034670 +Patch25157: xfs-underflow-bug-in-xfs_attrlist_by_handle.patch + # END OF PATCH DEFINITIONS %endif @@ -1573,6 +1576,9 @@ ApplyPatch libertas-potential-oops-in-debugfs.patch #CVE-2013-6380 rhbz 1033593 1034304 ApplyPatch aacraid-prevent-invalid-pointer-dereference.patch +#CVE-2013-6382 rhbz 1033603 1034670 +ApplyPatch xfs-underflow-bug-in-xfs_attrlist_by_handle.patch + # END OF PATCH APPLICATIONS %endif @@ -2414,6 +2420,9 @@ fi # ||----w | # || || %changelog +* Tue Nov 26 2013 Josh Boyer +- CVE-2013-6382 xfs: missing check for ZERO_SIZE_PTR (rhbz 1033603 1034670) + * Mon Nov 25 2013 Josh Boyer - CVE-2013-6380 aacraid: invalid pointer dereference (rhbz 1033593 1034304) - CVE-2013-6378 libertas: potential oops in debugfs (rhbz 1033578 1034183) diff --git a/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch b/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch new file mode 100644 index 000000000..6c7f60dd9 --- /dev/null +++ b/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch @@ -0,0 +1,149 @@ +Bugzilla: 1033603 +Upstream-status: Submitted but not queued http://thread.gmane.org/gmane.comp.file-systems.xfs.general/57654 + +Path: news.gmane.org!not-for-mail +From: Dan Carpenter +Newsgroups: gmane.comp.file-systems.xfs.general +Subject: [patch] xfs: underflow bug in xfs_attrlist_by_handle() +Date: Thu, 31 Oct 2013 21:00:10 +0300 +Lines: 43 +Approved: news@gmane.org +Message-ID: <20131031180010.GA24839@longonot.mountain> +References: <20131025144452.GA28451@ngolde.de> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1383242609 27303 80.91.229.3 (31 Oct 2013 18:03:29 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Thu, 31 Oct 2013 18:03:29 +0000 (UTC) +Cc: Fabian Yamaguchi , security@kernel.org, + Alex Elder , Nico Golde , xfs@oss.sgi.com +To: Ben Myers +Original-X-From: xfs-bounces@oss.sgi.com Thu Oct 31 19:03:33 2013 +Return-path: +Envelope-to: sgi-linux-xfs@gmane.org +Original-Received: from oss.sgi.com ([192.48.182.195]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Vbwag-0001Ow-Sv + for sgi-linux-xfs@gmane.org; Thu, 31 Oct 2013 19:03:31 +0100 +Original-Received: from oss.sgi.com (localhost [IPv6:::1]) + by oss.sgi.com (Postfix) with ESMTP id DB14A7F85; + Thu, 31 Oct 2013 13:03:28 -0500 (CDT) +X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com +X-Spam-Level: +X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY + autolearn=ham version=3.3.1 +X-Original-To: xfs@oss.sgi.com +Delivered-To: xfs@oss.sgi.com +Original-Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) + by oss.sgi.com (Postfix) with ESMTP id A0ED87F83 + for ; Thu, 31 Oct 2013 13:03:27 -0500 (CDT) +Original-Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) + by relay1.corp.sgi.com (Postfix) with ESMTP id 71E0A8F804B + for ; Thu, 31 Oct 2013 11:03:24 -0700 (PDT) +X-ASG-Debug-ID: 1383242599-04bdf0789a41ef30001-NocioJ +Original-Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by + cuda.sgi.com with ESMTP id CWKetu2Mc6MhJZij (version=TLSv1 + cipher=AES256-SHA bits=256 verify=NO); + Thu, 31 Oct 2013 11:03:20 -0700 (PDT) +X-Barracuda-Envelope-From: dan.carpenter@oracle.com +X-Barracuda-Apparent-Source-IP: 156.151.31.81 +Original-Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) + by userp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with + ESMTP id r9VI3AZn009606 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Thu, 31 Oct 2013 18:03:11 GMT +Original-Received: from aserz7022.oracle.com (aserz7022.oracle.com [141.146.126.231]) + by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id + r9VI39qG016923 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); + Thu, 31 Oct 2013 18:03:10 GMT +Original-Received: from abhmt101.oracle.com (abhmt101.oracle.com [141.146.116.53]) + by aserz7022.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id + r9VI395m016915; Thu, 31 Oct 2013 18:03:09 GMT +Original-Received: from longonot.mountain (/105.160.144.228) + by default (Oracle Beehive Gateway v4.0) + with ESMTP ; Thu, 31 Oct 2013 11:03:08 -0700 +X-ASG-Orig-Subj: [patch] xfs: underflow bug in xfs_attrlist_by_handle() +Content-Disposition: inline +In-Reply-To: <20131025144452.GA28451@ngolde.de> +User-Agent: Mutt/1.5.21 (2010-09-15) +X-Source-IP: acsinet22.oracle.com [141.146.126.238] +X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] +X-Barracuda-Start-Time: 1383242600 +X-Barracuda-Encrypted: AES256-SHA +X-Barracuda-URL: http://192.48.157.11:80/cgi-mod/mark.cgi +X-Virus-Scanned: by bsmtpd at sgi.com +X-Barracuda-BRTS-Status: 1 +X-Barracuda-Spam-Score: 0.00 +X-Barracuda-Spam-Status: No, + SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 + QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=UNPARSEABLE_RELAY +X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.141937 + Rule breakdown below + pts rule name description + ---- ---------------------- + -------------------------------------------------- + 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay + lines +X-BeenThere: xfs@oss.sgi.com +X-Mailman-Version: 2.1.14 +Precedence: list +List-Id: XFS Filesystem from SGI +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Errors-To: xfs-bounces@oss.sgi.com +Original-Sender: xfs-bounces@oss.sgi.com +Xref: news.gmane.org gmane.comp.file-systems.xfs.general:57654 +Archived-At: + +If we allocate less than sizeof(struct attrlist) then we end up +corrupting memory or doing a ZERO_PTR_SIZE dereference. + +This can only be triggered with CAP_SYS_ADMIN. + +Reported-by: Nico Golde +Reported-by: Fabian Yamaguchi +Signed-off-by: Dan Carpenter + +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 4d61340..33ad9a7 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -442,7 +442,8 @@ xfs_attrlist_by_handle( + return -XFS_ERROR(EPERM); + if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t))) + return -XFS_ERROR(EFAULT); +- if (al_hreq.buflen > XATTR_LIST_MAX) ++ if (al_hreq.buflen < sizeof(struct attrlist) || ++ al_hreq.buflen > XATTR_LIST_MAX) + return -XFS_ERROR(EINVAL); + + /* +diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c +index e8fb123..a7992f8 100644 +--- a/fs/xfs/xfs_ioctl32.c ++++ b/fs/xfs/xfs_ioctl32.c +@@ -356,7 +356,8 @@ xfs_compat_attrlist_by_handle( + if (copy_from_user(&al_hreq, arg, + sizeof(compat_xfs_fsop_attrlist_handlereq_t))) + return -XFS_ERROR(EFAULT); +- if (al_hreq.buflen > XATTR_LIST_MAX) ++ if (al_hreq.buflen < sizeof(struct attrlist) || ++ al_hreq.buflen > XATTR_LIST_MAX) + return -XFS_ERROR(EINVAL); + + /* + +_______________________________________________ +xfs mailing list +xfs@oss.sgi.com +http://oss.sgi.com/mailman/listinfo/xfs + From 5b9366d603bd9aa7b8c9fc919f94441ae98f5c95 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Nov 2013 13:59:14 -0500 Subject: [PATCH 475/492] Fix crash in via-velocity driver (rhbz 1022733) --- kernel.spec | 7 + ...netif_receive_skb-use-in-irq-disable.patch | 121 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch diff --git a/kernel.spec b/kernel.spec index 4d51140b8..a6a1bf947 100644 --- a/kernel.spec +++ b/kernel.spec @@ -821,6 +821,9 @@ Patch25156: aacraid-prevent-invalid-pointer-dereference.patch #CVE-2013-6382 rhbz 1033603 1034670 Patch25157: xfs-underflow-bug-in-xfs_attrlist_by_handle.patch +#rhbz 1022733 +Patch25158: via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch + # END OF PATCH DEFINITIONS %endif @@ -1579,6 +1582,9 @@ ApplyPatch aacraid-prevent-invalid-pointer-dereference.patch #CVE-2013-6382 rhbz 1033603 1034670 ApplyPatch xfs-underflow-bug-in-xfs_attrlist_by_handle.patch +#rhbz 1022733 +ApplyPatch via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch + # END OF PATCH APPLICATIONS %endif @@ -2421,6 +2427,7 @@ fi # || || %changelog * Tue Nov 26 2013 Josh Boyer +- Fix crash in via-velocity driver (rhbz 1022733) - CVE-2013-6382 xfs: missing check for ZERO_SIZE_PTR (rhbz 1033603 1034670) * Mon Nov 25 2013 Josh Boyer diff --git a/via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch b/via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch new file mode 100644 index 000000000..820f47056 --- /dev/null +++ b/via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch @@ -0,0 +1,121 @@ +Bugzilla: 1022733 +Upstream: Submitted for 3.13 and 3.12.y stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp116929oab; + Mon, 25 Nov 2013 15:45:36 -0800 (PST) +X-Received: by 10.68.254.105 with SMTP id ah9mr20726084pbd.87.1385423136297; + Mon, 25 Nov 2013 15:45:36 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id am2si28999873pad.96.2013.11.25.15.44.53 + for ; + Mon, 25 Nov 2013 15:45:36 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=netdev-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753536Ab3KYXl6 (ORCPT + 99 others); + Mon, 25 Nov 2013 18:41:58 -0500 +Received: from violet.fr.zoreil.com ([92.243.8.30]:57806 "EHLO + violet.fr.zoreil.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751913Ab3KYXlz (ORCPT + ); Mon, 25 Nov 2013 18:41:55 -0500 +Received: from violet.fr.zoreil.com (localhost [127.0.0.1]) + by violet.fr.zoreil.com (8.14.5/8.14.5) with ESMTP id rAPNewrt012676; + Tue, 26 Nov 2013 00:40:58 +0100 +Received: (from romieu@localhost) + by violet.fr.zoreil.com (8.14.5/8.14.5/Submit) id rAPNewbX012675; + Tue, 26 Nov 2013 00:40:58 +0100 +Date: Tue, 26 Nov 2013 00:40:58 +0100 +From: Francois Romieu +To: netdev@vger.kernel.org +Cc: David Miller , + "Alex A. Schmidt" , + Michele Baldessari , + Jamie Heilman , + Julia Lawall +Subject: [PATCH net 1/1] via-velocity: fix netif_receive_skb use in irq + disabled section. +Message-ID: <20131125234058.GA12566@electric-eye.fr.zoreil.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +X-Organisation: Land of Sunshine Inc. +User-Agent: Mutt/1.5.21 (2010-09-15) +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +2fdac010bdcf10a30711b6924612dfc40daf19b8 ("via-velocity.c: update napi +implementation") overlooked an irq disabling spinlock when the Rx part +of the NAPI poll handler was converted from netif_rx to netif_receive_skb. + +NAPI Rx processing can be taken out of the locked section with a pair of +napi_{disable / enable} since it only races with the MTU change function. + +An heavier rework of the NAPI locking would be able to perform NAPI Tx +before Rx where I simply removed one of velocity_tx_srv calls. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1022733 +Fixes: 2fdac010bdcf (via-velocity.c: update napi implementation) +Signed-off-by: Francois Romieu +Tested-by: Alex A. Schmidt +Cc: Jamie Heilman +Cc: Michele Baldessari +Cc: Julia Lawall +--- + + It is relevant for stable 3.11.x and 3.12.y. + + drivers/net/ethernet/via/via-velocity.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c +index d022bf9..ad61d26 100644 +--- a/drivers/net/ethernet/via/via-velocity.c ++++ b/drivers/net/ethernet/via/via-velocity.c +@@ -2172,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget) + unsigned int rx_done; + unsigned long flags; + +- spin_lock_irqsave(&vptr->lock, flags); + /* + * Do rx and tx twice for performance (taken from the VIA + * out-of-tree driver). + */ +- rx_done = velocity_rx_srv(vptr, budget / 2); +- velocity_tx_srv(vptr); +- rx_done += velocity_rx_srv(vptr, budget - rx_done); ++ rx_done = velocity_rx_srv(vptr, budget); ++ spin_lock_irqsave(&vptr->lock, flags); + velocity_tx_srv(vptr); +- + /* If budget not fully consumed, exit the polling mode */ + if (rx_done < budget) { + napi_complete(napi); +@@ -2342,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) + if (ret < 0) + goto out_free_tmp_vptr_1; + ++ napi_disable(&vptr->napi); ++ + spin_lock_irqsave(&vptr->lock, flags); + + netif_stop_queue(dev); +@@ -2362,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) + + velocity_give_many_rx_descs(vptr); + ++ napi_enable(&vptr->napi); ++ + mac_enable_int(vptr->mac_regs); + netif_start_queue(dev); + +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe netdev" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html From fdd4605b142461905f7d88feff6fafed74143484 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Nov 2013 14:22:21 -0500 Subject: [PATCH 476/492] Add patch to fix usbnet URB handling (rhbz 998342) --- kernel.spec | 7 ++++ ...et-fix-status-interrupt-urb-handling.patch | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 usbnet-fix-status-interrupt-urb-handling.patch diff --git a/kernel.spec b/kernel.spec index a6a1bf947..0783267db 100644 --- a/kernel.spec +++ b/kernel.spec @@ -824,6 +824,9 @@ Patch25157: xfs-underflow-bug-in-xfs_attrlist_by_handle.patch #rhbz 1022733 Patch25158: via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch +#rhbz 998342 +Patch25159: usbnet-fix-status-interrupt-urb-handling.patch + # END OF PATCH DEFINITIONS %endif @@ -1585,6 +1588,9 @@ ApplyPatch xfs-underflow-bug-in-xfs_attrlist_by_handle.patch #rhbz 1022733 ApplyPatch via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch +#rhbz 998342 +ApplyPatch usbnet-fix-status-interrupt-urb-handling.patch + # END OF PATCH APPLICATIONS %endif @@ -2427,6 +2433,7 @@ fi # || || %changelog * Tue Nov 26 2013 Josh Boyer +- Add patch to fix usbnet URB handling (rhbz 998342) - Fix crash in via-velocity driver (rhbz 1022733) - CVE-2013-6382 xfs: missing check for ZERO_SIZE_PTR (rhbz 1033603 1034670) diff --git a/usbnet-fix-status-interrupt-urb-handling.patch b/usbnet-fix-status-interrupt-urb-handling.patch new file mode 100644 index 000000000..74bf3978d --- /dev/null +++ b/usbnet-fix-status-interrupt-urb-handling.patch @@ -0,0 +1,37 @@ +From 52f48d0d9aaa621ffa5e08d79da99a3f8c93b848 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Tue, 12 Nov 2013 16:34:41 +0100 +Subject: [PATCH] usbnet: fix status interrupt urb handling + +Since commit 7b0c5f21f348a66de495868b8df0284e8dfd6bbf +"sierra_net: keep status interrupt URB active", sierra_net triggers +status interrupt polling before the net_device is opened (in order to +properly receive the sync message response). + +To be able to receive further interrupts, the interrupt urb needs to be +re-submitted, so this patch removes the bogus check for netif_running(). + +Signed-off-by: Felix Fietkau +Tested-by: Dan Williams +Signed-off-by: David S. Miller +--- + drivers/net/usb/usbnet.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 90a429b..8494bb5 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -204,9 +204,6 @@ static void intr_complete (struct urb *urb) + break; + } + +- if (!netif_running (dev->net)) +- return; +- + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status != 0) + netif_err(dev, timer, dev->net, +-- +1.8.3.1 + From df42286ed7ab7cb1c9935ff4c1a7ce583096a326 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 29 Nov 2013 10:23:44 -0500 Subject: [PATCH 477/492] Fix memory leak in qxl (from Dave Airlie) --- ...memory-leak-in-release-list-handling.patch | 27 +++++++++++++++++++ kernel.spec | 5 ++++ 2 files changed, 32 insertions(+) create mode 100644 drm-qxl-fix-memory-leak-in-release-list-handling.patch diff --git a/drm-qxl-fix-memory-leak-in-release-list-handling.patch b/drm-qxl-fix-memory-leak-in-release-list-handling.patch new file mode 100644 index 000000000..542d0276d --- /dev/null +++ b/drm-qxl-fix-memory-leak-in-release-list-handling.patch @@ -0,0 +1,27 @@ +From 1b28c3e628315ac0d9ef2d3fac0403f05ae692db Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 28 Nov 2013 05:39:03 +0000 +Subject: drm/qxl: fix memory leak in release list handling + +wow no idea how I got this far without seeing this, +leaking the entries in the list makes kmalloc-64 slab grow. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=65121 +Cc: stable@vger.kernel.org +Reported-by: Matthew Stapleton +Signed-off-by: Dave Airlie +--- +diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c +index 0109a96..821ab7b 100644 +--- a/drivers/gpu/drm/qxl/qxl_release.c ++++ b/drivers/gpu/drm/qxl/qxl_release.c +@@ -92,6 +92,7 @@ qxl_release_free(struct qxl_device *qdev, + - DRM_FILE_OFFSET); + qxl_fence_remove_release(&bo->fence, release->id); + qxl_bo_unref(&bo); ++ kfree(entry); + } + spin_lock(&qdev->release_idr_lock); + idr_remove(&qdev->release_idr, release->id); +-- +cgit v0.9.0.2-2-gbebe diff --git a/kernel.spec b/kernel.spec index 0783267db..8428571ee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,7 @@ Patch25137: cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch Patch25143: drm-qxl-backport-fixes-for-Fedora.patch +Patch25160: drm-qxl-fix-memory-leak-in-release-list-handling.patch Patch25144: Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch @@ -1552,6 +1553,7 @@ ApplyPatch cifs-Allow-LANMAN-auth-for-unencapsulated-auth-methods.patch ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch +ApplyPatch drm-qxl-fix-memory-leak-in-release-list-handling.patch ApplyPatch Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch @@ -2432,6 +2434,9 @@ fi # ||----w | # || || %changelog +* Fri Nov 29 2013 Josh Boyer +- Fix memory leak in qxl (from Dave Airlie) + * Tue Nov 26 2013 Josh Boyer - Add patch to fix usbnet URB handling (rhbz 998342) - Fix crash in via-velocity driver (rhbz 1022733) From 6f3bcbea0d949b8560db0c6096cefd9a385079b1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 29 Nov 2013 14:00:07 -0500 Subject: [PATCH 478/492] Linux v3.11.10 --- ...-prevent-invalid-pointer-dereference.patch | 42 ------------- ...-one-error-in-non-block-size-request.patch | 40 ------------- ...ate-csums-properly-with-prealloc-ext.patch | 60 ------------------- kernel.spec | 29 +-------- libertas-potential-oops-in-debugfs.patch | 50 ---------------- sources | 2 +- 6 files changed, 4 insertions(+), 219 deletions(-) delete mode 100644 aacraid-prevent-invalid-pointer-dereference.patch delete mode 100644 ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch delete mode 100644 btrfs-relocate-csums-properly-with-prealloc-ext.patch delete mode 100644 libertas-potential-oops-in-debugfs.patch diff --git a/aacraid-prevent-invalid-pointer-dereference.patch b/aacraid-prevent-invalid-pointer-dereference.patch deleted file mode 100644 index f5517aba9..000000000 --- a/aacraid-prevent-invalid-pointer-dereference.patch +++ /dev/null @@ -1,42 +0,0 @@ -Bugzilla: 1033593 -Upstream-status: 3.13 - -From b4789b8e6be3151a955ade74872822f30e8cd914 Mon Sep 17 00:00:00 2001 -From: Mahesh Rajashekhara -Date: Thu, 31 Oct 2013 14:01:02 +0530 -Subject: [PATCH] aacraid: prevent invalid pointer dereference - -It appears that driver runs into a problem here if fibsize is too small -because we allocate user_srbcmd with fibsize size only but later we -access it until user_srbcmd->sg.count to copy it over to srbcmd. - -It is not correct to test (fibsize < sizeof(*user_srbcmd)) because this -structure already includes one sg element and this is not needed for -commands without data. So, we would recommend to add the following -(instead of test for fibsize == 0). - -Signed-off-by: Mahesh Rajashekhara -Reported-by: Nico Golde -Reported-by: Fabian Yamaguchi -Signed-off-by: Linus Torvalds ---- - drivers/scsi/aacraid/commctrl.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c -index d85ac1a..fbcd48d 100644 ---- a/drivers/scsi/aacraid/commctrl.c -+++ b/drivers/scsi/aacraid/commctrl.c -@@ -511,7 +511,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) - goto cleanup; - } - -- if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) { -+ if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || -+ (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { - rcode = -EINVAL; - goto cleanup; - } --- -1.8.3.1 - diff --git a/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch b/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch deleted file mode 100644 index c8d015491..000000000 --- a/ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch +++ /dev/null @@ -1,40 +0,0 @@ -Stephan Mueller reported to me recently a error in random number generation in -the ansi cprng. If several small requests are made that are less than the -instances block size, the remainder for loop code doesn't increment -rand_data_valid in the last iteration, meaning that the last bytes in the -rand_data buffer gets reused on the subsequent smaller-than-a-block request for -random data. - -The fix is pretty easy, just re-code the for loop to make sure that -rand_data_valid gets incremented appropriately - -Signed-off-by: Neil Horman -Reported-by: Stephan Mueller -CC: Stephan Mueller -CC: Petr Matousek -CC: Herbert Xu -CC: "David S. Miller" ---- - crypto/ansi_cprng.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c -index c0bb377..666f196 100644 ---- a/crypto/ansi_cprng.c -+++ b/crypto/ansi_cprng.c -@@ -230,11 +230,11 @@ remainder: - */ - if (byte_count < DEFAULT_BLK_SZ) { - empty_rbuf: -- for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; -- ctx->rand_data_valid++) { -+ while (ctx->rand_data_valid < DEFAULT_BLK_SZ) { - *ptr = ctx->rand_data[ctx->rand_data_valid]; - ptr++; - byte_count--; -+ ctx->rand_data_valid++; - if (byte_count == 0) - goto done; - } --- -1.8.3.1 diff --git a/btrfs-relocate-csums-properly-with-prealloc-ext.patch b/btrfs-relocate-csums-properly-with-prealloc-ext.patch deleted file mode 100644 index e103f703a..000000000 --- a/btrfs-relocate-csums-properly-with-prealloc-ext.patch +++ /dev/null @@ -1,60 +0,0 @@ -A user reported a problem where they were getting csum errors when running a -balance and running systemd's journal. This is because systemd is awesome and -fallocate()'s its log space and writes into it. Unfortunately we assume that -when we read in all the csums for an extent that they are sequential starting at -the bytenr we care about. This obviously isn't the case for prealloc extents, -where we could have written to the middle of the prealloc extent only, which -means the csum would be for the bytenr in the middle of our range and not the -front of our range. Fix this by offsetting the new bytenr we are logging to -based on the original bytenr the csum was for. With this patch I no longer see -the csum errors I was seeing. Thanks, - -Cc: stable@xxxxxxxxxxxxxxx -Reported-by: Chris Murphy -Signed-off-by: Josef Bacik ---- - fs/btrfs/relocation.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c -index 5ca7ea9..b7afeaa 100644 ---- a/fs/btrfs/relocation.c -+++ b/fs/btrfs/relocation.c -@@ -4472,6 +4472,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) - struct btrfs_root *root = BTRFS_I(inode)->root; - int ret; - u64 disk_bytenr; -+ u64 new_bytenr; - LIST_HEAD(list); - - ordered = btrfs_lookup_ordered_extent(inode, file_pos); -@@ -4483,13 +4484,24 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) - if (ret) - goto out; - -- disk_bytenr = ordered->start; - while (!list_empty(&list)) { - sums = list_entry(list.next, struct btrfs_ordered_sum, list); - list_del_init(&sums->list); - -- sums->bytenr = disk_bytenr; -- disk_bytenr += sums->len; -+ /* -+ * We need to offset the new_bytenr based on where the csum is. -+ * We need to do this because we will read in entire prealloc -+ * extents but we may have written to say the middle of the -+ * prealloc extent, so we need to make sure the csum goes with -+ * the right disk offset. -+ * -+ * We can do this because the data reloc inode refers strictly -+ * to the on disk bytes, so we don't have to worry about -+ * disk_len vs real len like with real inodes since it's all -+ * disk length. -+ */ -+ new_bytenr = ordered->start + (sums->bytenr - disk_bytenr); -+ sums->bytenr = new_bytenr; - - btrfs_add_ordered_sum(inode, ordered, sums); - } --- -1.8.3.1 diff --git a/kernel.spec b/kernel.spec index 8428571ee..f6755f784 100644 --- a/kernel.spec +++ b/kernel.spec @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -733,9 +733,6 @@ Patch25057: iwl4965-better-skb-management-in-rx-path.patch #rhbz 963715 Patch25077: media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-4345 rhbz 1007690 1009136 -Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch - #rhbz 971893 Patch25106: bonding-driver-alb-learning.patch @@ -772,9 +769,6 @@ Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch Patch25130: fix-radeon-sound.patch Patch25149: drm-radeon-24hz-audio-fixes.patch -#rhbz 1011714 -Patch25131: btrfs-relocate-csums-properly-with-prealloc-ext.patch - #rhbz 984696 Patch25132: rt2800usb-slow-down-TX-status-polling.patch @@ -813,12 +807,6 @@ Patch25152: sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch Patch25153: sunrpc-replace-gssd_running-with-more-reliable-check.patch Patch25154: nfs-check-gssd-running-before-krb5i-auth.patch -#CVE-2013-6378 rhbz 1033578 1034183 -Patch25155: libertas-potential-oops-in-debugfs.patch - -#CVE-2013-6380 rhbz 1033593 1034304 -Patch25156: aacraid-prevent-invalid-pointer-dereference.patch - #CVE-2013-6382 rhbz 1033603 1034670 Patch25157: xfs-underflow-bug-in-xfs_attrlist_by_handle.patch @@ -1498,9 +1486,6 @@ ApplyPatch iwl4965-better-skb-management-in-rx-path.patch #rhbz 963715 ApplyPatch media-cx23885-Fix-TeVii-S471-regression-since-introduction-of-ts2020.patch -#CVE-2013-4345 rhbz 1007690 1009136 -ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch - #rhbz 985522 ApplyPatch ntp-Make-periodic-RTC-update-more-reliable.patch @@ -1537,9 +1522,6 @@ ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch ApplyPatch fix-radeon-sound.patch ApplyPatch drm-radeon-24hz-audio-fixes.patch -#rhbz 1011714 -ApplyPatch btrfs-relocate-csums-properly-with-prealloc-ext.patch - #rhbz 984696 ApplyPatch rt2800usb-slow-down-TX-status-polling.patch @@ -1578,12 +1560,6 @@ ApplyPatch sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch ApplyPatch sunrpc-replace-gssd_running-with-more-reliable-check.patch ApplyPatch nfs-check-gssd-running-before-krb5i-auth.patch -#CVE-2013-6378 rhbz 1033578 1034183 -ApplyPatch libertas-potential-oops-in-debugfs.patch - -#CVE-2013-6380 rhbz 1033593 1034304 -ApplyPatch aacraid-prevent-invalid-pointer-dereference.patch - #CVE-2013-6382 rhbz 1033603 1034670 ApplyPatch xfs-underflow-bug-in-xfs_attrlist_by_handle.patch @@ -2434,7 +2410,8 @@ fi # ||----w | # || || %changelog -* Fri Nov 29 2013 Josh Boyer +* Fri Nov 29 2013 Josh Boyer - 3.11.10-100 +- Linux v3.11.10 - Fix memory leak in qxl (from Dave Airlie) * Tue Nov 26 2013 Josh Boyer diff --git a/libertas-potential-oops-in-debugfs.patch b/libertas-potential-oops-in-debugfs.patch deleted file mode 100644 index 02e72d8f9..000000000 --- a/libertas-potential-oops-in-debugfs.patch +++ /dev/null @@ -1,50 +0,0 @@ -Bugzilla: 1034183 -Upstream-status: 3.13 - -From a497e47d4aec37aaf8f13509f3ef3d1f6a717d88 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 30 Oct 2013 20:12:51 +0300 -Subject: [PATCH] libertas: potential oops in debugfs - -If we do a zero size allocation then it will oops. Also we can't be -sure the user passes us a NUL terminated string so I've added a -terminator. - -This code can only be triggered by root. - -Reported-by: Nico Golde -Reported-by: Fabian Yamaguchi -Signed-off-by: Dan Carpenter -Acked-by: Dan Williams -Signed-off-by: John W. Linville ---- - drivers/net/wireless/libertas/debugfs.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c -index 668dd27..cc6a0a5 100644 ---- a/drivers/net/wireless/libertas/debugfs.c -+++ b/drivers/net/wireless/libertas/debugfs.c -@@ -913,7 +913,10 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, - char *p2; - struct debug_data *d = f->private_data; - -- pdata = kmalloc(cnt, GFP_KERNEL); -+ if (cnt == 0) -+ return 0; -+ -+ pdata = kmalloc(cnt + 1, GFP_KERNEL); - if (pdata == NULL) - return 0; - -@@ -922,6 +925,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, - kfree(pdata); - return 0; - } -+ pdata[cnt] = '\0'; - - p0 = pdata; - for (i = 0; i < num_of_items; i++) { --- -1.8.3.1 - diff --git a/sources b/sources index 391b9ff05..c634d10c0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ fea363551ff45fbe4cb88497b863b261 linux-3.11.tar.xz -6cea7db9419cefdf4c3a4bcc89bf904b patch-3.11.9.xz +c918da07cf5ad4240945ae56c4de3bc0 patch-3.11.10.xz From d90c5c245b136bb8feec2e7c2bc71cd150c71fc4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 30 Nov 2013 09:12:19 -0500 Subject: [PATCH 479/492] Add bugzilla and upstream-status fields to qxl memory leak patch --- drm-qxl-fix-memory-leak-in-release-list-handling.patch | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drm-qxl-fix-memory-leak-in-release-list-handling.patch b/drm-qxl-fix-memory-leak-in-release-list-handling.patch index 542d0276d..8ed4819f2 100644 --- a/drm-qxl-fix-memory-leak-in-release-list-handling.patch +++ b/drm-qxl-fix-memory-leak-in-release-list-handling.patch @@ -1,3 +1,6 @@ +Bugzilla: N/A +Upstream-status: 3.13 + From 1b28c3e628315ac0d9ef2d3fac0403f05ae692db Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Nov 2013 05:39:03 +0000 From 6d027eb2982007924b41f4b76dd44fde620012b7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 30 Nov 2013 13:35:27 -0500 Subject: [PATCH 480/492] CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887) --- ...t-in-recv_error-and-rxpmtu-functions.patch | 253 +++++++++++++++++ ...kage-of-uninitialized-memory-to-user.patch | 256 ++++++++++++++++++ kernel.spec | 11 + 3 files changed, 520 insertions(+) create mode 100644 inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch create mode 100644 inet-prevent-leakage-of-uninitialized-memory-to-user.patch diff --git a/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch b/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch new file mode 100644 index 000000000..b76fd2a36 --- /dev/null +++ b/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch @@ -0,0 +1,253 @@ +Bugzilla: 1035887 +Upstream-status: 3.13 + +From 4be402ba6158068d53ab0268f1affa9d82dae2ec Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Fri, 22 Nov 2013 23:46:12 +0000 +Subject: [PATCH] inet: fix addr_len/msg->msg_namelen assignment in recv_error + and rxpmtu functions + +Commit bceaa90240b6019ed73b49965eac7d167610be69 ("inet: prevent leakage +of uninitialized memory to user in recv syscalls") conditionally updated +addr_len if the msg_name is written to. The recv_error and rxpmtu +functions relied on the recvmsg functions to set up addr_len before. + +As this does not happen any more we have to pass addr_len to those +functions as well and set it to the size of the corresponding sockaddr +length. + +This broke traceroute and such. + +Fixes: bceaa90240b6 ("inet: prevent leakage of uninitialized memory to user in recv syscalls") +Reported-by: Brad Spengler +Reported-by: Tom Labanowski +Cc: mpb +Cc: David S. Miller +Cc: Eric Dumazet +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/ip.h | 2 +- + include/net/ipv6.h | 4 ++-- + include/net/ping.h | 3 ++- + net/ipv4/ip_sockglue.c | 3 ++- + net/ipv4/ping.c | 5 +++-- + net/ipv4/raw.c | 2 +- + net/ipv4/udp.c | 2 +- + net/ipv6/datagram.c | 7 +++++-- + net/ipv6/ping.c | 3 ++- + net/ipv6/raw.c | 4 ++-- + net/ipv6/udp.c | 4 ++-- + net/l2tp/l2tp_ip6.c | 2 +- + 12 files changed, 24 insertions(+), 17 deletions(-) + +diff --git a/include/net/ip.h b/include/net/ip.h +index 5e52688..301f10c 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -464,7 +464,7 @@ extern int compat_ip_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen); + extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); + +-extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); ++extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); + extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index bbf1c8f..5529d79 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -802,8 +802,8 @@ extern int compat_ipv6_getsockopt(struct sock *sk, + extern int ip6_datagram_connect(struct sock *sk, + struct sockaddr *addr, int addr_len); + +-extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); +-extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); ++extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); ++extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, int *addr_len); + extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, + u32 info, u8 *payload); + extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); +diff --git a/include/net/ping.h b/include/net/ping.h +index 5db0224..2b496e9 100644 +--- a/include/net/ping.h ++++ b/include/net/ping.h +@@ -31,7 +31,8 @@ + + /* Compatibility glue so we can support IPv6 when it's compiled as a module */ + struct pingv6_ops { +- int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); ++ int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len); + int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index d9c4f11..23e6ab0 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf + /* + * Handle MSG_ERRQUEUE + */ +-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) ++int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + struct sock_exterr_skb *serr; + struct sk_buff *skb, *skb2; +@@ -405,6 +405,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) + serr->addr_offset); + sin->sin_port = serr->port; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 92fb6ff..ac31877 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -838,10 +838,11 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { +- return ip_recv_error(sk, msg, len); ++ return ip_recv_error(sk, msg, len, addr_len); + #if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { +- return pingv6_ops.ipv6_recv_error(sk, msg, len); ++ return pingv6_ops.ipv6_recv_error(sk, msg, len, ++ addr_len); + #endif + } + } +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index ca4c3f1..7d3db78 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -695,7 +695,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + goto out; + + if (flags & MSG_ERRQUEUE) { +- err = ip_recv_error(sk, msg, len); ++ err = ip_recv_error(sk, msg, len, addr_len); + goto out; + } + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index a7003de..1ef8794 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1210,7 +1210,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + bool slow; + + if (flags & MSG_ERRQUEUE) +- return ip_recv_error(sk, msg, len); ++ return ip_recv_error(sk, msg, len, addr_len); + + try_again: + skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 48b6bd2..7a0fd80 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) + /* + * Handle MSG_ERRQUEUE + */ +-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) ++int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + struct ipv6_pinfo *np = inet6_sk(sk); + struct sock_exterr_skb *serr; +@@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) + &sin->sin6_addr); + sin->sin6_scope_id = 0; + } ++ *addr_len = sizeof(*sin); + } + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); +@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error); + /* + * Handle IPV6_RECVPATHMTU + */ +-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) ++int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len) + { + struct ipv6_pinfo *np = inet6_sk(sk); + struct sk_buff *skb; +@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) + sin->sin6_port = 0; + sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; + sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; ++ *addr_len = sizeof(*sin); + } + + put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index 18f19df..7856e96 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = { + + + /* Compatibility glue so we can support IPv6 when it's compiled as a module */ +-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) ++static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len) + { + return -EAFNOSUPPORT; + } +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 2f303bf..430067c 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -467,10 +467,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, + return -EOPNOTSUPP; + + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + if (np->rxpmtu && np->rxopt.bits.rxpmtu) +- return ipv6_recv_rxpmtu(sk, msg, len); ++ return ipv6_recv_rxpmtu(sk, msg, len, addr_len); + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index a59beed..3d2758d 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -375,10 +375,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + bool slow; + + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + if (np->rxpmtu && np->rxopt.bits.rxpmtu) +- return ipv6_recv_rxpmtu(sk, msg, len); ++ return ipv6_recv_rxpmtu(sk, msg, len, addr_len); + + try_again: + skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index b8a6039..e6e8408 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -665,7 +665,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, + *addr_len = sizeof(*lsa); + + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) +-- +1.8.3.1 + diff --git a/inet-prevent-leakage-of-uninitialized-memory-to-user.patch b/inet-prevent-leakage-of-uninitialized-memory-to-user.patch new file mode 100644 index 000000000..c5b941134 --- /dev/null +++ b/inet-prevent-leakage-of-uninitialized-memory-to-user.patch @@ -0,0 +1,256 @@ +Bugzilla: 1035887 +Upstream-status: 3.13 + +From bceaa90240b6019ed73b49965eac7d167610be69 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Mon, 18 Nov 2013 04:20:45 +0100 +Subject: [PATCH] inet: prevent leakage of uninitialized memory to user in recv + syscalls + +Only update *addr_len when we actually fill in sockaddr, otherwise we +can return uninitialized memory from the stack to the caller in the +recvfrom, recvmmsg and recvmsg syscalls. Drop the the (addr_len == NULL) +checks because we only get called with a valid addr_len pointer either +from sock_common_recvmsg or inet_recvmsg. + +If a blocking read waits on a socket which is concurrently shut down we +now return zero and set msg_msgnamelen to 0. + +Reported-by: mpb +Suggested-by: Eric Dumazet +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ieee802154/dgram.c | 3 +-- + net/ipv4/ping.c | 19 +++++++------------ + net/ipv4/raw.c | 4 +--- + net/ipv4/udp.c | 7 +------ + net/ipv6/raw.c | 4 +--- + net/ipv6/udp.c | 5 +---- + net/l2tp/l2tp_ip.c | 4 +--- + net/phonet/datagram.c | 9 ++++----- + 8 files changed, 17 insertions(+), 38 deletions(-) + +diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c +index 581a595..1865fdf 100644 +--- a/net/ieee802154/dgram.c ++++ b/net/ieee802154/dgram.c +@@ -315,9 +315,8 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, + if (saddr) { + saddr->family = AF_IEEE802154; + saddr->addr = mac_cb(skb)->sa; +- } +- if (addr_len) + *addr_len = sizeof(*saddr); ++ } + + if (flags & MSG_TRUNC) + copied = skb->len; +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 9afbdb1..aacefa0 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -830,8 +830,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + { + struct inet_sock *isk = inet_sk(sk); + int family = sk->sk_family; +- struct sockaddr_in *sin; +- struct sockaddr_in6 *sin6; + struct sk_buff *skb; + int copied, err; + +@@ -841,13 +839,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + if (flags & MSG_OOB) + goto out; + +- if (addr_len) { +- if (family == AF_INET) +- *addr_len = sizeof(*sin); +- else if (family == AF_INET6 && addr_len) +- *addr_len = sizeof(*sin6); +- } +- + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { + return ip_recv_error(sk, msg, len); +@@ -877,11 +868,13 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { +- sin = (struct sockaddr_in *) msg->msg_name; ++ struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; ++ + sin->sin_family = AF_INET; + sin->sin_port = 0 /* skb->h.uh->source */; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); +@@ -890,17 +883,19 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); +- sin6 = (struct sockaddr_in6 *) msg->msg_name; ++ struct sockaddr_in6 *sin6 = ++ (struct sockaddr_in6 *)msg->msg_name; ++ + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; +- + sin6->sin6_flowinfo = 0; + if (np->sndflow) + sin6->sin6_flowinfo = ip6_flowinfo(ip6); + + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); ++ *addr_len = sizeof(*sin6); + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 41e1d28..5cb8ddb 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -696,9 +696,6 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + if (flags & MSG_OOB) + goto out; + +- if (addr_len) +- *addr_len = sizeof(*sin); +- + if (flags & MSG_ERRQUEUE) { + err = ip_recv_error(sk, msg, len); + goto out; +@@ -726,6 +723,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_port = 0; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 89909dd..998431c 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1235,12 +1235,6 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + int is_udplite = IS_UDPLITE(sk); + bool slow; + +- /* +- * Check any passed addresses +- */ +- if (addr_len) +- *addr_len = sizeof(*sin); +- + if (flags & MSG_ERRQUEUE) + return ip_recv_error(sk, msg, len); + +@@ -1302,6 +1296,7 @@ try_again: + sin->sin_port = udp_hdr(skb)->source; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 3c00842..e24ff1d 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -465,9 +465,6 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, + if (flags & MSG_OOB) + return -EOPNOTSUPP; + +- if (addr_len) +- *addr_len=sizeof(*sin6); +- + if (flags & MSG_ERRQUEUE) + return ipv6_recv_error(sk, msg, len); + +@@ -506,6 +503,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, + sin6->sin6_flowinfo = 0; + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); ++ *addr_len = sizeof(*sin6); + } + + sock_recv_ts_and_drops(msg, sk, skb); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index f3893e8..81eb8cf 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -392,9 +392,6 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + int is_udp4; + bool slow; + +- if (addr_len) +- *addr_len = sizeof(struct sockaddr_in6); +- + if (flags & MSG_ERRQUEUE) + return ipv6_recv_error(sk, msg, len); + +@@ -480,7 +477,7 @@ try_again: + ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); + } +- ++ *addr_len = sizeof(*sin6); + } + if (is_udp4) { + if (inet->cmsg_flags) +diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c +index 571db8d..da1a1ce 100644 +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -518,9 +518,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + if (flags & MSG_OOB) + goto out; + +- if (addr_len) +- *addr_len = sizeof(*sin); +- + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; +@@ -543,6 +540,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_port = 0; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c +index 12c30f3..38946b2 100644 +--- a/net/phonet/datagram.c ++++ b/net/phonet/datagram.c +@@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, + MSG_CMSG_COMPAT)) + goto out_nofree; + +- if (addr_len) +- *addr_len = sizeof(sa); +- + skb = skb_recv_datagram(sk, flags, noblock, &rval); + if (skb == NULL) + goto out_nofree; +@@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, + + rval = (flags & MSG_TRUNC) ? skb->len : copylen; + +- if (msg->msg_name != NULL) +- memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn)); ++ if (msg->msg_name != NULL) { ++ memcpy(msg->msg_name, &sa, sizeof(sa)); ++ *addr_len = sizeof(sa); ++ } + + out: + skb_free_datagram(sk, skb); +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index f6755f784..6c7fc751b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -816,6 +816,10 @@ Patch25158: via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch #rhbz 998342 Patch25159: usbnet-fix-status-interrupt-urb-handling.patch +#CVE-2013-6405 rhbz 1035875 1035887 +Patch25161: inet-prevent-leakage-of-uninitialized-memory-to-user.patch +Patch25162: inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch + # END OF PATCH DEFINITIONS %endif @@ -1569,6 +1573,10 @@ ApplyPatch via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch #rhbz 998342 ApplyPatch usbnet-fix-status-interrupt-urb-handling.patch +#CVE-2013-6405 rhbz 1035875 1035887 +ApplyPatch inet-prevent-leakage-of-uninitialized-memory-to-user.patch +ApplyPatch inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch + # END OF PATCH APPLICATIONS %endif @@ -2410,6 +2418,9 @@ fi # ||----w | # || || %changelog +* Sat Nov 30 2013 Josh Boyer +- CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887) + * Fri Nov 29 2013 Josh Boyer - 3.11.10-100 - Linux v3.11.10 - Fix memory leak in qxl (from Dave Airlie) From 45b5fd05358e5fd93de08b13a8c32f9a540aca5e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Dec 2013 09:09:55 -0500 Subject: [PATCH 481/492] Add patches to fix rfkill switch on Dell machines (rhbz 958826) --- ...evert-dell-laptop-Remove-rfkill-code.patch | 399 ++++++++++++++++++ ...ptop-Only-enable-rfkill-on-Latitudes.patch | 104 +++++ kernel.spec | 11 + 3 files changed, 514 insertions(+) create mode 100644 0001-Revert-dell-laptop-Remove-rfkill-code.patch create mode 100644 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch diff --git a/0001-Revert-dell-laptop-Remove-rfkill-code.patch b/0001-Revert-dell-laptop-Remove-rfkill-code.patch new file mode 100644 index 000000000..c9bf8c5ab --- /dev/null +++ b/0001-Revert-dell-laptop-Remove-rfkill-code.patch @@ -0,0 +1,399 @@ +Bugzilla: 958826 +Upstream-status: 3.13 + +From 4cc8a57425c623753b10b77b15392e5b83baa5a3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:16 +0100 +Subject: [PATCH 1/2] Revert "dell-laptop: Remove rfkill code" + +Without rfkill functionality in dell-laptop I have the following problems: +-If the hardware radio switch is set to disable the radio, then userspace + will still think it can use wireless and bluetooth. +-The wwan / 3g modem cannot be soft blocked without the dell-laptop rfkill + functionality + +I know the rfkill functionality was removed from the dell-laptop driver because +it caused more problems then it fixed, and the blacklist for it was growing out +of control. + +But in the thread discussing this Dell mentioned that they only QA the rfkill +acpi interface on Latitudes and indeed there have been no blacklist entries +for Latitudes. Therefor I would like to bring the rfkill functionality back +only for Latitudes. This patch is a straight-forward revert. The next patch +in this set will drop the blacklist and replace it with a Latitude check. + +This reverts commit a6c2390cd6d2083d27a2359658e08f2d3df375ac. + +Conflicts: + drivers/platform/x86/dell-laptop.c + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 289 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 289 insertions(+) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index bb77e18..55f75a2 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -89,6 +90,9 @@ static struct platform_driver platform_driver = { + + static struct platform_device *platform_device; + static struct backlight_device *dell_backlight_device; ++static struct rfkill *wifi_rfkill; ++static struct rfkill *bluetooth_rfkill; ++static struct rfkill *wwan_rfkill; + + static const struct dmi_system_id dell_device_table[] __initconst = { + { +@@ -115,6 +119,53 @@ static const struct dmi_system_id dell_device_table[] __initconst = { + }; + MODULE_DEVICE_TABLE(dmi, dell_device_table); + ++static struct dmi_system_id dell_blacklist[] = { ++ /* Supported by compal-laptop */ ++ { ++ .ident = "Dell Mini 9", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 10", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 10v", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 1012", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), ++ }, ++ }, ++ { ++ .ident = "Dell Inspiron 11z", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 12", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), ++ }, ++ }, ++ {} ++}; ++ + static struct dmi_system_id dell_quirks[] = { + { + .callback = dmi_matched, +@@ -355,6 +406,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, + return buffer; + } + ++/* Derived from information in DellWirelessCtl.cpp: ++ Class 17, select 11 is radio control. It returns an array of 32-bit values. ++ ++ Input byte 0 = 0: Wireless information ++ ++ result[0]: return code ++ result[1]: ++ Bit 0: Hardware switch supported ++ Bit 1: Wifi locator supported ++ Bit 2: Wifi is supported ++ Bit 3: Bluetooth is supported ++ Bit 4: WWAN is supported ++ Bit 5: Wireless keyboard supported ++ Bits 6-7: Reserved ++ Bit 8: Wifi is installed ++ Bit 9: Bluetooth is installed ++ Bit 10: WWAN is installed ++ Bits 11-15: Reserved ++ Bit 16: Hardware switch is on ++ Bit 17: Wifi is blocked ++ Bit 18: Bluetooth is blocked ++ Bit 19: WWAN is blocked ++ Bits 20-31: Reserved ++ result[2]: NVRAM size in bytes ++ result[3]: NVRAM format version number ++ ++ Input byte 0 = 2: Wireless switch configuration ++ result[0]: return code ++ result[1]: ++ Bit 0: Wifi controlled by switch ++ Bit 1: Bluetooth controlled by switch ++ Bit 2: WWAN controlled by switch ++ Bits 3-6: Reserved ++ Bit 7: Wireless switch config locked ++ Bit 8: Wifi locator enabled ++ Bits 9-14: Reserved ++ Bit 15: Wifi locator setting locked ++ Bits 16-31: Reserved ++*/ ++ ++static int dell_rfkill_set(void *data, bool blocked) ++{ ++ int disable = blocked ? 1 : 0; ++ unsigned long radio = (unsigned long)data; ++ int hwswitch_bit = (unsigned long)data - 1; ++ int ret = 0; ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ ++ /* If the hardware switch controls this radio, and the hardware ++ switch is disabled, don't allow changing the software state */ ++ if ((hwswitch_state & BIT(hwswitch_bit)) && ++ !(buffer->output[1] & BIT(16))) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ buffer->input[0] = (1 | (radio<<8) | (disable << 16)); ++ dell_send_request(buffer, 17, 11); ++ ++out: ++ release_buffer(); ++ return ret; ++} ++ ++static void dell_rfkill_query(struct rfkill *rfkill, void *data) ++{ ++ int status; ++ int bit = (unsigned long)data + 16; ++ int hwswitch_bit = (unsigned long)data - 1; ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ status = buffer->output[1]; ++ release_buffer(); ++ ++ rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); ++ ++ if (hwswitch_state & (BIT(hwswitch_bit))) ++ rfkill_set_hw_state(rfkill, !(status & BIT(16))); ++} ++ ++static const struct rfkill_ops dell_rfkill_ops = { ++ .set_block = dell_rfkill_set, ++ .query = dell_rfkill_query, ++}; ++ + static struct dentry *dell_laptop_dir; + + static int dell_debugfs_show(struct seq_file *s, void *data) +@@ -424,6 +563,108 @@ static const struct file_operations dell_debugfs_fops = { + .release = single_release, + }; + ++static void dell_update_rfkill(struct work_struct *ignored) ++{ ++ if (wifi_rfkill) ++ dell_rfkill_query(wifi_rfkill, (void *)1); ++ if (bluetooth_rfkill) ++ dell_rfkill_query(bluetooth_rfkill, (void *)2); ++ if (wwan_rfkill) ++ dell_rfkill_query(wwan_rfkill, (void *)3); ++} ++static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); ++ ++ ++static int __init dell_setup_rfkill(void) ++{ ++ int status; ++ int ret; ++ ++ if (dmi_check_system(dell_blacklist)) { ++ pr_info("Blacklisted hardware detected - not enabling rfkill\n"); ++ return 0; ++ } ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ status = buffer->output[1]; ++ buffer->input[0] = 0x2; ++ dell_send_request(buffer, 17, 11); ++ hwswitch_state = buffer->output[1]; ++ release_buffer(); ++ ++ if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { ++ wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, ++ RFKILL_TYPE_WLAN, ++ &dell_rfkill_ops, (void *) 1); ++ if (!wifi_rfkill) { ++ ret = -ENOMEM; ++ goto err_wifi; ++ } ++ ret = rfkill_register(wifi_rfkill); ++ if (ret) ++ goto err_wifi; ++ } ++ ++ if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { ++ bluetooth_rfkill = rfkill_alloc("dell-bluetooth", ++ &platform_device->dev, ++ RFKILL_TYPE_BLUETOOTH, ++ &dell_rfkill_ops, (void *) 2); ++ if (!bluetooth_rfkill) { ++ ret = -ENOMEM; ++ goto err_bluetooth; ++ } ++ ret = rfkill_register(bluetooth_rfkill); ++ if (ret) ++ goto err_bluetooth; ++ } ++ ++ if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { ++ wwan_rfkill = rfkill_alloc("dell-wwan", ++ &platform_device->dev, ++ RFKILL_TYPE_WWAN, ++ &dell_rfkill_ops, (void *) 3); ++ if (!wwan_rfkill) { ++ ret = -ENOMEM; ++ goto err_wwan; ++ } ++ ret = rfkill_register(wwan_rfkill); ++ if (ret) ++ goto err_wwan; ++ } ++ ++ return 0; ++err_wwan: ++ rfkill_destroy(wwan_rfkill); ++ if (bluetooth_rfkill) ++ rfkill_unregister(bluetooth_rfkill); ++err_bluetooth: ++ rfkill_destroy(bluetooth_rfkill); ++ if (wifi_rfkill) ++ rfkill_unregister(wifi_rfkill); ++err_wifi: ++ rfkill_destroy(wifi_rfkill); ++ ++ return ret; ++} ++ ++static void dell_cleanup_rfkill(void) ++{ ++ if (wifi_rfkill) { ++ rfkill_unregister(wifi_rfkill); ++ rfkill_destroy(wifi_rfkill); ++ } ++ if (bluetooth_rfkill) { ++ rfkill_unregister(bluetooth_rfkill); ++ rfkill_destroy(bluetooth_rfkill); ++ } ++ if (wwan_rfkill) { ++ rfkill_unregister(wwan_rfkill); ++ rfkill_destroy(wwan_rfkill); ++ } ++} ++ + static int dell_send_intensity(struct backlight_device *bd) + { + int ret = 0; +@@ -515,6 +756,30 @@ static void touchpad_led_exit(void) + led_classdev_unregister(&touchpad_led); + } + ++static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, ++ struct serio *port) ++{ ++ static bool extended; ++ ++ if (str & 0x20) ++ return false; ++ ++ if (unlikely(data == 0xe0)) { ++ extended = true; ++ return false; ++ } else if (unlikely(extended)) { ++ switch (data) { ++ case 0x8: ++ schedule_delayed_work(&dell_rfkill_work, ++ round_jiffies_relative(HZ)); ++ break; ++ } ++ extended = false; ++ } ++ ++ return false; ++} ++ + static int __init dell_init(void) + { + int max_intensity = 0; +@@ -557,10 +822,26 @@ static int __init dell_init(void) + } + buffer = page_address(bufferpage); + ++ ret = dell_setup_rfkill(); ++ ++ if (ret) { ++ pr_warn("Unable to setup rfkill\n"); ++ goto fail_rfkill; ++ } ++ ++ ret = i8042_install_filter(dell_laptop_i8042_filter); ++ if (ret) { ++ pr_warn("Unable to install key filter\n"); ++ goto fail_filter; ++ } ++ + if (quirks && quirks->touchpad_led) + touchpad_led_init(&platform_device->dev); + + dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); ++ if (dell_laptop_dir != NULL) ++ debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, ++ &dell_debugfs_fops); + + #ifdef CONFIG_ACPI + /* In the event of an ACPI backlight being available, don't +@@ -603,6 +884,11 @@ static int __init dell_init(void) + return 0; + + fail_backlight: ++ i8042_remove_filter(dell_laptop_i8042_filter); ++ cancel_delayed_work_sync(&dell_rfkill_work); ++fail_filter: ++ dell_cleanup_rfkill(); ++fail_rfkill: + free_page((unsigned long)bufferpage); + fail_buffer: + platform_device_del(platform_device); +@@ -620,7 +906,10 @@ static void __exit dell_exit(void) + debugfs_remove_recursive(dell_laptop_dir); + if (quirks && quirks->touchpad_led) + touchpad_led_exit(); ++ i8042_remove_filter(dell_laptop_i8042_filter); ++ cancel_delayed_work_sync(&dell_rfkill_work); + backlight_device_unregister(dell_backlight_device); ++ dell_cleanup_rfkill(); + if (platform_device) { + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); +-- +1.8.3.1 + diff --git a/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch b/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch new file mode 100644 index 000000000..5a80e28be --- /dev/null +++ b/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch @@ -0,0 +1,104 @@ +Bugzilla: 958826 +Upstream-status: 3.13 + +From 2a92551845bbbc8421ba908cd14bbdf065e0f454 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:17 +0100 +Subject: [PATCH 2/2] dell-laptop: Only enable rfkill on Latitudes + +The rfkill functionality was removed from the dell-laptop driver because it +was causing problems on various non Latitude models, and the blacklist kept +growing and growing. In the thread discussing this Dell mentioned that they +only QA the rfkill acpi interface on Latitudes and indeed there have been +no blacklist entries for Latitudes. + +Note that the blacklist contained no Vostros either, and most Vostros have +a hardware switch too, so we could consider supporting Vostros with a +hardware switch too. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 57 +++++--------------------------------- + 1 file changed, 7 insertions(+), 50 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 55f75a2..bae932b 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -119,53 +119,6 @@ static const struct dmi_system_id dell_device_table[] __initconst = { + }; + MODULE_DEVICE_TABLE(dmi, dell_device_table); + +-static struct dmi_system_id dell_blacklist[] = { +- /* Supported by compal-laptop */ +- { +- .ident = "Dell Mini 9", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), +- }, +- }, +- { +- .ident = "Dell Mini 10", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), +- }, +- }, +- { +- .ident = "Dell Mini 10v", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), +- }, +- }, +- { +- .ident = "Dell Mini 1012", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), +- }, +- }, +- { +- .ident = "Dell Inspiron 11z", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), +- }, +- }, +- { +- .ident = "Dell Mini 12", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), +- }, +- }, +- {} +-}; +- + static struct dmi_system_id dell_quirks[] = { + { + .callback = dmi_matched, +@@ -579,11 +532,15 @@ static int __init dell_setup_rfkill(void) + { + int status; + int ret; ++ const char *product; + +- if (dmi_check_system(dell_blacklist)) { +- pr_info("Blacklisted hardware detected - not enabling rfkill\n"); ++ /* ++ * rfkill causes trouble on various non Latitudes, according to Dell ++ * actually testing the rfkill functionality is only done on Latitudes. ++ */ ++ product = dmi_get_system_info(DMI_PRODUCT_NAME); ++ if (!product || strncmp(product, "Latitude", 8)) + return 0; +- } + + get_buffer(); + dell_send_request(buffer, 17, 11); +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 6c7fc751b..f6dfbb12c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -820,6 +820,10 @@ Patch25159: usbnet-fix-status-interrupt-urb-handling.patch Patch25161: inet-prevent-leakage-of-uninitialized-memory-to-user.patch Patch25162: inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch +#rhbz 958826 +Patch25164: 0001-Revert-dell-laptop-Remove-rfkill-code.patch +Patch25165: 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch + # END OF PATCH DEFINITIONS %endif @@ -1577,6 +1581,10 @@ ApplyPatch usbnet-fix-status-interrupt-urb-handling.patch ApplyPatch inet-prevent-leakage-of-uninitialized-memory-to-user.patch ApplyPatch inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch +#rhbz 958826 +ApplyPatch 0001-Revert-dell-laptop-Remove-rfkill-code.patch +ApplyPatch 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch + # END OF PATCH APPLICATIONS %endif @@ -2418,6 +2426,9 @@ fi # ||----w | # || || %changelog +* Tue Dec 03 2013 Josh Boyer +- Add patches to fix rfkill switch on Dell machines (rhbz 958826) + * Sat Nov 30 2013 Josh Boyer - CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887) From 4ec4a04f08ec5cbe2bc6843198eac62d0704d4b5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Dec 2013 08:20:09 -0500 Subject: [PATCH 482/492] Update dell-laptop patches with whole series from 3.13 All of them are needed so it works on most Latitude machines. Otherwise it's hit or miss --- ...evert-dell-laptop-Remove-rfkill-code.patch | 399 ------- ...ptop-Only-enable-rfkill-on-Latitudes.patch | 104 -- dell-laptop.patch | 1017 +++++++++++++++++ kernel.spec | 6 +- 4 files changed, 1019 insertions(+), 507 deletions(-) delete mode 100644 0001-Revert-dell-laptop-Remove-rfkill-code.patch delete mode 100644 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch create mode 100644 dell-laptop.patch diff --git a/0001-Revert-dell-laptop-Remove-rfkill-code.patch b/0001-Revert-dell-laptop-Remove-rfkill-code.patch deleted file mode 100644 index c9bf8c5ab..000000000 --- a/0001-Revert-dell-laptop-Remove-rfkill-code.patch +++ /dev/null @@ -1,399 +0,0 @@ -Bugzilla: 958826 -Upstream-status: 3.13 - -From 4cc8a57425c623753b10b77b15392e5b83baa5a3 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sun, 17 Nov 2013 14:00:16 +0100 -Subject: [PATCH 1/2] Revert "dell-laptop: Remove rfkill code" - -Without rfkill functionality in dell-laptop I have the following problems: --If the hardware radio switch is set to disable the radio, then userspace - will still think it can use wireless and bluetooth. --The wwan / 3g modem cannot be soft blocked without the dell-laptop rfkill - functionality - -I know the rfkill functionality was removed from the dell-laptop driver because -it caused more problems then it fixed, and the blacklist for it was growing out -of control. - -But in the thread discussing this Dell mentioned that they only QA the rfkill -acpi interface on Latitudes and indeed there have been no blacklist entries -for Latitudes. Therefor I would like to bring the rfkill functionality back -only for Latitudes. This patch is a straight-forward revert. The next patch -in this set will drop the blacklist and replace it with a Latitude check. - -This reverts commit a6c2390cd6d2083d27a2359658e08f2d3df375ac. - -Conflicts: - drivers/platform/x86/dell-laptop.c - -Signed-off-by: Hans de Goede -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/dell-laptop.c | 289 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 289 insertions(+) - -diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c -index bb77e18..55f75a2 100644 ---- a/drivers/platform/x86/dell-laptop.c -+++ b/drivers/platform/x86/dell-laptop.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -89,6 +90,9 @@ static struct platform_driver platform_driver = { - - static struct platform_device *platform_device; - static struct backlight_device *dell_backlight_device; -+static struct rfkill *wifi_rfkill; -+static struct rfkill *bluetooth_rfkill; -+static struct rfkill *wwan_rfkill; - - static const struct dmi_system_id dell_device_table[] __initconst = { - { -@@ -115,6 +119,53 @@ static const struct dmi_system_id dell_device_table[] __initconst = { - }; - MODULE_DEVICE_TABLE(dmi, dell_device_table); - -+static struct dmi_system_id dell_blacklist[] = { -+ /* Supported by compal-laptop */ -+ { -+ .ident = "Dell Mini 9", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), -+ }, -+ }, -+ { -+ .ident = "Dell Mini 10", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), -+ }, -+ }, -+ { -+ .ident = "Dell Mini 10v", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), -+ }, -+ }, -+ { -+ .ident = "Dell Mini 1012", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), -+ }, -+ }, -+ { -+ .ident = "Dell Inspiron 11z", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), -+ }, -+ }, -+ { -+ .ident = "Dell Mini 12", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), -+ }, -+ }, -+ {} -+}; -+ - static struct dmi_system_id dell_quirks[] = { - { - .callback = dmi_matched, -@@ -355,6 +406,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, - return buffer; - } - -+/* Derived from information in DellWirelessCtl.cpp: -+ Class 17, select 11 is radio control. It returns an array of 32-bit values. -+ -+ Input byte 0 = 0: Wireless information -+ -+ result[0]: return code -+ result[1]: -+ Bit 0: Hardware switch supported -+ Bit 1: Wifi locator supported -+ Bit 2: Wifi is supported -+ Bit 3: Bluetooth is supported -+ Bit 4: WWAN is supported -+ Bit 5: Wireless keyboard supported -+ Bits 6-7: Reserved -+ Bit 8: Wifi is installed -+ Bit 9: Bluetooth is installed -+ Bit 10: WWAN is installed -+ Bits 11-15: Reserved -+ Bit 16: Hardware switch is on -+ Bit 17: Wifi is blocked -+ Bit 18: Bluetooth is blocked -+ Bit 19: WWAN is blocked -+ Bits 20-31: Reserved -+ result[2]: NVRAM size in bytes -+ result[3]: NVRAM format version number -+ -+ Input byte 0 = 2: Wireless switch configuration -+ result[0]: return code -+ result[1]: -+ Bit 0: Wifi controlled by switch -+ Bit 1: Bluetooth controlled by switch -+ Bit 2: WWAN controlled by switch -+ Bits 3-6: Reserved -+ Bit 7: Wireless switch config locked -+ Bit 8: Wifi locator enabled -+ Bits 9-14: Reserved -+ Bit 15: Wifi locator setting locked -+ Bits 16-31: Reserved -+*/ -+ -+static int dell_rfkill_set(void *data, bool blocked) -+{ -+ int disable = blocked ? 1 : 0; -+ unsigned long radio = (unsigned long)data; -+ int hwswitch_bit = (unsigned long)data - 1; -+ int ret = 0; -+ -+ get_buffer(); -+ dell_send_request(buffer, 17, 11); -+ -+ /* If the hardware switch controls this radio, and the hardware -+ switch is disabled, don't allow changing the software state */ -+ if ((hwswitch_state & BIT(hwswitch_bit)) && -+ !(buffer->output[1] & BIT(16))) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ buffer->input[0] = (1 | (radio<<8) | (disable << 16)); -+ dell_send_request(buffer, 17, 11); -+ -+out: -+ release_buffer(); -+ return ret; -+} -+ -+static void dell_rfkill_query(struct rfkill *rfkill, void *data) -+{ -+ int status; -+ int bit = (unsigned long)data + 16; -+ int hwswitch_bit = (unsigned long)data - 1; -+ -+ get_buffer(); -+ dell_send_request(buffer, 17, 11); -+ status = buffer->output[1]; -+ release_buffer(); -+ -+ rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); -+ -+ if (hwswitch_state & (BIT(hwswitch_bit))) -+ rfkill_set_hw_state(rfkill, !(status & BIT(16))); -+} -+ -+static const struct rfkill_ops dell_rfkill_ops = { -+ .set_block = dell_rfkill_set, -+ .query = dell_rfkill_query, -+}; -+ - static struct dentry *dell_laptop_dir; - - static int dell_debugfs_show(struct seq_file *s, void *data) -@@ -424,6 +563,108 @@ static const struct file_operations dell_debugfs_fops = { - .release = single_release, - }; - -+static void dell_update_rfkill(struct work_struct *ignored) -+{ -+ if (wifi_rfkill) -+ dell_rfkill_query(wifi_rfkill, (void *)1); -+ if (bluetooth_rfkill) -+ dell_rfkill_query(bluetooth_rfkill, (void *)2); -+ if (wwan_rfkill) -+ dell_rfkill_query(wwan_rfkill, (void *)3); -+} -+static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); -+ -+ -+static int __init dell_setup_rfkill(void) -+{ -+ int status; -+ int ret; -+ -+ if (dmi_check_system(dell_blacklist)) { -+ pr_info("Blacklisted hardware detected - not enabling rfkill\n"); -+ return 0; -+ } -+ -+ get_buffer(); -+ dell_send_request(buffer, 17, 11); -+ status = buffer->output[1]; -+ buffer->input[0] = 0x2; -+ dell_send_request(buffer, 17, 11); -+ hwswitch_state = buffer->output[1]; -+ release_buffer(); -+ -+ if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { -+ wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, -+ RFKILL_TYPE_WLAN, -+ &dell_rfkill_ops, (void *) 1); -+ if (!wifi_rfkill) { -+ ret = -ENOMEM; -+ goto err_wifi; -+ } -+ ret = rfkill_register(wifi_rfkill); -+ if (ret) -+ goto err_wifi; -+ } -+ -+ if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { -+ bluetooth_rfkill = rfkill_alloc("dell-bluetooth", -+ &platform_device->dev, -+ RFKILL_TYPE_BLUETOOTH, -+ &dell_rfkill_ops, (void *) 2); -+ if (!bluetooth_rfkill) { -+ ret = -ENOMEM; -+ goto err_bluetooth; -+ } -+ ret = rfkill_register(bluetooth_rfkill); -+ if (ret) -+ goto err_bluetooth; -+ } -+ -+ if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { -+ wwan_rfkill = rfkill_alloc("dell-wwan", -+ &platform_device->dev, -+ RFKILL_TYPE_WWAN, -+ &dell_rfkill_ops, (void *) 3); -+ if (!wwan_rfkill) { -+ ret = -ENOMEM; -+ goto err_wwan; -+ } -+ ret = rfkill_register(wwan_rfkill); -+ if (ret) -+ goto err_wwan; -+ } -+ -+ return 0; -+err_wwan: -+ rfkill_destroy(wwan_rfkill); -+ if (bluetooth_rfkill) -+ rfkill_unregister(bluetooth_rfkill); -+err_bluetooth: -+ rfkill_destroy(bluetooth_rfkill); -+ if (wifi_rfkill) -+ rfkill_unregister(wifi_rfkill); -+err_wifi: -+ rfkill_destroy(wifi_rfkill); -+ -+ return ret; -+} -+ -+static void dell_cleanup_rfkill(void) -+{ -+ if (wifi_rfkill) { -+ rfkill_unregister(wifi_rfkill); -+ rfkill_destroy(wifi_rfkill); -+ } -+ if (bluetooth_rfkill) { -+ rfkill_unregister(bluetooth_rfkill); -+ rfkill_destroy(bluetooth_rfkill); -+ } -+ if (wwan_rfkill) { -+ rfkill_unregister(wwan_rfkill); -+ rfkill_destroy(wwan_rfkill); -+ } -+} -+ - static int dell_send_intensity(struct backlight_device *bd) - { - int ret = 0; -@@ -515,6 +756,30 @@ static void touchpad_led_exit(void) - led_classdev_unregister(&touchpad_led); - } - -+static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, -+ struct serio *port) -+{ -+ static bool extended; -+ -+ if (str & 0x20) -+ return false; -+ -+ if (unlikely(data == 0xe0)) { -+ extended = true; -+ return false; -+ } else if (unlikely(extended)) { -+ switch (data) { -+ case 0x8: -+ schedule_delayed_work(&dell_rfkill_work, -+ round_jiffies_relative(HZ)); -+ break; -+ } -+ extended = false; -+ } -+ -+ return false; -+} -+ - static int __init dell_init(void) - { - int max_intensity = 0; -@@ -557,10 +822,26 @@ static int __init dell_init(void) - } - buffer = page_address(bufferpage); - -+ ret = dell_setup_rfkill(); -+ -+ if (ret) { -+ pr_warn("Unable to setup rfkill\n"); -+ goto fail_rfkill; -+ } -+ -+ ret = i8042_install_filter(dell_laptop_i8042_filter); -+ if (ret) { -+ pr_warn("Unable to install key filter\n"); -+ goto fail_filter; -+ } -+ - if (quirks && quirks->touchpad_led) - touchpad_led_init(&platform_device->dev); - - dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); -+ if (dell_laptop_dir != NULL) -+ debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, -+ &dell_debugfs_fops); - - #ifdef CONFIG_ACPI - /* In the event of an ACPI backlight being available, don't -@@ -603,6 +884,11 @@ static int __init dell_init(void) - return 0; - - fail_backlight: -+ i8042_remove_filter(dell_laptop_i8042_filter); -+ cancel_delayed_work_sync(&dell_rfkill_work); -+fail_filter: -+ dell_cleanup_rfkill(); -+fail_rfkill: - free_page((unsigned long)bufferpage); - fail_buffer: - platform_device_del(platform_device); -@@ -620,7 +906,10 @@ static void __exit dell_exit(void) - debugfs_remove_recursive(dell_laptop_dir); - if (quirks && quirks->touchpad_led) - touchpad_led_exit(); -+ i8042_remove_filter(dell_laptop_i8042_filter); -+ cancel_delayed_work_sync(&dell_rfkill_work); - backlight_device_unregister(dell_backlight_device); -+ dell_cleanup_rfkill(); - if (platform_device) { - platform_device_unregister(platform_device); - platform_driver_unregister(&platform_driver); --- -1.8.3.1 - diff --git a/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch b/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch deleted file mode 100644 index 5a80e28be..000000000 --- a/0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch +++ /dev/null @@ -1,104 +0,0 @@ -Bugzilla: 958826 -Upstream-status: 3.13 - -From 2a92551845bbbc8421ba908cd14bbdf065e0f454 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sun, 17 Nov 2013 14:00:17 +0100 -Subject: [PATCH 2/2] dell-laptop: Only enable rfkill on Latitudes - -The rfkill functionality was removed from the dell-laptop driver because it -was causing problems on various non Latitude models, and the blacklist kept -growing and growing. In the thread discussing this Dell mentioned that they -only QA the rfkill acpi interface on Latitudes and indeed there have been -no blacklist entries for Latitudes. - -Note that the blacklist contained no Vostros either, and most Vostros have -a hardware switch too, so we could consider supporting Vostros with a -hardware switch too. - -Signed-off-by: Hans de Goede -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/dell-laptop.c | 57 +++++--------------------------------- - 1 file changed, 7 insertions(+), 50 deletions(-) - -diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c -index 55f75a2..bae932b 100644 ---- a/drivers/platform/x86/dell-laptop.c -+++ b/drivers/platform/x86/dell-laptop.c -@@ -119,53 +119,6 @@ static const struct dmi_system_id dell_device_table[] __initconst = { - }; - MODULE_DEVICE_TABLE(dmi, dell_device_table); - --static struct dmi_system_id dell_blacklist[] = { -- /* Supported by compal-laptop */ -- { -- .ident = "Dell Mini 9", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), -- }, -- }, -- { -- .ident = "Dell Mini 10", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), -- }, -- }, -- { -- .ident = "Dell Mini 10v", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), -- }, -- }, -- { -- .ident = "Dell Mini 1012", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), -- }, -- }, -- { -- .ident = "Dell Inspiron 11z", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), -- }, -- }, -- { -- .ident = "Dell Mini 12", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), -- }, -- }, -- {} --}; -- - static struct dmi_system_id dell_quirks[] = { - { - .callback = dmi_matched, -@@ -579,11 +532,15 @@ static int __init dell_setup_rfkill(void) - { - int status; - int ret; -+ const char *product; - -- if (dmi_check_system(dell_blacklist)) { -- pr_info("Blacklisted hardware detected - not enabling rfkill\n"); -+ /* -+ * rfkill causes trouble on various non Latitudes, according to Dell -+ * actually testing the rfkill functionality is only done on Latitudes. -+ */ -+ product = dmi_get_system_info(DMI_PRODUCT_NAME); -+ if (!product || strncmp(product, "Latitude", 8)) - return 0; -- } - - get_buffer(); - dell_send_request(buffer, 17, 11); --- -1.8.3.1 - diff --git a/dell-laptop.patch b/dell-laptop.patch new file mode 100644 index 000000000..906d93519 --- /dev/null +++ b/dell-laptop.patch @@ -0,0 +1,1017 @@ +Bugzilla: 958826 +Upstream-status: 3.13 + +From 4cc8a57425c623753b10b77b15392e5b83baa5a3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:16 +0100 +Subject: [PATCH 01/12] Revert "dell-laptop: Remove rfkill code" + +Without rfkill functionality in dell-laptop I have the following problems: +-If the hardware radio switch is set to disable the radio, then userspace + will still think it can use wireless and bluetooth. +-The wwan / 3g modem cannot be soft blocked without the dell-laptop rfkill + functionality + +I know the rfkill functionality was removed from the dell-laptop driver because +it caused more problems then it fixed, and the blacklist for it was growing out +of control. + +But in the thread discussing this Dell mentioned that they only QA the rfkill +acpi interface on Latitudes and indeed there have been no blacklist entries +for Latitudes. Therefor I would like to bring the rfkill functionality back +only for Latitudes. This patch is a straight-forward revert. The next patch +in this set will drop the blacklist and replace it with a Latitude check. + +This reverts commit a6c2390cd6d2083d27a2359658e08f2d3df375ac. + +Conflicts: + drivers/platform/x86/dell-laptop.c + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 289 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 289 insertions(+) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index bb77e18..55f75a2 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -89,6 +90,9 @@ static struct platform_driver platform_driver = { + + static struct platform_device *platform_device; + static struct backlight_device *dell_backlight_device; ++static struct rfkill *wifi_rfkill; ++static struct rfkill *bluetooth_rfkill; ++static struct rfkill *wwan_rfkill; + + static const struct dmi_system_id dell_device_table[] __initconst = { + { +@@ -115,6 +119,53 @@ static const struct dmi_system_id dell_device_table[] __initconst = { + }; + MODULE_DEVICE_TABLE(dmi, dell_device_table); + ++static struct dmi_system_id dell_blacklist[] = { ++ /* Supported by compal-laptop */ ++ { ++ .ident = "Dell Mini 9", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 10", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 10v", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 1012", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), ++ }, ++ }, ++ { ++ .ident = "Dell Inspiron 11z", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), ++ }, ++ }, ++ { ++ .ident = "Dell Mini 12", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), ++ }, ++ }, ++ {} ++}; ++ + static struct dmi_system_id dell_quirks[] = { + { + .callback = dmi_matched, +@@ -355,6 +406,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, + return buffer; + } + ++/* Derived from information in DellWirelessCtl.cpp: ++ Class 17, select 11 is radio control. It returns an array of 32-bit values. ++ ++ Input byte 0 = 0: Wireless information ++ ++ result[0]: return code ++ result[1]: ++ Bit 0: Hardware switch supported ++ Bit 1: Wifi locator supported ++ Bit 2: Wifi is supported ++ Bit 3: Bluetooth is supported ++ Bit 4: WWAN is supported ++ Bit 5: Wireless keyboard supported ++ Bits 6-7: Reserved ++ Bit 8: Wifi is installed ++ Bit 9: Bluetooth is installed ++ Bit 10: WWAN is installed ++ Bits 11-15: Reserved ++ Bit 16: Hardware switch is on ++ Bit 17: Wifi is blocked ++ Bit 18: Bluetooth is blocked ++ Bit 19: WWAN is blocked ++ Bits 20-31: Reserved ++ result[2]: NVRAM size in bytes ++ result[3]: NVRAM format version number ++ ++ Input byte 0 = 2: Wireless switch configuration ++ result[0]: return code ++ result[1]: ++ Bit 0: Wifi controlled by switch ++ Bit 1: Bluetooth controlled by switch ++ Bit 2: WWAN controlled by switch ++ Bits 3-6: Reserved ++ Bit 7: Wireless switch config locked ++ Bit 8: Wifi locator enabled ++ Bits 9-14: Reserved ++ Bit 15: Wifi locator setting locked ++ Bits 16-31: Reserved ++*/ ++ ++static int dell_rfkill_set(void *data, bool blocked) ++{ ++ int disable = blocked ? 1 : 0; ++ unsigned long radio = (unsigned long)data; ++ int hwswitch_bit = (unsigned long)data - 1; ++ int ret = 0; ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ ++ /* If the hardware switch controls this radio, and the hardware ++ switch is disabled, don't allow changing the software state */ ++ if ((hwswitch_state & BIT(hwswitch_bit)) && ++ !(buffer->output[1] & BIT(16))) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ buffer->input[0] = (1 | (radio<<8) | (disable << 16)); ++ dell_send_request(buffer, 17, 11); ++ ++out: ++ release_buffer(); ++ return ret; ++} ++ ++static void dell_rfkill_query(struct rfkill *rfkill, void *data) ++{ ++ int status; ++ int bit = (unsigned long)data + 16; ++ int hwswitch_bit = (unsigned long)data - 1; ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ status = buffer->output[1]; ++ release_buffer(); ++ ++ rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); ++ ++ if (hwswitch_state & (BIT(hwswitch_bit))) ++ rfkill_set_hw_state(rfkill, !(status & BIT(16))); ++} ++ ++static const struct rfkill_ops dell_rfkill_ops = { ++ .set_block = dell_rfkill_set, ++ .query = dell_rfkill_query, ++}; ++ + static struct dentry *dell_laptop_dir; + + static int dell_debugfs_show(struct seq_file *s, void *data) +@@ -424,6 +563,108 @@ static const struct file_operations dell_debugfs_fops = { + .release = single_release, + }; + ++static void dell_update_rfkill(struct work_struct *ignored) ++{ ++ if (wifi_rfkill) ++ dell_rfkill_query(wifi_rfkill, (void *)1); ++ if (bluetooth_rfkill) ++ dell_rfkill_query(bluetooth_rfkill, (void *)2); ++ if (wwan_rfkill) ++ dell_rfkill_query(wwan_rfkill, (void *)3); ++} ++static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); ++ ++ ++static int __init dell_setup_rfkill(void) ++{ ++ int status; ++ int ret; ++ ++ if (dmi_check_system(dell_blacklist)) { ++ pr_info("Blacklisted hardware detected - not enabling rfkill\n"); ++ return 0; ++ } ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ status = buffer->output[1]; ++ buffer->input[0] = 0x2; ++ dell_send_request(buffer, 17, 11); ++ hwswitch_state = buffer->output[1]; ++ release_buffer(); ++ ++ if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { ++ wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, ++ RFKILL_TYPE_WLAN, ++ &dell_rfkill_ops, (void *) 1); ++ if (!wifi_rfkill) { ++ ret = -ENOMEM; ++ goto err_wifi; ++ } ++ ret = rfkill_register(wifi_rfkill); ++ if (ret) ++ goto err_wifi; ++ } ++ ++ if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { ++ bluetooth_rfkill = rfkill_alloc("dell-bluetooth", ++ &platform_device->dev, ++ RFKILL_TYPE_BLUETOOTH, ++ &dell_rfkill_ops, (void *) 2); ++ if (!bluetooth_rfkill) { ++ ret = -ENOMEM; ++ goto err_bluetooth; ++ } ++ ret = rfkill_register(bluetooth_rfkill); ++ if (ret) ++ goto err_bluetooth; ++ } ++ ++ if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { ++ wwan_rfkill = rfkill_alloc("dell-wwan", ++ &platform_device->dev, ++ RFKILL_TYPE_WWAN, ++ &dell_rfkill_ops, (void *) 3); ++ if (!wwan_rfkill) { ++ ret = -ENOMEM; ++ goto err_wwan; ++ } ++ ret = rfkill_register(wwan_rfkill); ++ if (ret) ++ goto err_wwan; ++ } ++ ++ return 0; ++err_wwan: ++ rfkill_destroy(wwan_rfkill); ++ if (bluetooth_rfkill) ++ rfkill_unregister(bluetooth_rfkill); ++err_bluetooth: ++ rfkill_destroy(bluetooth_rfkill); ++ if (wifi_rfkill) ++ rfkill_unregister(wifi_rfkill); ++err_wifi: ++ rfkill_destroy(wifi_rfkill); ++ ++ return ret; ++} ++ ++static void dell_cleanup_rfkill(void) ++{ ++ if (wifi_rfkill) { ++ rfkill_unregister(wifi_rfkill); ++ rfkill_destroy(wifi_rfkill); ++ } ++ if (bluetooth_rfkill) { ++ rfkill_unregister(bluetooth_rfkill); ++ rfkill_destroy(bluetooth_rfkill); ++ } ++ if (wwan_rfkill) { ++ rfkill_unregister(wwan_rfkill); ++ rfkill_destroy(wwan_rfkill); ++ } ++} ++ + static int dell_send_intensity(struct backlight_device *bd) + { + int ret = 0; +@@ -515,6 +756,30 @@ static void touchpad_led_exit(void) + led_classdev_unregister(&touchpad_led); + } + ++static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, ++ struct serio *port) ++{ ++ static bool extended; ++ ++ if (str & 0x20) ++ return false; ++ ++ if (unlikely(data == 0xe0)) { ++ extended = true; ++ return false; ++ } else if (unlikely(extended)) { ++ switch (data) { ++ case 0x8: ++ schedule_delayed_work(&dell_rfkill_work, ++ round_jiffies_relative(HZ)); ++ break; ++ } ++ extended = false; ++ } ++ ++ return false; ++} ++ + static int __init dell_init(void) + { + int max_intensity = 0; +@@ -557,10 +822,26 @@ static int __init dell_init(void) + } + buffer = page_address(bufferpage); + ++ ret = dell_setup_rfkill(); ++ ++ if (ret) { ++ pr_warn("Unable to setup rfkill\n"); ++ goto fail_rfkill; ++ } ++ ++ ret = i8042_install_filter(dell_laptop_i8042_filter); ++ if (ret) { ++ pr_warn("Unable to install key filter\n"); ++ goto fail_filter; ++ } ++ + if (quirks && quirks->touchpad_led) + touchpad_led_init(&platform_device->dev); + + dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); ++ if (dell_laptop_dir != NULL) ++ debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, ++ &dell_debugfs_fops); + + #ifdef CONFIG_ACPI + /* In the event of an ACPI backlight being available, don't +@@ -603,6 +884,11 @@ static int __init dell_init(void) + return 0; + + fail_backlight: ++ i8042_remove_filter(dell_laptop_i8042_filter); ++ cancel_delayed_work_sync(&dell_rfkill_work); ++fail_filter: ++ dell_cleanup_rfkill(); ++fail_rfkill: + free_page((unsigned long)bufferpage); + fail_buffer: + platform_device_del(platform_device); +@@ -620,7 +906,10 @@ static void __exit dell_exit(void) + debugfs_remove_recursive(dell_laptop_dir); + if (quirks && quirks->touchpad_led) + touchpad_led_exit(); ++ i8042_remove_filter(dell_laptop_i8042_filter); ++ cancel_delayed_work_sync(&dell_rfkill_work); + backlight_device_unregister(dell_backlight_device); ++ dell_cleanup_rfkill(); + if (platform_device) { + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); +-- +1.8.3.1 + + +From 2a92551845bbbc8421ba908cd14bbdf065e0f454 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:17 +0100 +Subject: [PATCH 02/12] dell-laptop: Only enable rfkill on Latitudes + +The rfkill functionality was removed from the dell-laptop driver because it +was causing problems on various non Latitude models, and the blacklist kept +growing and growing. In the thread discussing this Dell mentioned that they +only QA the rfkill acpi interface on Latitudes and indeed there have been +no blacklist entries for Latitudes. + +Note that the blacklist contained no Vostros either, and most Vostros have +a hardware switch too, so we could consider supporting Vostros with a +hardware switch too. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 57 +++++--------------------------------- + 1 file changed, 7 insertions(+), 50 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 55f75a2..bae932b 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -119,53 +119,6 @@ static const struct dmi_system_id dell_device_table[] __initconst = { + }; + MODULE_DEVICE_TABLE(dmi, dell_device_table); + +-static struct dmi_system_id dell_blacklist[] = { +- /* Supported by compal-laptop */ +- { +- .ident = "Dell Mini 9", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), +- }, +- }, +- { +- .ident = "Dell Mini 10", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), +- }, +- }, +- { +- .ident = "Dell Mini 10v", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), +- }, +- }, +- { +- .ident = "Dell Mini 1012", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), +- }, +- }, +- { +- .ident = "Dell Inspiron 11z", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), +- }, +- }, +- { +- .ident = "Dell Mini 12", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), +- }, +- }, +- {} +-}; +- + static struct dmi_system_id dell_quirks[] = { + { + .callback = dmi_matched, +@@ -579,11 +532,15 @@ static int __init dell_setup_rfkill(void) + { + int status; + int ret; ++ const char *product; + +- if (dmi_check_system(dell_blacklist)) { +- pr_info("Blacklisted hardware detected - not enabling rfkill\n"); ++ /* ++ * rfkill causes trouble on various non Latitudes, according to Dell ++ * actually testing the rfkill functionality is only done on Latitudes. ++ */ ++ product = dmi_get_system_info(DMI_PRODUCT_NAME); ++ if (!product || strncmp(product, "Latitude", 8)) + return 0; +- } + + get_buffer(); + dell_send_request(buffer, 17, 11); +-- +1.8.3.1 + + +From ddde708217af6d5fe43c0086247c05ed317076b4 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:18 +0100 +Subject: [PATCH 03/12] dell-laptop: If there is no hwswitch, then clear all + hw-controlled bits + +To ensure we don't enter any hw-switch related code paths on machines without +a hw-switch. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index bae932b..48fabf6 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -548,6 +548,9 @@ static int __init dell_setup_rfkill(void) + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_state = buffer->output[1]; ++ /* If there is no hwswitch, then clear all hw-controlled bits */ ++ if (!(status & BIT(0))) ++ hwswitch_state &= ~7; + release_buffer(); + + if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { +-- +1.8.3.1 + + +From d038880efd9dd222c67fd31fbfca3440d0db3a06 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:19 +0100 +Subject: [PATCH 04/12] dell-laptop: Only get status from BIOS once when + updating + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 48fabf6..06f281b 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -425,21 +425,24 @@ out: + return ret; + } + ++static void dell_rfkill_update(struct rfkill *rfkill, int radio, int status) ++{ ++ rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); ++ ++ if (hwswitch_state & (BIT(radio - 1))) ++ rfkill_set_hw_state(rfkill, !(status & BIT(16))); ++} ++ + static void dell_rfkill_query(struct rfkill *rfkill, void *data) + { + int status; +- int bit = (unsigned long)data + 16; +- int hwswitch_bit = (unsigned long)data - 1; + + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + release_buffer(); + +- rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); +- +- if (hwswitch_state & (BIT(hwswitch_bit))) +- rfkill_set_hw_state(rfkill, !(status & BIT(16))); ++ dell_rfkill_update(rfkill, (unsigned long)data, status); + } + + static const struct rfkill_ops dell_rfkill_ops = { +@@ -518,12 +521,19 @@ static const struct file_operations dell_debugfs_fops = { + + static void dell_update_rfkill(struct work_struct *ignored) + { ++ int status; ++ ++ get_buffer(); ++ dell_send_request(buffer, 17, 11); ++ status = buffer->output[1]; ++ release_buffer(); ++ + if (wifi_rfkill) +- dell_rfkill_query(wifi_rfkill, (void *)1); ++ dell_rfkill_update(wifi_rfkill, 1, status); + if (bluetooth_rfkill) +- dell_rfkill_query(bluetooth_rfkill, (void *)2); ++ dell_rfkill_update(bluetooth_rfkill, 2, status); + if (wwan_rfkill) +- dell_rfkill_query(wwan_rfkill, (void *)3); ++ dell_rfkill_update(wwan_rfkill, 3, status); + } + static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + +-- +1.8.3.1 + + +From 33f9359abb9f6ded3e7b6dc98b1468c83404af49 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:20 +0100 +Subject: [PATCH 05/12] dell-laptop: Don't set sw_state from the query callback + +The query callback should only update the hw_state, see the comment in +net/rfkill/core.c in rfkill_set_block, which is its only caller. + +rfkill_set_block will modify the sw_state directly after calling query so +calling set_sw_state is an expensive NOP. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 06f281b..7f47396 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -425,10 +425,15 @@ out: + return ret; + } + +-static void dell_rfkill_update(struct rfkill *rfkill, int radio, int status) ++static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, ++ int status) + { + rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); ++} + ++static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, ++ int status) ++{ + if (hwswitch_state & (BIT(radio - 1))) + rfkill_set_hw_state(rfkill, !(status & BIT(16))); + } +@@ -442,7 +447,7 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) + status = buffer->output[1]; + release_buffer(); + +- dell_rfkill_update(rfkill, (unsigned long)data, status); ++ dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status); + } + + static const struct rfkill_ops dell_rfkill_ops = { +@@ -528,12 +533,18 @@ static void dell_update_rfkill(struct work_struct *ignored) + status = buffer->output[1]; + release_buffer(); + +- if (wifi_rfkill) +- dell_rfkill_update(wifi_rfkill, 1, status); +- if (bluetooth_rfkill) +- dell_rfkill_update(bluetooth_rfkill, 2, status); +- if (wwan_rfkill) +- dell_rfkill_update(wwan_rfkill, 3, status); ++ if (wifi_rfkill) { ++ dell_rfkill_update_hw_state(wifi_rfkill, 1, status); ++ dell_rfkill_update_sw_state(wifi_rfkill, 1, status); ++ } ++ if (bluetooth_rfkill) { ++ dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status); ++ dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); ++ } ++ if (wwan_rfkill) { ++ dell_rfkill_update_hw_state(wwan_rfkill, 3, status); ++ dell_rfkill_update_sw_state(wwan_rfkill, 3, status); ++ } + } + static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + +-- +1.8.3.1 + + +From 3f56588a79a06a0499db0077cad6675762ddc40e Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:21 +0100 +Subject: [PATCH 06/12] dell-laptop: Don't read-back sw_state on machines with + a hardware switch + +On machines with a hardware switch, the blocking settings can not be changed +through a Fn + wireless-key combo, so there is no reason to read back the +blocking state from the BIOS. + +Reading back is not only not necessary it is actually harmful, since on some +machines the blocking state will be cleared to all 0 after a wireless switch +toggle, even for radios not controlled by the hw-switch (yeah firmware bugs). + +This causes "magic" changes to the sw_state. This is inconsistent with other +rfkill drivers which preserve the sw_state over a hw kill on / off. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 7f47396..80de0cc 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -428,7 +428,10 @@ out: + static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, + int status) + { +- rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); ++ if (!(status & BIT(0))) { ++ /* No hw-switch, sync BIOS state to sw_state */ ++ rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); ++ } + } + + static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, +-- +1.8.3.1 + + +From 4d39d88ceb83e88953a76df8b1fa10f43f328038 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:22 +0100 +Subject: [PATCH 07/12] dell-laptop: Allow changing the sw_state while the + radio is blocked by hw + +This makes dell-laptop's rfkill code consistent with other drivers which +allow sw_state changes while hw blocked. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 80de0cc..834f499 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -404,7 +404,6 @@ static int dell_rfkill_set(void *data, bool blocked) + int disable = blocked ? 1 : 0; + unsigned long radio = (unsigned long)data; + int hwswitch_bit = (unsigned long)data - 1; +- int ret = 0; + + get_buffer(); + dell_send_request(buffer, 17, 11); +@@ -412,17 +411,15 @@ static int dell_rfkill_set(void *data, bool blocked) + /* If the hardware switch controls this radio, and the hardware + switch is disabled, don't allow changing the software state */ + if ((hwswitch_state & BIT(hwswitch_bit)) && +- !(buffer->output[1] & BIT(16))) { +- ret = -EINVAL; ++ !(buffer->output[1] & BIT(16))) + goto out; +- } + + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); + dell_send_request(buffer, 17, 11); + + out: + release_buffer(); +- return ret; ++ return 0; + } + + static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, +-- +1.8.3.1 + + +From 04c9a3a06c47b337b90a91e458716262cc45b103 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:23 +0100 +Subject: [PATCH 08/12] dell-laptop: Sync current block state to BIOS on hw + switch change + +This is necessary for 3 reasons: +1) To apply sw_state changes made while hw-blocked +2) To set all the blocked bits for hw-switch controlled radios to 1 when the + switch gets changed to off, this is necessary on some models to actually + turn the radio status LEDs off. +3) On some models non hw-switch controlled radios will have their block bit + cleared (potentially undoing a soft-block) on hw-switch toggle, this + restores the sw-block in this case. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 834f499..7f59624 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -422,10 +422,16 @@ out: + return 0; + } + ++/* Must be called with the buffer held */ + static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, + int status) + { +- if (!(status & BIT(0))) { ++ if (status & BIT(0)) { ++ /* Has hw-switch, sync sw_state to BIOS */ ++ int block = rfkill_blocked(rfkill); ++ buffer->input[0] = (1 | (radio << 8) | (block << 16)); ++ dell_send_request(buffer, 17, 11); ++ } else { + /* No hw-switch, sync BIOS state to sw_state */ + rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); + } +@@ -445,9 +451,10 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; +- release_buffer(); + + dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status); ++ ++ release_buffer(); + } + + static const struct rfkill_ops dell_rfkill_ops = { +@@ -531,7 +538,6 @@ static void dell_update_rfkill(struct work_struct *ignored) + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; +- release_buffer(); + + if (wifi_rfkill) { + dell_rfkill_update_hw_state(wifi_rfkill, 1, status); +@@ -545,6 +551,8 @@ static void dell_update_rfkill(struct work_struct *ignored) + dell_rfkill_update_hw_state(wwan_rfkill, 3, status); + dell_rfkill_update_sw_state(wwan_rfkill, 3, status); + } ++ ++ release_buffer(); + } + static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + +-- +1.8.3.1 + + +From ed1128989ab242f44664b446702a512e5695c4b7 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:24 +0100 +Subject: [PATCH 09/12] dell-laptop: Do not skip setting blocked bit rfkill_set + while hw-blocked + +Instead when hw-blocked always write 1 to the blocked bit for the radio in +question. This is necessary to properly set all the blocked bits for hw-switch +controlled radios to 1 after power-on and resume. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index 7f59624..b33b779 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -409,15 +409,14 @@ static int dell_rfkill_set(void *data, bool blocked) + dell_send_request(buffer, 17, 11); + + /* If the hardware switch controls this radio, and the hardware +- switch is disabled, don't allow changing the software state */ ++ switch is disabled, always disable the radio */ + if ((hwswitch_state & BIT(hwswitch_bit)) && + !(buffer->output[1] & BIT(16))) +- goto out; ++ disable = 1; + + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); + dell_send_request(buffer, 17, 11); + +-out: + release_buffer(); + return 0; + } +-- +1.8.3.1 + + +From 26c22d63a70f62e0832c6d9f2a2690ab0155d584 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:25 +0100 +Subject: [PATCH 10/12] dell-laptop: Wait less long before updating rfkill + after an rfkill keypress + +Some time is needed for the BIOS to do its work, but 250ms should be plenty. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index b33b779..fe20f67 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -759,7 +759,7 @@ static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, +- round_jiffies_relative(HZ)); ++ round_jiffies_relative(HZ / 4)); + break; + } + extended = false; +-- +1.8.3.1 + + +From 8e0e668d0aa09d2eb0a7a260b6c7801796e01bd3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:26 +0100 +Subject: [PATCH 11/12] dell-laptop: Add a force_rfkill module parameter + +Setting force_rfkill will cause the dell-laptop rfkill code to skip its +whitelist checks, this will allow individual users to override the whitelist, +as well as to gather info from users to improve the checks. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index fe20f67..bd67c89 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -93,6 +93,10 @@ static struct backlight_device *dell_backlight_device; + static struct rfkill *wifi_rfkill; + static struct rfkill *bluetooth_rfkill; + static struct rfkill *wwan_rfkill; ++static bool force_rfkill; ++ ++module_param(force_rfkill, bool, 0444); ++MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models"); + + static const struct dmi_system_id dell_device_table[] __initconst = { + { +@@ -567,7 +571,7 @@ static int __init dell_setup_rfkill(void) + * actually testing the rfkill functionality is only done on Latitudes. + */ + product = dmi_get_system_info(DMI_PRODUCT_NAME); +- if (!product || strncmp(product, "Latitude", 8)) ++ if (!force_rfkill && (!product || strncmp(product, "Latitude", 8))) + return 0; + + get_buffer(); +-- +1.8.3.1 + + +From 2bd4ac139259bb605fc0325a7dda33e2fbb67ae3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 17 Nov 2013 14:00:27 +0100 +Subject: [PATCH 12/12] dell-laptop: Only enable rfkill functionality on + laptops with a hw killswitch + +All my testing has been on laptops with a hw killswitch, so to be on the +safe side disable rfkill functionality on models without a hw killswitch for +now. Once we gather some feedback on laptops without a hw killswitch this +decision maybe reconsidered. + +Signed-off-by: Hans de Goede +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/dell-laptop.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index bd67c89..c608b1d 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -580,11 +580,18 @@ static int __init dell_setup_rfkill(void) + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_state = buffer->output[1]; +- /* If there is no hwswitch, then clear all hw-controlled bits */ +- if (!(status & BIT(0))) +- hwswitch_state &= ~7; + release_buffer(); + ++ if (!(status & BIT(0))) { ++ if (force_rfkill) { ++ /* No hwsitch, clear all hw-controlled bits */ ++ hwswitch_state &= ~7; ++ } else { ++ /* rfkill is only tested on laptops with a hwswitch */ ++ return 0; ++ } ++ } ++ + if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { + wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, + RFKILL_TYPE_WLAN, +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index f6dfbb12c..e2e31dfd1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -821,8 +821,7 @@ Patch25161: inet-prevent-leakage-of-uninitialized-memory-to-user.patch Patch25162: inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch #rhbz 958826 -Patch25164: 0001-Revert-dell-laptop-Remove-rfkill-code.patch -Patch25165: 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch +Patch25164: dell-laptop.patch # END OF PATCH DEFINITIONS @@ -1582,8 +1581,7 @@ ApplyPatch inet-prevent-leakage-of-uninitialized-memory-to-user.patch ApplyPatch inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch #rhbz 958826 -ApplyPatch 0001-Revert-dell-laptop-Remove-rfkill-code.patch -ApplyPatch 0002-dell-laptop-Only-enable-rfkill-on-Latitudes.patch +ApplyPatch dell-laptop.patch # END OF PATCH APPLICATIONS From 26ef1781a0f9d49d2eeb6d4e09c77509eb3264f7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Dec 2013 08:50:43 -0500 Subject: [PATCH 483/492] CVE-2013-XXXX net: memory leak in recvmsg (rhbz 1039845 1039874) --- kernel.spec | 10 + ...sg-handler-msg_name-and-msg_namelen-.patch | 771 ++++++++++++++++++ 2 files changed, 781 insertions(+) create mode 100644 net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch diff --git a/kernel.spec b/kernel.spec index e2e31dfd1..16c5750b4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -823,6 +823,10 @@ Patch25162: inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-fu #rhbz 958826 Patch25164: dell-laptop.patch +#CVE-2013-XXXX rhbz 1039845 1039874 +Patch25165: net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch + + # END OF PATCH DEFINITIONS %endif @@ -1583,6 +1587,9 @@ ApplyPatch inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-fun #rhbz 958826 ApplyPatch dell-laptop.patch +#CVE-2013-XXXX rhbz 1039845 1039874 +ApplyPatch net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch + # END OF PATCH APPLICATIONS %endif @@ -2424,6 +2431,9 @@ fi # ||----w | # || || %changelog +* Tue Dec 10 2013 Josh Boyer +- CVE-2013-XXXX net: memory leak in recvmsg (rhbz 1039845 1039874) + * Tue Dec 03 2013 Josh Boyer - Add patches to fix rfkill switch on Dell machines (rhbz 958826) diff --git a/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch b/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch new file mode 100644 index 000000000..08c6302f6 --- /dev/null +++ b/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch @@ -0,0 +1,771 @@ +From 9cb9fb275f8794546dc31a79f2f02127fed5baf2 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Thu, 21 Nov 2013 03:14:22 +0100 +Subject: [PATCH] net: rework recvmsg handler msg_name and msg_namelen logic + +[ Upstream commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c ] + +This patch now always passes msg->msg_namelen as 0. recvmsg handlers must +set msg_namelen to the proper size <= sizeof(struct sockaddr_storage) +to return msg_name to the user. + +This prevents numerous uninitialized memory leaks we had in the +recvmsg handlers and makes it harder for new code to accidentally leak +uninitialized memory. + +Optimize for the case recvfrom is called with NULL as address. We don't +need to copy the address at all, so set it to NULL before invoking the +recvmsg handler. We can do so, because all the recvmsg handlers must +cope with the case a plain read() is called on them. read() also sets +msg_name to NULL. + +Also document these changes in include/linux/net.h as suggested by David +Miller. + +Changes since RFC: + +Set msg->msg_name = NULL if user specified a NULL in msg_name but had a +non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't +affect sendto as it would bail out earlier while trying to copy-in the +address. It also more naturally reflects the logic by the callers of +verify_iovec. + +With this change in place I could remove " +if (!uaddr || msg_sys->msg_namelen == 0) + msg->msg_name = NULL +". + +This change does not alter the user visible error logic as we ignore +msg_namelen as long as msg_name is NULL. + +Also remove two unnecessary curly brackets in ___sys_recvmsg and change +comments to netdev style. + +Cc: David Miller +Suggested-by: Eric Dumazet +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + crypto/algif_hash.c | 2 -- + crypto/algif_skcipher.c | 1 - + drivers/isdn/mISDN/socket.c | 13 ++++--------- + drivers/net/ppp/pppoe.c | 2 -- + include/linux/net.h | 8 ++++++++ + net/appletalk/ddp.c | 16 +++++++--------- + net/atm/common.c | 2 -- + net/ax25/af_ax25.c | 4 ++-- + net/bluetooth/af_bluetooth.c | 4 ---- + net/bluetooth/hci_sock.c | 2 -- + net/bluetooth/rfcomm/sock.c | 1 - + net/bluetooth/sco.c | 1 - + net/caif/caif_socket.c | 4 ---- + net/compat.c | 3 ++- + net/core/iovec.c | 3 ++- + net/ipx/af_ipx.c | 3 +-- + net/irda/af_irda.c | 4 ---- + net/iucv/af_iucv.c | 2 -- + net/key/af_key.c | 1 - + net/l2tp/l2tp_ppp.c | 2 -- + net/llc/af_llc.c | 2 -- + net/netlink/af_netlink.c | 2 -- + net/netrom/af_netrom.c | 3 +-- + net/nfc/llcp_sock.c | 2 -- + net/nfc/rawsock.c | 2 -- + net/packet/af_packet.c | 32 +++++++++++++++----------------- + net/rds/recv.c | 2 -- + net/rose/af_rose.c | 8 +++++--- + net/rxrpc/ar-recvmsg.c | 9 ++++++--- + net/socket.c | 19 +++++++++++-------- + net/tipc/socket.c | 6 ------ + net/unix/af_unix.c | 5 ----- + net/vmw_vsock/af_vsock.c | 2 -- + net/vmw_vsock/vmci_transport.c | 2 -- + net/x25/af_x25.c | 3 +-- + 35 files changed, 65 insertions(+), 112 deletions(-) + +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index 0262210..ef5356c 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -161,8 +161,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, + else if (len < ds) + msg->msg_flags |= MSG_TRUNC; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + if (ctx->more) { + ctx->more = 0; +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index a1c4f0a..6a6dfc0 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -432,7 +432,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, + long copied = 0; + + lock_sock(sk); +- msg->msg_namelen = 0; + for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; + iovlen--, iov++) { + unsigned long seglen = iov->iov_len; +diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c +index e47dcb9..5cefb47 100644 +--- a/drivers/isdn/mISDN/socket.c ++++ b/drivers/isdn/mISDN/socket.c +@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + { + struct sk_buff *skb; + struct sock *sk = sock->sk; +- struct sockaddr_mISDN *maddr; + + int copied, err; + +@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return err; + +- if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) { +- msg->msg_namelen = sizeof(struct sockaddr_mISDN); +- maddr = (struct sockaddr_mISDN *)msg->msg_name; ++ if (msg->msg_name) { ++ struct sockaddr_mISDN *maddr = msg->msg_name; ++ + maddr->family = AF_ISDN; + maddr->dev = _pms(sk)->dev->id; + if ((sk->sk_protocol == ISDN_P_LAPD_TE) || +@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + maddr->sapi = _pms(sk)->ch.addr & 0xFF; + maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF; + } +- } else { +- if (msg->msg_namelen) +- printk(KERN_WARNING "%s: too small namelen %d\n", +- __func__, msg->msg_namelen); +- msg->msg_namelen = 0; ++ msg->msg_namelen = sizeof(*maddr); + } + + copied = skb->len + MISDN_HEADER_LEN; +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index 5f66e30..82ee6ed 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, + if (error < 0) + goto end; + +- m->msg_namelen = 0; +- + if (skb) { + total_len = min_t(size_t, total_len, skb->len); + error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); +diff --git a/include/linux/net.h b/include/linux/net.h +index 4f27575..8bd9d92 100644 +--- a/include/linux/net.h ++++ b/include/linux/net.h +@@ -163,6 +163,14 @@ struct proto_ops { + #endif + int (*sendmsg) (struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len); ++ /* Notes for implementing recvmsg: ++ * =============================== ++ * msg->msg_namelen should get updated by the recvmsg handlers ++ * iff msg_name != NULL. It is by default 0 to prevent ++ * returning uninitialized memory to user space. The recvfrom ++ * handlers can assume that msg.msg_name is either NULL or has ++ * a minimum size of sizeof(struct sockaddr_storage). ++ */ + int (*recvmsg) (struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags); +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index 7fee50d..7d424ac 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1735,7 +1735,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr + size_t size, int flags) + { + struct sock *sk = sock->sk; +- struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; + struct ddpehdr *ddp; + int copied = 0; + int offset = 0; +@@ -1764,14 +1763,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr + } + err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied); + +- if (!err) { +- if (sat) { +- sat->sat_family = AF_APPLETALK; +- sat->sat_port = ddp->deh_sport; +- sat->sat_addr.s_node = ddp->deh_snode; +- sat->sat_addr.s_net = ddp->deh_snet; +- } +- msg->msg_namelen = sizeof(*sat); ++ if (!err && msg->msg_name) { ++ struct sockaddr_at *sat = msg->msg_name; ++ sat->sat_family = AF_APPLETALK; ++ sat->sat_port = ddp->deh_sport; ++ sat->sat_addr.s_node = ddp->deh_snode; ++ sat->sat_addr.s_net = ddp->deh_snet; ++ msg->msg_namelen = sizeof(*sat); + } + + skb_free_datagram(sk, skb); /* Free the datagram. */ +diff --git a/net/atm/common.c b/net/atm/common.c +index 737bef5..7b49100 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -531,8 +531,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + struct sk_buff *skb; + int copied, error = -EINVAL; + +- msg->msg_namelen = 0; +- + if (sock->state != SS_CONNECTED) + return -ENOTCONN; + +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 4b4d2b7..78c474f 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -1636,11 +1636,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + +- if (msg->msg_namelen != 0) { +- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; ++ if (msg->msg_name) { + ax25_digi digi; + ax25_address src; + const unsigned char *mac = skb_mac_header(skb); ++ struct sockaddr_ax25 *sax = msg->msg_name; + + memset(sax, 0, sizeof(struct full_sockaddr_ax25)); + ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, +diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c +index 9096137..6629cdc 100644 +--- a/net/bluetooth/af_bluetooth.c ++++ b/net/bluetooth/af_bluetooth.c +@@ -221,8 +221,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags & (MSG_OOB)) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) { + if (sk->sk_shutdown & RCV_SHUTDOWN) +@@ -287,8 +285,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags & MSG_OOB) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + BT_DBG("sk %p size %zu", sk, size); + + lock_sock(sk); +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index 9bd7d95..fa4bf66 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -752,8 +752,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return err; + +- msg->msg_namelen = 0; +- + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 30b3721..c1c6028 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -608,7 +608,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { + rfcomm_dlc_accept(d); +- msg->msg_namelen = 0; + return 0; + } + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index e7bd4ee..2bb1d3a 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -700,7 +700,6 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { + sco_conn_defer_accept(pi->conn->hcon, 0); + sk->sk_state = BT_CONFIG; +- msg->msg_namelen = 0; + + release_sock(sk); + return 0; +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index 05a41c7..d6be3ed 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, + if (m->msg_flags&MSG_OOB) + goto read_error; + +- m->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags, 0 , &ret); + if (!skb) + goto read_error; +@@ -361,8 +359,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags&MSG_OOB) + goto out; + +- msg->msg_namelen = 0; +- + /* + * Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg +diff --git a/net/compat.c b/net/compat.c +index 8903258..618c6a8 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + if (err < 0) + return err; + } +- kern_msg->msg_name = kern_address; ++ if (kern_msg->msg_name) ++ kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + +diff --git a/net/core/iovec.c b/net/core/iovec.c +index de178e4..9a31515 100644 +--- a/net/core/iovec.c ++++ b/net/core/iovec.c +@@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + if (err < 0) + return err; + } +- m->msg_name = address; ++ if (m->msg_name) ++ m->msg_name = address; + } else { + m->msg_name = NULL; + } +diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c +index 7a1e0fc..e096025 100644 +--- a/net/ipx/af_ipx.c ++++ b/net/ipx/af_ipx.c +@@ -1823,8 +1823,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + if (skb->tstamp.tv64) + sk->sk_stamp = skb->tstamp; + +- msg->msg_namelen = sizeof(*sipx); +- + if (sipx) { + sipx->sipx_family = AF_IPX; + sipx->sipx_port = ipx->ipx_source.sock; +@@ -1832,6 +1830,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; + sipx->sipx_type = ipx->ipx_type; + sipx->sipx_zero = 0; ++ msg->msg_namelen = sizeof(*sipx); + } + rc = copied; + +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index 0578d4f..a5e62ef5 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1385,8 +1385,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, + + IRDA_DEBUG(4, "%s()\n", __func__); + +- msg->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); + if (!skb) +@@ -1451,8 +1449,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, + target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); + timeo = sock_rcvtimeo(sk, noblock); + +- msg->msg_namelen = 0; +- + do { + int chunk; + struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 168aff5..c4b7218 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -1324,8 +1324,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + int err = 0; + u32 offset; + +- msg->msg_namelen = 0; +- + if ((sk->sk_state == IUCV_DISCONN) && + skb_queue_empty(&iucv->backlog_skb_q) && + skb_queue_empty(&sk->sk_receive_queue) && +diff --git a/net/key/af_key.c b/net/key/af_key.c +index ab8bd2c..66f51c5 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3623,7 +3623,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb, + if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) + goto out; + +- msg->msg_namelen = 0; + skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err); + if (skb == NULL) + goto out; +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 8c46b27..44441c0 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -197,8 +197,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sk->sk_state & PPPOX_BOUND) + goto end; + +- msg->msg_namelen = 0; +- + err = 0; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 48aaa89..8870988 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, + int target; /* Read at least this many bytes */ + long timeo; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + copied = -ENOTCONN; + if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 0c61b59..90b654b 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2317,8 +2317,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, + } + #endif + +- msg->msg_namelen = 0; +- + copied = data_skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 698814b..53c19a3 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -1179,10 +1179,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, + sax->sax25_family = AF_NETROM; + skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, + AX25_ADDR_LEN); ++ msg->msg_namelen = sizeof(*sax); + } + +- msg->msg_namelen = sizeof(*sax); +- + skb_free_datagram(sk, skb); + + release_sock(sk); +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index d308402..824c605 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -807,8 +807,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + pr_debug("%p %zu\n", sk, len); + +- msg->msg_namelen = 0; +- + lock_sock(sk); + + if (sk->sk_state == LLCP_CLOSED && +diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c +index 313bf1b..5d11f4a 100644 +--- a/net/nfc/rawsock.c ++++ b/net/nfc/rawsock.c +@@ -241,8 +241,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return rc; + +- msg->msg_namelen = 0; +- + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 75c8bbf..739c50d 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2694,7 +2694,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sock *sk = sock->sk; + struct sk_buff *skb; + int copied, err; +- struct sockaddr_ll *sll; + int vnet_hdr_len = 0; + + err = -EINVAL; +@@ -2777,22 +2776,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + goto out_free; + } + +- /* +- * If the address length field is there to be filled in, we fill +- * it in now. +- */ +- +- sll = &PACKET_SKB_CB(skb)->sa.ll; +- if (sock->type == SOCK_PACKET) +- msg->msg_namelen = sizeof(struct sockaddr_pkt); +- else +- msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); +- +- /* +- * You lose any data beyond the buffer you gave. If it worries a +- * user program they can ask the device for its MTU anyway. ++ /* You lose any data beyond the buffer you gave. If it worries ++ * a user program they can ask the device for its MTU ++ * anyway. + */ +- + copied = skb->len; + if (copied > len) { + copied = len; +@@ -2805,9 +2792,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + + sock_recv_ts_and_drops(msg, sk, skb); + +- if (msg->msg_name) ++ if (msg->msg_name) { ++ /* If the address length field is there to be filled ++ * in, we fill it in now. ++ */ ++ if (sock->type == SOCK_PACKET) { ++ msg->msg_namelen = sizeof(struct sockaddr_pkt); ++ } else { ++ struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; ++ msg->msg_namelen = sll->sll_halen + ++ offsetof(struct sockaddr_ll, sll_addr); ++ } + memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, + msg->msg_namelen); ++ } + + if (pkt_sk(sk)->auxdata) { + struct tpacket_auxdata aux; +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 9f0f17c..de339b2 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + + rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + +- msg->msg_namelen = 0; +- + if (msg_flags & MSG_OOB) + goto out; + +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index e98fcfb..33af772 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -1216,7 +1216,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, + { + struct sock *sk = sock->sk; + struct rose_sock *rose = rose_sk(sk); +- struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; + size_t copied; + unsigned char *asmptr; + struct sk_buff *skb; +@@ -1252,8 +1251,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + +- if (srose != NULL) { +- memset(srose, 0, msg->msg_namelen); ++ if (msg->msg_name) { ++ struct sockaddr_rose *srose; ++ ++ memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); ++ srose = msg->msg_name; + srose->srose_family = AF_ROSE; + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; +diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c +index 4b48687..898492a 100644 +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, + + /* copy the peer address and timestamp */ + if (!continue_call) { +- if (msg->msg_name && msg->msg_namelen > 0) ++ if (msg->msg_name) { ++ size_t len = ++ sizeof(call->conn->trans->peer->srx); + memcpy(msg->msg_name, +- &call->conn->trans->peer->srx, +- sizeof(call->conn->trans->peer->srx)); ++ &call->conn->trans->peer->srx, len); ++ msg->msg_namelen = len; ++ } + sock_recv_ts_and_drops(msg, &rx->sk, skb); + } + +diff --git a/net/socket.c b/net/socket.c +index 4b94643..5158ff7 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1849,8 +1849,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, + msg.msg_iov = &iov; + iov.iov_len = size; + iov.iov_base = ubuf; +- msg.msg_name = (struct sockaddr *)&address; +- msg.msg_namelen = sizeof(address); ++ /* Save some cycles and don't copy the address if not needed */ ++ msg.msg_name = addr ? (struct sockaddr *)&address : NULL; ++ /* We assume all kernel code knows the size of sockaddr_storage */ ++ msg.msg_namelen = 0; + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + err = sock_recvmsg(sock, &msg, size, flags); +@@ -2230,16 +2232,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + goto out; + } + +- /* +- * Save the user-mode address (verify_iovec will change the +- * kernel msghdr to use the kernel address space) ++ /* Save the user-mode address (verify_iovec will change the ++ * kernel msghdr to use the kernel address space) + */ +- + uaddr = (__force void __user *)msg_sys->msg_name; + uaddr_len = COMPAT_NAMELEN(msg); +- if (MSG_CMSG_COMPAT & flags) { ++ if (MSG_CMSG_COMPAT & flags) + err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); +- } else ++ else + err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); + if (err < 0) + goto out_freeiov; +@@ -2248,6 +2248,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + cmsg_ptr = (unsigned long)msg_sys->msg_control; + msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); + ++ /* We assume all kernel code knows the size of sockaddr_storage */ ++ msg_sys->msg_namelen = 0; ++ + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index 6cc7ddd..dffdbea 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -984,9 +984,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, + goto exit; + } + +- /* will be updated in set_orig_addr() if needed */ +- m->msg_namelen = 0; +- + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + restart: + +@@ -1095,9 +1092,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, + goto exit; + } + +- /* will be updated in set_orig_addr() if needed */ +- m->msg_namelen = 0; +- + target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index e64bbcf..6c66e8d 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1762,7 +1762,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk) + { + struct unix_sock *u = unix_sk(sk); + +- msg->msg_namelen = 0; + if (u->addr) { + msg->msg_namelen = u->addr->len; + memcpy(msg->msg_name, u->addr->name, u->addr->len); +@@ -1786,8 +1785,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags&MSG_OOB) + goto out; + +- msg->msg_namelen = 0; +- + err = mutex_lock_interruptible(&u->readlock); + if (err) { + err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); +@@ -1927,8 +1924,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); + timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); + +- msg->msg_namelen = 0; +- + /* Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg + */ +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 4d93346..16f721c 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1663,8 +1663,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, + vsk = vsock_sk(sk); + err = 0; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + + if (sk->sk_state != SS_CONNECTED) { +diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c +index ffc11df..73ca104 100644 +--- a/net/vmw_vsock/vmci_transport.c ++++ b/net/vmw_vsock/vmci_transport.c +@@ -1746,8 +1746,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb, + if (flags & MSG_OOB || flags & MSG_ERRQUEUE) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + /* Retrieve the head sk_buff from the socket's receive queue. */ + err = 0; + skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err); +diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c +index 45a3ab5..7622789 100644 +--- a/net/x25/af_x25.c ++++ b/net/x25/af_x25.c +@@ -1340,10 +1340,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sx25) { + sx25->sx25_family = AF_X25; + sx25->sx25_addr = x25->dest_addr; ++ msg->msg_namelen = sizeof(*sx25); + } + +- msg->msg_namelen = sizeof(struct sockaddr_x25); +- + x25_check_rbuf(sk); + rc = copied; + out_free_dgram: +-- +1.8.3.1 + From 8e4f825019e89989e1cf6d7bbddde239173cdf46 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Dec 2013 08:53:51 -0500 Subject: [PATCH 484/492] Add patch fields --- net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch b/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch index 08c6302f6..3ec6d0194 100644 --- a/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch +++ b/net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch @@ -1,3 +1,6 @@ +Bugzilla: 1039874 +Upstream-status: 3.13 and 3.12.4 + From 9cb9fb275f8794546dc31a79f2f02127fed5baf2 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 21 Nov 2013 03:14:22 +0100 From 841005a8d612a20d84f208b05b8113d4881956dc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 11 Dec 2013 08:47:06 -0500 Subject: [PATCH 485/492] Add patches to support ETPS/2 Elantech touchpads (rhbz 1030802) --- ...dd-support-for-newer-August-2013-dev.patch | 36 ++++++ ...y-differentiate-between-clickpads-an.patch | 110 ++++++++++++++++++ kernel.spec | 10 ++ 3 files changed, 156 insertions(+) create mode 100644 Input-elantech-add-support-for-newer-August-2013-dev.patch create mode 100644 elantech-Properly-differentiate-between-clickpads-an.patch diff --git a/Input-elantech-add-support-for-newer-August-2013-dev.patch b/Input-elantech-add-support-for-newer-August-2013-dev.patch new file mode 100644 index 000000000..e67f2800a --- /dev/null +++ b/Input-elantech-add-support-for-newer-August-2013-dev.patch @@ -0,0 +1,36 @@ +Bugzilla: 1030802 +Upstream-status: 3.13 + +From 9cb80b965eaf7af1369f6e16f48a05fbaaccc021 Mon Sep 17 00:00:00 2001 +From: Matt Walker +Date: Thu, 5 Dec 2013 12:39:02 -0800 +Subject: [PATCH] Input: elantech - add support for newer (August 2013) devices + +Added detection for newer Elantech touchpads, so that kernel doesn't +fall-back to default PS/2 driver. Supports touchpads released after +~August 2013. Fixes bug: +https://lists.launchpad.net/kernel-packages/msg18481.html + +Tested on an Acer Aspire S7-392-6302. + +Signed-off by: Matt Walker +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 8551dca..597e9b8 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd) + break; + case 6: + case 7: ++ case 8: + etd->hw_version = 4; + break; + default: +-- +1.8.3.1 + diff --git a/elantech-Properly-differentiate-between-clickpads-an.patch b/elantech-Properly-differentiate-between-clickpads-an.patch new file mode 100644 index 000000000..3fc49980b --- /dev/null +++ b/elantech-Properly-differentiate-between-clickpads-an.patch @@ -0,0 +1,110 @@ +Bugzilla: 1030802 +Upstream-status: http://www.mail-archive.com/linux-input@vger.kernel.org/msg07220.html + +From e1c7fa5fbb6688bd464658ff8a93bdf23c442065 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 9 Dec 2013 15:18:04 +0100 +Subject: [PATCH v2] elantech: Properly differentiate between clickpads and + normal touchpads + +The current assumption in the elantech driver that hw version 3 touchpads are +never clickpads and hw version 4 touchpads are always clickpads is wrong. + +There are several bug reports for this, ie: +https://bugzilla.redhat.com/show_bug.cgi?id=1030802 +http://superuser.com/questions/619582/right-elantech-touchpad-button-not-working-in-linux + +I've spend a couple of hours wading through various bugzillas, +launchpads and forum posts to create a list of fw-versions and capabilities +for different laptop models to find a good method to differentiate between +clickpads and versions with separate hardware buttons. + +Which shows that a device being a clickpad is reliable indicated by bit 12 +being set in the fw_version. I've included the gathered list inside the driver, +so that we've this info at hand if we need to revisit this later. + +Signed-off-by: Hans de Goede +--- + drivers/input/mouse/elantech.c | 45 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 42 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 597e9b8..ef1cf52 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -486,6 +486,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse) + unsigned char *packet = psmouse->packet; + + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); ++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + input_mt_report_pointer_emulation(dev, true); + input_sync(dev); + } +@@ -984,6 +985,44 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, + } + + /* ++ * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in ++ * fw_version for this is based on the following fw_version & caps table: ++ * ++ * Laptop-model: fw_version: caps: buttons: ++ * Acer S3 0x461f00 10, 13, 0e clickpad ++ * Acer S7-392 0x581f01 50, 17, 0d clickpad ++ * Acer V5-131 0x461f02 01, 16, 0c clickpad ++ * Acer V5-551 0x461f00 ? clickpad ++ * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons ++ * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons ++ * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons ++ * Asus UX31 0x361f00 20, 15, 0e clickpad ++ * Asus UX32VD 0x361f02 00, 15, 0e clickpad ++ * Avatar AVIU-145A2 0x361f00 ? clickpad ++ * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons ++ * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) ++ * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons ++ * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad ++ * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad ++ * Samsung NP900X3E-A02 0x575f03 ? clickpad ++ * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad ++ * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons ++ * Samsung RF710 0x450f00 ? 2 hw buttons ++ * System76 Pangolin 0x250f01 ? 2 hw buttons ++ * (*) + 3 trackpoint buttons ++ */ ++static void elantech_set_buttonpad_prop(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ ++ if (etd->fw_version & 0x001000) { ++ __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); ++ __clear_bit(BTN_RIGHT, dev->keybit); ++ } ++} ++ ++/* + * Set the appropriate event bits for the input subsystem + */ + static int elantech_set_input_params(struct psmouse *psmouse) +@@ -1026,6 +1065,8 @@ static int elantech_set_input_params(struct psmouse *psmouse) + __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + /* fall through */ + case 3: ++ if (etd->hw_version == 3) ++ elantech_set_buttonpad_prop(psmouse); + input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + if (etd->reports_pressure) { +@@ -1047,9 +1088,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) + */ + psmouse_warn(psmouse, "couldn't query resolution data.\n"); + } +- /* v4 is clickpad, with only one button. */ +- __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); +- __clear_bit(BTN_RIGHT, dev->keybit); ++ elantech_set_buttonpad_prop(psmouse); + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); + /* For X to recognize me as touchpad. */ + input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); +-- +1.8.4.2 + diff --git a/kernel.spec b/kernel.spec index 16c5750b4..005b9b133 100644 --- a/kernel.spec +++ b/kernel.spec @@ -826,6 +826,9 @@ Patch25164: dell-laptop.patch #CVE-2013-XXXX rhbz 1039845 1039874 Patch25165: net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch +#rhbz 1030802 +Patch25170: Input-elantech-add-support-for-newer-August-2013-dev.patch +Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch # END OF PATCH DEFINITIONS @@ -1590,6 +1593,10 @@ ApplyPatch dell-laptop.patch #CVE-2013-XXXX rhbz 1039845 1039874 ApplyPatch net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch +#rhbz 1030802 +ApplyPatch Input-elantech-add-support-for-newer-August-2013-dev.patch +ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch + # END OF PATCH APPLICATIONS %endif @@ -2431,6 +2438,9 @@ fi # ||----w | # || || %changelog +* Wed Dec 11 2013 Josh Boyer +- Add patches to support ETPS/2 Elantech touchpads (rhbz 1030802) + * Tue Dec 10 2013 Josh Boyer - CVE-2013-XXXX net: memory leak in recvmsg (rhbz 1039845 1039874) From c519a21724446b74ef8823fb8c9f7ae0bb831de0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Dec 2013 16:06:22 -0500 Subject: [PATCH 486/492] CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) --- ...6-Fix-potential-divide-by-0-in-lapic.patch | 102 ++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 111 insertions(+) create mode 100644 KVM-x86-Fix-potential-divide-by-0-in-lapic.patch diff --git a/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch b/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch new file mode 100644 index 000000000..8e144dff4 --- /dev/null +++ b/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch @@ -0,0 +1,102 @@ +Bugzilla: 1042081 +Upstream-status: 3.13 and sent for stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp361402oab; + Thu, 12 Dec 2013 12:43:43 -0800 (PST) +X-Received: by 10.68.241.134 with SMTP id wi6mr15423072pbc.44.1386881023599; + Thu, 12 Dec 2013 12:43:43 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id w3si17375457pbh.89.2013.12.12.12.43.07 + for ; + Thu, 12 Dec 2013 12:43:43 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1752145Ab3LLUiu (ORCPT + + 99 others); Thu, 12 Dec 2013 15:38:50 -0500 +Received: from mail-ee0-f45.google.com ([74.125.83.45]:47138 "EHLO + mail-ee0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751902Ab3LLUhP (ORCPT + ); + Thu, 12 Dec 2013 15:37:15 -0500 +Received: by mail-ee0-f45.google.com with SMTP id d49so478739eek.32 + for ; Thu, 12 Dec 2013 12:37:13 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=sender:from:to:cc:subject:date:message-id; + bh=Fa9qXXe9oER+jgB6WXA5v2LyR8O2Vaag7ZsOsv67MLg=; + b=WbBUzKN8o3OzB75st3w60z/rVczWaaxrvWc2URlwJwZ0lgqObvbXvAb3ophFJxsr/O + P3rEj33CGt5vFAmZWsrST8I4pVb7IPZYqmPuBklMhDmvegy2um2xEDCyIuI0oybwgple + n1dYPBTNqBhiiLgIUeKgEf88yU5dsAgKOZSTnkMYhDSy9pnGxRda4WtErJ+SHjvcMaX3 + t2Vt97egJ2n+e+2BvnpS8xZ8biqp6/l3EzvdsL4W849fUUshAKva4Npu0T/D4E3JIp2O + 3uY+geb/txJL2rOCacT3RljUb3+zAy2zhqGSjKR3AHePFNIX9RxfMi/vlPmTjO0vfmCP + H86Q== +X-Received: by 10.14.2.73 with SMTP id 49mr10139590eee.15.1386880633625; + Thu, 12 Dec 2013 12:37:13 -0800 (PST) +Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) + by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.11 + for + (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Thu, 12 Dec 2013 12:37:12 -0800 (PST) +From: Paolo Bonzini +To: linux-kernel@vger.kernel.org +Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, + Andy Honig , stable@vger.kernel.org +Subject: [PATCH] KVM: x86: Fix potential divide by 0 in lapic (CVE-2013-6367) +Date: Thu, 12 Dec 2013 21:36:52 +0100 +Message-Id: <1386880614-23300-2-git-send-email-pbonzini@redhat.com> +X-Mailer: git-send-email 1.8.3.1 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +From: Andy Honig + +Under guest controllable circumstances apic_get_tmcct will execute a +divide by zero and cause a crash. If the guest cpuid support +tsc deadline timers and performs the following sequence of requests +the host will crash. +- Set the mode to periodic +- Set the TMICT to 0 +- Set the mode bits to 11 (neither periodic, nor one shot, nor tsc deadline) +- Set the TMICT to non-zero. +Then the lapic_timer.period will be 0, but the TMICT will not be. If the +guest then reads from the TMCCT then the host will perform a divide by 0. + +This patch ensures that if the lapic_timer.period is 0, then the division +does not occur. + +Reported-by: Andrew Honig +Cc: stable@vger.kernel.org +Signed-off-by: Andrew Honig +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/lapic.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 5439117d5c4c..89b52ec7d09c 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -841,7 +841,8 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic) + ASSERT(apic != NULL); + + /* if initial count is 0, current count should also be 0 */ +- if (kvm_apic_get_reg(apic, APIC_TMICT) == 0) ++ if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 || ++ apic->lapic_timer.period == 0) + return 0; + + remaining = hrtimer_get_remaining(&apic->lapic_timer.timer); +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/kernel.spec b/kernel.spec index 005b9b133..698796928 100644 --- a/kernel.spec +++ b/kernel.spec @@ -830,6 +830,9 @@ Patch25165: net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch Patch25170: Input-elantech-add-support-for-newer-August-2013-dev.patch Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch +#CVE-2013-6367 rhbz 1032207 1042081 +Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch + # END OF PATCH DEFINITIONS %endif @@ -1597,6 +1600,9 @@ ApplyPatch net-rework-recvmsg-handler-msg_name-and-msg_namelen-.patch ApplyPatch Input-elantech-add-support-for-newer-August-2013-dev.patch ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch +#CVE-2013-6367 rhbz 1032207 1042081 +ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch + # END OF PATCH APPLICATIONS %endif @@ -2438,6 +2444,9 @@ fi # ||----w | # || || %changelog +* Thu Dec 12 2013 Josh Boyer +- CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) + * Wed Dec 11 2013 Josh Boyer - Add patches to support ETPS/2 Elantech touchpads (rhbz 1030802) From 537c688651c6ade3e5ab865f414e7df03a79fd84 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Dec 2013 16:15:05 -0500 Subject: [PATCH 487/492] CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) --- ...synchronization-to-_cached-functions.patch | 247 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 254 insertions(+) create mode 100644 KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch diff --git a/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch new file mode 100644 index 000000000..a37d4cf29 --- /dev/null +++ b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch @@ -0,0 +1,247 @@ +Bugzilla: 1042090 +Upstream-status: 3.13 and sent for stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp361293oab; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +X-Received: by 10.68.244.2 with SMTP id xc2mr15600217pbc.58.1386880872483; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id 5si8126292pbj.245.2013.12.12.12.40.49 + for ; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751901Ab3LLUiK (ORCPT + 64 others); + Thu, 12 Dec 2013 15:38:10 -0500 +Received: from mail-ea0-f169.google.com ([209.85.215.169]:43997 "EHLO + mail-ea0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751940Ab3LLUhR (ORCPT + ); Thu, 12 Dec 2013 15:37:17 -0500 +Received: by mail-ea0-f169.google.com with SMTP id l9so411843eaj.0 + for ; Thu, 12 Dec 2013 12:37:15 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=sender:from:to:cc:subject:date:message-id; + bh=2MLmYgVGbv9FpnyP90yrPKk21SJoXFj93yQcaRn4G8Y=; + b=ouBadI22VTf1UuezbySC80FWJYdpF/8Ks6I8f5rq1/7SDQPTpScjOYjZX0UtIf1ihj + aeQ7IHqpmIYGKWadUbH2l88ZP1+rP7T+f2dZQeCb3HLNsPum0Ix8dzm/koeDnuS3dx75 + 50E9ZcFXO13Hx24tM8p0SAuYZ1DvbCNnPRK0yxHOmCtCWe+mQLBIgig1rg8TzSAazWm7 + 8LhpztDlIzNyZcfzKQvtdqTOBdnhadx5x39fxOe54Yw4JbppDa7R+BY5Jz6GOd3U0Op1 + Nf97rU0pe/jeyOtjF0LVs/d9iyPPeRoSE+VAr91iT8qj9S2PFEN1QxxWL8sdvsDPZK6B + ZCmw== +X-Received: by 10.14.182.199 with SMTP id o47mr10030582eem.7.1386880635352; + Thu, 12 Dec 2013 12:37:15 -0800 (PST) +Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) + by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.13 + for + (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Thu, 12 Dec 2013 12:37:14 -0800 (PST) +From: Paolo Bonzini +To: linux-kernel@vger.kernel.org +Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, + Andy Honig , stable@vger.kernel.org +Subject: [PATCH] KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368) +Date: Thu, 12 Dec 2013 21:36:53 +0100 +Message-Id: <1386880614-23300-3-git-send-email-pbonzini@redhat.com> +X-Mailer: git-send-email 1.8.3.1 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +From: Andy Honig + +In kvm_lapic_sync_from_vapic and kvm_lapic_sync_to_vapic there is the +potential to corrupt kernel memory if userspace provides an address that +is at the end of a page. This patches concerts those functions to use +kvm_write_guest_cached and kvm_read_guest_cached. It also checks the +vapic_address specified by userspace during ioctl processing and returns +an error to userspace if the address is not a valid GPA. + +This is generally not guest triggerable, because the required write is +done by firmware that runs before the guest. Also, it only affects AMD +processors and oldish Intel that do not have the FlexPriority feature +(unless you disable FlexPriority, of course; then newer processors are +also affected). + +Fixes: b93463aa59d6 ('KVM: Accelerated apic support') + +Reported-by: Andrew Honig +Cc: stable@vger.kernel.org +Signed-off-by: Andrew Honig +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/lapic.c | 27 +++++++++++++++------------ + arch/x86/kvm/lapic.h | 4 ++-- + arch/x86/kvm/x86.c | 40 +--------------------------------------- + 3 files changed, 18 insertions(+), 53 deletions(-) + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 89b52ec7d09c..b8bec45c1610 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1692,7 +1692,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu, + void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) + { + u32 data; +- void *vapic; + + if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention)) + apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic); +@@ -1700,9 +1699,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) + if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) + return; + +- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); +- data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)); +- kunmap_atomic(vapic); ++ kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, ++ sizeof(u32)); + + apic_set_tpr(vcpu->arch.apic, data & 0xff); + } +@@ -1738,7 +1736,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) + u32 data, tpr; + int max_irr, max_isr; + struct kvm_lapic *apic = vcpu->arch.apic; +- void *vapic; + + apic_sync_pv_eoi_to_guest(vcpu, apic); + +@@ -1754,18 +1751,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) + max_isr = 0; + data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24); + +- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); +- *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data; +- kunmap_atomic(vapic); ++ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, ++ sizeof(u32)); + } + +-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) ++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) + { +- vcpu->arch.apic->vapic_addr = vapic_addr; +- if (vapic_addr) ++ if (vapic_addr) { ++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ++ &vcpu->arch.apic->vapic_cache, ++ vapic_addr, sizeof(u32))) ++ return -EINVAL; + __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); +- else ++ } else { + __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); ++ } ++ ++ vcpu->arch.apic->vapic_addr = vapic_addr; ++ return 0; + } + + int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) +diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h +index c730ac9fe801..c8b0d0d2da5c 100644 +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -34,7 +34,7 @@ struct kvm_lapic { + */ + void *regs; + gpa_t vapic_addr; +- struct page *vapic_page; ++ struct gfn_to_hva_cache vapic_cache; + unsigned long pending_events; + unsigned int sipi_vector; + }; +@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); + void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset); + void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector); + +-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); ++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); + void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); + void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 21ef1ba184ae..5d004da1e35d 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, + r = -EFAULT; + if (copy_from_user(&va, argp, sizeof va)) + goto out; +- r = 0; +- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); ++ r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); + break; + } + case KVM_X86_SETUP_MCE: { +@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) + !kvm_event_needs_reinjection(vcpu); + } + +-static int vapic_enter(struct kvm_vcpu *vcpu) +-{ +- struct kvm_lapic *apic = vcpu->arch.apic; +- struct page *page; +- +- if (!apic || !apic->vapic_addr) +- return 0; +- +- page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); +- if (is_error_page(page)) +- return -EFAULT; +- +- vcpu->arch.apic->vapic_page = page; +- return 0; +-} +- +-static void vapic_exit(struct kvm_vcpu *vcpu) +-{ +- struct kvm_lapic *apic = vcpu->arch.apic; +- int idx; +- +- if (!apic || !apic->vapic_addr) +- return; +- +- idx = srcu_read_lock(&vcpu->kvm->srcu); +- kvm_release_page_dirty(apic->vapic_page); +- mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); +- srcu_read_unlock(&vcpu->kvm->srcu, idx); +-} +- + static void update_cr8_intercept(struct kvm_vcpu *vcpu) + { + int max_irr, tpr; +@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) + struct kvm *kvm = vcpu->kvm; + + vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); +- r = vapic_enter(vcpu); +- if (r) { +- srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); +- return r; +- } + + r = 1; + while (r > 0) { +@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) + + srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); + +- vapic_exit(vcpu); +- + return r; + } + +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index 698796928..b3f608fb2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -833,6 +833,9 @@ Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch #CVE-2013-6367 rhbz 1032207 1042081 Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch +#CVE-2013-6368 rhbz 1032210 1042090 +Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch + # END OF PATCH DEFINITIONS %endif @@ -1603,6 +1606,9 @@ ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch #CVE-2013-6367 rhbz 1032207 1042081 ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch +#CVE-2013-6368 rhbz 1032210 1042090 +ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch + # END OF PATCH APPLICATIONS %endif @@ -2445,6 +2451,7 @@ fi # || || %changelog * Thu Dec 12 2013 Josh Boyer +- CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) - CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) * Wed Dec 11 2013 Josh Boyer From 20c505206af10a3f91a4b8b8f17f0a1f5b8d8349 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Dec 2013 16:19:51 -0500 Subject: [PATCH 488/492] CVE-2013-6376 kvm: BUG_ON in apic_cluster_id (rhbz 1033106 1042099) --- ...ix-guest-initiated-crash-with-x2apic.patch | 109 ++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 116 insertions(+) create mode 100644 KVM-x86-fix-guest-initiated-crash-with-x2apic.patch diff --git a/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch b/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch new file mode 100644 index 000000000..c84fc61b9 --- /dev/null +++ b/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch @@ -0,0 +1,109 @@ +Bugzilla: 1042099 +Upstream-status: 3.13 and sent for stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp361370oab; + Thu, 12 Dec 2013 12:42:56 -0800 (PST) +X-Received: by 10.43.172.4 with SMTP id nw4mr8453091icc.25.1386880976232; + Thu, 12 Dec 2013 12:42:56 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id 2si15667240pax.109.2013.12.12.12.42.31 + for ; + Thu, 12 Dec 2013 12:42:56 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751853Ab3LLUiJ (ORCPT + 64 others); + Thu, 12 Dec 2013 15:38:09 -0500 +Received: from mail-ee0-f54.google.com ([74.125.83.54]:48290 "EHLO + mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751884Ab3LLUhS (ORCPT + ); Thu, 12 Dec 2013 15:37:18 -0500 +Received: by mail-ee0-f54.google.com with SMTP id e51so406857eek.13 + for ; Thu, 12 Dec 2013 12:37:17 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=sender:from:to:cc:subject:date:message-id; + bh=VG00enyRpNYeJLwAwqWOGuy3mCBmvpmEBgLPB1IiKNo=; + b=p0BlraPBMTIxTXGUuJyYTYRxuMKATenNpVX01fyzNpSYZsMruyMU/sJ8gdc2991eao + ZU+66Xlnbd+AyQiuq4P9sMv6Gvax6MvJg04SMZWnLWoZGonmIIwSPch1UKLSJzRN7K+N + +Ot3jLtNBYBoREljPkbscbMVOJ2y+S7N61oOZ7IHZNyXVFWDlW8aunduSgc3cytBEhkx + UMUUbHVLo+XrXtuggFrmn8oUfJ1hiHQSpOyx8bi0ztxlEjL4DEFpJsKbjRe4sGRgeUy6 + dRk+7dEcILKBTRVvXaJSriXG5bhZTbcZ5gZab27Ilm1H8Va5Z6R+9C1AwX2x5CQA7Mb1 + Edug== +X-Received: by 10.14.107.3 with SMTP id n3mr9951281eeg.67.1386880636981; + Thu, 12 Dec 2013 12:37:16 -0800 (PST) +Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) + by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.15 + for + (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Thu, 12 Dec 2013 12:37:16 -0800 (PST) +From: Paolo Bonzini +To: linux-kernel@vger.kernel.org +Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, + stable@vger.kernel.org +Subject: [PATCH] KVM: x86: fix guest-initiated crash with x2apic (CVE-2013-6376) +Date: Thu, 12 Dec 2013 21:36:54 +0100 +Message-Id: <1386880614-23300-4-git-send-email-pbonzini@redhat.com> +X-Mailer: git-send-email 1.8.3.1 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +From: Gleb Natapov + +A guest can cause a BUG_ON() leading to a host kernel crash. +When the guest writes to the ICR to request an IPI, while in x2apic +mode the following things happen, the destination is read from +ICR2, which is a register that the guest can control. + +kvm_irq_delivery_to_apic_fast uses the high 16 bits of ICR2 as the +cluster id. A BUG_ON is triggered, which is a protection against +accessing map->logical_map with an out-of-bounds access and manages +to avoid that anything really unsafe occurs. + +The logic in the code is correct from real HW point of view. The problem +is that KVM supports only one cluster with ID 0 in clustered mode, but +the code that has the bug does not take this into account. + +Reported-by: Lars Bull +Cc: stable@vger.kernel.org +Signed-off-by: Gleb Natapov +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/lapic.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index b8bec45c1610..801dc3fd66e1 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -143,6 +143,8 @@ static inline int kvm_apic_id(struct kvm_lapic *apic) + return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff; + } + ++#define KMV_X2APIC_CID_BITS 0 ++ + static void recalculate_apic_map(struct kvm *kvm) + { + struct kvm_apic_map *new, *old = NULL; +@@ -180,7 +182,8 @@ static void recalculate_apic_map(struct kvm *kvm) + if (apic_x2apic_mode(apic)) { + new->ldr_bits = 32; + new->cid_shift = 16; +- new->cid_mask = new->lid_mask = 0xffff; ++ new->cid_mask = (1 << KMV_X2APIC_CID_BITS) - 1; ++ new->lid_mask = 0xffff; + } else if (kvm_apic_sw_enabled(apic) && + !new->cid_mask /* flat mode */ && + kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) { +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index b3f608fb2..dd9fb5761 100644 --- a/kernel.spec +++ b/kernel.spec @@ -836,6 +836,9 @@ Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch #CVE-2013-6368 rhbz 1032210 1042090 Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch +#CVE-2013-6376 rhbz 1033106 1042099 +Patch25174: KVM-x86-fix-guest-initiated-crash-with-x2apic.patch + # END OF PATCH DEFINITIONS %endif @@ -1609,6 +1612,9 @@ ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch #CVE-2013-6368 rhbz 1032210 1042090 ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch +#CVE-2013-6376 rhbz 1033106 1042099 +ApplyPatch KVM-x86-fix-guest-initiated-crash-with-x2apic.patch + # END OF PATCH APPLICATIONS %endif @@ -2451,6 +2457,7 @@ fi # || || %changelog * Thu Dec 12 2013 Josh Boyer +- CVE-2013-6376 kvm: BUG_ON in apic_cluster_id (rhbz 1033106 1042099) - CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) - CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) From 9f1cdfc65fe0e6489ec6c1f75fb05946592e3a05 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Dec 2013 16:23:58 -0500 Subject: [PATCH 489/492] CVE-2013-4587 kvm: out-of-bounds access (rhbz 1030986 1042071) --- KVM-Improve-create-VCPU-parameter.patch | 93 +++++++++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 100 insertions(+) create mode 100644 KVM-Improve-create-VCPU-parameter.patch diff --git a/KVM-Improve-create-VCPU-parameter.patch b/KVM-Improve-create-VCPU-parameter.patch new file mode 100644 index 000000000..5c5746259 --- /dev/null +++ b/KVM-Improve-create-VCPU-parameter.patch @@ -0,0 +1,93 @@ +Bugzilla: 1042071 +Upstream-status: 3.13 and sent to stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp361298oab; + Thu, 12 Dec 2013 12:41:21 -0800 (PST) +X-Received: by 10.50.109.132 with SMTP id hs4mr33803866igb.34.1386880880893; + Thu, 12 Dec 2013 12:41:20 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id q8si17378346pav.173.2013.12.12.12.40.57 + for ; + Thu, 12 Dec 2013 12:41:20 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1752041Ab3LLUhR (ORCPT + 64 others); + Thu, 12 Dec 2013 15:37:17 -0500 +Received: from mail-ea0-f179.google.com ([209.85.215.179]:43785 "EHLO + mail-ea0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751761Ab3LLUhN (ORCPT + ); Thu, 12 Dec 2013 15:37:13 -0500 +Received: by mail-ea0-f179.google.com with SMTP id r15so485140ead.24 + for ; Thu, 12 Dec 2013 12:37:11 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=sender:from:to:cc:subject:date:message-id; + bh=3nLdta59rbActmGe9iq6aMqjNBfzfF7lqy0gb7EeI0I=; + b=fWKHZKszZQjXAVDzYAlwX8s4+UNEomYiCAX0zvDzW7A5Yiy28MUt0QbNu6288Pu+Qs + NJ38SpDcPLWzGknYOLggLa21nXsv4tX9vp4FFEY4i3H5iCVpXbvxIc+n9ZVOzWY2wkxK + HR1Xf24kJ9FPuV/LoIyu5RlHZUm95BoAe7TxRZWlkcxQ0vEOSAyZQwH4EIj6SS7fXI1d + PoqZKm7100ib0/wm6I49cF2b0EXRTSOYrgZneyniPVGpfTkpN2atNcEgdLSvAWQKEI+p + 79Dt0/BJd2CIuqgUbZBlA8pH6a119FtfrVqxVWJAmVvsv9lpkMIjJrFTj9yqpUFKeeYB + XTeA== +X-Received: by 10.14.6.136 with SMTP id 8mr9978716een.11.1386880631657; + Thu, 12 Dec 2013 12:37:11 -0800 (PST) +Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) + by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.00 + for + (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Thu, 12 Dec 2013 12:37:01 -0800 (PST) +From: Paolo Bonzini +To: linux-kernel@vger.kernel.org +Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, + Andy Honig , stable@vger.kernel.org +Subject: [PATCH] KVM: Improve create VCPU parameter +Date: Thu, 12 Dec 2013 21:36:51 +0100 +Message-Id: <1386880614-23300-1-git-send-email-pbonzini@redhat.com> +X-Mailer: git-send-email 1.8.3.1 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +From: Andy Honig + +In multiple functions the vcpu_id is used as an offset into a bitfield. Ag +malicious user could specify a vcpu_id greater than 255 in order to set or +clear bits in kernel memory. This could be used to elevate priveges in the +kernel. This patch verifies that the vcpu_id provided is less than 255. +The api documentation already specifies that the vcpu_id must be less than +max_vcpus, but this is currently not checked. + +Reported-by: Andrew Honig +Cc: stable@vger.kernel.org +Signed-off-by: Andrew Honig +Signed-off-by: Paolo Bonzini +--- + virt/kvm/kvm_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index a0aa84b5941a..4f588bc94186 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1898,6 +1898,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) + int r; + struct kvm_vcpu *vcpu, *v; + ++ if (id >= KVM_MAX_VCPUS) ++ return -EINVAL; ++ + vcpu = kvm_arch_vcpu_create(kvm, id); + if (IS_ERR(vcpu)) + return PTR_ERR(vcpu); +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index dd9fb5761..505702bd6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -839,6 +839,9 @@ Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch #CVE-2013-6376 rhbz 1033106 1042099 Patch25174: KVM-x86-fix-guest-initiated-crash-with-x2apic.patch +#CVE-2013-4587 rhbz 1030986 1042071 +Patch25175: KVM-Improve-create-VCPU-parameter.patch + # END OF PATCH DEFINITIONS %endif @@ -1615,6 +1618,9 @@ ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch #CVE-2013-6376 rhbz 1033106 1042099 ApplyPatch KVM-x86-fix-guest-initiated-crash-with-x2apic.patch +#CVE-2013-4587 rhbz 1030986 1042071 +ApplyPatch KVM-Improve-create-VCPU-parameter.patch + # END OF PATCH APPLICATIONS %endif @@ -2457,6 +2463,7 @@ fi # || || %changelog * Thu Dec 12 2013 Josh Boyer +- CVE-2013-4587 kvm: out-of-bounds access (rhbz 1030986 1042071) - CVE-2013-6376 kvm: BUG_ON in apic_cluster_id (rhbz 1033106 1042099) - CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) - CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) From 2916df04826e5d1e20750da39a1f375d13f99aa8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 16 Dec 2013 10:51:18 -0500 Subject: [PATCH 490/492] Fix host lockup in bridge code when starting from virt guest (rhbz 1025770) --- ..._handler_data-in-code-executed-on-no.patch | 83 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 92 insertions(+) create mode 100644 br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch diff --git a/br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch b/br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch new file mode 100644 index 000000000..21e749291 --- /dev/null +++ b/br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch @@ -0,0 +1,83 @@ +Bugzilla: 1025770 +Upstream-status: 3.13 (commit 859828c0ea476b42f3a) + +From 1a62121ead27a218d4b02b7130a6f5f6ca9c247e Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Thu, 5 Dec 2013 16:27:37 +0100 +Subject: [PATCH] br: fix use of ->rx_handler_data in code executed on + non-rx_handler path + +br_stp_rcv() is reached by non-rx_handler path. That means there is no +guarantee that dev is bridge port and therefore simple NULL check of +->rx_handler_data is not enough. There is need to check if dev is really +bridge port and since only rcu read lock is held here, do it by checking +->rx_handler pointer. + +Note that synchronize_net() in netdev_rx_handler_unregister() ensures +this approach as valid. + +Introduced originally by: +commit f350a0a87374418635689471606454abc7beaa3a + "bridge: use rx_handler_data pointer to store net_bridge_port pointer" + +Fixed but not in the best way by: +commit b5ed54e94d324f17c97852296d61a143f01b227a + "bridge: fix RCU races with bridge port" + +Reintroduced by: +commit 716ec052d2280d511e10e90ad54a86f5b5d4dcc2 + "bridge: fix NULL pointer deref of br_port_get_rcu" + +Please apply to stable trees as well. Thanks. + +RH bugzilla reference: https://bugzilla.redhat.com/show_bug.cgi?id=1025770 + +Reported-by: Laine Stump +Debugged-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Jiri Pirko +Acked-by: Michael S. Tsirkin +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/bridge/br_private.h | 10 ++++++++++ + net/bridge/br_stp_bpdu.c | 2 +- + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index e14c33b..9a63c42 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -442,6 +442,16 @@ extern netdev_features_t br_features_recompute(struct net_bridge *br, + extern int br_handle_frame_finish(struct sk_buff *skb); + extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb); + ++static inline bool br_rx_handler_check_rcu(const struct net_device *dev) ++{ ++ return rcu_dereference(dev->rx_handler) == br_handle_frame; ++} ++ ++static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev) ++{ ++ return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL; ++} ++ + /* br_ioctl.c */ + extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg); +diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c +index 8660ea3..bdb459d 100644 +--- a/net/bridge/br_stp_bpdu.c ++++ b/net/bridge/br_stp_bpdu.c +@@ -153,7 +153,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, + if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0) + goto err; + +- p = br_port_get_rcu(dev); ++ p = br_port_get_check_rcu(dev); + if (!p) + goto err; + +-- +1.8.3.1 + diff --git a/kernel.spec b/kernel.spec index 505702bd6..8bff14d2b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -842,6 +842,9 @@ Patch25174: KVM-x86-fix-guest-initiated-crash-with-x2apic.patch #CVE-2013-4587 rhbz 1030986 1042071 Patch25175: KVM-Improve-create-VCPU-parameter.patch +#rhbz 1025770 +Patch25176: br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch + # END OF PATCH DEFINITIONS %endif @@ -1621,6 +1624,9 @@ ApplyPatch KVM-x86-fix-guest-initiated-crash-with-x2apic.patch #CVE-2013-4587 rhbz 1030986 1042071 ApplyPatch KVM-Improve-create-VCPU-parameter.patch +#rhbz 1025770 +ApplyPatch br-fix-use-of-rx_handler_data-in-code-executed-on-no.patch + # END OF PATCH APPLICATIONS %endif @@ -2462,6 +2468,9 @@ fi # ||----w | # || || %changelog +* Mon Dec 16 2013 Josh Boyer +- Fix host lockup in bridge code when starting from virt guest (rhbz 1025770) + * Thu Dec 12 2013 Josh Boyer - CVE-2013-4587 kvm: out-of-bounds access (rhbz 1030986 1042071) - CVE-2013-6376 kvm: BUG_ON in apic_cluster_id (rhbz 1033106 1042099) From 20214bd8d2ca20a8a15d7092ca495881fce9daf1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Dec 2013 10:01:07 -0500 Subject: [PATCH 491/492] Drop acpi-sony-nonvs-blacklist.patch This still applies through some confounding patch magic, but the entries were added to the upstream kernel with commits ddf6ce45a7b and d11c78e97e1d46a93e. Over 2 years ago. Sigh. --- acpi-sony-nonvs-blacklist.patch | 38 --------------------------------- kernel.spec | 3 +-- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 acpi-sony-nonvs-blacklist.patch diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch deleted file mode 100644 index db500e8bf..000000000 --- a/acpi-sony-nonvs-blacklist.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c -index 3ed80b2..17fc718 100644 ---- a/drivers/acpi/sleep.c -+++ b/drivers/acpi/sleep.c -@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - }, - { - .callback = init_nvs_nosave, -+ .ident = "Sony Vaio VGN-FW21E", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), -+ }, -+ }, -+ { -+ .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR11M", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c -index 0e46fae..6d9a3ab 100644 ---- a/drivers/acpi/sleep.c -+++ b/drivers/acpi/sleep.c -@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - }, - { - .callback = init_nvs_nosave, -+ .ident = "Sony Vaio VPCEB17FX", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), -+ }, -+ }, -+ { -+ .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR11M", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/kernel.spec b/kernel.spec index 8bff14d2b..b60ae5e45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,8 +644,8 @@ Patch100: taint-vbox.patch Patch110: vmbugon-warnon.patch Patch390: defaults-acpi-video.patch + Patch394: acpi-debug-infinite-loop.patch -Patch396: acpi-sony-nonvs-blacklist.patch Patch450: input-kill-stupid-messages.patch Patch452: no-pcspkr-modalias.patch @@ -1416,7 +1416,6 @@ ApplyPatch arm-tegra-usb-no-reset-linux33.patch # ACPI ApplyPatch defaults-acpi-video.patch ApplyPatch acpi-debug-infinite-loop.patch -ApplyPatch acpi-sony-nonvs-blacklist.patch # # PCI From 00e8dab1681ce334796fceb290da4eec8391421f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Dec 2013 11:24:37 -0500 Subject: [PATCH 492/492] Drop drm-i915-dp-stfu.patch (On Dec 17, 2013) 10:35 < jwb> ajax, drm-i915-dp-stfu.patch 10:36 < jwb> ajax, is that something upstreamable? 10:37 <@ajax> it's probably worth dropping at this point 10:37 <@ajax> if it's still as noisy as it was then it's probably worth investigating --- drm-i915-dp-stfu.patch | 53 ------------------------------------------ kernel.spec | 2 -- 2 files changed, 55 deletions(-) delete mode 100644 drm-i915-dp-stfu.patch diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch deleted file mode 100644 index fb2e58ee9..000000000 --- a/drm-i915-dp-stfu.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index fb2fbc1..0aaf67d 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -283,7 +283,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) - pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; - - if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) { -- WARN(1, "eDP powered off while attempting aux channel communication.\n"); -+ DRM_ERROR("eDP powered off while attempting aux channel communication.\n"); - DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", - I915_READ(pp_stat_reg), - I915_READ(pp_ctrl_reg)); -@@ -376,7 +376,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, - } - - if (try == 3) { -- WARN(1, "dp_aux_ch not started status 0x%08x\n", -+ DRM_ERROR("dp_aux_ch not started status 0x%08x\n", - I915_READ(ch_ctl)); - ret = -EBUSY; - goto out; -@@ -995,8 +995,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) - return; - DRM_DEBUG_KMS("Turn eDP VDD on\n"); - -- WARN(intel_dp->want_panel_vdd, -- "eDP VDD already requested on\n"); -+ if (intel_dp->want_panel_vdd) -+ DRM_ERROR("eDP VDD already requested on\n"); - - intel_dp->want_panel_vdd = true; - -@@ -1070,7 +1070,8 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) - return; - - DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); -- WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); -+ if (!intel_dp->want_panel_vdd) -+ DRM_ERROR("eDP VDD not forced on"); - - intel_dp->want_panel_vdd = false; - -@@ -1144,7 +1145,8 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp) - - DRM_DEBUG_KMS("Turn eDP power off\n"); - -- WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); -+ if (!intel_dp->want_panel_vdd) -+ DRM_ERROR("Need VDD to turn off panel\n"); - - pp = ironlake_get_pp_control(intel_dp); - /* We need to switch off panel power _and_ force vdd, for otherwise some diff --git a/kernel.spec b/kernel.spec index b60ae5e45..915e1a147 100644 --- a/kernel.spec +++ b/kernel.spec @@ -671,7 +671,6 @@ Patch1000: devel-pekey-secure-boot-20130502.patch # nouveau + drm fixes # intel drm is all merged upstream Patch1824: drm-intel-next.patch -Patch1825: drm-i915-dp-stfu.patch # mustard patch to shut abrt up. please drop (and notify ajax) whenever it # fails to apply Patch1826: drm-i915-tv-detect-hush.patch @@ -1468,7 +1467,6 @@ ApplyPatch devel-pekey-secure-boot-20130502.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-tv-detect-hush.patch # silence the ACPI blacklist code